summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/CGBlocks.cpp36
-rw-r--r--lib/CodeGen/CGBlocks.h1
-rw-r--r--lib/CodeGen/CGClass.cpp11
-rw-r--r--lib/CodeGen/CGCleanup.cpp2
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp465
-rw-r--r--lib/CodeGen/CGDebugInfo.h12
-rw-r--r--lib/CodeGen/CGDecl.cpp386
-rw-r--r--lib/CodeGen/CGException.cpp16
-rw-r--r--lib/CodeGen/CGExpr.cpp82
-rw-r--r--lib/CodeGen/CGObjC.cpp25
-rw-r--r--lib/CodeGen/CGObjCGNU.cpp15
-rw-r--r--lib/CodeGen/CGObjCMac.cpp11
-rw-r--r--lib/CodeGen/CGRecordLayoutBuilder.cpp26
-rw-r--r--lib/CodeGen/CodeGenFunction.h50
-rw-r--r--lib/CodeGen/CodeGenModule.cpp2
-rw-r--r--lib/CodeGen/CodeGenModule.h11
-rw-r--r--lib/CodeGen/TargetInfo.cpp11
17 files changed, 771 insertions, 391 deletions
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index a35648d..9587de2 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -895,12 +895,9 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
QualType selfTy = getContext().VoidPtrTy;
IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor");
- // FIXME: this leaks, and we only need it very temporarily.
- ImplicitParamDecl *selfDecl =
- ImplicitParamDecl::Create(getContext(),
- const_cast<BlockDecl*>(blockDecl),
- SourceLocation(), II, selfTy);
- args.push_back(std::make_pair(selfDecl, selfTy));
+ ImplicitParamDecl selfDecl(const_cast<BlockDecl*>(blockDecl),
+ SourceLocation(), II, selfTy);
+ args.push_back(std::make_pair(&selfDecl, selfTy));
// Now add the rest of the parameters.
for (BlockDecl::param_const_iterator i = blockDecl->param_begin(),
@@ -928,12 +925,11 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
blockInfo.getBlockExpr()->getBody()->getLocEnd());
CurFuncDecl = outerFnDecl; // StartFunction sets this to blockDecl
- // Okay. Undo some of what StartFunction did. We really don't need
- // an alloca for the block address; in theory we could remove it,
- // but that might do unpleasant things to debug info.
- llvm::AllocaInst *blockAddrAlloca
- = cast<llvm::AllocaInst>(LocalDeclMap[selfDecl]);
- llvm::Value *blockAddr = Builder.CreateLoad(blockAddrAlloca);
+ // Okay. Undo some of what StartFunction did.
+
+ // Pull the 'self' reference out of the local decl map.
+ llvm::Value *blockAddr = LocalDeclMap[&selfDecl];
+ LocalDeclMap.erase(&selfDecl);
BlockPointer = Builder.CreateBitCast(blockAddr,
blockInfo.StructureType->getPointerTo(),
"block");
@@ -1010,7 +1006,7 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
continue;
}
- DI->EmitDeclareOfBlockDeclRefVariable(variable, blockAddrAlloca,
+ DI->EmitDeclareOfBlockDeclRefVariable(variable, BlockPointer,
Builder, blockInfo);
}
}
@@ -1376,10 +1372,9 @@ llvm::Constant *CodeGenModule::BuildbyrefCopyHelper(const llvm::Type *T,
BlockFieldFlags flags,
unsigned align,
const VarDecl *var) {
- // All alignments below that of pointer alignment collapse down to just
- // pointer alignment, as we always have at least that much alignment to begin
- // with.
- align /= unsigned(getTarget().getPointerAlign(0) / 8);
+ // All alignments below pointer alignment are bumped up, as we
+ // always have at least that much alignment to begin with.
+ if (align < PointerAlignInBytes) align = PointerAlignInBytes;
// As an optimization, we only generate a single function of each kind we
// might need. We need a different one for each alignment and for each
@@ -1396,10 +1391,9 @@ llvm::Constant *CodeGenModule::BuildbyrefDestroyHelper(const llvm::Type *T,
BlockFieldFlags flags,
unsigned align,
const VarDecl *var) {
- // All alignments below that of pointer alignment collpase down to just
- // pointer alignment, as we always have at least that much alignment to begin
- // with.
- align /= unsigned(getTarget().getPointerAlign(0) / 8);
+ // All alignments below pointer alignment are bumped up, as we
+ // always have at least that much alignment to begin with.
+ if (align < PointerAlignInBytes) align = PointerAlignInBytes;
// As an optimization, we only generate a single function of each kind we
// might need. We need a different one for each alignment and for each
diff --git a/lib/CodeGen/CGBlocks.h b/lib/CodeGen/CGBlocks.h
index bee729d..0bc8bca 100644
--- a/lib/CodeGen/CGBlocks.h
+++ b/lib/CodeGen/CGBlocks.h
@@ -177,7 +177,6 @@ public:
const BlockExpr *Block;
CharUnits BlockSize;
CharUnits BlockAlign;
- llvm::SmallVector<const Expr*, 8> BlockLayout;
const Capture &getCapture(const VarDecl *var) const {
llvm::DenseMap<const VarDecl*, Capture>::const_iterator
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index 8e88beb..cd28bbe 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtCXX.h"
+#include "clang/Frontend/CodeGenOptions.h"
using namespace clang;
using namespace CodeGen;
@@ -1140,6 +1141,16 @@ CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
llvm::Value *This,
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd) {
+
+ CGDebugInfo *DI = getDebugInfo();
+ if (DI && CGM.getCodeGenOpts().LimitDebugInfo) {
+ // If debug info for this class has been emitted then this is the right time
+ // to do so.
+ const CXXRecordDecl *Parent = D->getParent();
+ DI->getOrCreateRecordType(CGM.getContext().getTypeDeclType(Parent),
+ Parent->getLocation());
+ }
+
if (D->isTrivial()) {
if (ArgBeg == ArgEnd) {
// Trivial default constructor, no codegen required.
diff --git a/lib/CodeGen/CGCleanup.cpp b/lib/CodeGen/CGCleanup.cpp
index 374ede8..1d7901a 100644
--- a/lib/CodeGen/CGCleanup.cpp
+++ b/lib/CodeGen/CGCleanup.cpp
@@ -876,7 +876,7 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
///
/// As a side-effect, this method clears the insertion point.
void CodeGenFunction::EmitBranchThroughCleanup(JumpDest Dest) {
- assert(Dest.getScopeDepth().encloses(EHStack.getInnermostNormalCleanup())
+ assert(Dest.getScopeDepth().encloses(EHStack.stable_begin())
&& "stale jump destination");
if (!HaveInsertPoint())
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 469b460..dfd9f56 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -156,14 +156,14 @@ CGDebugInfo::getClassName(RecordDecl *RD) {
llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
if (!Loc.isValid())
// If Location is not valid then use main input file.
- return DBuilder.CreateFile(TheCU.getFilename(), TheCU.getDirectory());
+ return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory());
SourceManager &SM = CGM.getContext().getSourceManager();
PresumedLoc PLoc = SM.getPresumedLoc(Loc);
if (PLoc.isInvalid() || llvm::StringRef(PLoc.getFilename()).empty())
// If the location is not valid then use main input file.
- return DBuilder.CreateFile(TheCU.getFilename(), TheCU.getDirectory());
+ return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory());
// Cache the results.
const char *fname = PLoc.getFilename();
@@ -176,7 +176,7 @@ llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
return llvm::DIFile(cast<llvm::MDNode>(it->second));
}
- llvm::DIFile F = DBuilder.CreateFile(PLoc.getFilename(), getCurrentDirname());
+ llvm::DIFile F = DBuilder.createFile(PLoc.getFilename(), getCurrentDirname());
DIFileCache[fname] = F;
return F;
@@ -185,7 +185,7 @@ llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
/// getOrCreateMainFile - Get the file info for main compile unit.
llvm::DIFile CGDebugInfo::getOrCreateMainFile() {
- return DBuilder.CreateFile(TheCU.getFilename(), TheCU.getDirectory());
+ return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory());
}
/// getLineNumber - Get line number for the location. If location is invalid
@@ -264,7 +264,7 @@ void CGDebugInfo::CreateCompileUnit() {
RuntimeVers = LO.ObjCNonFragileABI ? 2 : 1;
// Create new compile unit.
- DBuilder.CreateCompileUnit(
+ DBuilder.createCompileUnit(
LangTag, Filename, getCurrentDirname(),
Producer,
LO.Optimize, CGM.getCodeGenOpts().DwarfDebugFlags, RuntimeVers);
@@ -282,7 +282,7 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
case BuiltinType::Void:
return llvm::DIType();
case BuiltinType::ObjCClass:
- return DBuilder.CreateStructType(TheCU, "objc_class",
+ return DBuilder.createStructType(TheCU, "objc_class",
getOrCreateMainFile(), 0, 0, 0,
llvm::DIDescriptor::FlagFwdDecl,
llvm::DIArray());
@@ -293,28 +293,28 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
// } *id;
llvm::DIType OCTy =
- DBuilder.CreateStructType(TheCU, "objc_class",
+ DBuilder.createStructType(TheCU, "objc_class",
getOrCreateMainFile(), 0, 0, 0,
llvm::DIDescriptor::FlagFwdDecl,
llvm::DIArray());
unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
- llvm::DIType ISATy = DBuilder.CreatePointerType(OCTy, Size);
+ llvm::DIType ISATy = DBuilder.createPointerType(OCTy, Size);
llvm::SmallVector<llvm::Value *, 16> EltTys;
llvm::DIType FieldTy =
- DBuilder.CreateMemberType("isa", getOrCreateMainFile(),
+ DBuilder.createMemberType("isa", getOrCreateMainFile(),
0,Size, 0, 0, 0, ISATy);
EltTys.push_back(FieldTy);
llvm::DIArray Elements =
- DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size());
+ DBuilder.getOrCreateArray(EltTys.data(), EltTys.size());
- return DBuilder.CreateStructType(TheCU, "objc_object",
+ return DBuilder.createStructType(TheCU, "objc_object",
getOrCreateMainFile(),
0, 0, 0, 0, Elements);
}
case BuiltinType::ObjCSel: {
- return DBuilder.CreateStructType(TheCU, "objc_selector",
+ return DBuilder.createStructType(TheCU, "objc_selector",
getOrCreateMainFile(), 0, 0, 0,
llvm::DIDescriptor::FlagFwdDecl,
llvm::DIArray());
@@ -350,7 +350,7 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
uint64_t Size = CGM.getContext().getTypeSize(BT);
uint64_t Align = CGM.getContext().getTypeAlign(BT);
llvm::DIType DbgTy =
- DBuilder.CreateBasicType(BTName, Size, Align, Encoding);
+ DBuilder.createBasicType(BTName, Size, Align, Encoding);
return DbgTy;
}
@@ -363,7 +363,7 @@ llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty) {
uint64_t Size = CGM.getContext().getTypeSize(Ty);
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
llvm::DIType DbgTy =
- DBuilder.CreateBasicType("complex", Size, Align, Encoding);
+ DBuilder.createBasicType("complex", Size, Align, Encoding);
return DbgTy;
}
@@ -399,7 +399,7 @@ llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile Unit) {
// No need to fill in the Name, Line, Size, Alignment, Offset in case of
// CVR derived types.
- llvm::DIType DbgTy = DBuilder.CreateQualifiedType(Tag, FromTy);
+ llvm::DIType DbgTy = DBuilder.createQualifiedType(Tag, FromTy);
return DbgTy;
}
@@ -430,19 +430,19 @@ llvm::DIType CGDebugInfo::CreatePointeeType(QualType PointeeTy,
llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());
unsigned Line = getLineNumber(RD->getLocation());
llvm::DIDescriptor FDContext =
- getContextDescriptor(dyn_cast<Decl>(RD->getDeclContext()));
+ getContextDescriptor(cast<Decl>(RD->getDeclContext()));
if (RD->isStruct())
- return DBuilder.CreateStructType(FDContext, RD->getName(), DefUnit,
+ return DBuilder.createStructType(FDContext, RD->getName(), DefUnit,
Line, 0, 0, llvm::DIType::FlagFwdDecl,
llvm::DIArray());
else if (RD->isUnion())
- return DBuilder.CreateUnionType(FDContext, RD->getName(), DefUnit,
+ return DBuilder.createUnionType(FDContext, RD->getName(), DefUnit,
Line, 0, 0, llvm::DIType::FlagFwdDecl,
llvm::DIArray());
else {
assert(RD->isClass() && "Unknown RecordType!");
- return DBuilder.CreateClassType(FDContext, RD->getName(), DefUnit,
+ return DBuilder.createClassType(FDContext, RD->getName(), DefUnit,
Line, 0, 0, 0, llvm::DIType::FlagFwdDecl,
llvm::DIType(), llvm::DIArray());
}
@@ -457,7 +457,7 @@ llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag,
llvm::DIFile Unit) {
if (Tag == llvm::dwarf::DW_TAG_reference_type)
- return DBuilder.CreateReferenceType(CreatePointeeType(PointeeTy, Unit));
+ return DBuilder.createReferenceType(CreatePointeeType(PointeeTy, Unit));
// Bit size, align and offset of the type.
// Size is always the size of a pointer. We can't use getTypeSize here
@@ -467,7 +467,7 @@ llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag,
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
return
- DBuilder.CreatePointerType(CreatePointeeType(PointeeTy, Unit), Size, Align);
+ DBuilder.createPointerType(CreatePointeeType(PointeeTy, Unit), Size, Align);
}
llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
@@ -488,20 +488,20 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
EltTys.push_back(CreateMemberType(Unit, FType, "reserved", &FieldOffset));
EltTys.push_back(CreateMemberType(Unit, FType, "Size", &FieldOffset));
- Elements = DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size());
+ Elements = DBuilder.getOrCreateArray(EltTys.data(), EltTys.size());
EltTys.clear();
unsigned Flags = llvm::DIDescriptor::FlagAppleBlock;
unsigned LineNo = getLineNumber(CurLoc);
- EltTy = DBuilder.CreateStructType(Unit, "__block_descriptor",
+ EltTy = DBuilder.createStructType(Unit, "__block_descriptor",
Unit, LineNo, FieldOffset, 0,
Flags, Elements);
// Bit size, align and offset of the type.
uint64_t Size = CGM.getContext().getTypeSize(Ty);
- DescTy = DBuilder.CreatePointerType(EltTy, Size);
+ DescTy = DBuilder.createPointerType(EltTy, Size);
FieldOffset = 0;
FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
@@ -516,20 +516,20 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
FieldTy = DescTy;
FieldSize = CGM.getContext().getTypeSize(Ty);
FieldAlign = CGM.getContext().getTypeAlign(Ty);
- FieldTy = DBuilder.CreateMemberType("__descriptor", Unit,
+ FieldTy = DBuilder.createMemberType("__descriptor", Unit,
LineNo, FieldSize, FieldAlign,
FieldOffset, 0, FieldTy);
EltTys.push_back(FieldTy);
FieldOffset += FieldSize;
- Elements = DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size());
+ Elements = DBuilder.getOrCreateArray(EltTys.data(), EltTys.size());
- EltTy = DBuilder.CreateStructType(Unit, "__block_literal_generic",
+ EltTy = DBuilder.createStructType(Unit, "__block_literal_generic",
Unit, LineNo, FieldOffset, 0,
Flags, Elements);
BlockLiteralGenericSet = true;
- BlockLiteralGeneric = DBuilder.CreatePointerType(EltTy, Size);
+ BlockLiteralGeneric = DBuilder.createPointerType(EltTy, Size);
return BlockLiteralGeneric;
}
@@ -543,7 +543,7 @@ llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty,
// We don't set size information, but do specify where the typedef was
// declared.
unsigned Line = getLineNumber(Ty->getDecl()->getLocation());
- llvm::DIType DbgTy = DBuilder.CreateTypedef(Src, Ty->getDecl()->getName(),
+ llvm::DIType DbgTy = DBuilder.createTypedef(Src, Ty->getDecl()->getName(),
Unit, Line);
return DbgTy;
}
@@ -558,66 +558,76 @@ llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty,
// Set up remainder of arguments if there is a prototype.
// FIXME: IF NOT, HOW IS THIS REPRESENTED? llvm-gcc doesn't represent '...'!
if (isa<FunctionNoProtoType>(Ty))
- EltTys.push_back(DBuilder.CreateUnspecifiedParameter());
+ EltTys.push_back(DBuilder.createUnspecifiedParameter());
else if (const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(Ty)) {
for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
EltTys.push_back(getOrCreateType(FTP->getArgType(i), Unit));
}
llvm::DIArray EltTypeArray =
- DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size());
+ DBuilder.getOrCreateArray(EltTys.data(), EltTys.size());
- llvm::DIType DbgTy = DBuilder.CreateSubroutineType(Unit, EltTypeArray);
+ llvm::DIType DbgTy = DBuilder.createSubroutineType(Unit, EltTypeArray);
return DbgTy;
}
+llvm::DIType CGDebugInfo::createFieldType(llvm::StringRef name,
+ QualType type,
+ Expr *bitWidth,
+ SourceLocation loc,
+ AccessSpecifier AS,
+ uint64_t offsetInBits,
+ llvm::DIFile tunit) {
+ llvm::DIType debugType = getOrCreateType(type, tunit);
+
+ // Get the location for the field.
+ llvm::DIFile file = getOrCreateFile(loc);
+ unsigned line = getLineNumber(loc);
+
+ uint64_t sizeInBits = 0;
+ unsigned alignInBits = 0;
+ if (!type->isIncompleteArrayType()) {
+ llvm::tie(sizeInBits, alignInBits) = CGM.getContext().getTypeInfo(type);
+
+ if (bitWidth)
+ sizeInBits = bitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue();
+ }
+
+ unsigned flags = 0;
+ if (AS == clang::AS_private)
+ flags |= llvm::DIDescriptor::FlagPrivate;
+ else if (AS == clang::AS_protected)
+ flags |= llvm::DIDescriptor::FlagProtected;
+
+ return DBuilder.createMemberType(name, file, line, sizeInBits, alignInBits,
+ offsetInBits, flags, debugType);
+}
+
/// CollectRecordFields - A helper function to collect debug info for
/// record fields. This is used while creating debug info entry for a Record.
void CGDebugInfo::
-CollectRecordFields(const RecordDecl *RD, llvm::DIFile Unit,
- llvm::SmallVectorImpl<llvm::Value *> &EltTys) {
- unsigned FieldNo = 0;
- const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
- for (RecordDecl::field_iterator I = RD->field_begin(),
- E = RD->field_end();
- I != E; ++I, ++FieldNo) {
- FieldDecl *Field = *I;
- llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
- llvm::StringRef FieldName = Field->getName();
-
- // Ignore unnamed fields. Do not ignore unnamed records.
- if (FieldName.empty() && !isa<RecordType>(Field->getType()))
+CollectRecordFields(const RecordDecl *record, llvm::DIFile tunit,
+ llvm::SmallVectorImpl<llvm::Value *> &elements) {
+ unsigned fieldNo = 0;
+ const ASTRecordLayout &layout = CGM.getContext().getASTRecordLayout(record);
+ for (RecordDecl::field_iterator I = record->field_begin(),
+ E = record->field_end();
+ I != E; ++I, ++fieldNo) {
+ FieldDecl *field = *I;
+
+ llvm::StringRef name = field->getName();
+ QualType type = field->getType();
+
+ // Ignore unnamed fields unless they're anonymous structs/unions.
+ if (name.empty() && !type->isRecordType())
continue;
- // Get the location for the field.
- llvm::DIFile FieldDefUnit = getOrCreateFile(Field->getLocation());
- unsigned FieldLine = getLineNumber(Field->getLocation());
- QualType FType = Field->getType();
- uint64_t FieldSize = 0;
- unsigned FieldAlign = 0;
- if (!FType->isIncompleteArrayType()) {
-
- // Bit size, align and offset of the type.
- FieldSize = CGM.getContext().getTypeSize(FType);
- Expr *BitWidth = Field->getBitWidth();
- if (BitWidth)
- FieldSize = BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue();
- FieldAlign = CGM.getContext().getTypeAlign(FType);
- }
+ llvm::DIType fieldType
+ = createFieldType(name, type, field->getBitWidth(),
+ field->getLocation(), field->getAccess(),
+ layout.getFieldOffset(fieldNo), tunit);
- uint64_t FieldOffset = RL.getFieldOffset(FieldNo);
-
- unsigned Flags = 0;
- AccessSpecifier Access = I->getAccess();
- if (Access == clang::AS_private)
- Flags |= llvm::DIDescriptor::FlagPrivate;
- else if (Access == clang::AS_protected)
- Flags |= llvm::DIDescriptor::FlagProtected;
-
- FieldTy = DBuilder.CreateMemberType(FieldName, FieldDefUnit,
- FieldLine, FieldSize, FieldAlign,
- FieldOffset, Flags, FieldTy);
- EltTys.push_back(FieldTy);
+ elements.push_back(fieldType);
}
}
@@ -649,7 +659,7 @@ CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method,
QualType ThisPtr =
Context.getPointerType(Context.getTagDeclType(Method->getParent()));
llvm::DIType ThisPtrType =
- DBuilder.CreateArtificialType(getOrCreateType(ThisPtr, Unit));
+ DBuilder.createArtificialType(getOrCreateType(ThisPtr, Unit));
TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType;
Elts.push_back(ThisPtrType);
@@ -660,9 +670,9 @@ CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method,
Elts.push_back(Args.getElement(i));
llvm::DIArray EltTypeArray =
- DBuilder.GetOrCreateArray(Elts.data(), Elts.size());
+ DBuilder.getOrCreateArray(Elts.data(), Elts.size());
- return DBuilder.CreateSubroutineType(Unit, EltTypeArray);
+ return DBuilder.createSubroutineType(Unit, EltTypeArray);
}
/// isFunctionLocalClass - Return true if CXXRecordDecl is defined
@@ -736,7 +746,7 @@ CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method,
Flags |= llvm::DIDescriptor::FlagPrototyped;
llvm::DISubprogram SP =
- DBuilder.CreateMethod(RecordTy , MethodName, MethodLinkageName,
+ DBuilder.createMethod(RecordTy , MethodName, MethodLinkageName,
MethodDefUnit, MethodLine,
MethodTy, /*isLocalToUnit=*/false,
/* isDefinition=*/ false,
@@ -780,7 +790,7 @@ CollectCXXFriends(const CXXRecordDecl *RD, llvm::DIFile Unit,
for (CXXRecordDecl::friend_iterator BI = RD->friend_begin(),
BE = RD->friend_end(); BI != BE; ++BI) {
if (TypeSourceInfo *TInfo = (*BI)->getFriendType())
- EltTys.push_back(DBuilder.CreateFriend(RecordTy,
+ EltTys.push_back(DBuilder.createFriend(RecordTy,
getOrCreateType(TInfo->getType(),
Unit)));
}
@@ -818,7 +828,7 @@ CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile Unit,
BFlags |= llvm::DIDescriptor::FlagProtected;
llvm::DIType DTy =
- DBuilder.CreateInheritance(RecordTy,
+ DBuilder.createInheritance(RecordTy,
getOrCreateType(BI->getType(), Unit),
BaseOffset, BFlags);
EltTys.push_back(DTy);
@@ -834,12 +844,12 @@ llvm::DIType CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile Unit) {
/* Function type */
llvm::Value *STy = getOrCreateType(Context.IntTy, Unit);
- llvm::DIArray SElements = DBuilder.GetOrCreateArray(&STy, 1);
- llvm::DIType SubTy = DBuilder.CreateSubroutineType(Unit, SElements);
+ llvm::DIArray SElements = DBuilder.getOrCreateArray(&STy, 1);
+ llvm::DIType SubTy = DBuilder.createSubroutineType(Unit, SElements);
unsigned Size = Context.getTypeSize(Context.VoidPtrTy);
- llvm::DIType vtbl_ptr_type = DBuilder.CreatePointerType(SubTy, Size, 0,
+ llvm::DIType vtbl_ptr_type = DBuilder.createPointerType(SubTy, Size, 0,
"__vtbl_ptr_type");
- VTablePtrType = DBuilder.CreatePointerType(vtbl_ptr_type, Size);
+ VTablePtrType = DBuilder.createPointerType(vtbl_ptr_type, Size);
return VTablePtrType;
}
@@ -872,7 +882,7 @@ CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile Unit,
unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
llvm::DIType VPTR
- = DBuilder.CreateMemberType(getVTableName(RD), Unit,
+ = DBuilder.createMemberType(getVTableName(RD), Unit,
0, Size, 0, 0, 0,
getOrCreateVTablePtrType(Unit));
EltTys.push_back(VPTR);
@@ -882,7 +892,7 @@ CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile Unit,
llvm::DIType CGDebugInfo::getOrCreateRecordType(QualType RTy,
SourceLocation Loc) {
llvm::DIType T = getOrCreateType(RTy, getOrCreateFile(Loc));
- DBuilder.RetainType(T);
+ DBuilder.retainType(T);
return T;
}
@@ -902,13 +912,13 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
// may refer to the forward decl if the struct is recursive) and replace all
// uses of the forward declaration with the final definition.
llvm::DIDescriptor FDContext =
- getContextDescriptor(dyn_cast<Decl>(RD->getDeclContext()));
+ getContextDescriptor(cast<Decl>(RD->getDeclContext()));
// If this is just a forward declaration, construct an appropriately
// marked node and just return it.
if (!RD->getDefinition()) {
llvm::DIType FwdDecl =
- DBuilder.CreateStructType(FDContext, RD->getName(),
+ DBuilder.createStructType(FDContext, RD->getName(),
DefUnit, Line, 0, 0,
llvm::DIDescriptor::FlagFwdDecl,
llvm::DIArray());
@@ -916,7 +926,7 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
return FwdDecl;
}
- llvm::DIType FwdDecl = DBuilder.CreateTemporaryType(DefUnit);
+ llvm::DIType FwdDecl = DBuilder.createTemporaryType(DefUnit);
llvm::MDNode *MN = FwdDecl;
llvm::TrackingVH<llvm::MDNode> FwdDeclNode = MN;
@@ -952,7 +962,7 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
llvm::DIType VTy = getOrCreateType(V->getType(), VUnit);
// Do not use DIGlobalVariable for enums.
if (VTy.getTag() != llvm::dwarf::DW_TAG_enumeration_type) {
- DBuilder.CreateStaticVariable(FwdDecl, VName, VName, VUnit,
+ DBuilder.createStaticVariable(FwdDecl, VName, VName, VUnit,
getLineNumber(V->getLocation()),
VTy, true, CI);
}
@@ -973,13 +983,13 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
if (TA.getKind() == TemplateArgument::Type) {
llvm::DIType TTy = getOrCreateType(TA.getAsType(), Unit);
llvm::DITemplateTypeParameter TTP =
- DBuilder.CreateTemplateTypeParameter(TheCU, TTy.getName(), TTy);
+ DBuilder.createTemplateTypeParameter(TheCU, TTy.getName(), TTy);
TemplateParams.push_back(TTP);
} else if (TA.getKind() == TemplateArgument::Integral) {
llvm::DIType TTy = getOrCreateType(TA.getIntegralType(), Unit);
// FIXME: Get parameter name, instead of parameter type name.
llvm::DITemplateValueParameter TVP =
- DBuilder.CreateTemplateValueParameter(TheCU, TTy.getName(), TTy,
+ DBuilder.createTemplateValueParameter(TheCU, TTy.getName(), TTy,
TA.getAsIntegral()->getZExtValue());
TemplateParams.push_back(TVP);
}
@@ -994,19 +1004,19 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
RegionMap.erase(RI);
llvm::DIDescriptor RDContext =
- getContextDescriptor(dyn_cast<Decl>(RD->getDeclContext()));
+ getContextDescriptor(cast<Decl>(RD->getDeclContext()));
llvm::StringRef RDName = RD->getName();
uint64_t Size = CGM.getContext().getTypeSize(Ty);
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
llvm::DIArray Elements =
- DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size());
+ DBuilder.getOrCreateArray(EltTys.data(), EltTys.size());
llvm::MDNode *RealDecl = NULL;
if (RD->isStruct())
- RealDecl = DBuilder.CreateStructType(RDContext, RDName, DefUnit, Line,
+ RealDecl = DBuilder.createStructType(RDContext, RDName, DefUnit, Line,
Size, Align, 0, Elements);
else if (RD->isUnion())
- RealDecl = DBuilder.CreateUnionType(RDContext, RDName, DefUnit, Line,
+ RealDecl = DBuilder.createUnionType(RDContext, RDName, DefUnit, Line,
Size, Align, 0, Elements);
else {
assert(RD->isClass() && "Unknown RecordType!");
@@ -1030,8 +1040,8 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
else if (CXXDecl->isDynamicClass())
ContainingType = FwdDecl;
llvm::DIArray TParamsArray =
- DBuilder.GetOrCreateArray(TemplateParams.data(), TemplateParams.size());
- RealDecl = DBuilder.CreateClassType(RDContext, RDName, DefUnit, Line,
+ DBuilder.getOrCreateArray(TemplateParams.data(), TemplateParams.size());
+ RealDecl = DBuilder.createClassType(RDContext, RDName, DefUnit, Line,
Size, Align, 0, 0, llvm::DIType(),
Elements, ContainingType,
TParamsArray);
@@ -1067,7 +1077,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
// debug type.
if (ID->isForwardDecl()) {
llvm::DIType FwdDecl =
- DBuilder.CreateStructType(Unit, ID->getName(),
+ DBuilder.createStructType(Unit, ID->getName(),
DefUnit, Line, 0, 0, 0,
llvm::DIArray(), RuntimeLang);
return FwdDecl;
@@ -1079,7 +1089,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
// its members. Finally, we create a descriptor for the complete type (which
// may refer to the forward decl if the struct is recursive) and replace all
// uses of the forward declaration with the final definition.
- llvm::DIType FwdDecl = DBuilder.CreateTemporaryType(DefUnit);
+ llvm::DIType FwdDecl = DBuilder.createTemporaryType(DefUnit);
llvm::MDNode *MN = FwdDecl;
llvm::TrackingVH<llvm::MDNode> FwdDeclNode = MN;
@@ -1101,7 +1111,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
return llvm::DIType();
llvm::DIType InhTag =
- DBuilder.CreateInheritance(FwdDecl, SClassTy, 0, 0);
+ DBuilder.createInheritance(FwdDecl, SClassTy, 0, 0);
EltTys.push_back(InhTag);
}
@@ -1146,14 +1156,14 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
else if (Field->getAccessControl() == ObjCIvarDecl::Private)
Flags = llvm::DIDescriptor::FlagPrivate;
- FieldTy = DBuilder.CreateMemberType(FieldName, FieldDefUnit,
+ FieldTy = DBuilder.createMemberType(FieldName, FieldDefUnit,
FieldLine, FieldSize, FieldAlign,
FieldOffset, Flags, FieldTy);
EltTys.push_back(FieldTy);
}
llvm::DIArray Elements =
- DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size());
+ DBuilder.getOrCreateArray(EltTys.data(), EltTys.size());
RegionStack.pop_back();
llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator RI =
@@ -1166,7 +1176,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
llvm::DIType RealDecl =
- DBuilder.CreateStructType(Unit, ID->getName(), DefUnit,
+ DBuilder.createStructType(Unit, ID->getName(), DefUnit,
Line, Size, Align, 0,
Elements, RuntimeLang);
@@ -1194,14 +1204,14 @@ llvm::DIType CGDebugInfo::CreateType(const VectorType *Ty,
if (NumElems > 0)
--NumElems;
- llvm::Value *Subscript = DBuilder.GetOrCreateSubrange(0, NumElems);
- llvm::DIArray SubscriptArray = DBuilder.GetOrCreateArray(&Subscript, 1);
+ llvm::Value *Subscript = DBuilder.getOrCreateSubrange(0, NumElems);
+ llvm::DIArray SubscriptArray = DBuilder.getOrCreateArray(&Subscript, 1);
uint64_t Size = CGM.getContext().getTypeSize(Ty);
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
return
- DBuilder.CreateVectorType(Size, Align, ElementTy, SubscriptArray);
+ DBuilder.createVectorType(Size, Align, ElementTy, SubscriptArray);
}
llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty,
@@ -1238,16 +1248,16 @@ llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty,
if (CAT->getSize().getZExtValue())
Upper = CAT->getSize().getZExtValue() - 1;
// FIXME: Verify this is right for VLAs.
- Subscripts.push_back(DBuilder.GetOrCreateSubrange(0, Upper));
+ Subscripts.push_back(DBuilder.getOrCreateSubrange(0, Upper));
EltTy = Ty->getElementType();
}
}
llvm::DIArray SubscriptArray =
- DBuilder.GetOrCreateArray(Subscripts.data(), Subscripts.size());
+ DBuilder.getOrCreateArray(Subscripts.data(), Subscripts.size());
llvm::DIType DbgTy =
- DBuilder.CreateArrayType(Size, Align, getOrCreateType(EltTy, Unit),
+ DBuilder.createArrayType(Size, Align, getOrCreateType(EltTy, Unit),
SubscriptArray);
return DbgTy;
}
@@ -1283,21 +1293,21 @@ llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty,
// FIXME: This should probably be a function type instead.
ElementTypes[0] =
- DBuilder.CreateMemberType("ptr", U, 0,
+ DBuilder.createMemberType("ptr", U, 0,
Info.first, Info.second, FieldOffset, 0,
PointerDiffDITy);
FieldOffset += Info.first;
ElementTypes[1] =
- DBuilder.CreateMemberType("ptr", U, 0,
+ DBuilder.createMemberType("ptr", U, 0,
Info.first, Info.second, FieldOffset, 0,
PointerDiffDITy);
llvm::DIArray Elements =
- DBuilder.GetOrCreateArray(&ElementTypes[0],
+ DBuilder.getOrCreateArray(&ElementTypes[0],
llvm::array_lengthof(ElementTypes));
- return DBuilder.CreateStructType(U, llvm::StringRef("test"),
+ return DBuilder.createStructType(U, llvm::StringRef("test"),
U, 0, FieldOffset,
0, 0, Elements);
}
@@ -1312,13 +1322,13 @@ llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED) {
Enum = ED->enumerator_begin(), EnumEnd = ED->enumerator_end();
Enum != EnumEnd; ++Enum) {
Enumerators.push_back(
- DBuilder.CreateEnumerator(Enum->getName(),
+ DBuilder.createEnumerator(Enum->getName(),
Enum->getInitVal().getZExtValue()));
}
// Return a CompositeType for the enum itself.
llvm::DIArray EltArray =
- DBuilder.GetOrCreateArray(Enumerators.data(), Enumerators.size());
+ DBuilder.getOrCreateArray(Enumerators.data(), Enumerators.size());
llvm::DIFile DefUnit = getOrCreateFile(ED->getLocation());
unsigned Line = getLineNumber(ED->getLocation());
@@ -1329,9 +1339,9 @@ llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED) {
Align = CGM.getContext().getTypeAlign(ED->getTypeForDecl());
}
llvm::DIDescriptor EnumContext =
- getContextDescriptor(dyn_cast<Decl>(ED->getDeclContext()));
+ getContextDescriptor(cast<Decl>(ED->getDeclContext()));
llvm::DIType DbgTy =
- DBuilder.CreateEnumerationType(EnumContext, ED->getName(), DefUnit, Line,
+ DBuilder.createEnumerationType(EnumContext, ED->getName(), DefUnit, Line,
Size, Align, EltArray);
return DbgTy;
}
@@ -1485,7 +1495,7 @@ llvm::DIType CGDebugInfo::CreateMemberType(llvm::DIFile Unit, QualType FType,
llvm::DIType FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
uint64_t FieldSize = CGM.getContext().getTypeSize(FType);
unsigned FieldAlign = CGM.getContext().getTypeAlign(FType);
- llvm::DIType Ty = DBuilder.CreateMemberType(Name, Unit, 0,
+ llvm::DIType Ty = DBuilder.createMemberType(Name, Unit, 0,
FieldSize, FieldAlign,
*Offset, 0, FieldTy);
*Offset += FieldSize;
@@ -1548,7 +1558,7 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType,
if (D->isImplicit())
Flags |= llvm::DIDescriptor::FlagArtificial;
llvm::DISubprogram SP =
- DBuilder.CreateFunction(FDContext, Name, LinkageName, Unit,
+ DBuilder.createFunction(FDContext, Name, LinkageName, Unit,
LineNo, getOrCreateType(FnType, Unit),
Fn->hasInternalLinkage(), true/*definition*/,
Flags, CGM.getLangOptions().Optimize, Fn);
@@ -1640,7 +1650,7 @@ void CGDebugInfo::UpdateLineDirectiveRegion(CGBuilderTy &Builder) {
/// region - "llvm.dbg.region.start.".
void CGDebugInfo::EmitRegionStart(CGBuilderTy &Builder) {
llvm::DIDescriptor D =
- DBuilder.CreateLexicalBlock(RegionStack.empty() ?
+ DBuilder.createLexicalBlock(RegionStack.empty() ?
llvm::DIDescriptor() :
llvm::DIDescriptor(RegionStack.back()),
getOrCreateFile(CurLoc),
@@ -1725,18 +1735,18 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD,
FieldAlign = Align.getQuantity()*8;
*XOffset = FieldOffset;
- FieldTy = DBuilder.CreateMemberType(VD->getName(), Unit,
+ FieldTy = DBuilder.createMemberType(VD->getName(), Unit,
0, FieldSize, FieldAlign,
FieldOffset, 0, FieldTy);
EltTys.push_back(FieldTy);
FieldOffset += FieldSize;
llvm::DIArray Elements =
- DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size());
+ DBuilder.getOrCreateArray(EltTys.data(), EltTys.size());
unsigned Flags = llvm::DIDescriptor::FlagBlockByrefStruct;
- return DBuilder.CreateStructType(Unit, "", Unit, 0, FieldOffset, 0, Flags,
+ return DBuilder.createStructType(Unit, "", Unit, 0, FieldOffset, 0, Flags,
Elements);
}
@@ -1762,13 +1772,13 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
// If Storage is an aggregate returned as 'sret' then let debugger know
// about this.
if (Arg->hasStructRetAttr())
- Ty = DBuilder.CreateReferenceType(Ty);
+ Ty = DBuilder.createReferenceType(Ty);
else if (CXXRecordDecl *Record = VD->getType()->getAsCXXRecordDecl()) {
// If an aggregate variable has non trivial destructor or non trivial copy
// constructor than it is pass indirectly. Let debug info know about this
// by using reference of the aggregate type as a argument type.
if (!Record->hasTrivialCopyConstructor() || !Record->hasTrivialDestructor())
- Ty = DBuilder.CreateReferenceType(Ty);
+ Ty = DBuilder.createReferenceType(Ty);
}
}
@@ -1799,27 +1809,27 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
// Create the descriptor for the variable.
llvm::DIVariable D =
- DBuilder.CreateComplexVariable(Tag,
+ DBuilder.createComplexVariable(Tag,
llvm::DIDescriptor(RegionStack.back()),
VD->getName(), Unit, Line, Ty,
addr.data(), addr.size());
// Insert an llvm.dbg.declare into the current block.
llvm::Instruction *Call =
- DBuilder.InsertDeclare(Storage, D, Builder.GetInsertBlock());
+ DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());
Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
return;
}
// Create the descriptor for the variable.
llvm::DIVariable D =
- DBuilder.CreateLocalVariable(Tag, llvm::DIDescriptor(Scope),
+ DBuilder.createLocalVariable(Tag, llvm::DIDescriptor(Scope),
Name, Unit, Line, Ty,
CGM.getLangOptions().Optimize, Flags);
// Insert an llvm.dbg.declare into the current block.
llvm::Instruction *Call =
- DBuilder.InsertDeclare(Storage, D, Builder.GetInsertBlock());
+ DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());
Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
return;
@@ -1827,33 +1837,34 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
// If VD is an anonymous union then Storage represents value for
// all union fields.
- if (const RecordType *RT = dyn_cast<RecordType>(VD->getType()))
- if (const RecordDecl *RD = dyn_cast<RecordDecl>(RT->getDecl()))
- if (RD->isUnion()) {
- for (RecordDecl::field_iterator I = RD->field_begin(),
- E = RD->field_end();
- I != E; ++I) {
- FieldDecl *Field = *I;
- llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
- llvm::StringRef FieldName = Field->getName();
+ if (const RecordType *RT = dyn_cast<RecordType>(VD->getType())) {
+ const RecordDecl *RD = cast<RecordDecl>(RT->getDecl());
+ if (RD->isUnion()) {
+ for (RecordDecl::field_iterator I = RD->field_begin(),
+ E = RD->field_end();
+ I != E; ++I) {
+ FieldDecl *Field = *I;
+ llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
+ llvm::StringRef FieldName = Field->getName();
- // Ignore unnamed fields. Do not ignore unnamed records.
- if (FieldName.empty() && !isa<RecordType>(Field->getType()))
- continue;
+ // Ignore unnamed fields. Do not ignore unnamed records.
+ if (FieldName.empty() && !isa<RecordType>(Field->getType()))
+ continue;
- // Use VarDecl's Tag, Scope and Line number.
- llvm::DIVariable D =
- DBuilder.CreateLocalVariable(Tag, llvm::DIDescriptor(Scope),
- FieldName, Unit, Line, FieldTy,
- CGM.getLangOptions().Optimize, Flags);
+ // Use VarDecl's Tag, Scope and Line number.
+ llvm::DIVariable D =
+ DBuilder.createLocalVariable(Tag, llvm::DIDescriptor(Scope),
+ FieldName, Unit, Line, FieldTy,
+ CGM.getLangOptions().Optimize, Flags);
- // Insert an llvm.dbg.declare into the current block.
- llvm::Instruction *Call =
- DBuilder.InsertDeclare(Storage, D, Builder.GetInsertBlock());
+ // Insert an llvm.dbg.declare into the current block.
+ llvm::Instruction *Call =
+ DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());
- Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
- }
+ Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
}
+ }
+ }
}
/// EmitDeclare - Emit local variable declaration debug info.
@@ -1887,7 +1898,6 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
llvm::SmallVector<llvm::Value *, 9> addr;
const llvm::Type *Int64Ty = llvm::Type::getInt64Ty(CGM.getLLVMContext());
- addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref));
addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus));
addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
if (isByRef) {
@@ -1905,12 +1915,12 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
// Create the descriptor for the variable.
llvm::DIVariable D =
- DBuilder.CreateComplexVariable(Tag, llvm::DIDescriptor(RegionStack.back()),
+ DBuilder.createComplexVariable(Tag, llvm::DIDescriptor(RegionStack.back()),
VD->getName(), Unit, Line, Ty,
addr.data(), addr.size());
// Insert an llvm.dbg.declare into the current block.
llvm::Instruction *Call =
- DBuilder.InsertDeclare(Storage, D, Builder.GetInsertBlock());
+ DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());
llvm::MDNode *Scope = RegionStack.back();
Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
@@ -1936,7 +1946,146 @@ void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *VD, llvm::Value *AI,
EmitDeclare(VD, llvm::dwarf::DW_TAG_arg_variable, AI, Builder);
}
+namespace {
+ struct BlockLayoutChunk {
+ uint64_t OffsetInBits;
+ const BlockDecl::Capture *Capture;
+ };
+ bool operator<(const BlockLayoutChunk &l, const BlockLayoutChunk &r) {
+ return l.OffsetInBits < r.OffsetInBits;
+ }
+}
+
+void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
+ llvm::Value *addr,
+ CGBuilderTy &Builder) {
+ ASTContext &C = CGM.getContext();
+ const BlockDecl *blockDecl = block.getBlockDecl();
+
+ // Collect some general information about the block's location.
+ SourceLocation loc = blockDecl->getCaretLocation();
+ llvm::DIFile tunit = getOrCreateFile(loc);
+ unsigned line = getLineNumber(loc);
+ unsigned column = getColumnNumber(loc);
+
+ // Build the debug-info type for the block literal.
+ llvm::DIDescriptor enclosingContext =
+ getContextDescriptor(cast<Decl>(blockDecl->getDeclContext()));
+
+ const llvm::StructLayout *blockLayout =
+ CGM.getTargetData().getStructLayout(block.StructureType);
+
+ llvm::SmallVector<llvm::Value*, 16> fields;
+ fields.push_back(createFieldType("__isa", C.VoidPtrTy, 0, loc, AS_public,
+ blockLayout->getElementOffsetInBits(0),
+ tunit));
+ fields.push_back(createFieldType("__flags", C.IntTy, 0, loc, AS_public,
+ blockLayout->getElementOffsetInBits(1),
+ tunit));
+ fields.push_back(createFieldType("__reserved", C.IntTy, 0, loc, AS_public,
+ blockLayout->getElementOffsetInBits(2),
+ tunit));
+ fields.push_back(createFieldType("__FuncPtr", C.VoidPtrTy, 0, loc, AS_public,
+ blockLayout->getElementOffsetInBits(3),
+ tunit));
+ fields.push_back(createFieldType("__descriptor",
+ C.getPointerType(block.NeedsCopyDispose ?
+ C.getBlockDescriptorExtendedType() :
+ C.getBlockDescriptorType()),
+ 0, loc, AS_public,
+ blockLayout->getElementOffsetInBits(4),
+ tunit));
+
+ // We want to sort the captures by offset, not because DWARF
+ // requires this, but because we're paranoid about debuggers.
+ llvm::SmallVector<BlockLayoutChunk, 8> chunks;
+
+ // 'this' capture.
+ if (blockDecl->capturesCXXThis()) {
+ BlockLayoutChunk chunk;
+ chunk.OffsetInBits =
+ blockLayout->getElementOffsetInBits(block.CXXThisIndex);
+ chunk.Capture = 0;
+ chunks.push_back(chunk);
+ }
+
+ // Variable captures.
+ for (BlockDecl::capture_const_iterator
+ i = blockDecl->capture_begin(), e = blockDecl->capture_end();
+ i != e; ++i) {
+ const BlockDecl::Capture &capture = *i;
+ const VarDecl *variable = capture.getVariable();
+ const CGBlockInfo::Capture &captureInfo = block.getCapture(variable);
+ // Ignore constant captures.
+ if (captureInfo.isConstant())
+ continue;
+
+ BlockLayoutChunk chunk;
+ chunk.OffsetInBits =
+ blockLayout->getElementOffsetInBits(captureInfo.getIndex());
+ chunk.Capture = &capture;
+ chunks.push_back(chunk);
+ }
+
+ // Sort by offset.
+ llvm::array_pod_sort(chunks.begin(), chunks.end());
+
+ for (llvm::SmallVectorImpl<BlockLayoutChunk>::iterator
+ i = chunks.begin(), e = chunks.end(); i != e; ++i) {
+ uint64_t offsetInBits = i->OffsetInBits;
+ const BlockDecl::Capture *capture = i->Capture;
+
+ // If we have a null capture, this must be the C++ 'this' capture.
+ if (!capture) {
+ const CXXMethodDecl *method =
+ cast<CXXMethodDecl>(blockDecl->getNonClosureContext());
+ QualType type = method->getThisType(C);
+
+ fields.push_back(createFieldType("this", type, 0, loc, AS_public,
+ offsetInBits, tunit));
+ continue;
+ }
+
+ const VarDecl *variable = capture->getVariable();
+ QualType type = (capture->isByRef() ? C.VoidPtrTy : variable->getType());
+ llvm::StringRef name = variable->getName();
+ fields.push_back(createFieldType(name, type, 0, loc, AS_public,
+ offsetInBits, tunit));
+ }
+
+ llvm::SmallString<36> typeName;
+ llvm::raw_svector_ostream(typeName)
+ << "__block_literal_" << CGM.getUniqueBlockCount();
+
+ llvm::DIArray fieldsArray =
+ DBuilder.getOrCreateArray(fields.data(), fields.size());
+
+ llvm::DIType type =
+ DBuilder.createStructType(tunit, typeName.str(), tunit, line,
+ CGM.getContext().toBits(block.BlockSize),
+ CGM.getContext().toBits(block.BlockAlign),
+ 0, fieldsArray);
+ type = DBuilder.createPointerType(type, CGM.PointerWidthInBits);
+
+ // Get overall information about the block.
+ unsigned flags = llvm::DIDescriptor::FlagArtificial;
+ llvm::MDNode *scope = RegionStack.back();
+ llvm::StringRef name = ".block_descriptor";
+
+ // Create the descriptor for the parameter.
+ llvm::DIVariable debugVar =
+ DBuilder.createLocalVariable(llvm::dwarf::DW_TAG_arg_variable,
+ llvm::DIDescriptor(scope),
+ name, tunit, line, type,
+ CGM.getLangOptions().Optimize, flags);
+
+ // Insert an llvm.dbg.value into the current block.
+ llvm::Instruction *declare =
+ DBuilder.insertDbgValueIntrinsic(addr, 0, debugVar,
+ Builder.GetInsertBlock());
+ declare->setDebugLoc(llvm::DebugLoc::get(line, column, scope));
+}
/// EmitGlobalVariable - Emit information about a global variable.
void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
@@ -1967,7 +2116,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
LinkageName = llvm::StringRef();
llvm::DIDescriptor DContext =
getContextDescriptor(dyn_cast<Decl>(D->getDeclContext()));
- DBuilder.CreateStaticVariable(DContext, DeclName, LinkageName,
+ DBuilder.createStaticVariable(DContext, DeclName, LinkageName,
Unit, LineNo, getOrCreateType(T, Unit),
Var->hasInternalLinkage(), Var);
}
@@ -1994,7 +2143,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
ArrayType::Normal, 0);
}
- DBuilder.CreateGlobalVariable(Name, Unit, LineNo,
+ DBuilder.createGlobalVariable(Name, Unit, LineNo,
getOrCreateType(T, Unit),
Var->hasInternalLinkage(), Var);
}
@@ -2013,7 +2162,7 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD,
// Do not use DIGlobalVariable for enums.
if (Ty.getTag() == llvm::dwarf::DW_TAG_enumeration_type)
return;
- DBuilder.CreateStaticVariable(Unit, Name, Name, Unit,
+ DBuilder.createStaticVariable(Unit, Name, Name, Unit,
getLineNumber(VD->getLocation()),
Ty, true, Init);
}
@@ -2032,7 +2181,7 @@ CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl) {
llvm::DIDescriptor Context =
getContextDescriptor(dyn_cast<Decl>(NSDecl->getDeclContext()));
llvm::DINameSpace NS =
- DBuilder.CreateNameSpace(Context, NSDecl->getName(), FileD, LineNo);
+ DBuilder.createNameSpace(Context, NSDecl->getName(), FileD, LineNo);
NameSpaceCache[NSDecl] = llvm::WeakVH(NS);
return NS;
}
diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h
index 6a9ab9c..a390788 100644
--- a/lib/CodeGen/CGDebugInfo.h
+++ b/lib/CodeGen/CGDebugInfo.h
@@ -123,7 +123,10 @@ class CGDebugInfo {
llvm::SmallVectorImpl<llvm::Value *> &EltTys,
llvm::DIType RecordTy);
-
+ llvm::DIType createFieldType(llvm::StringRef name, QualType type,
+ Expr *bitWidth, SourceLocation loc,
+ AccessSpecifier AS, uint64_t offsetInBits,
+ llvm::DIFile tunit);
void CollectRecordFields(const RecordDecl *Decl, llvm::DIFile F,
llvm::SmallVectorImpl<llvm::Value *> &E);
@@ -180,6 +183,13 @@ public:
void EmitDeclareOfArgVariable(const VarDecl *Decl, llvm::Value *AI,
CGBuilderTy &Builder);
+ /// EmitDeclareOfBlockLiteralArgVariable - Emit call to
+ /// llvm.dbg.declare for the block-literal argument to a block
+ /// invocation function.
+ void EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
+ llvm::Value *addr,
+ CGBuilderTy &Builder);
+
/// EmitGlobalVariable - Emit information about a global variable.
void EmitGlobalVariable(llvm::GlobalVariable *GV, const VarDecl *Decl);
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index a87dfae..f4db01d 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -474,14 +474,19 @@ namespace {
struct CallCleanupFunction : EHScopeStack::Cleanup {
llvm::Constant *CleanupFn;
const CGFunctionInfo &FnInfo;
- llvm::Value *Addr;
const VarDecl &Var;
CallCleanupFunction(llvm::Constant *CleanupFn, const CGFunctionInfo *Info,
- llvm::Value *Addr, const VarDecl *Var)
- : CleanupFn(CleanupFn), FnInfo(*Info), Addr(Addr), Var(*Var) {}
+ const VarDecl *Var)
+ : CleanupFn(CleanupFn), FnInfo(*Info), Var(*Var) {}
void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ DeclRefExpr DRE(const_cast<VarDecl*>(&Var), Var.getType(), VK_LValue,
+ SourceLocation());
+ // Compute the address of the local variable, in case it's a byref
+ // or something.
+ llvm::Value *Addr = CGF.EmitDeclRefLValue(&DRE).getAddress();
+
// In some cases, the type of the function argument will be different from
// the type of the pointer. An example of this is
// void f(void* arg);
@@ -543,7 +548,7 @@ static bool canEmitInitWithFewStoresAfterMemset(llvm::Constant *Init,
/// canEmitInitWithFewStoresAfterMemset returned true for, emit the scalar
/// stores that would be required.
static void emitStoresForInitAfterMemset(llvm::Constant *Init, llvm::Value *Loc,
- CGBuilderTy &Builder) {
+ bool isVolatile, CGBuilderTy &Builder) {
// Zero doesn't require any stores.
if (isa<llvm::ConstantAggregateZero>(Init) ||
isa<llvm::ConstantPointerNull>(Init) ||
@@ -554,7 +559,7 @@ static void emitStoresForInitAfterMemset(llvm::Constant *Init, llvm::Value *Loc,
isa<llvm::ConstantVector>(Init) || isa<llvm::BlockAddress>(Init) ||
isa<llvm::ConstantExpr>(Init)) {
if (!Init->isNullValue())
- Builder.CreateStore(Init, Loc);
+ Builder.CreateStore(Init, Loc, isVolatile);
return;
}
@@ -567,7 +572,7 @@ static void emitStoresForInitAfterMemset(llvm::Constant *Init, llvm::Value *Loc,
// Otherwise, get a pointer to the element and emit it.
emitStoresForInitAfterMemset(Elt, Builder.CreateConstGEP2_32(Loc, 0, i),
- Builder);
+ isVolatile, Builder);
}
}
@@ -597,37 +602,55 @@ static bool shouldUseMemSetPlusStoresToInitialize(llvm::Constant *Init,
/// EmitAutoVarDecl - Emit code and set up an entry in LocalDeclMap for a
/// variable declaration with auto, register, or no storage class specifier.
/// These turn into simple stack objects, or GlobalValues depending on target.
-void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D,
- SpecialInitFn *SpecialInit) {
+void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D) {
+ AutoVarEmission emission = EmitAutoVarAlloca(D);
+ EmitAutoVarInit(emission);
+ EmitAutoVarCleanups(emission);
+}
+
+/// EmitAutoVarAlloca - Emit the alloca and debug information for a
+/// local variable. Does not emit initalization or destruction.
+CodeGenFunction::AutoVarEmission
+CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
QualType Ty = D.getType();
- unsigned Alignment = getContext().getDeclAlign(&D).getQuantity();
+
+ AutoVarEmission emission(D);
+
bool isByRef = D.hasAttr<BlocksAttr>();
- bool needsDispose = false;
- CharUnits Align = CharUnits::Zero();
- bool IsSimpleConstantInitializer = false;
+ emission.IsByRef = isByRef;
+
+ CharUnits alignment = getContext().getDeclAlign(&D);
+ emission.Alignment = alignment;
- bool NRVO = false;
- llvm::Value *NRVOFlag = 0;
llvm::Value *DeclPtr;
if (Ty->isConstantSizeType()) {
if (!Target.useGlobalsForAutomaticVariables()) {
- NRVO = getContext().getLangOptions().ElideConstructors &&
- D.isNRVOVariable();
- // If this value is an array or struct, is POD, and if the initializer is
- // a staticly determinable constant, try to optimize it (unless the NRVO
- // is already optimizing this).
- if (!NRVO && D.getInit() && !isByRef &&
- (Ty->isArrayType() || Ty->isRecordType()) &&
- Ty->isPODType() &&
+ bool NRVO = getContext().getLangOptions().ElideConstructors &&
+ D.isNRVOVariable();
+
+ // If this value is a POD array or struct with a statically
+ // determinable constant initializer, there are optimizations we
+ // can do.
+ // TODO: we can potentially constant-evaluate non-POD structs and
+ // arrays as long as the initialization is trivial (e.g. if they
+ // have a non-trivial destructor, but not a non-trivial constructor).
+ if (D.getInit() &&
+ (Ty->isArrayType() || Ty->isRecordType()) && Ty->isPODType() &&
D.getInit()->isConstantInitializer(getContext(), false)) {
- // If this variable is marked 'const', emit the value as a global.
- if (CGM.getCodeGenOpts().MergeAllConstants &&
- Ty.isConstant(getContext())) {
- EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage);
- return;
+
+ // If the variable's a const type, and it's neither an NRVO
+ // candidate nor a __block variable, emit it as a global instead.
+ if (CGM.getCodeGenOpts().MergeAllConstants && Ty.isConstQualified() &&
+ !NRVO && !isByRef) {
+ EmitStaticVarDecl(D, llvm::GlobalValue::PrivateLinkage);
+
+ emission.Address = 0; // signal this condition to later callbacks
+ assert(emission.wasEmittedAsGlobal());
+ return emission;
}
-
- IsSimpleConstantInitializer = true;
+
+ // Otherwise, tell the initialization code that we're in this case.
+ emission.IsConstantAggregate = true;
}
// A normal fixed sized variable becomes an alloca in the entry block,
@@ -646,12 +669,13 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D,
// to this variable. Set it to zero to indicate that NRVO was not
// applied.
llvm::Value *Zero = Builder.getFalse();
- NRVOFlag = CreateTempAlloca(Zero->getType(), "nrvo");
+ llvm::Value *NRVOFlag = CreateTempAlloca(Zero->getType(), "nrvo");
EnsureInsertPoint();
Builder.CreateStore(Zero, NRVOFlag);
// Record the NRVO flag for this variable.
NRVOFlags[&D] = NRVOFlag;
+ emission.NRVOFlag = NRVOFlag;
}
}
} else {
@@ -661,11 +685,11 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D,
llvm::AllocaInst *Alloc = CreateTempAlloca(LTy);
Alloc->setName(D.getNameAsString());
- Align = getContext().getDeclAlign(&D);
+ CharUnits allocaAlignment = alignment;
if (isByRef)
- Align = std::max(Align,
+ allocaAlignment = std::max(allocaAlignment,
getContext().toCharUnitsFromBits(Target.getPointerAlign(0)));
- Alloc->setAlignment(Align.getQuantity());
+ Alloc->setAlignment(allocaAlignment.getQuantity());
DeclPtr = Alloc;
}
} else {
@@ -707,7 +731,7 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D,
// Allocate memory for the array.
llvm::AllocaInst *VLA =
Builder.CreateAlloca(llvm::Type::getInt8Ty(getLLVMContext()), VLASize, "vla");
- VLA->setAlignment(getContext().getDeclAlign(&D).getQuantity());
+ VLA->setAlignment(alignment.getQuantity());
DeclPtr = Builder.CreateBitCast(VLA, LElemPtrTy, "tmp");
}
@@ -715,6 +739,7 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D,
llvm::Value *&DMEntry = LocalDeclMap[&D];
assert(DMEntry == 0 && "Decl already exists in localdeclmap!");
DMEntry = DeclPtr;
+ emission.Address = DeclPtr;
// Emit debug info for local var declaration.
if (CGDebugInfo *DI = getDebugInfo()) {
@@ -727,53 +752,92 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D,
DI->EmitDeclareOfAutoVariable(&D, DeclPtr, Builder);
}
+ return emission;
+}
+
+/// Determines whether the given __block variable is potentially
+/// captured by the given expression.
+static bool isCapturedBy(const VarDecl &var, const Expr *e) {
+ // Skip the most common kinds of expressions that make
+ // hierarchy-walking expensive.
+ e = e->IgnoreParenCasts();
+
+ if (const BlockExpr *be = dyn_cast<BlockExpr>(e)) {
+ const BlockDecl *block = be->getBlockDecl();
+ for (BlockDecl::capture_const_iterator i = block->capture_begin(),
+ e = block->capture_end(); i != e; ++i) {
+ if (i->getVariable() == &var)
+ return true;
+ }
+
+ // No need to walk into the subexpressions.
+ return false;
+ }
+
+ for (Stmt::const_child_range children = e->children(); children; ++children)
+ if (isCapturedBy(var, cast<Expr>(*children)))
+ return true;
+
+ return false;
+}
+
+void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
+ assert(emission.Variable && "emission was not valid!");
+
+ // If this was emitted as a global constant, we're done.
+ if (emission.wasEmittedAsGlobal()) return;
+
+ const VarDecl &D = *emission.Variable;
+ QualType type = D.getType();
+
// If this local has an initializer, emit it now.
const Expr *Init = D.getInit();
// If we are at an unreachable point, we don't need to emit the initializer
// unless it contains a label.
if (!HaveInsertPoint()) {
- if (!ContainsLabel(Init))
- Init = 0;
- else
- EnsureInsertPoint();
+ if (!Init || !ContainsLabel(Init)) return;
+ EnsureInsertPoint();
}
- if (isByRef) {
- EnsureInsertPoint();
+ CharUnits alignment = emission.Alignment;
+
+ if (emission.IsByRef) {
llvm::Value *V;
BlockFieldFlags fieldFlags;
bool fieldNeedsCopyDispose = false;
- needsDispose = true;
-
- if (Ty->isBlockPointerType()) {
+ if (type->isBlockPointerType()) {
fieldFlags |= BLOCK_FIELD_IS_BLOCK;
fieldNeedsCopyDispose = true;
- } else if (getContext().isObjCNSObjectType(Ty) ||
- Ty->isObjCObjectPointerType()) {
+ } else if (getContext().isObjCNSObjectType(type) ||
+ type->isObjCObjectPointerType()) {
fieldFlags |= BLOCK_FIELD_IS_OBJECT;
fieldNeedsCopyDispose = true;
} else if (getLangOptions().CPlusPlus) {
if (getContext().getBlockVarCopyInits(&D))
fieldNeedsCopyDispose = true;
- else if (const CXXRecordDecl *record = D.getType()->getAsCXXRecordDecl())
+ else if (const CXXRecordDecl *record = type->getAsCXXRecordDecl())
fieldNeedsCopyDispose = !record->hasTrivialDestructor();
}
+ llvm::Value *addr = emission.Address;
+
// FIXME: Someone double check this.
- if (Ty.isObjCGCWeak())
+ if (type.isObjCGCWeak())
fieldFlags |= BLOCK_FIELD_IS_WEAK;
+ // Initialize the 'isa', which is just 0 or 1.
int isa = 0;
if (fieldFlags & BLOCK_FIELD_IS_WEAK)
isa = 1;
V = Builder.CreateIntToPtr(Builder.getInt32(isa), Int8PtrTy, "isa");
- Builder.CreateStore(V, Builder.CreateStructGEP(DeclPtr, 0, "byref.isa"));
+ Builder.CreateStore(V, Builder.CreateStructGEP(addr, 0, "byref.isa"));
- Builder.CreateStore(DeclPtr, Builder.CreateStructGEP(DeclPtr, 1,
- "byref.forwarding"));
+ // Store the address of the variable into its own forwarding pointer.
+ Builder.CreateStore(addr,
+ Builder.CreateStructGEP(addr, 1, "byref.forwarding"));
// Blocks ABI:
// c) the flags field is set to either 0 if no helper functions are
@@ -781,150 +845,157 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D,
BlockFlags flags;
if (fieldNeedsCopyDispose) flags |= BLOCK_HAS_COPY_DISPOSE;
Builder.CreateStore(llvm::ConstantInt::get(IntTy, flags.getBitMask()),
- Builder.CreateStructGEP(DeclPtr, 2, "byref.flags"));
+ Builder.CreateStructGEP(addr, 2, "byref.flags"));
const llvm::Type *V1;
- V1 = cast<llvm::PointerType>(DeclPtr->getType())->getElementType();
+ V1 = cast<llvm::PointerType>(addr->getType())->getElementType();
V = llvm::ConstantInt::get(IntTy, CGM.GetTargetTypeStoreSize(V1).getQuantity());
- Builder.CreateStore(V, Builder.CreateStructGEP(DeclPtr, 3, "byref.size"));
+ Builder.CreateStore(V, Builder.CreateStructGEP(addr, 3, "byref.size"));
if (fieldNeedsCopyDispose) {
- llvm::Value *copy_helper = Builder.CreateStructGEP(DeclPtr, 4);
- Builder.CreateStore(CGM.BuildbyrefCopyHelper(DeclPtr->getType(),
- fieldFlags,
- Align.getQuantity(), &D),
+ llvm::Value *copy_helper = Builder.CreateStructGEP(addr, 4);
+ Builder.CreateStore(CGM.BuildbyrefCopyHelper(addr->getType(), fieldFlags,
+ alignment.getQuantity(), &D),
copy_helper);
- llvm::Value *destroy_helper = Builder.CreateStructGEP(DeclPtr, 5);
- Builder.CreateStore(CGM.BuildbyrefDestroyHelper(DeclPtr->getType(),
+ llvm::Value *destroy_helper = Builder.CreateStructGEP(addr, 5);
+ Builder.CreateStore(CGM.BuildbyrefDestroyHelper(addr->getType(),
fieldFlags,
- Align.getQuantity(), &D),
+ alignment.getQuantity(),
+ &D),
destroy_helper);
}
}
- if (SpecialInit) {
- SpecialInit(*this, D, DeclPtr);
- } else if (Init) {
- llvm::Value *Loc = DeclPtr;
-
- bool isVolatile = getContext().getCanonicalType(Ty).isVolatileQualified();
+ if (!Init) return;
+
+ // Check whether this is a byref variable that's potentially
+ // captured and moved by its own initializer. If so, we'll need to
+ // emit the initializer first, then copy into the variable.
+ bool capturedByInit = emission.IsByRef && isCapturedBy(D, Init);
+
+ llvm::Value *Loc =
+ capturedByInit ? emission.Address : emission.getObjectAddress(*this);
+
+ bool isVolatile = type.isVolatileQualified();
- // If the initializer was a simple constant initializer, we can optimize it
- // in various ways.
- if (IsSimpleConstantInitializer) {
- llvm::Constant *Init = CGM.EmitConstantExpr(D.getInit(), Ty,this);
- assert(Init != 0 && "Wasn't a simple constant init?");
-
- llvm::Value *SizeVal =
- llvm::ConstantInt::get(IntPtrTy,
- getContext().getTypeSizeInChars(Ty).getQuantity());
-
- const llvm::Type *BP = Int8PtrTy;
- if (Loc->getType() != BP)
- Loc = Builder.CreateBitCast(Loc, BP, "tmp");
+ // If this is a simple aggregate initialization, we can optimize it
+ // in various ways.
+ if (emission.IsConstantAggregate) {
+ assert(!capturedByInit && "constant init contains a capturing block?");
+
+ llvm::Constant *Init = CGM.EmitConstantExpr(D.getInit(), type, this);
+ assert(Init != 0 && "Wasn't a simple constant init?");
- // If the initializer is all or mostly zeros, codegen with memset then do
- // a few stores afterward.
- if (shouldUseMemSetPlusStoresToInitialize(Init,
+ llvm::Value *SizeVal =
+ llvm::ConstantInt::get(IntPtrTy,
+ getContext().getTypeSizeInChars(type).getQuantity());
+
+ const llvm::Type *BP = Int8PtrTy;
+ if (Loc->getType() != BP)
+ Loc = Builder.CreateBitCast(Loc, BP, "tmp");
+
+ // If the initializer is all or mostly zeros, codegen with memset then do
+ // a few stores afterward.
+ if (shouldUseMemSetPlusStoresToInitialize(Init,
CGM.getTargetData().getTypeAllocSize(Init->getType()))) {
- Builder.CreateMemSet(Loc, Builder.getInt8(0), SizeVal,
- Align.getQuantity(), false);
- if (!Init->isNullValue()) {
- Loc = Builder.CreateBitCast(Loc, Init->getType()->getPointerTo());
- emitStoresForInitAfterMemset(Init, Loc, Builder);
- }
-
- } else {
- // Otherwise, create a temporary global with the initializer then
- // memcpy from the global to the alloca.
- std::string Name = GetStaticDeclName(*this, D, ".");
- llvm::GlobalVariable *GV =
+ Builder.CreateMemSet(Loc, llvm::ConstantInt::get(Int8Ty, 0), SizeVal,
+ alignment.getQuantity(), isVolatile);
+ if (!Init->isNullValue()) {
+ Loc = Builder.CreateBitCast(Loc, Init->getType()->getPointerTo());
+ emitStoresForInitAfterMemset(Init, Loc, isVolatile, Builder);
+ }
+ } else {
+ // Otherwise, create a temporary global with the initializer then
+ // memcpy from the global to the alloca.
+ std::string Name = GetStaticDeclName(*this, D, ".");
+ llvm::GlobalVariable *GV =
new llvm::GlobalVariable(CGM.getModule(), Init->getType(), true,
llvm::GlobalValue::InternalLinkage,
Init, Name, 0, false, 0);
- GV->setAlignment(Align.getQuantity());
+ GV->setAlignment(alignment.getQuantity());
- llvm::Value *SrcPtr = GV;
- if (SrcPtr->getType() != BP)
- SrcPtr = Builder.CreateBitCast(SrcPtr, BP, "tmp");
+ llvm::Value *SrcPtr = GV;
+ if (SrcPtr->getType() != BP)
+ SrcPtr = Builder.CreateBitCast(SrcPtr, BP, "tmp");
- Builder.CreateMemCpy(Loc, SrcPtr, SizeVal, Align.getQuantity(), false);
- }
- } else if (Ty->isReferenceType()) {
- RValue RV = EmitReferenceBindingToExpr(Init, &D);
- if (isByRef)
- Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
- D.getNameAsString());
- EmitStoreOfScalar(RV.getScalarVal(), Loc, false, Alignment, Ty);
- } else if (!hasAggregateLLVMType(Init->getType())) {
- llvm::Value *V = EmitScalarExpr(Init);
- if (isByRef) {
- // When RHS has side-effect, must go through "forwarding' field
- // to get to the address of the __block variable descriptor.
- if (Init->HasSideEffects(getContext()))
- Loc = BuildBlockByrefAddress(DeclPtr, &D);
- else
- Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
- D.getNameAsString());
- }
- EmitStoreOfScalar(V, Loc, isVolatile, Alignment, Ty);
- } else if (Init->getType()->isAnyComplexType()) {
- if (isByRef)
- Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
- D.getNameAsString());
- EmitComplexExprIntoAddr(Init, Loc, isVolatile);
- } else {
- if (isByRef)
- Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
- D.getNameAsString());
- EmitAggExpr(Init, AggValueSlot::forAddr(Loc, isVolatile, true, false));
+ Builder.CreateMemCpy(Loc, SrcPtr, SizeVal, alignment.getQuantity(),
+ isVolatile);
}
+ } else if (type->isReferenceType()) {
+ RValue RV = EmitReferenceBindingToExpr(Init, &D);
+ if (capturedByInit) Loc = BuildBlockByrefAddress(Loc, &D);
+ EmitStoreOfScalar(RV.getScalarVal(), Loc, false, alignment.getQuantity(),
+ type);
+ } else if (!hasAggregateLLVMType(type)) {
+ llvm::Value *V = EmitScalarExpr(Init);
+ if (capturedByInit) Loc = BuildBlockByrefAddress(Loc, &D);
+ EmitStoreOfScalar(V, Loc, isVolatile, alignment.getQuantity(), type);
+ } else if (type->isAnyComplexType()) {
+ ComplexPairTy complex = EmitComplexExpr(Init);
+ if (capturedByInit) Loc = BuildBlockByrefAddress(Loc, &D);
+ StoreComplexToAddr(complex, Loc, isVolatile);
+ } else {
+ // TODO: how can we delay here if D is captured by its initializer?
+ EmitAggExpr(Init, AggValueSlot::forAddr(Loc, isVolatile, true, false));
}
+}
- // Handle CXX destruction of variables.
- QualType DtorTy(Ty);
- while (const ArrayType *Array = getContext().getAsArrayType(DtorTy))
- DtorTy = getContext().getBaseElementType(Array);
- if (const RecordType *RT = DtorTy->getAs<RecordType>())
- if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) {
+ assert(emission.Variable && "emission was not valid!");
+
+ // If this was emitted as a global constant, we're done.
+ if (emission.wasEmittedAsGlobal()) return;
+
+ const VarDecl &D = *emission.Variable;
+
+ // Handle C++ destruction of variables.
+ if (getLangOptions().CPlusPlus) {
+ QualType type = D.getType();
+ QualType baseType = getContext().getBaseElementType(type);
+ if (const RecordType *RT = baseType->getAs<RecordType>()) {
+ CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RT->getDecl());
if (!ClassDecl->hasTrivialDestructor()) {
// Note: We suppress the destructor call when the corresponding NRVO
// flag has been set.
- llvm::Value *Loc = DeclPtr;
- if (isByRef)
- Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
- D.getNameAsString());
+
+ // Note that for __block variables, we want to destroy the
+ // original stack object, not the possible forwarded object.
+ llvm::Value *Loc = emission.getObjectAddress(*this);
const CXXDestructorDecl *D = ClassDecl->getDestructor();
assert(D && "EmitLocalBlockVarDecl - destructor is nul");
- if (const ConstantArrayType *Array =
- getContext().getAsConstantArrayType(Ty)) {
+ if (type != baseType) {
+ const ConstantArrayType *Array =
+ getContext().getAsConstantArrayType(type);
+ assert(Array && "types changed without array?");
EHStack.pushCleanup<CallArrayDtor>(NormalAndEHCleanup,
D, Array, Loc);
} else {
EHStack.pushCleanup<CallVarDtor>(NormalAndEHCleanup,
- D, NRVOFlag, Loc);
+ D, emission.NRVOFlag, Loc);
}
}
+ }
}
- // Handle the cleanup attribute
+ // Handle the cleanup attribute.
if (const CleanupAttr *CA = D.getAttr<CleanupAttr>()) {
const FunctionDecl *FD = CA->getFunctionDecl();
- llvm::Constant* F = CGM.GetAddrOfFunction(FD);
+ llvm::Constant *F = CGM.GetAddrOfFunction(FD);
assert(F && "Could not find function!");
const CGFunctionInfo &Info = CGM.getTypes().getFunctionInfo(FD);
- EHStack.pushCleanup<CallCleanupFunction>(NormalAndEHCleanup,
- F, &Info, DeclPtr, &D);
+ EHStack.pushCleanup<CallCleanupFunction>(NormalAndEHCleanup, F, &Info, &D);
}
- // If this is a block variable, clean it up.
- if (needsDispose && CGM.getLangOptions().getGCMode() != LangOptions::GCOnly)
- EHStack.pushCleanup<CallBlockRelease>(NormalAndEHCleanup, DeclPtr);
+ // If this is a block variable, call _Block_object_destroy
+ // (on the unforwarded address).
+ if (emission.IsByRef &&
+ CGM.getLangOptions().getGCMode() != LangOptions::GCOnly)
+ EHStack.pushCleanup<CallBlockRelease>(NormalAndEHCleanup, emission.Address);
}
/// Emit an alloca (or GlobalValue depending on target)
@@ -933,6 +1004,24 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) {
// FIXME: Why isn't ImplicitParamDecl a ParmVarDecl?
assert((isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)) &&
"Invalid argument to EmitParmDecl");
+
+ Arg->setName(D.getName());
+
+ // Use better IR generation for certain implicit parameters.
+ if (isa<ImplicitParamDecl>(D)) {
+ // The only implicit argument a block has is its literal.
+ if (BlockInfo) {
+ LocalDeclMap[&D] = Arg;
+
+ if (CGDebugInfo *DI = getDebugInfo()) {
+ DI->setLocation(D.getLocation());
+ DI->EmitDeclareOfBlockLiteralArgVariable(*BlockInfo, Arg, Builder);
+ }
+
+ return;
+ }
+ }
+
QualType Ty = D.getType();
llvm::Value *DeclPtr;
@@ -949,7 +1038,6 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) {
getContext().getDeclAlign(&D).getQuantity(), Ty,
CGM.getTBAAInfo(Ty));
}
- Arg->setName(D.getName());
llvm::Value *&DMEntry = LocalDeclMap[&D];
assert(DMEntry == 0 && "Decl already exists in localdeclmap!");
diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp
index 6181965..4bce081 100644
--- a/lib/CodeGen/CGException.cpp
+++ b/lib/CodeGen/CGException.cpp
@@ -1086,14 +1086,14 @@ static void BeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *S) {
// 3. Enter __cxa_end_catch cleanup
// 4. Enter dtor cleanup
//
- // We do this by initializing the exception variable with a
- // "special initializer", InitCatchParam. Delegation sequence:
+ // We do this by using a slightly abnormal initialization process.
+ // Delegation sequence:
// - ExitCXXTryStmt opens a RunCleanupsScope
- // - EmitLocalBlockVarDecl creates the variable and debug info
+ // - EmitAutoVarAlloca creates the variable and debug info
// - InitCatchParam initializes the variable from the exception
- // - CallBeginCatch calls __cxa_begin_catch
- // - CallBeginCatch enters the __cxa_end_catch cleanup
- // - EmitLocalBlockVarDecl enters the variable destructor cleanup
+ // - CallBeginCatch calls __cxa_begin_catch
+ // - CallBeginCatch enters the __cxa_end_catch cleanup
+ // - EmitAutoVarCleanups enters the variable destructor cleanup
// - EmitCXXTryStmt emits the code for the catch body
// - EmitCXXTryStmt close the RunCleanupsScope
@@ -1105,7 +1105,9 @@ static void BeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *S) {
}
// Emit the local.
- CGF.EmitAutoVarDecl(*CatchParam, &InitCatchParam);
+ CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam);
+ InitCatchParam(CGF, *CatchParam, var.getObjectAddress(CGF));
+ CGF.EmitAutoVarCleanups(var);
}
namespace {
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 1b7e7a0..2abaadf 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -260,6 +260,10 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E,
}
}
+ if (const OpaqueValueExpr *opaque = dyn_cast<OpaqueValueExpr>(E))
+ if (opaque->getType()->isRecordType())
+ return CGF.EmitOpaqueValueLValue(opaque).getAddress();
+
// Nothing changed.
break;
}
@@ -1606,39 +1610,67 @@ LValue CodeGenFunction::EmitLValueForAnonRecordField(llvm::Value *BaseValue,
}
}
-LValue CodeGenFunction::EmitLValueForField(llvm::Value *BaseValue,
- const FieldDecl *Field,
- unsigned CVRQualifiers) {
- if (Field->isBitField())
- return EmitLValueForBitfield(BaseValue, Field, CVRQualifiers);
+LValue CodeGenFunction::EmitLValueForField(llvm::Value *baseAddr,
+ const FieldDecl *field,
+ unsigned cvr) {
+ if (field->isBitField())
+ return EmitLValueForBitfield(baseAddr, field, cvr);
- const CGRecordLayout &RL =
- CGM.getTypes().getCGRecordLayout(Field->getParent());
- unsigned idx = RL.getLLVMFieldNo(Field);
- llvm::Value *V = Builder.CreateStructGEP(BaseValue, idx, "tmp");
+ const RecordDecl *rec = field->getParent();
+ QualType type = field->getType();
+
+ bool mayAlias = rec->hasAttr<MayAliasAttr>();
- // Match union field type.
- if (Field->getParent()->isUnion()) {
- const llvm::Type *FieldTy =
- CGM.getTypes().ConvertTypeForMem(Field->getType());
- const llvm::PointerType *BaseTy =
- cast<llvm::PointerType>(BaseValue->getType());
- unsigned AS = BaseTy->getAddressSpace();
- V = Builder.CreateBitCast(V,
- llvm::PointerType::get(FieldTy, AS),
- "tmp");
+ llvm::Value *addr;
+ if (rec->isUnion()) {
+ // For unions, we just cast to the appropriate type.
+ assert(!type->isReferenceType() && "union has reference member");
+
+ const llvm::Type *llvmType = CGM.getTypes().ConvertTypeForMem(type);
+ unsigned AS =
+ cast<llvm::PointerType>(baseAddr->getType())->getAddressSpace();
+ addr = Builder.CreateBitCast(baseAddr, llvmType->getPointerTo(AS),
+ field->getName());
+ } else {
+ // For structs, we GEP to the field that the record layout suggests.
+ unsigned idx = CGM.getTypes().getCGRecordLayout(rec).getLLVMFieldNo(field);
+ addr = Builder.CreateStructGEP(baseAddr, idx, field->getName());
+
+ // If this is a reference field, load the reference right now.
+ if (const ReferenceType *refType = type->getAs<ReferenceType>()) {
+ llvm::LoadInst *load = Builder.CreateLoad(addr, "ref");
+ if (cvr & Qualifiers::Volatile) load->setVolatile(true);
+
+ if (CGM.shouldUseTBAA()) {
+ llvm::MDNode *tbaa;
+ if (mayAlias)
+ tbaa = CGM.getTBAAInfo(getContext().CharTy);
+ else
+ tbaa = CGM.getTBAAInfo(type);
+ CGM.DecorateInstruction(load, tbaa);
+ }
+
+ addr = load;
+ mayAlias = false;
+ type = refType->getPointeeType();
+ cvr = 0; // qualifiers don't recursively apply to referencee
+ }
}
- if (Field->getType()->isReferenceType())
- V = Builder.CreateLoad(V, "tmp");
- unsigned Alignment = getContext().getDeclAlign(Field).getQuantity();
- LValue LV = MakeAddrLValue(V, Field->getType(), Alignment);
- LV.getQuals().addCVRQualifiers(CVRQualifiers);
+ unsigned alignment = getContext().getDeclAlign(field).getQuantity();
+ LValue LV = MakeAddrLValue(addr, type, alignment);
+ LV.getQuals().addCVRQualifiers(cvr);
// __weak attribute on a field is ignored.
if (LV.getQuals().getObjCGCAttr() == Qualifiers::Weak)
LV.getQuals().removeObjCGCAttr();
-
+
+ // Fields of may_alias structs act like 'char' for TBAA purposes.
+ // FIXME: this should get propagated down through anonymous structs
+ // and unions.
+ if (mayAlias && LV.getTBAAInfo())
+ LV.setTBAAInfo(CGM.getTBAAInfo(getContext().CharTy));
+
return LV;
}
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
index 08c458b..5d34907 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -663,6 +663,11 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
return;
}
+ // The local variable comes into scope immediately.
+ AutoVarEmission variable = AutoVarEmission::invalid();
+ if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement()))
+ variable = EmitAutoVarAlloca(*cast<VarDecl>(SD->getSingleDecl()));
+
CGDebugInfo *DI = getDebugInfo();
if (DI) {
DI->setLocation(S.getSourceRange().getBegin());
@@ -799,22 +804,23 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
// Initialize the element variable.
RunCleanupsScope elementVariableScope(*this);
- bool elementIsDecl;
+ bool elementIsVariable;
LValue elementLValue;
QualType elementType;
if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement())) {
- EmitStmt(SD);
- const VarDecl* D = cast<VarDecl>(SD->getSingleDecl());
+ // Initialize the variable, in case it's a __block variable or something.
+ EmitAutoVarInit(variable);
+ const VarDecl* D = cast<VarDecl>(SD->getSingleDecl());
DeclRefExpr tempDRE(const_cast<VarDecl*>(D), D->getType(),
VK_LValue, SourceLocation());
elementLValue = EmitLValue(&tempDRE);
elementType = D->getType();
- elementIsDecl = true;
+ elementIsVariable = true;
} else {
elementLValue = LValue(); // suppress warning
elementType = cast<Expr>(S.getElement())->getType();
- elementIsDecl = false;
+ elementIsVariable = false;
}
const llvm::Type *convertedElementType = ConvertType(elementType);
@@ -837,11 +843,16 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
// Make sure we have an l-value. Yes, this gets evaluated every
// time through the loop.
- if (!elementIsDecl)
+ if (!elementIsVariable)
elementLValue = EmitLValue(cast<Expr>(S.getElement()));
EmitStoreThroughLValue(RValue::get(CurrentItem), elementLValue, elementType);
+ // If we do have an element variable, this assignment is the end of
+ // its initialization.
+ if (elementIsVariable)
+ EmitAutoVarCleanups(variable);
+
// Perform the loop body, setting up break and continue labels.
BreakContinueStack.push_back(BreakContinue(LoopEnd, AfterBody));
{
@@ -891,7 +902,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
// No more elements.
EmitBlock(EmptyBB);
- if (!elementIsDecl) {
+ if (!elementIsVariable) {
// If the element was not a declaration, set it to be null.
llvm::Value *null = llvm::Constant::getNullValue(convertedElementType);
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp
index d481e77..5f19dc6 100644
--- a/lib/CodeGen/CGObjCGNU.cpp
+++ b/lib/CodeGen/CGObjCGNU.cpp
@@ -949,7 +949,12 @@ llvm::Constant *CGObjCGNU::GenerateClassStructure(
Elements.push_back(MakeConstantString(Name, ".class_name"));
Elements.push_back(Zero);
Elements.push_back(llvm::ConstantInt::get(LongTy, info));
- Elements.push_back(InstanceSize);
+ if (isMeta) {
+ llvm::TargetData td(&TheModule);
+ Elements.push_back(llvm::ConstantInt::get(LongTy,
+ td.getTypeSizeInBits(ClassTy)/8));
+ } else
+ Elements.push_back(InstanceSize);
Elements.push_back(IVars);
Elements.push_back(Methods);
Elements.push_back(NULLPtr);
@@ -1831,9 +1836,9 @@ llvm::Function *CGObjCGNU::GetPropertyGetFunction() {
std::vector<const llvm::Type*> Params;
Params.push_back(IdTy);
Params.push_back(SelectorTy);
- Params.push_back(IntTy);
+ Params.push_back(SizeTy);
Params.push_back(BoolTy);
- // void objc_getProperty (id, SEL, int, bool)
+ // void objc_getProperty (id, SEL, ptrdiff_t, bool)
const llvm::FunctionType *FTy =
llvm::FunctionType::get(IdTy, Params, false);
return cast<llvm::Function>(CGM.CreateRuntimeFunction(FTy,
@@ -1844,11 +1849,11 @@ llvm::Function *CGObjCGNU::GetPropertySetFunction() {
std::vector<const llvm::Type*> Params;
Params.push_back(IdTy);
Params.push_back(SelectorTy);
- Params.push_back(IntTy);
+ Params.push_back(SizeTy);
Params.push_back(IdTy);
Params.push_back(BoolTy);
Params.push_back(BoolTy);
- // void objc_setProperty (id, SEL, int, id, bool, bool)
+ // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
const llvm::FunctionType *FTy =
llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false);
return cast<llvm::Function>(CGM.CreateRuntimeFunction(FTy,
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index 7c679b9..8dbd85f 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -46,6 +46,15 @@ using namespace CodeGen;
// don't belong in CGObjCRuntime either so we will live with it for
// now.
+static void EmitNullReturnInitialization(CodeGenFunction &CGF,
+ ReturnValueSlot &returnSlot,
+ QualType resultType) {
+ // Force the return slot to exist.
+ if (!returnSlot.getValue())
+ returnSlot = ReturnValueSlot(CGF.CreateMemTemp(resultType), false);
+ CGF.EmitNullInitialization(returnSlot.getValue(), resultType);
+}
+
static uint64_t LookupFieldBitOffset(CodeGen::CodeGenModule &CGM,
const ObjCInterfaceDecl *OID,
const ObjCImplementationDecl *ID,
@@ -1639,6 +1648,7 @@ CGObjCCommonMac::EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF,
llvm::Constant *Fn = NULL;
if (CGM.ReturnTypeUsesSRet(FnInfo)) {
+ EmitNullReturnInitialization(CGF, Return, ResultType);
Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
: ObjCTypes.getSendStretFn(IsSuper);
} else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
@@ -5629,6 +5639,7 @@ CodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend(
llvm::Constant *Fn = 0;
std::string Name("\01l_");
if (CGM.ReturnTypeUsesSRet(FnInfo)) {
+ EmitNullReturnInitialization(CGF, Return, ResultType);
if (IsSuper) {
Fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
Name += "objc_msgSendSuper2_stret_fixup";
diff --git a/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp
index 4b19aef..ceae66f 100644
--- a/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -207,8 +207,9 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types,
uint64_t ContainingTypeSizeInBits,
unsigned ContainingTypeAlign) {
const llvm::Type *Ty = Types.ConvertTypeForMemRecursive(FD->getType());
- uint64_t TypeSizeInBytes = Types.getTargetData().getTypeAllocSize(Ty);
- uint64_t TypeSizeInBits = TypeSizeInBytes * 8;
+ CharUnits TypeSizeInBytes =
+ CharUnits::fromQuantity(Types.getTargetData().getTypeAllocSize(Ty));
+ uint64_t TypeSizeInBits = Types.getContext().toBits(TypeSizeInBytes);
bool IsSigned = FD->getType()->isSignedIntegerType();
@@ -249,7 +250,7 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types,
uint64_t AccessStart = FieldOffset - (FieldOffset % AccessWidth);
// Adjust initial access size to fit within record.
- while (AccessWidth > 8 &&
+ while (AccessWidth > Types.getTarget().getCharWidth() &&
AccessStart + AccessWidth > ContainingTypeSizeInBits) {
AccessWidth >>= 1;
AccessStart = FieldOffset - (FieldOffset % AccessWidth);
@@ -262,7 +263,8 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types,
if (AccessStart + AccessWidth > ContainingTypeSizeInBits) {
// If so, reduce access size to the next smaller power-of-two and retry.
AccessWidth >>= 1;
- assert(AccessWidth >= 8 && "Cannot access under byte size!");
+ assert(AccessWidth >= Types.getTarget().getCharWidth()
+ && "Cannot access under byte size!");
continue;
}
@@ -329,7 +331,7 @@ void CGRecordLayoutBuilder::LayoutBitField(const FieldDecl *D,
if (fieldSize == 0)
return;
- uint64_t nextFieldOffsetInBits = NextFieldOffset.getQuantity() * 8;
+ uint64_t nextFieldOffsetInBits = Types.getContext().toBits(NextFieldOffset);
unsigned numBytesToAppend;
if (fieldOffset < nextFieldOffsetInBits) {
@@ -378,8 +380,10 @@ bool CGRecordLayoutBuilder::LayoutField(const FieldDecl *D,
CheckZeroInitializable(D->getType());
- assert(fieldOffset % 8 == 0 && "FieldOffset is not on a byte boundary!");
- CharUnits fieldOffsetInBytes = CharUnits::fromQuantity(fieldOffset / 8);
+ assert(fieldOffset % Types.getTarget().getCharWidth() == 0
+ && "field offset is not on a byte boundary!");
+ CharUnits fieldOffsetInBytes
+ = Types.getContext().toCharUnitsFromBits(fieldOffset);
const llvm::Type *Ty = Types.ConvertTypeForMemRecursive(D->getType());
CharUnits typeAlignment = getTypeAlignment(Ty);
@@ -396,7 +400,7 @@ bool CGRecordLayoutBuilder::LayoutField(const FieldDecl *D,
const RecordDecl *RD = cast<RecordDecl>(RT->getDecl());
if (const MaxFieldAlignmentAttr *MFAA =
RD->getAttr<MaxFieldAlignmentAttr>()) {
- if (MFAA->getAlignment() != typeAlignment.getQuantity() * 8)
+ if (MFAA->getAlignment() != Types.getContext().toBits(typeAlignment))
return false;
}
}
@@ -728,7 +732,8 @@ bool CGRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
void CGRecordLayoutBuilder::AppendTailPadding(uint64_t RecordSize) {
assert(RecordSize % 8 == 0 && "Invalid record size!");
- CharUnits RecordSizeInBytes = CharUnits::fromQuantity(RecordSize / 8);
+ CharUnits RecordSizeInBytes =
+ Types.getContext().toCharUnitsFromBits(RecordSize);
assert(NextFieldOffset <= RecordSizeInBytes && "Size mismatch!");
CharUnits AlignedNextFieldOffset =
@@ -920,7 +925,8 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) {
// Verify that every component access is within the structure.
uint64_t FieldOffset = SL->getElementOffsetInBits(AI.FieldIndex);
- uint64_t AccessBitOffset = FieldOffset + AI.FieldByteOffset * 8;
+ uint64_t AccessBitOffset = FieldOffset +
+ getContext().toBits(CharUnits::fromQuantity(AI.FieldByteOffset));
assert(AccessBitOffset + AI.AccessWidth <= TypeSizeInBits &&
"Invalid bit-field access (out of range)!");
}
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 67ef414..be646fb 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -1555,7 +1555,55 @@ public:
/// EmitAutoVarDecl - Emit an auto variable declaration.
///
/// This function can be called with a null (unreachable) insert point.
- void EmitAutoVarDecl(const VarDecl &D, SpecialInitFn *SpecialInit = 0);
+ void EmitAutoVarDecl(const VarDecl &D);
+
+ class AutoVarEmission {
+ friend class CodeGenFunction;
+
+ const VarDecl *Variable;
+
+ /// The alignment of the variable.
+ CharUnits Alignment;
+
+ /// The address of the alloca. Null if the variable was emitted
+ /// as a global constant.
+ llvm::Value *Address;
+
+ llvm::Value *NRVOFlag;
+
+ /// True if the variable is a __block variable.
+ bool IsByRef;
+
+ /// True if the variable is of aggregate type and has a constant
+ /// initializer.
+ bool IsConstantAggregate;
+
+ struct Invalid {};
+ AutoVarEmission(Invalid) : Variable(0) {}
+
+ AutoVarEmission(const VarDecl &variable)
+ : Variable(&variable), Address(0), NRVOFlag(0),
+ IsByRef(false), IsConstantAggregate(false) {}
+
+ bool wasEmittedAsGlobal() const { return Address == 0; }
+
+ public:
+ static AutoVarEmission invalid() { return AutoVarEmission(Invalid()); }
+
+ /// Returns the address of the object within this declaration.
+ /// Note that this does not chase the forwarding pointer for
+ /// __block decls.
+ llvm::Value *getObjectAddress(CodeGenFunction &CGF) const {
+ if (!IsByRef) return Address;
+
+ return CGF.Builder.CreateStructGEP(Address,
+ CGF.getByRefValueLLVMField(Variable),
+ Variable->getNameAsString());
+ }
+ };
+ AutoVarEmission EmitAutoVarAlloca(const VarDecl &var);
+ void EmitAutoVarInit(const AutoVarEmission &emission);
+ void EmitAutoVarCleanups(const AutoVarEmission &emission);
void EmitStaticVarDecl(const VarDecl &D,
llvm::GlobalValue::LinkageTypes Linkage);
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 9e5d7cf..a8453c3 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -97,6 +97,8 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO,
Int32Ty = llvm::Type::getInt32Ty(LLVMContext);
Int64Ty = llvm::Type::getInt64Ty(LLVMContext);
PointerWidthInBits = C.Target.getPointerWidth(0);
+ PointerAlignInBytes =
+ C.toCharUnitsFromBits(C.Target.getPointerAlign(0)).getQuantity();
IntTy = llvm::IntegerType::get(LLVMContext, C.Target.getIntWidth());
IntPtrTy = llvm::IntegerType::get(LLVMContext, PointerWidthInBits);
Int8PtrTy = Int8Ty->getPointerTo(0);
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index b6bd37c..73e6ece 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -120,8 +120,11 @@ namespace CodeGen {
const llvm::PointerType *Int8PtrPtrTy;
};
- /// The width of an address-zero pointer.
+ /// The width of a pointer into the generic address space.
unsigned char PointerWidthInBits;
+
+ /// The alignment of a pointer into the generic address space.
+ unsigned char PointerAlignInBytes;
};
/// CodeGenModule - This class organizes the cross-function state that is used
@@ -292,6 +295,8 @@ public:
const TargetCodeGenInfo &getTargetCodeGenInfo();
bool isTargetDarwin() const;
+ bool shouldUseTBAA() const { return TBAA != 0; }
+
llvm::MDNode *getTBAAInfo(QualType QTy);
static void DecorateInstruction(llvm::Instruction *Inst,
@@ -386,8 +391,8 @@ public:
unsigned Align,
const VarDecl *variable);
- /// getGlobalUniqueCount - Fetches the global unique block count.
- int getGlobalUniqueCount() { return ++Block.GlobalUniqueCount; }
+ /// getUniqueBlockCount - Fetches the global unique block count.
+ int getUniqueBlockCount() { return ++Block.GlobalUniqueCount; }
/// getBlockDescriptorType - Fetches the type of a generic block
/// descriptor.
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index d74b3f3..2ffc840 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -2105,8 +2105,15 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty) const {
RT->getDecl()->hasFlexibleArrayMember())
return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
- // FIXME: mingw64-gcc emits 128-bit struct as i128
- if (Size <= 128 &&
+ // FIXME: mingw-w64-gcc emits 128-bit struct as i128
+ if (Size == 128 &&
+ getContext().Target.getTriple().getOS() == llvm::Triple::MinGW32)
+ return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),
+ Size));
+
+ // MS x64 ABI requirement: "Any argument that doesn't fit in 8 bytes, or is
+ // not 1, 2, 4, or 8 bytes, must be passed by reference."
+ if (Size <= 64 &&
(Size & (Size - 1)) == 0)
return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),
Size));
OpenPOWER on IntegriCloud