summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/ABIInfo.h147
-rw-r--r--lib/CodeGen/BackendUtil.cpp40
-rw-r--r--lib/CodeGen/CGAtomic.cpp231
-rw-r--r--lib/CodeGen/CGBlocks.cpp40
-rw-r--r--lib/CodeGen/CGBuiltin.cpp2556
-rw-r--r--lib/CodeGen/CGCUDARuntime.cpp4
-rw-r--r--lib/CodeGen/CGCXX.cpp249
-rw-r--r--lib/CodeGen/CGCXXABI.cpp42
-rw-r--r--lib/CodeGen/CGCXXABI.h157
-rw-r--r--lib/CodeGen/CGCall.cpp237
-rw-r--r--lib/CodeGen/CGCall.h200
-rw-r--r--lib/CodeGen/CGClass.cpp393
-rw-r--r--lib/CodeGen/CGCleanup.cpp39
-rw-r--r--lib/CodeGen/CGCleanup.h12
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp1355
-rw-r--r--lib/CodeGen/CGDebugInfo.h176
-rw-r--r--lib/CodeGen/CGDecl.cpp119
-rw-r--r--lib/CodeGen/CGDeclCXX.cpp80
-rw-r--r--lib/CodeGen/CGException.cpp33
-rw-r--r--lib/CodeGen/CGExpr.cpp939
-rw-r--r--lib/CodeGen/CGExprAgg.cpp285
-rw-r--r--lib/CodeGen/CGExprCXX.cpp235
-rw-r--r--lib/CodeGen/CGExprComplex.cpp167
-rw-r--r--lib/CodeGen/CGExprConstant.cpp95
-rw-r--r--lib/CodeGen/CGExprScalar.cpp402
-rw-r--r--lib/CodeGen/CGObjC.cpp30
-rw-r--r--lib/CodeGen/CGObjCGNU.cpp59
-rw-r--r--lib/CodeGen/CGObjCMac.cpp29
-rw-r--r--lib/CodeGen/CGObjCRuntime.cpp1
-rw-r--r--lib/CodeGen/CGRTTI.cpp62
-rw-r--r--lib/CodeGen/CGRecordLayoutBuilder.cpp54
-rw-r--r--lib/CodeGen/CGStmt.cpp184
-rw-r--r--lib/CodeGen/CGVTT.cpp34
-rw-r--r--lib/CodeGen/CGVTables.cpp363
-rw-r--r--lib/CodeGen/CGVTables.h40
-rw-r--r--lib/CodeGen/CGValue.h30
-rw-r--r--lib/CodeGen/CMakeLists.txt2
-rw-r--r--lib/CodeGen/CodeGenABITypes.cpp69
-rw-r--r--lib/CodeGen/CodeGenAction.cpp17
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp152
-rw-r--r--lib/CodeGen/CodeGenFunction.h714
-rw-r--r--lib/CodeGen/CodeGenModule.cpp723
-rw-r--r--lib/CodeGen/CodeGenModule.h120
-rw-r--r--lib/CodeGen/CodeGenTBAA.cpp73
-rw-r--r--lib/CodeGen/CodeGenTBAA.h2
-rw-r--r--lib/CodeGen/CodeGenTypes.cpp7
-rw-r--r--lib/CodeGen/CodeGenTypes.h7
-rw-r--r--lib/CodeGen/EHScopeStack.h489
-rw-r--r--lib/CodeGen/ItaniumCXXABI.cpp514
-rw-r--r--lib/CodeGen/MicrosoftCXXABI.cpp1289
-rw-r--r--lib/CodeGen/MicrosoftVBTables.cpp233
-rw-r--r--lib/CodeGen/MicrosoftVBTables.h129
-rw-r--r--lib/CodeGen/ModuleBuilder.cpp36
-rw-r--r--lib/CodeGen/TargetInfo.cpp842
-rw-r--r--lib/CodeGen/TargetInfo.h34
55 files changed, 9873 insertions, 4698 deletions
diff --git a/lib/CodeGen/ABIInfo.h b/lib/CodeGen/ABIInfo.h
index df6dc72..468fe04 100644
--- a/lib/CodeGen/ABIInfo.h
+++ b/lib/CodeGen/ABIInfo.h
@@ -25,6 +25,7 @@ namespace clang {
class TargetInfo;
namespace CodeGen {
+ class CGCXXABI;
class CGFunctionInfo;
class CodeGenFunction;
class CodeGenTypes;
@@ -35,151 +36,6 @@ namespace clang {
// the targets to support this, since the Targets currently live in a
// layer below types n'stuff.
- /// ABIArgInfo - Helper class to encapsulate information about how a
- /// specific C type should be passed to or returned from a function.
- class ABIArgInfo {
- public:
- enum Kind {
- /// Direct - Pass the argument directly using the normal converted LLVM
- /// type, or by coercing to another specified type stored in
- /// 'CoerceToType'). If an offset is specified (in UIntData), then the
- /// argument passed is offset by some number of bytes in the memory
- /// representation. A dummy argument is emitted before the real argument
- /// if the specified type stored in "PaddingType" is not zero.
- Direct,
-
- /// Extend - Valid only for integer argument types. Same as 'direct'
- /// but also emit a zero/sign extension attribute.
- Extend,
-
- /// Indirect - Pass the argument indirectly via a hidden pointer
- /// with the specified alignment (0 indicates default alignment).
- Indirect,
-
- /// Ignore - Ignore the argument (treat as void). Useful for void and
- /// empty structs.
- Ignore,
-
- /// Expand - Only valid for aggregate argument types. The structure should
- /// be expanded into consecutive arguments for its constituent fields.
- /// Currently expand is only allowed on structures whose fields
- /// are all scalar types or are themselves expandable types.
- Expand,
-
- KindFirst=Direct, KindLast=Expand
- };
-
- private:
- Kind TheKind;
- llvm::Type *TypeData;
- llvm::Type *PaddingType;
- unsigned UIntData;
- bool BoolData0;
- bool BoolData1;
- bool InReg;
- bool PaddingInReg;
-
- ABIArgInfo(Kind K, llvm::Type *TD, unsigned UI, bool B0, bool B1, bool IR,
- bool PIR, llvm::Type* P)
- : TheKind(K), TypeData(TD), PaddingType(P), UIntData(UI), BoolData0(B0),
- BoolData1(B1), InReg(IR), PaddingInReg(PIR) {}
-
- public:
- ABIArgInfo() : TheKind(Direct), TypeData(0), UIntData(0) {}
-
- static ABIArgInfo getDirect(llvm::Type *T = 0, unsigned Offset = 0,
- llvm::Type *Padding = 0) {
- return ABIArgInfo(Direct, T, Offset, false, false, false, false, Padding);
- }
- static ABIArgInfo getDirectInReg(llvm::Type *T = 0) {
- return ABIArgInfo(Direct, T, 0, false, false, true, false, 0);
- }
- static ABIArgInfo getExtend(llvm::Type *T = 0) {
- return ABIArgInfo(Extend, T, 0, false, false, false, false, 0);
- }
- static ABIArgInfo getExtendInReg(llvm::Type *T = 0) {
- return ABIArgInfo(Extend, T, 0, false, false, true, false, 0);
- }
- static ABIArgInfo getIgnore() {
- return ABIArgInfo(Ignore, 0, 0, false, false, false, false, 0);
- }
- static ABIArgInfo getIndirect(unsigned Alignment, bool ByVal = true
- , bool Realign = false
- , llvm::Type *Padding = 0) {
- return ABIArgInfo(Indirect, 0, Alignment, ByVal, Realign, false, false,
- Padding);
- }
- static ABIArgInfo getIndirectInReg(unsigned Alignment, bool ByVal = true
- , bool Realign = false) {
- return ABIArgInfo(Indirect, 0, Alignment, ByVal, Realign, true, false, 0);
- }
- static ABIArgInfo getExpand() {
- return ABIArgInfo(Expand, 0, 0, false, false, false, false, 0);
- }
- static ABIArgInfo getExpandWithPadding(bool PaddingInReg,
- llvm::Type *Padding) {
- return ABIArgInfo(Expand, 0, 0, false, false, false, PaddingInReg,
- Padding);
- }
-
- Kind getKind() const { return TheKind; }
- bool isDirect() const { return TheKind == Direct; }
- bool isExtend() const { return TheKind == Extend; }
- bool isIgnore() const { return TheKind == Ignore; }
- bool isIndirect() const { return TheKind == Indirect; }
- bool isExpand() const { return TheKind == Expand; }
-
- bool canHaveCoerceToType() const {
- return TheKind == Direct || TheKind == Extend;
- }
-
- // Direct/Extend accessors
- unsigned getDirectOffset() const {
- assert((isDirect() || isExtend()) && "Not a direct or extend kind");
- return UIntData;
- }
-
- llvm::Type *getPaddingType() const {
- return PaddingType;
- }
-
- bool getPaddingInReg() const {
- return PaddingInReg;
- }
-
- llvm::Type *getCoerceToType() const {
- assert(canHaveCoerceToType() && "Invalid kind!");
- return TypeData;
- }
-
- void setCoerceToType(llvm::Type *T) {
- assert(canHaveCoerceToType() && "Invalid kind!");
- TypeData = T;
- }
-
- bool getInReg() const {
- assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
- return InReg;
- }
-
- // Indirect accessors
- unsigned getIndirectAlign() const {
- assert(TheKind == Indirect && "Invalid kind!");
- return UIntData;
- }
-
- bool getIndirectByVal() const {
- assert(TheKind == Indirect && "Invalid kind!");
- return BoolData0;
- }
-
- bool getIndirectRealign() const {
- assert(TheKind == Indirect && "Invalid kind!");
- return BoolData1;
- }
-
- void dump() const;
- };
/// ABIInfo - Target specific hooks for defining how a type should be
/// passed or returned from functions.
@@ -194,6 +50,7 @@ namespace clang {
virtual ~ABIInfo();
+ CodeGen::CGCXXABI &getCXXABI() const;
ASTContext &getContext() const;
llvm::LLVMContext &getVMContext() const;
const llvm::DataLayout &getDataLayout() const;
diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp
index 45079c0..90b0f68 100644
--- a/lib/CodeGen/BackendUtil.cpp
+++ b/lib/CodeGen/BackendUtil.cpp
@@ -154,6 +154,14 @@ static void addObjCARCOptPass(const PassManagerBuilder &Builder, PassManagerBase
PM.add(createObjCARCOptPass());
}
+static void addSampleProfileLoaderPass(const PassManagerBuilder &Builder,
+ PassManagerBase &PM) {
+ const PassManagerBuilderWrapper &BuilderWrapper =
+ static_cast<const PassManagerBuilderWrapper &>(Builder);
+ const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
+ PM.add(createSampleProfileLoaderPass(CGOpts.SampleProfileFile));
+}
+
static void addBoundsCheckingPass(const PassManagerBuilder &Builder,
PassManagerBase &PM) {
PM.add(createBoundsCheckingPass());
@@ -206,6 +214,14 @@ static void addThreadSanitizerPass(const PassManagerBuilder &Builder,
PM.add(createThreadSanitizerPass(CGOpts.SanitizerBlacklistFile));
}
+static void addDataFlowSanitizerPass(const PassManagerBuilder &Builder,
+ PassManagerBase &PM) {
+ const PassManagerBuilderWrapper &BuilderWrapper =
+ static_cast<const PassManagerBuilderWrapper&>(Builder);
+ const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
+ PM.add(createDataFlowSanitizerPass(CGOpts.SanitizerBlacklistFile));
+}
+
void EmitAssemblyHelper::CreatePasses(TargetMachine *TM) {
unsigned OptLevel = CodeGenOpts.OptimizationLevel;
CodeGenOptions::InliningMethod Inlining = CodeGenOpts.getInlining();
@@ -220,10 +236,17 @@ void EmitAssemblyHelper::CreatePasses(TargetMachine *TM) {
PassManagerBuilderWrapper PMBuilder(CodeGenOpts, LangOpts);
PMBuilder.OptLevel = OptLevel;
PMBuilder.SizeLevel = CodeGenOpts.OptimizeSize;
+ PMBuilder.BBVectorize = CodeGenOpts.VectorizeBB;
+ PMBuilder.SLPVectorize = CodeGenOpts.VectorizeSLP;
+ PMBuilder.LoopVectorize = CodeGenOpts.VectorizeLoop;
- PMBuilder.DisableSimplifyLibCalls = !CodeGenOpts.SimplifyLibCalls;
PMBuilder.DisableUnitAtATime = !CodeGenOpts.UnitAtATime;
PMBuilder.DisableUnrollLoops = !CodeGenOpts.UnrollLoops;
+ PMBuilder.RerollLoops = CodeGenOpts.RerollLoops;
+
+ if (!CodeGenOpts.SampleProfileFile.empty())
+ PMBuilder.addExtension(PassManagerBuilder::EP_EarlyAsPossible,
+ addSampleProfileLoaderPass);
// In ObjC ARC mode, add the main ARC optimization passes.
if (LangOpts.ObjCAutoRefCount) {
@@ -235,7 +258,7 @@ void EmitAssemblyHelper::CreatePasses(TargetMachine *TM) {
addObjCARCOptPass);
}
- if (LangOpts.Sanitize.Bounds) {
+ if (LangOpts.Sanitize.LocalBounds) {
PMBuilder.addExtension(PassManagerBuilder::EP_ScalarOptimizerLate,
addBoundsCheckingPass);
PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
@@ -263,6 +286,13 @@ void EmitAssemblyHelper::CreatePasses(TargetMachine *TM) {
addThreadSanitizerPass);
}
+ if (LangOpts.Sanitize.DataFlow) {
+ PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
+ addDataFlowSanitizerPass);
+ PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
+ addDataFlowSanitizerPass);
+ }
+
// Figure out TargetLibraryInfo.
Triple TargetTriple(TheModule->getTargetTriple());
PMBuilder.LibraryInfo = new TargetLibraryInfo(TargetTriple);
@@ -410,13 +440,10 @@ TargetMachine *EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) {
// Set frame pointer elimination mode.
if (!CodeGenOpts.DisableFPElim) {
Options.NoFramePointerElim = false;
- Options.NoFramePointerElimNonLeaf = false;
} else if (CodeGenOpts.OmitLeafFramePointer) {
Options.NoFramePointerElim = false;
- Options.NoFramePointerElimNonLeaf = true;
} else {
Options.NoFramePointerElim = true;
- Options.NoFramePointerElimNonLeaf = true;
}
if (CodeGenOpts.UseInitArray)
@@ -452,11 +479,9 @@ TargetMachine *EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) {
Options.UnsafeFPMath = CodeGenOpts.UnsafeFPMath;
Options.UseSoftFloat = CodeGenOpts.SoftFloat;
Options.StackAlignmentOverride = CodeGenOpts.StackAlignment;
- Options.RealignStack = CodeGenOpts.StackRealignment;
Options.DisableTailCalls = CodeGenOpts.DisableTailCalls;
Options.TrapFuncName = CodeGenOpts.TrapFuncName;
Options.PositionIndependentExecutable = LangOpts.PIELevel != 0;
- Options.SSPBufferSize = CodeGenOpts.SSPBufferSize;
Options.EnableSegmentedStacks = CodeGenOpts.EnableSegmentedStacks;
TargetMachine *TM = TheTarget->createTargetMachine(Triple, TargetOpts.CPU,
@@ -529,6 +554,7 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action, raw_ostream *OS) {
Action != Backend_EmitLL);
TargetMachine *TM = CreateTargetMachine(UsesCodeGen);
if (UsesCodeGen && !TM) return;
+ llvm::OwningPtr<TargetMachine> TMOwner(CodeGenOpts.DisableFree ? 0 : TM);
CreatePasses(TM);
switch (Action) {
diff --git a/lib/CodeGen/CGAtomic.cpp b/lib/CodeGen/CGAtomic.cpp
index 0b48a5c..0df2a40 100644
--- a/lib/CodeGen/CGAtomic.cpp
+++ b/lib/CodeGen/CGAtomic.cpp
@@ -15,6 +15,8 @@
#include "CGCall.h"
#include "CodeGenModule.h"
#include "clang/AST/ASTContext.h"
+#include "clang/CodeGen/CGFunctionInfo.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Operator.h"
@@ -92,7 +94,7 @@ namespace {
return (ValueSizeInBits != AtomicSizeInBits);
}
- void emitMemSetZeroIfNecessary(LValue dest) const;
+ bool emitMemSetZeroIfNecessary(LValue dest) const;
llvm::Value *getAtomicSizeValue() const {
CharUnits size = CGF.getContext().toCharUnitsFromBits(AtomicSizeInBits);
@@ -105,7 +107,8 @@ namespace {
/// Turn an atomic-layout object into an r-value.
RValue convertTempToRValue(llvm::Value *addr,
- AggValueSlot resultSlot) const;
+ AggValueSlot resultSlot,
+ SourceLocation loc) const;
/// Copy an atomic r-value into atomic-layout memory.
void emitCopyIntoMemory(RValue rvalue, LValue lvalue) const;
@@ -163,21 +166,22 @@ bool AtomicInfo::requiresMemSetZero(llvm::Type *type) const {
return !isFullSizeType(CGF.CGM, type->getStructElementType(0),
AtomicSizeInBits / 2);
- // Just be pessimistic about aggregates.
+ // Padding in structs has an undefined bit pattern. User beware.
case TEK_Aggregate:
- return true;
+ return false;
}
llvm_unreachable("bad evaluation kind");
}
-void AtomicInfo::emitMemSetZeroIfNecessary(LValue dest) const {
+bool AtomicInfo::emitMemSetZeroIfNecessary(LValue dest) const {
llvm::Value *addr = dest.getAddress();
if (!requiresMemSetZero(addr->getType()->getPointerElementType()))
- return;
+ return false;
CGF.Builder.CreateMemSet(addr, llvm::ConstantInt::get(CGF.Int8Ty, 0),
AtomicSizeInBits / 8,
dest.getAlignment().getQuantity());
+ return true;
}
static void
@@ -317,6 +321,22 @@ EmitValToTemp(CodeGenFunction &CGF, Expr *E) {
return DeclPtr;
}
+static void
+AddDirectArgument(CodeGenFunction &CGF, CallArgList &Args,
+ bool UseOptimizedLibcall, llvm::Value *Val, QualType ValTy,
+ SourceLocation Loc) {
+ if (UseOptimizedLibcall) {
+ // Load value and pass it to the function directly.
+ unsigned Align = CGF.getContext().getTypeAlignInChars(ValTy).getQuantity();
+ Val = CGF.EmitLoadOfScalar(Val, false, Align, ValTy, Loc);
+ Args.add(RValue::get(Val), ValTy);
+ } else {
+ // Non-optimized functions always take a reference.
+ Args.add(RValue::get(CGF.EmitCastToVoidPtr(Val)),
+ CGF.getContext().VoidPtrTy);
+ }
+}
+
RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) {
QualType AtomicTy = E->getPtr()->getType()->getPointeeType();
QualType MemTy = AtomicTy;
@@ -424,67 +444,142 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) {
// Use a library call. See: http://gcc.gnu.org/wiki/Atomic/GCCMM/LIbrary .
if (UseLibcall) {
+ bool UseOptimizedLibcall = false;
+ switch (E->getOp()) {
+ case AtomicExpr::AO__c11_atomic_fetch_add:
+ case AtomicExpr::AO__atomic_fetch_add:
+ case AtomicExpr::AO__c11_atomic_fetch_and:
+ case AtomicExpr::AO__atomic_fetch_and:
+ case AtomicExpr::AO__c11_atomic_fetch_or:
+ case AtomicExpr::AO__atomic_fetch_or:
+ case AtomicExpr::AO__c11_atomic_fetch_sub:
+ case AtomicExpr::AO__atomic_fetch_sub:
+ case AtomicExpr::AO__c11_atomic_fetch_xor:
+ case AtomicExpr::AO__atomic_fetch_xor:
+ // For these, only library calls for certain sizes exist.
+ UseOptimizedLibcall = true;
+ break;
+ default:
+ // Only use optimized library calls for sizes for which they exist.
+ if (Size == 1 || Size == 2 || Size == 4 || Size == 8)
+ UseOptimizedLibcall = true;
+ break;
+ }
- SmallVector<QualType, 5> Params;
CallArgList Args;
- // Size is always the first parameter
- Args.add(RValue::get(llvm::ConstantInt::get(SizeTy, Size)),
- getContext().getSizeType());
- // Atomic address is always the second parameter
- Args.add(RValue::get(EmitCastToVoidPtr(Ptr)),
- getContext().VoidPtrTy);
+ if (!UseOptimizedLibcall) {
+ // For non-optimized library calls, the size is the first parameter
+ Args.add(RValue::get(llvm::ConstantInt::get(SizeTy, Size)),
+ getContext().getSizeType());
+ }
+ // Atomic address is the first or second parameter
+ Args.add(RValue::get(EmitCastToVoidPtr(Ptr)), getContext().VoidPtrTy);
- const char* LibCallName;
- QualType RetTy = getContext().VoidTy;
+ std::string LibCallName;
+ QualType RetTy;
+ bool HaveRetTy = false;
switch (E->getOp()) {
// There is only one libcall for compare an exchange, because there is no
// optimisation benefit possible from a libcall version of a weak compare
// and exchange.
- // bool __atomic_compare_exchange(size_t size, void *obj, void *expected,
+ // bool __atomic_compare_exchange(size_t size, void *mem, void *expected,
// void *desired, int success, int failure)
+ // bool __atomic_compare_exchange_N(T *mem, T *expected, T desired,
+ // int success, int failure)
case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
case AtomicExpr::AO__atomic_compare_exchange:
case AtomicExpr::AO__atomic_compare_exchange_n:
LibCallName = "__atomic_compare_exchange";
RetTy = getContext().BoolTy;
- Args.add(RValue::get(EmitCastToVoidPtr(Val1)),
- getContext().VoidPtrTy);
- Args.add(RValue::get(EmitCastToVoidPtr(Val2)),
- getContext().VoidPtrTy);
- Args.add(RValue::get(Order),
- getContext().IntTy);
+ HaveRetTy = true;
+ Args.add(RValue::get(EmitCastToVoidPtr(Val1)), getContext().VoidPtrTy);
+ AddDirectArgument(*this, Args, UseOptimizedLibcall, Val2, MemTy,
+ E->getExprLoc());
+ Args.add(RValue::get(Order), getContext().IntTy);
Order = OrderFail;
break;
// void __atomic_exchange(size_t size, void *mem, void *val, void *return,
// int order)
+ // T __atomic_exchange_N(T *mem, T val, int order)
case AtomicExpr::AO__c11_atomic_exchange:
case AtomicExpr::AO__atomic_exchange_n:
case AtomicExpr::AO__atomic_exchange:
LibCallName = "__atomic_exchange";
- Args.add(RValue::get(EmitCastToVoidPtr(Val1)),
- getContext().VoidPtrTy);
- Args.add(RValue::get(EmitCastToVoidPtr(Dest)),
- getContext().VoidPtrTy);
+ AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1, MemTy,
+ E->getExprLoc());
break;
// void __atomic_store(size_t size, void *mem, void *val, int order)
+ // void __atomic_store_N(T *mem, T val, int order)
case AtomicExpr::AO__c11_atomic_store:
case AtomicExpr::AO__atomic_store:
case AtomicExpr::AO__atomic_store_n:
LibCallName = "__atomic_store";
- Args.add(RValue::get(EmitCastToVoidPtr(Val1)),
- getContext().VoidPtrTy);
+ RetTy = getContext().VoidTy;
+ HaveRetTy = true;
+ AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1, MemTy,
+ E->getExprLoc());
break;
// void __atomic_load(size_t size, void *mem, void *return, int order)
+ // T __atomic_load_N(T *mem, int order)
case AtomicExpr::AO__c11_atomic_load:
case AtomicExpr::AO__atomic_load:
case AtomicExpr::AO__atomic_load_n:
LibCallName = "__atomic_load";
- Args.add(RValue::get(EmitCastToVoidPtr(Dest)),
- getContext().VoidPtrTy);
+ break;
+ // T __atomic_fetch_add_N(T *mem, T val, int order)
+ case AtomicExpr::AO__c11_atomic_fetch_add:
+ case AtomicExpr::AO__atomic_fetch_add:
+ LibCallName = "__atomic_fetch_add";
+ AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1, MemTy,
+ E->getExprLoc());
+ break;
+ // T __atomic_fetch_and_N(T *mem, T val, int order)
+ case AtomicExpr::AO__c11_atomic_fetch_and:
+ case AtomicExpr::AO__atomic_fetch_and:
+ LibCallName = "__atomic_fetch_and";
+ AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1, MemTy,
+ E->getExprLoc());
+ break;
+ // T __atomic_fetch_or_N(T *mem, T val, int order)
+ case AtomicExpr::AO__c11_atomic_fetch_or:
+ case AtomicExpr::AO__atomic_fetch_or:
+ LibCallName = "__atomic_fetch_or";
+ AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1, MemTy,
+ E->getExprLoc());
+ break;
+ // T __atomic_fetch_sub_N(T *mem, T val, int order)
+ case AtomicExpr::AO__c11_atomic_fetch_sub:
+ case AtomicExpr::AO__atomic_fetch_sub:
+ LibCallName = "__atomic_fetch_sub";
+ AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1, MemTy,
+ E->getExprLoc());
+ break;
+ // T __atomic_fetch_xor_N(T *mem, T val, int order)
+ case AtomicExpr::AO__c11_atomic_fetch_xor:
+ case AtomicExpr::AO__atomic_fetch_xor:
+ LibCallName = "__atomic_fetch_xor";
+ AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1, MemTy,
+ E->getExprLoc());
break;
default: return EmitUnsupportedRValue(E, "atomic library call");
}
+
+ // Optimized functions have the size in their name.
+ if (UseOptimizedLibcall)
+ LibCallName += "_" + llvm::utostr(Size);
+ // By default, assume we return a value of the atomic type.
+ if (!HaveRetTy) {
+ if (UseOptimizedLibcall) {
+ // Value is returned directly.
+ RetTy = MemTy;
+ } else {
+ // Value is returned through parameter before the order.
+ RetTy = getContext().VoidTy;
+ Args.add(RValue::get(EmitCastToVoidPtr(Dest)),
+ getContext().VoidPtrTy);
+ }
+ }
// order is always the last parameter
Args.add(RValue::get(Order),
getContext().IntTy);
@@ -495,11 +590,11 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) {
llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FuncInfo);
llvm::Constant *Func = CGM.CreateRuntimeFunction(FTy, LibCallName);
RValue Res = EmitCall(FuncInfo, Func, ReturnValueSlot(), Args);
- if (E->isCmpXChg())
+ if (!RetTy->isVoidType())
return Res;
if (E->getType()->isVoidType())
return RValue::get(0);
- return convertTempToRValue(Dest, E->getType());
+ return convertTempToRValue(Dest, E->getType(), E->getExprLoc());
}
bool IsStore = E->getOp() == AtomicExpr::AO__c11_atomic_store ||
@@ -554,7 +649,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) {
}
if (E->getType()->isVoidType())
return RValue::get(0);
- return convertTempToRValue(OrigDest, E->getType());
+ return convertTempToRValue(OrigDest, E->getType(), E->getExprLoc());
}
// Long case, when Order isn't obviously constant.
@@ -616,7 +711,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) {
Builder.SetInsertPoint(ContBB);
if (E->getType()->isVoidType())
return RValue::get(0);
- return convertTempToRValue(OrigDest, E->getType());
+ return convertTempToRValue(OrigDest, E->getType(), E->getExprLoc());
}
llvm::Value *AtomicInfo::emitCastToAtomicIntPointer(llvm::Value *addr) const {
@@ -628,48 +723,30 @@ llvm::Value *AtomicInfo::emitCastToAtomicIntPointer(llvm::Value *addr) const {
}
RValue AtomicInfo::convertTempToRValue(llvm::Value *addr,
- AggValueSlot resultSlot) const {
- if (EvaluationKind == TEK_Aggregate) {
- // Nothing to do if the result is ignored.
- if (resultSlot.isIgnored()) return resultSlot.asRValue();
-
- assert(resultSlot.getAddr() == addr || hasPadding());
-
- // In these cases, we should have emitted directly into the result slot.
- if (!hasPadding() || resultSlot.isValueOfAtomic())
- return resultSlot.asRValue();
-
- // Otherwise, fall into the common path.
- }
+ AggValueSlot resultSlot,
+ SourceLocation loc) const {
+ if (EvaluationKind == TEK_Aggregate)
+ return resultSlot.asRValue();
// Drill into the padding structure if we have one.
if (hasPadding())
addr = CGF.Builder.CreateStructGEP(addr, 0);
- // If we're emitting to an aggregate, copy into the result slot.
- if (EvaluationKind == TEK_Aggregate) {
- CGF.EmitAggregateCopy(resultSlot.getAddr(), addr, getValueType(),
- resultSlot.isVolatile());
- return resultSlot.asRValue();
- }
-
// Otherwise, just convert the temporary to an r-value using the
// normal conversion routine.
- return CGF.convertTempToRValue(addr, getValueType());
+ return CGF.convertTempToRValue(addr, getValueType(), loc);
}
/// Emit a load from an l-value of atomic type. Note that the r-value
/// we produce is an r-value of the atomic *value* type.
-RValue CodeGenFunction::EmitAtomicLoad(LValue src, AggValueSlot resultSlot) {
+RValue CodeGenFunction::EmitAtomicLoad(LValue src, SourceLocation loc,
+ AggValueSlot resultSlot) {
AtomicInfo atomics(*this, src);
// Check whether we should use a library call.
if (atomics.shouldUseLibcall()) {
llvm::Value *tempAddr;
- if (resultSlot.isValueOfAtomic()) {
- assert(atomics.getEvaluationKind() == TEK_Aggregate);
- tempAddr = resultSlot.getPaddedAtomicAddr();
- } else if (!resultSlot.isIgnored() && !atomics.hasPadding()) {
+ if (!resultSlot.isIgnored()) {
assert(atomics.getEvaluationKind() == TEK_Aggregate);
tempAddr = resultSlot.getAddr();
} else {
@@ -690,7 +767,7 @@ RValue CodeGenFunction::EmitAtomicLoad(LValue src, AggValueSlot resultSlot) {
emitAtomicLibcall(*this, "__atomic_load", getContext().VoidTy, args);
// Produce the r-value.
- return atomics.convertTempToRValue(tempAddr, resultSlot);
+ return atomics.convertTempToRValue(tempAddr, resultSlot, loc);
}
// Okay, we're doing this natively.
@@ -733,16 +810,10 @@ RValue CodeGenFunction::EmitAtomicLoad(LValue src, AggValueSlot resultSlot) {
llvm::Value *temp;
bool tempIsVolatile = false;
CharUnits tempAlignment;
- if (atomics.getEvaluationKind() == TEK_Aggregate &&
- (!atomics.hasPadding() || resultSlot.isValueOfAtomic())) {
+ if (atomics.getEvaluationKind() == TEK_Aggregate) {
assert(!resultSlot.isIgnored());
- if (resultSlot.isValueOfAtomic()) {
- temp = resultSlot.getPaddedAtomicAddr();
- tempAlignment = atomics.getAtomicAlignment();
- } else {
- temp = resultSlot.getAddr();
- tempAlignment = atomics.getValueAlignment();
- }
+ temp = resultSlot.getAddr();
+ tempAlignment = atomics.getValueAlignment();
tempIsVolatile = resultSlot.isVolatile();
} else {
temp = CreateMemTemp(atomics.getAtomicType(), "atomic-load-temp");
@@ -754,7 +825,7 @@ RValue CodeGenFunction::EmitAtomicLoad(LValue src, AggValueSlot resultSlot) {
Builder.CreateAlignedStore(result, castTemp, tempAlignment.getQuantity())
->setVolatile(tempIsVolatile);
- return atomics.convertTempToRValue(temp, resultSlot);
+ return atomics.convertTempToRValue(temp, resultSlot, loc);
}
@@ -812,8 +883,7 @@ llvm::Value *AtomicInfo::materializeRValue(RValue rvalue) const {
/// Note that the r-value is expected to be an r-value *of the atomic
/// type*; this means that for aggregate r-values, it should include
/// storage for any padding that was necessary.
-void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest,
- bool isInit) {
+void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest, bool isInit) {
// If this is an aggregate r-value, it should agree in type except
// maybe for address-space qualification.
assert(!rvalue.isAggregate() ||
@@ -910,13 +980,11 @@ void CodeGenFunction::EmitAtomicInit(Expr *init, LValue dest) {
}
case TEK_Aggregate: {
- // Memset the buffer first if there's any possibility of
- // uninitialized internal bits.
- atomics.emitMemSetZeroIfNecessary(dest);
-
- // HACK: whether the initializer actually has an atomic type
- // doesn't really seem reliable right now.
+ // Fix up the destination if the initializer isn't an expression
+ // of atomic type.
+ bool Zeroed = false;
if (!init->getType()->isAtomicType()) {
+ Zeroed = atomics.emitMemSetZeroIfNecessary(dest);
dest = atomics.projectValue(dest);
}
@@ -924,7 +992,10 @@ void CodeGenFunction::EmitAtomicInit(Expr *init, LValue dest) {
AggValueSlot slot = AggValueSlot::forLValue(dest,
AggValueSlot::IsNotDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased);
+ AggValueSlot::IsNotAliased,
+ Zeroed ? AggValueSlot::IsZeroed :
+ AggValueSlot::IsNotZeroed);
+
EmitAggExpr(init, slot);
return;
}
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index ded019e..692f9a0 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -63,14 +63,16 @@ static llvm::Constant *buildDisposeHelper(CodeGenModule &CGM,
/// buildBlockDescriptor is accessed from 5th field of the Block_literal
/// meta-data and contains stationary information about the block literal.
/// Its definition will have 4 (or optinally 6) words.
+/// \code
/// struct Block_descriptor {
/// unsigned long reserved;
/// unsigned long size; // size of Block_literal metadata in bytes.
/// void *copy_func_helper_decl; // optional copy helper.
/// void *destroy_func_decl; // optioanl destructor helper.
-/// void *block_method_encoding_address;//@encode for block literal signature.
+/// void *block_method_encoding_address; // @encode for block literal signature.
/// void *block_layout_info; // encoding of captured block variables.
/// };
+/// \endcode
static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM,
const CGBlockInfo &blockInfo) {
ASTContext &C = CGM.getContext();
@@ -353,14 +355,9 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
// First, 'this'.
if (block->capturesCXXThis()) {
- const DeclContext *DC = block->getDeclContext();
- for (; isa<BlockDecl>(DC); DC = cast<BlockDecl>(DC)->getDeclContext())
- ;
- QualType thisType;
- if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC))
- thisType = C.getPointerType(C.getRecordType(RD));
- else
- thisType = cast<CXXMethodDecl>(DC)->getThisType(C);
+ assert(CGF && CGF->CurFuncDecl && isa<CXXMethodDecl>(CGF->CurFuncDecl) &&
+ "Can't capture 'this' outside a method");
+ QualType thisType = cast<CXXMethodDecl>(CGF->CurFuncDecl)->getThisType(C);
llvm::Type *llvmType = CGM.getTypes().ConvertType(thisType);
std::pair<CharUnits,CharUnits> tinfo
@@ -837,7 +834,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
type->isBlockPointerType()) {
// Load the block and do a simple retain.
LValue srcLV = MakeAddrLValue(src, type, align);
- llvm::Value *value = EmitLoadOfScalar(srcLV);
+ llvm::Value *value = EmitLoadOfScalar(srcLV, SourceLocation());
value = EmitARCRetainNonBlock(value);
// Do a primitive store to the block field.
@@ -934,7 +931,7 @@ llvm::Type *CodeGenModule::getGenericBlockLiteralType() {
}
-RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E,
+RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
ReturnValueSlot ReturnValue) {
const BlockPointerType *BPT =
E->getCallee()->getType()->getAs<BlockPointerType>();
@@ -1092,8 +1089,6 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
bool IsLambdaConversionToBlock) {
const BlockDecl *blockDecl = blockInfo.getBlockDecl();
- // Check if we should generate debug info for this block function.
- maybeInitializeDebugInfo();
CurGD = GD;
BlockInfo = &blockInfo;
@@ -1167,9 +1162,8 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
Alloca->setAlignment(Align);
// Set the DebugLocation to empty, so the store is recognized as a
// frame setup instruction by llvm::DwarfDebug::beginFunction().
- Builder.DisableDebugLocations();
+ NoLocation NL(*this, Builder);
Builder.CreateAlignedStore(BlockPointer, Alloca, Align);
- Builder.EnableDebugLocations();
BlockPointerDbgLoc = Alloca;
}
@@ -1307,9 +1301,6 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
IdentifierInfo *II
= &CGM.getContext().Idents.get("__copy_helper_block_");
- // Check if we should generate debug info for this block helper function.
- maybeInitializeDebugInfo();
-
FunctionDecl *FD = FunctionDecl::Create(C,
C.getTranslationUnitDecl(),
SourceLocation(),
@@ -1317,7 +1308,10 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
SC_Static,
false,
false);
+ // Create a scope with an artificial location for the body of this function.
+ ArtificialLocation AL(*this, Builder);
StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation());
+ AL.Emit();
llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo();
@@ -1479,9 +1473,6 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) {
llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
"__destroy_helper_block_", &CGM.getModule());
- // Check if we should generate debug info for this block destroy function.
- maybeInitializeDebugInfo();
-
IdentifierInfo *II
= &CGM.getContext().Idents.get("__destroy_helper_block_");
@@ -1490,7 +1481,10 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) {
SourceLocation(), II, C.VoidTy, 0,
SC_Static,
false, false);
+ // Create a scope with an artificial location for the body of this function.
+ ArtificialLocation AL(*this, Builder);
StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation());
+ AL.Emit();
llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo();
@@ -1781,8 +1775,6 @@ generateByrefCopyHelper(CodeGenFunction &CGF,
SC_Static,
false, false);
- // Initialize debug info if necessary.
- CGF.maybeInitializeDebugInfo();
CGF.StartFunction(FD, R, Fn, FI, args, SourceLocation());
if (byrefInfo.needsCopy()) {
@@ -1854,8 +1846,6 @@ generateByrefDisposeHelper(CodeGenFunction &CGF,
SourceLocation(), II, R, 0,
SC_Static,
false, false);
- // Initialize debug info if necessary.
- CGF.maybeInitializeDebugInfo();
CGF.StartFunction(FD, R, Fn, FI, args, SourceLocation());
if (byrefInfo.needsDispose()) {
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index d187678..7726ad3 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -19,6 +19,7 @@
#include "clang/AST/Decl.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/CodeGen/CGFunctionInfo.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Intrinsics.h"
@@ -165,7 +166,7 @@ static Value *EmitFAbs(CodeGenFunction &CGF, Value *V, QualType ValTy) {
static RValue emitLibraryCall(CodeGenFunction &CGF, const FunctionDecl *Fn,
const CallExpr *E, llvm::Value *calleeValue) {
- return CGF.EmitCall(E->getCallee()->getType(), calleeValue,
+ return CGF.EmitCall(E->getCallee()->getType(), calleeValue, E->getLocStart(),
ReturnValueSlot(), E->arg_begin(), E->arg_end(), Fn);
}
@@ -408,8 +409,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
assert(CI);
uint64_t val = CI->getZExtValue();
CI = ConstantInt::get(Builder.getInt1Ty(), (val & 0x2) >> 1);
-
- Value *F = CGM.getIntrinsic(Intrinsic::objectsize, ResType);
+ // FIXME: Get right address space.
+ llvm::Type *Tys[] = { ResType, Builder.getInt8PtrTy(0) };
+ Value *F = CGM.getIntrinsic(Intrinsic::objectsize, Tys);
return RValue::get(Builder.CreateCall2(F, EmitScalarExpr(E->getArg(0)),CI));
}
case Builtin::BI__builtin_prefetch: {
@@ -602,6 +604,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
}
case Builtin::BIalloca:
+ case Builtin::BI_alloca:
case Builtin::BI__builtin_alloca: {
Value *Size = EmitScalarExpr(E->getArg(0));
return RValue::get(Builder.CreateAlloca(Builder.getInt8Ty(), Size));
@@ -1282,18 +1285,25 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BIsqrt:
case Builtin::BIsqrtf:
case Builtin::BIsqrtl: {
- // TODO: there is currently no set of optimizer flags
- // sufficient for us to rewrite sqrt to @llvm.sqrt.
- // -fmath-errno=0 is not good enough; we need finiteness.
- // We could probably precondition the call with an ult
- // against 0, but is that worth the complexity?
- break;
+ // Transform a call to sqrt* into a @llvm.sqrt.* intrinsic call, but only
+ // in finite- or unsafe-math mode (the intrinsic has different semantics
+ // for handling negative numbers compared to the library function, so
+ // -fmath-errno=0 is not enough).
+ if (!FD->hasAttr<ConstAttr>())
+ break;
+ if (!(CGM.getCodeGenOpts().UnsafeFPMath ||
+ CGM.getCodeGenOpts().NoNaNsFPMath))
+ break;
+ Value *Arg0 = EmitScalarExpr(E->getArg(0));
+ llvm::Type *ArgType = Arg0->getType();
+ Value *F = CGM.getIntrinsic(Intrinsic::sqrt, ArgType);
+ return RValue::get(Builder.CreateCall(F, Arg0));
}
case Builtin::BIpow:
case Builtin::BIpowf:
case Builtin::BIpowl: {
- // Rewrite sqrt to intrinsic if allowed.
+ // Transform a call to pow* into a @llvm.pow.* intrinsic call.
if (!FD->hasAttr<ConstAttr>())
break;
Value *Base = EmitScalarExpr(E->getArg(0));
@@ -1301,6 +1311,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
llvm::Type *ArgType = Base->getType();
Value *F = CGM.getIntrinsic(Intrinsic::pow, ArgType);
return RValue::get(Builder.CreateCall2(F, Base, Exponent));
+ break;
}
case Builtin::BIfma:
@@ -1345,10 +1356,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
StringRef Str = cast<StringLiteral>(AnnotationStrExpr)->getString();
return RValue::get(EmitAnnotationCall(F, AnnVal, Str, E->getExprLoc()));
}
+ case Builtin::BI__builtin_addcb:
case Builtin::BI__builtin_addcs:
case Builtin::BI__builtin_addc:
case Builtin::BI__builtin_addcl:
case Builtin::BI__builtin_addcll:
+ case Builtin::BI__builtin_subcb:
case Builtin::BI__builtin_subcs:
case Builtin::BI__builtin_subc:
case Builtin::BI__builtin_subcl:
@@ -1382,12 +1395,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
llvm::Intrinsic::ID IntrinsicId;
switch (BuiltinID) {
default: llvm_unreachable("Unknown multiprecision builtin id.");
+ case Builtin::BI__builtin_addcb:
case Builtin::BI__builtin_addcs:
case Builtin::BI__builtin_addc:
case Builtin::BI__builtin_addcl:
case Builtin::BI__builtin_addcll:
IntrinsicId = llvm::Intrinsic::uadd_with_overflow;
break;
+ case Builtin::BI__builtin_subcb:
case Builtin::BI__builtin_subcs:
case Builtin::BI__builtin_subc:
case Builtin::BI__builtin_subcl:
@@ -1410,6 +1425,79 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
CarryOutStore->setAlignment(CarryOutPtr.second);
return RValue::get(Sum2);
}
+ case Builtin::BI__builtin_uadd_overflow:
+ case Builtin::BI__builtin_uaddl_overflow:
+ case Builtin::BI__builtin_uaddll_overflow:
+ case Builtin::BI__builtin_usub_overflow:
+ case Builtin::BI__builtin_usubl_overflow:
+ case Builtin::BI__builtin_usubll_overflow:
+ case Builtin::BI__builtin_umul_overflow:
+ case Builtin::BI__builtin_umull_overflow:
+ case Builtin::BI__builtin_umulll_overflow:
+ case Builtin::BI__builtin_sadd_overflow:
+ case Builtin::BI__builtin_saddl_overflow:
+ case Builtin::BI__builtin_saddll_overflow:
+ case Builtin::BI__builtin_ssub_overflow:
+ case Builtin::BI__builtin_ssubl_overflow:
+ case Builtin::BI__builtin_ssubll_overflow:
+ case Builtin::BI__builtin_smul_overflow:
+ case Builtin::BI__builtin_smull_overflow:
+ case Builtin::BI__builtin_smulll_overflow: {
+
+ // We translate all of these builtins directly to the relevant llvm IR node.
+
+ // Scalarize our inputs.
+ llvm::Value *X = EmitScalarExpr(E->getArg(0));
+ llvm::Value *Y = EmitScalarExpr(E->getArg(1));
+ std::pair<llvm::Value *, unsigned> SumOutPtr =
+ EmitPointerWithAlignment(E->getArg(2));
+
+ // Decide which of the overflow intrinsics we are lowering to:
+ llvm::Intrinsic::ID IntrinsicId;
+ switch (BuiltinID) {
+ default: llvm_unreachable("Unknown security overflow builtin id.");
+ case Builtin::BI__builtin_uadd_overflow:
+ case Builtin::BI__builtin_uaddl_overflow:
+ case Builtin::BI__builtin_uaddll_overflow:
+ IntrinsicId = llvm::Intrinsic::uadd_with_overflow;
+ break;
+ case Builtin::BI__builtin_usub_overflow:
+ case Builtin::BI__builtin_usubl_overflow:
+ case Builtin::BI__builtin_usubll_overflow:
+ IntrinsicId = llvm::Intrinsic::usub_with_overflow;
+ break;
+ case Builtin::BI__builtin_umul_overflow:
+ case Builtin::BI__builtin_umull_overflow:
+ case Builtin::BI__builtin_umulll_overflow:
+ IntrinsicId = llvm::Intrinsic::umul_with_overflow;
+ break;
+ case Builtin::BI__builtin_sadd_overflow:
+ case Builtin::BI__builtin_saddl_overflow:
+ case Builtin::BI__builtin_saddll_overflow:
+ IntrinsicId = llvm::Intrinsic::sadd_with_overflow;
+ break;
+ case Builtin::BI__builtin_ssub_overflow:
+ case Builtin::BI__builtin_ssubl_overflow:
+ case Builtin::BI__builtin_ssubll_overflow:
+ IntrinsicId = llvm::Intrinsic::ssub_with_overflow;
+ break;
+ case Builtin::BI__builtin_smul_overflow:
+ case Builtin::BI__builtin_smull_overflow:
+ case Builtin::BI__builtin_smulll_overflow:
+ IntrinsicId = llvm::Intrinsic::smul_with_overflow;
+ break;
+ }
+
+
+ llvm::Value *Carry;
+ llvm::Value *Sum = EmitOverflowIntrinsic(*this, IntrinsicId, X, Y, Carry);
+ llvm::StoreInst *SumOutStore = Builder.CreateStore(Sum, SumOutPtr.first);
+ SumOutStore->setAlignment(SumOutPtr.second);
+
+ return RValue::get(Carry);
+ }
+ case Builtin::BI__builtin_addressof:
+ return RValue::get(EmitLValue(E->getArg(0)).getAddress());
case Builtin::BI__noop:
return RValue::get(0);
}
@@ -1512,6 +1600,7 @@ Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID,
return EmitX86BuiltinExpr(BuiltinID, E);
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
+ case llvm::Triple::ppc64le:
return EmitPPCBuiltinExpr(BuiltinID, E);
default:
return 0;
@@ -1519,24 +1608,28 @@ Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID,
}
static llvm::VectorType *GetNeonType(CodeGenFunction *CGF,
- NeonTypeFlags TypeFlags) {
+ NeonTypeFlags TypeFlags,
+ bool V1Ty=false) {
int IsQuad = TypeFlags.isQuad();
switch (TypeFlags.getEltType()) {
case NeonTypeFlags::Int8:
case NeonTypeFlags::Poly8:
- return llvm::VectorType::get(CGF->Int8Ty, 8 << IsQuad);
+ return llvm::VectorType::get(CGF->Int8Ty, V1Ty ? 1 : (8 << IsQuad));
case NeonTypeFlags::Int16:
case NeonTypeFlags::Poly16:
case NeonTypeFlags::Float16:
- return llvm::VectorType::get(CGF->Int16Ty, 4 << IsQuad);
+ return llvm::VectorType::get(CGF->Int16Ty, V1Ty ? 1 : (4 << IsQuad));
case NeonTypeFlags::Int32:
- return llvm::VectorType::get(CGF->Int32Ty, 2 << IsQuad);
+ return llvm::VectorType::get(CGF->Int32Ty, V1Ty ? 1 : (2 << IsQuad));
case NeonTypeFlags::Int64:
- return llvm::VectorType::get(CGF->Int64Ty, 1 << IsQuad);
+ case NeonTypeFlags::Poly64:
+ return llvm::VectorType::get(CGF->Int64Ty, V1Ty ? 1 : (1 << IsQuad));
case NeonTypeFlags::Float32:
- return llvm::VectorType::get(CGF->FloatTy, 2 << IsQuad);
+ return llvm::VectorType::get(CGF->FloatTy, V1Ty ? 1 : (2 << IsQuad));
+ case NeonTypeFlags::Float64:
+ return llvm::VectorType::get(CGF->DoubleTy, V1Ty ? 1 : (1 << IsQuad));
}
- llvm_unreachable("Invalid NeonTypeFlags element type!");
+ llvm_unreachable("Unknown vector element type!");
}
Value *CodeGenFunction::EmitNeonSplat(Value *V, Constant *C) {
@@ -1568,6 +1661,39 @@ Value *CodeGenFunction::EmitNeonShiftVector(Value *V, llvm::Type *Ty,
return llvm::ConstantVector::getSplat(VTy->getNumElements(), C);
}
+// \brief Right-shift a vector by a constant.
+Value *CodeGenFunction::EmitNeonRShiftImm(Value *Vec, Value *Shift,
+ llvm::Type *Ty, bool usgn,
+ const char *name) {
+ llvm::VectorType *VTy = cast<llvm::VectorType>(Ty);
+
+ int ShiftAmt = cast<ConstantInt>(Shift)->getSExtValue();
+ int EltSize = VTy->getScalarSizeInBits();
+
+ Vec = Builder.CreateBitCast(Vec, Ty);
+
+ // lshr/ashr are undefined when the shift amount is equal to the vector
+ // element size.
+ if (ShiftAmt == EltSize) {
+ if (usgn) {
+ // Right-shifting an unsigned value by its size yields 0.
+ llvm::Constant *Zero = ConstantInt::get(VTy->getElementType(), 0);
+ return llvm::ConstantVector::getSplat(VTy->getNumElements(), Zero);
+ } else {
+ // Right-shifting a signed value by its size is equivalent
+ // to a shift of size-1.
+ --ShiftAmt;
+ Shift = ConstantInt::get(VTy->getElementType(), ShiftAmt);
+ }
+ }
+
+ Shift = EmitNeonShiftVector(Shift, Ty, false);
+ if (usgn)
+ return Builder.CreateLShr(Vec, Shift, name);
+ else
+ return Builder.CreateAShr(Vec, Shift, name);
+}
+
/// GetPointeeAlignment - Given an expression with a pointer type, find the
/// alignment of the type referenced by the pointer. Skip over implicit
/// casts.
@@ -1623,8 +1749,1140 @@ CodeGenFunction::EmitPointerWithAlignment(const Expr *Addr) {
return std::make_pair(EmitScalarExpr(Addr), Align);
}
+static Value *EmitAArch64ScalarBuiltinExpr(CodeGenFunction &CGF,
+ unsigned BuiltinID,
+ const CallExpr *E) {
+ unsigned int Int = 0;
+ // Scalar result generated across vectors
+ bool AcrossVec = false;
+ // Extend element of one-element vector
+ bool ExtendEle = false;
+ bool OverloadInt = false;
+ bool OverloadCmpInt = false;
+ bool IsFpCmpZInt = false;
+ bool OverloadCvtInt = false;
+ bool OverloadWideInt = false;
+ bool OverloadNarrowInt = false;
+ const char *s = NULL;
+
+ SmallVector<Value *, 4> Ops;
+ for (unsigned i = 0, e = E->getNumArgs(); i != e; i++) {
+ Ops.push_back(CGF.EmitScalarExpr(E->getArg(i)));
+ }
+
+ // AArch64 scalar builtins are not overloaded, they do not have an extra
+ // argument that specifies the vector type, need to handle each case.
+ switch (BuiltinID) {
+ default: break;
+ case AArch64::BI__builtin_neon_vdups_lane_f32:
+ case AArch64::BI__builtin_neon_vdupd_lane_f64:
+ case AArch64::BI__builtin_neon_vdups_laneq_f32:
+ case AArch64::BI__builtin_neon_vdupd_laneq_f64: {
+ return CGF.Builder.CreateExtractElement(Ops[0], Ops[1], "vdup_lane");
+ }
+ case AArch64::BI__builtin_neon_vdupb_lane_i8:
+ case AArch64::BI__builtin_neon_vduph_lane_i16:
+ case AArch64::BI__builtin_neon_vdups_lane_i32:
+ case AArch64::BI__builtin_neon_vdupd_lane_i64:
+ case AArch64::BI__builtin_neon_vdupb_laneq_i8:
+ case AArch64::BI__builtin_neon_vduph_laneq_i16:
+ case AArch64::BI__builtin_neon_vdups_laneq_i32:
+ case AArch64::BI__builtin_neon_vdupd_laneq_i64: {
+ // The backend treats Neon scalar types as v1ix types
+ // So we want to dup lane from any vector to v1ix vector
+ // with shufflevector
+ s = "vdup_lane";
+ Value* SV = llvm::ConstantVector::getSplat(1, cast<ConstantInt>(Ops[1]));
+ Value *Result = CGF.Builder.CreateShuffleVector(Ops[0], Ops[0], SV, s);
+ llvm::Type *Ty = CGF.ConvertType(E->getCallReturnType());
+ // AArch64 intrinsic one-element vector type cast to
+ // scalar type expected by the builtin
+ return CGF.Builder.CreateBitCast(Result, Ty, s);
+ }
+ case AArch64::BI__builtin_neon_vqdmlalh_lane_s16 :
+ case AArch64::BI__builtin_neon_vqdmlalh_laneq_s16 :
+ case AArch64::BI__builtin_neon_vqdmlals_lane_s32 :
+ case AArch64::BI__builtin_neon_vqdmlals_laneq_s32 :
+ case AArch64::BI__builtin_neon_vqdmlslh_lane_s16 :
+ case AArch64::BI__builtin_neon_vqdmlslh_laneq_s16 :
+ case AArch64::BI__builtin_neon_vqdmlsls_lane_s32 :
+ case AArch64::BI__builtin_neon_vqdmlsls_laneq_s32 : {
+ Int = Intrinsic::arm_neon_vqadds;
+ if (BuiltinID == AArch64::BI__builtin_neon_vqdmlslh_lane_s16 ||
+ BuiltinID == AArch64::BI__builtin_neon_vqdmlslh_laneq_s16 ||
+ BuiltinID == AArch64::BI__builtin_neon_vqdmlsls_lane_s32 ||
+ BuiltinID == AArch64::BI__builtin_neon_vqdmlsls_laneq_s32) {
+ Int = Intrinsic::arm_neon_vqsubs;
+ }
+ // create vqdmull call with b * c[i]
+ llvm::Type *Ty = CGF.ConvertType(E->getArg(1)->getType());
+ llvm::VectorType *OpVTy = llvm::VectorType::get(Ty, 1);
+ Ty = CGF.ConvertType(E->getArg(0)->getType());
+ llvm::VectorType *ResVTy = llvm::VectorType::get(Ty, 1);
+ Value *F = CGF.CGM.getIntrinsic(Intrinsic::arm_neon_vqdmull, ResVTy);
+ Value *V = UndefValue::get(OpVTy);
+ llvm::Constant *CI = ConstantInt::get(CGF.Int32Ty, 0);
+ SmallVector<Value *, 2> MulOps;
+ MulOps.push_back(Ops[1]);
+ MulOps.push_back(Ops[2]);
+ MulOps[0] = CGF.Builder.CreateInsertElement(V, MulOps[0], CI);
+ MulOps[1] = CGF.Builder.CreateExtractElement(MulOps[1], Ops[3], "extract");
+ MulOps[1] = CGF.Builder.CreateInsertElement(V, MulOps[1], CI);
+ Value *MulRes = CGF.Builder.CreateCall2(F, MulOps[0], MulOps[1]);
+ // create vqadds call with a +/- vqdmull result
+ F = CGF.CGM.getIntrinsic(Int, ResVTy);
+ SmallVector<Value *, 2> AddOps;
+ AddOps.push_back(Ops[0]);
+ AddOps.push_back(MulRes);
+ V = UndefValue::get(ResVTy);
+ AddOps[0] = CGF.Builder.CreateInsertElement(V, AddOps[0], CI);
+ Value *AddRes = CGF.Builder.CreateCall2(F, AddOps[0], AddOps[1]);
+ return CGF.Builder.CreateBitCast(AddRes, Ty);
+ }
+ case AArch64::BI__builtin_neon_vfmas_lane_f32:
+ case AArch64::BI__builtin_neon_vfmas_laneq_f32:
+ case AArch64::BI__builtin_neon_vfmad_lane_f64:
+ case AArch64::BI__builtin_neon_vfmad_laneq_f64: {
+ llvm::Type *Ty = CGF.ConvertType(E->getCallReturnType());
+ Value *F = CGF.CGM.getIntrinsic(Intrinsic::fma, Ty);
+ Ops[2] = CGF.Builder.CreateExtractElement(Ops[2], Ops[3], "extract");
+ return CGF.Builder.CreateCall3(F, Ops[1], Ops[2], Ops[0]);
+ }
+ // Scalar Floating-point Multiply Extended
+ case AArch64::BI__builtin_neon_vmulxs_f32:
+ case AArch64::BI__builtin_neon_vmulxd_f64: {
+ Int = Intrinsic::aarch64_neon_vmulx;
+ llvm::Type *Ty = CGF.ConvertType(E->getCallReturnType());
+ return CGF.EmitNeonCall(CGF.CGM.getIntrinsic(Int, Ty), Ops, "vmulx");
+ }
+ case AArch64::BI__builtin_neon_vmul_n_f64: {
+ // v1f64 vmul_n_f64 should be mapped to Neon scalar mul lane
+ llvm::Type *VTy = GetNeonType(&CGF,
+ NeonTypeFlags(NeonTypeFlags::Float64, false, false));
+ Ops[0] = CGF.Builder.CreateBitCast(Ops[0], VTy);
+ llvm::Value *Idx = llvm::ConstantInt::get(CGF.Int32Ty, 0);
+ Ops[0] = CGF.Builder.CreateExtractElement(Ops[0], Idx, "extract");
+ Value *Result = CGF.Builder.CreateFMul(Ops[0], Ops[1]);
+ return CGF.Builder.CreateBitCast(Result, VTy);
+ }
+ case AArch64::BI__builtin_neon_vget_lane_i8:
+ case AArch64::BI__builtin_neon_vget_lane_i16:
+ case AArch64::BI__builtin_neon_vget_lane_i32:
+ case AArch64::BI__builtin_neon_vget_lane_i64:
+ case AArch64::BI__builtin_neon_vget_lane_f32:
+ case AArch64::BI__builtin_neon_vget_lane_f64:
+ case AArch64::BI__builtin_neon_vgetq_lane_i8:
+ case AArch64::BI__builtin_neon_vgetq_lane_i16:
+ case AArch64::BI__builtin_neon_vgetq_lane_i32:
+ case AArch64::BI__builtin_neon_vgetq_lane_i64:
+ case AArch64::BI__builtin_neon_vgetq_lane_f32:
+ case AArch64::BI__builtin_neon_vgetq_lane_f64:
+ return CGF.EmitARMBuiltinExpr(ARM::BI__builtin_neon_vget_lane_i8, E);
+ case AArch64::BI__builtin_neon_vset_lane_i8:
+ case AArch64::BI__builtin_neon_vset_lane_i16:
+ case AArch64::BI__builtin_neon_vset_lane_i32:
+ case AArch64::BI__builtin_neon_vset_lane_i64:
+ case AArch64::BI__builtin_neon_vset_lane_f32:
+ case AArch64::BI__builtin_neon_vset_lane_f64:
+ case AArch64::BI__builtin_neon_vsetq_lane_i8:
+ case AArch64::BI__builtin_neon_vsetq_lane_i16:
+ case AArch64::BI__builtin_neon_vsetq_lane_i32:
+ case AArch64::BI__builtin_neon_vsetq_lane_i64:
+ case AArch64::BI__builtin_neon_vsetq_lane_f32:
+ case AArch64::BI__builtin_neon_vsetq_lane_f64:
+ return CGF.EmitARMBuiltinExpr(ARM::BI__builtin_neon_vset_lane_i8, E);
+ // Crypto
+ case AArch64::BI__builtin_neon_vsha1h_u32:
+ Int = Intrinsic::arm_neon_sha1h;
+ s = "sha1h"; OverloadInt = true; break;
+ case AArch64::BI__builtin_neon_vsha1cq_u32:
+ Int = Intrinsic::aarch64_neon_sha1c;
+ s = "sha1c"; break;
+ case AArch64::BI__builtin_neon_vsha1pq_u32:
+ Int = Intrinsic::aarch64_neon_sha1p;
+ s = "sha1p"; break;
+ case AArch64::BI__builtin_neon_vsha1mq_u32:
+ Int = Intrinsic::aarch64_neon_sha1m;
+ s = "sha1m"; break;
+ // Scalar Add
+ case AArch64::BI__builtin_neon_vaddd_s64:
+ Int = Intrinsic::aarch64_neon_vaddds;
+ s = "vaddds"; break;
+ case AArch64::BI__builtin_neon_vaddd_u64:
+ Int = Intrinsic::aarch64_neon_vadddu;
+ s = "vadddu"; break;
+ // Scalar Sub
+ case AArch64::BI__builtin_neon_vsubd_s64:
+ Int = Intrinsic::aarch64_neon_vsubds;
+ s = "vsubds"; break;
+ case AArch64::BI__builtin_neon_vsubd_u64:
+ Int = Intrinsic::aarch64_neon_vsubdu;
+ s = "vsubdu"; break;
+ // Scalar Saturating Add
+ case AArch64::BI__builtin_neon_vqaddb_s8:
+ case AArch64::BI__builtin_neon_vqaddh_s16:
+ case AArch64::BI__builtin_neon_vqadds_s32:
+ case AArch64::BI__builtin_neon_vqaddd_s64:
+ Int = Intrinsic::arm_neon_vqadds;
+ s = "vqadds"; OverloadInt = true; break;
+ case AArch64::BI__builtin_neon_vqaddb_u8:
+ case AArch64::BI__builtin_neon_vqaddh_u16:
+ case AArch64::BI__builtin_neon_vqadds_u32:
+ case AArch64::BI__builtin_neon_vqaddd_u64:
+ Int = Intrinsic::arm_neon_vqaddu;
+ s = "vqaddu"; OverloadInt = true; break;
+ // Scalar Saturating Sub
+ case AArch64::BI__builtin_neon_vqsubb_s8:
+ case AArch64::BI__builtin_neon_vqsubh_s16:
+ case AArch64::BI__builtin_neon_vqsubs_s32:
+ case AArch64::BI__builtin_neon_vqsubd_s64:
+ Int = Intrinsic::arm_neon_vqsubs;
+ s = "vqsubs"; OverloadInt = true; break;
+ case AArch64::BI__builtin_neon_vqsubb_u8:
+ case AArch64::BI__builtin_neon_vqsubh_u16:
+ case AArch64::BI__builtin_neon_vqsubs_u32:
+ case AArch64::BI__builtin_neon_vqsubd_u64:
+ Int = Intrinsic::arm_neon_vqsubu;
+ s = "vqsubu"; OverloadInt = true; break;
+ // Scalar Shift Left
+ case AArch64::BI__builtin_neon_vshld_s64:
+ Int = Intrinsic::aarch64_neon_vshlds;
+ s = "vshlds"; break;
+ case AArch64::BI__builtin_neon_vshld_u64:
+ Int = Intrinsic::aarch64_neon_vshldu;
+ s = "vshldu"; break;
+ // Scalar Saturating Shift Left
+ case AArch64::BI__builtin_neon_vqshlb_s8:
+ case AArch64::BI__builtin_neon_vqshlh_s16:
+ case AArch64::BI__builtin_neon_vqshls_s32:
+ case AArch64::BI__builtin_neon_vqshld_s64:
+ Int = Intrinsic::aarch64_neon_vqshls;
+ s = "vqshls"; OverloadInt = true; break;
+ case AArch64::BI__builtin_neon_vqshlb_u8:
+ case AArch64::BI__builtin_neon_vqshlh_u16:
+ case AArch64::BI__builtin_neon_vqshls_u32:
+ case AArch64::BI__builtin_neon_vqshld_u64:
+ Int = Intrinsic::aarch64_neon_vqshlu;
+ s = "vqshlu"; OverloadInt = true; break;
+ // Scalar Rouding Shift Left
+ case AArch64::BI__builtin_neon_vrshld_s64:
+ Int = Intrinsic::aarch64_neon_vrshlds;
+ s = "vrshlds"; break;
+ case AArch64::BI__builtin_neon_vrshld_u64:
+ Int = Intrinsic::aarch64_neon_vrshldu;
+ s = "vrshldu"; break;
+ // Scalar Saturating Rouding Shift Left
+ case AArch64::BI__builtin_neon_vqrshlb_s8:
+ case AArch64::BI__builtin_neon_vqrshlh_s16:
+ case AArch64::BI__builtin_neon_vqrshls_s32:
+ case AArch64::BI__builtin_neon_vqrshld_s64:
+ Int = Intrinsic::aarch64_neon_vqrshls;
+ s = "vqrshls"; OverloadInt = true; break;
+ case AArch64::BI__builtin_neon_vqrshlb_u8:
+ case AArch64::BI__builtin_neon_vqrshlh_u16:
+ case AArch64::BI__builtin_neon_vqrshls_u32:
+ case AArch64::BI__builtin_neon_vqrshld_u64:
+ Int = Intrinsic::aarch64_neon_vqrshlu;
+ s = "vqrshlu"; OverloadInt = true; break;
+ // Scalar Reduce Pairwise Add
+ case AArch64::BI__builtin_neon_vpaddd_s64:
+ case AArch64::BI__builtin_neon_vpaddd_u64:
+ Int = Intrinsic::aarch64_neon_vpadd; s = "vpadd";
+ break;
+ case AArch64::BI__builtin_neon_vpadds_f32:
+ Int = Intrinsic::aarch64_neon_vpfadd; s = "vpfadd";
+ break;
+ case AArch64::BI__builtin_neon_vpaddd_f64:
+ Int = Intrinsic::aarch64_neon_vpfaddq; s = "vpfaddq";
+ break;
+ // Scalar Reduce Pairwise Floating Point Max
+ case AArch64::BI__builtin_neon_vpmaxs_f32:
+ Int = Intrinsic::aarch64_neon_vpmax; s = "vpmax";
+ break;
+ case AArch64::BI__builtin_neon_vpmaxqd_f64:
+ Int = Intrinsic::aarch64_neon_vpmaxq; s = "vpmaxq";
+ break;
+ // Scalar Reduce Pairwise Floating Point Min
+ case AArch64::BI__builtin_neon_vpmins_f32:
+ Int = Intrinsic::aarch64_neon_vpmin; s = "vpmin";
+ break;
+ case AArch64::BI__builtin_neon_vpminqd_f64:
+ Int = Intrinsic::aarch64_neon_vpminq; s = "vpminq";
+ break;
+ // Scalar Reduce Pairwise Floating Point Maxnm
+ case AArch64::BI__builtin_neon_vpmaxnms_f32:
+ Int = Intrinsic::aarch64_neon_vpfmaxnm; s = "vpfmaxnm";
+ break;
+ case AArch64::BI__builtin_neon_vpmaxnmqd_f64:
+ Int = Intrinsic::aarch64_neon_vpfmaxnmq; s = "vpfmaxnmq";
+ break;
+ // Scalar Reduce Pairwise Floating Point Minnm
+ case AArch64::BI__builtin_neon_vpminnms_f32:
+ Int = Intrinsic::aarch64_neon_vpfminnm; s = "vpfminnm";
+ break;
+ case AArch64::BI__builtin_neon_vpminnmqd_f64:
+ Int = Intrinsic::aarch64_neon_vpfminnmq; s = "vpfminnmq";
+ break;
+ // The followings are intrinsics with scalar results generated AcrossVec vectors
+ case AArch64::BI__builtin_neon_vaddlv_s8:
+ case AArch64::BI__builtin_neon_vaddlv_s16:
+ case AArch64::BI__builtin_neon_vaddlvq_s8:
+ case AArch64::BI__builtin_neon_vaddlvq_s16:
+ case AArch64::BI__builtin_neon_vaddlvq_s32:
+ Int = Intrinsic::aarch64_neon_saddlv;
+ AcrossVec = true; ExtendEle = true; s = "saddlv"; break;
+ case AArch64::BI__builtin_neon_vaddlv_u8:
+ case AArch64::BI__builtin_neon_vaddlv_u16:
+ case AArch64::BI__builtin_neon_vaddlvq_u8:
+ case AArch64::BI__builtin_neon_vaddlvq_u16:
+ case AArch64::BI__builtin_neon_vaddlvq_u32:
+ Int = Intrinsic::aarch64_neon_uaddlv;
+ AcrossVec = true; ExtendEle = true; s = "uaddlv"; break;
+ case AArch64::BI__builtin_neon_vmaxv_s8:
+ case AArch64::BI__builtin_neon_vmaxv_s16:
+ case AArch64::BI__builtin_neon_vmaxvq_s8:
+ case AArch64::BI__builtin_neon_vmaxvq_s16:
+ case AArch64::BI__builtin_neon_vmaxvq_s32:
+ Int = Intrinsic::aarch64_neon_smaxv;
+ AcrossVec = true; ExtendEle = false; s = "smaxv"; break;
+ case AArch64::BI__builtin_neon_vmaxv_u8:
+ case AArch64::BI__builtin_neon_vmaxv_u16:
+ case AArch64::BI__builtin_neon_vmaxvq_u8:
+ case AArch64::BI__builtin_neon_vmaxvq_u16:
+ case AArch64::BI__builtin_neon_vmaxvq_u32:
+ Int = Intrinsic::aarch64_neon_umaxv;
+ AcrossVec = true; ExtendEle = false; s = "umaxv"; break;
+ case AArch64::BI__builtin_neon_vminv_s8:
+ case AArch64::BI__builtin_neon_vminv_s16:
+ case AArch64::BI__builtin_neon_vminvq_s8:
+ case AArch64::BI__builtin_neon_vminvq_s16:
+ case AArch64::BI__builtin_neon_vminvq_s32:
+ Int = Intrinsic::aarch64_neon_sminv;
+ AcrossVec = true; ExtendEle = false; s = "sminv"; break;
+ case AArch64::BI__builtin_neon_vminv_u8:
+ case AArch64::BI__builtin_neon_vminv_u16:
+ case AArch64::BI__builtin_neon_vminvq_u8:
+ case AArch64::BI__builtin_neon_vminvq_u16:
+ case AArch64::BI__builtin_neon_vminvq_u32:
+ Int = Intrinsic::aarch64_neon_uminv;
+ AcrossVec = true; ExtendEle = false; s = "uminv"; break;
+ case AArch64::BI__builtin_neon_vaddv_s8:
+ case AArch64::BI__builtin_neon_vaddv_s16:
+ case AArch64::BI__builtin_neon_vaddvq_s8:
+ case AArch64::BI__builtin_neon_vaddvq_s16:
+ case AArch64::BI__builtin_neon_vaddvq_s32:
+ case AArch64::BI__builtin_neon_vaddvq_s64:
+ case AArch64::BI__builtin_neon_vaddv_u8:
+ case AArch64::BI__builtin_neon_vaddv_u16:
+ case AArch64::BI__builtin_neon_vaddvq_u8:
+ case AArch64::BI__builtin_neon_vaddvq_u16:
+ case AArch64::BI__builtin_neon_vaddvq_u32:
+ case AArch64::BI__builtin_neon_vaddvq_u64:
+ case AArch64::BI__builtin_neon_vaddv_f32:
+ case AArch64::BI__builtin_neon_vaddvq_f32:
+ case AArch64::BI__builtin_neon_vaddvq_f64:
+ Int = Intrinsic::aarch64_neon_vaddv;
+ AcrossVec = true; ExtendEle = false; s = "vaddv"; break;
+ case AArch64::BI__builtin_neon_vmaxv_f32:
+ case AArch64::BI__builtin_neon_vmaxvq_f32:
+ case AArch64::BI__builtin_neon_vmaxvq_f64:
+ Int = Intrinsic::aarch64_neon_vmaxv;
+ AcrossVec = true; ExtendEle = false; s = "vmaxv"; break;
+ case AArch64::BI__builtin_neon_vminv_f32:
+ case AArch64::BI__builtin_neon_vminvq_f32:
+ case AArch64::BI__builtin_neon_vminvq_f64:
+ Int = Intrinsic::aarch64_neon_vminv;
+ AcrossVec = true; ExtendEle = false; s = "vminv"; break;
+ case AArch64::BI__builtin_neon_vmaxnmv_f32:
+ case AArch64::BI__builtin_neon_vmaxnmvq_f32:
+ case AArch64::BI__builtin_neon_vmaxnmvq_f64:
+ Int = Intrinsic::aarch64_neon_vmaxnmv;
+ AcrossVec = true; ExtendEle = false; s = "vmaxnmv"; break;
+ case AArch64::BI__builtin_neon_vminnmv_f32:
+ case AArch64::BI__builtin_neon_vminnmvq_f32:
+ case AArch64::BI__builtin_neon_vminnmvq_f64:
+ Int = Intrinsic::aarch64_neon_vminnmv;
+ AcrossVec = true; ExtendEle = false; s = "vminnmv"; break;
+ // Scalar Integer Saturating Doubling Multiply Half High
+ case AArch64::BI__builtin_neon_vqdmulhh_s16:
+ case AArch64::BI__builtin_neon_vqdmulhs_s32:
+ Int = Intrinsic::arm_neon_vqdmulh;
+ s = "vqdmulh"; OverloadInt = true; break;
+ // Scalar Integer Saturating Rounding Doubling Multiply Half High
+ case AArch64::BI__builtin_neon_vqrdmulhh_s16:
+ case AArch64::BI__builtin_neon_vqrdmulhs_s32:
+ Int = Intrinsic::arm_neon_vqrdmulh;
+ s = "vqrdmulh"; OverloadInt = true; break;
+ // Scalar Floating-point Reciprocal Step and
+ case AArch64::BI__builtin_neon_vrecpss_f32:
+ case AArch64::BI__builtin_neon_vrecpsd_f64:
+ Int = Intrinsic::arm_neon_vrecps;
+ s = "vrecps"; OverloadInt = true; break;
+ // Scalar Floating-point Reciprocal Square Root Step
+ case AArch64::BI__builtin_neon_vrsqrtss_f32:
+ case AArch64::BI__builtin_neon_vrsqrtsd_f64:
+ Int = Intrinsic::arm_neon_vrsqrts;
+ s = "vrsqrts"; OverloadInt = true; break;
+ // Scalar Signed Integer Convert To Floating-point
+ case AArch64::BI__builtin_neon_vcvts_f32_s32:
+ Int = Intrinsic::aarch64_neon_vcvtf32_s32,
+ s = "vcvtf"; OverloadInt = false; break;
+ case AArch64::BI__builtin_neon_vcvtd_f64_s64:
+ Int = Intrinsic::aarch64_neon_vcvtf64_s64,
+ s = "vcvtf"; OverloadInt = false; break;
+ // Scalar Unsigned Integer Convert To Floating-point
+ case AArch64::BI__builtin_neon_vcvts_f32_u32:
+ Int = Intrinsic::aarch64_neon_vcvtf32_u32,
+ s = "vcvtf"; OverloadInt = false; break;
+ case AArch64::BI__builtin_neon_vcvtd_f64_u64:
+ Int = Intrinsic::aarch64_neon_vcvtf64_u64,
+ s = "vcvtf"; OverloadInt = false; break;
+ // Scalar Floating-point Converts
+ case AArch64::BI__builtin_neon_vcvtxd_f32_f64:
+ Int = Intrinsic::aarch64_neon_fcvtxn;
+ s = "vcvtxn"; OverloadCvtInt = true; break;
+ case AArch64::BI__builtin_neon_vcvtas_s32_f32:
+ case AArch64::BI__builtin_neon_vcvtad_s64_f64:
+ Int = Intrinsic::aarch64_neon_fcvtas;
+ s = "vcvtas"; OverloadCvtInt = true; break;
+ case AArch64::BI__builtin_neon_vcvtas_u32_f32:
+ case AArch64::BI__builtin_neon_vcvtad_u64_f64:
+ Int = Intrinsic::aarch64_neon_fcvtau;
+ s = "vcvtau"; OverloadCvtInt = true; break;
+ case AArch64::BI__builtin_neon_vcvtms_s32_f32:
+ case AArch64::BI__builtin_neon_vcvtmd_s64_f64:
+ Int = Intrinsic::aarch64_neon_fcvtms;
+ s = "vcvtms"; OverloadCvtInt = true; break;
+ case AArch64::BI__builtin_neon_vcvtms_u32_f32:
+ case AArch64::BI__builtin_neon_vcvtmd_u64_f64:
+ Int = Intrinsic::aarch64_neon_fcvtmu;
+ s = "vcvtmu"; OverloadCvtInt = true; break;
+ case AArch64::BI__builtin_neon_vcvtns_s32_f32:
+ case AArch64::BI__builtin_neon_vcvtnd_s64_f64:
+ Int = Intrinsic::aarch64_neon_fcvtns;
+ s = "vcvtns"; OverloadCvtInt = true; break;
+ case AArch64::BI__builtin_neon_vcvtns_u32_f32:
+ case AArch64::BI__builtin_neon_vcvtnd_u64_f64:
+ Int = Intrinsic::aarch64_neon_fcvtnu;
+ s = "vcvtnu"; OverloadCvtInt = true; break;
+ case AArch64::BI__builtin_neon_vcvtps_s32_f32:
+ case AArch64::BI__builtin_neon_vcvtpd_s64_f64:
+ Int = Intrinsic::aarch64_neon_fcvtps;
+ s = "vcvtps"; OverloadCvtInt = true; break;
+ case AArch64::BI__builtin_neon_vcvtps_u32_f32:
+ case AArch64::BI__builtin_neon_vcvtpd_u64_f64:
+ Int = Intrinsic::aarch64_neon_fcvtpu;
+ s = "vcvtpu"; OverloadCvtInt = true; break;
+ case AArch64::BI__builtin_neon_vcvts_s32_f32:
+ case AArch64::BI__builtin_neon_vcvtd_s64_f64:
+ Int = Intrinsic::aarch64_neon_fcvtzs;
+ s = "vcvtzs"; OverloadCvtInt = true; break;
+ case AArch64::BI__builtin_neon_vcvts_u32_f32:
+ case AArch64::BI__builtin_neon_vcvtd_u64_f64:
+ Int = Intrinsic::aarch64_neon_fcvtzu;
+ s = "vcvtzu"; OverloadCvtInt = true; break;
+ // Scalar Floating-point Reciprocal Estimate
+ case AArch64::BI__builtin_neon_vrecpes_f32:
+ case AArch64::BI__builtin_neon_vrecped_f64:
+ Int = Intrinsic::arm_neon_vrecpe;
+ s = "vrecpe"; OverloadInt = true; break;
+ // Scalar Floating-point Reciprocal Exponent
+ case AArch64::BI__builtin_neon_vrecpxs_f32:
+ case AArch64::BI__builtin_neon_vrecpxd_f64:
+ Int = Intrinsic::aarch64_neon_vrecpx;
+ s = "vrecpx"; OverloadInt = true; break;
+ // Scalar Floating-point Reciprocal Square Root Estimate
+ case AArch64::BI__builtin_neon_vrsqrtes_f32:
+ case AArch64::BI__builtin_neon_vrsqrted_f64:
+ Int = Intrinsic::arm_neon_vrsqrte;
+ s = "vrsqrte"; OverloadInt = true; break;
+ // Scalar Compare Equal
+ case AArch64::BI__builtin_neon_vceqd_s64:
+ case AArch64::BI__builtin_neon_vceqd_u64:
+ Int = Intrinsic::aarch64_neon_vceq; s = "vceq";
+ OverloadCmpInt = true; break;
+ // Scalar Compare Equal To Zero
+ case AArch64::BI__builtin_neon_vceqzd_s64:
+ case AArch64::BI__builtin_neon_vceqzd_u64:
+ Int = Intrinsic::aarch64_neon_vceq; s = "vceq";
+ // Add implicit zero operand.
+ Ops.push_back(llvm::Constant::getNullValue(Ops[0]->getType()));
+ OverloadCmpInt = true; break;
+ // Scalar Compare Greater Than or Equal
+ case AArch64::BI__builtin_neon_vcged_s64:
+ Int = Intrinsic::aarch64_neon_vcge; s = "vcge";
+ OverloadCmpInt = true; break;
+ case AArch64::BI__builtin_neon_vcged_u64:
+ Int = Intrinsic::aarch64_neon_vchs; s = "vcge";
+ OverloadCmpInt = true; break;
+ // Scalar Compare Greater Than or Equal To Zero
+ case AArch64::BI__builtin_neon_vcgezd_s64:
+ Int = Intrinsic::aarch64_neon_vcge; s = "vcge";
+ // Add implicit zero operand.
+ Ops.push_back(llvm::Constant::getNullValue(Ops[0]->getType()));
+ OverloadCmpInt = true; break;
+ // Scalar Compare Greater Than
+ case AArch64::BI__builtin_neon_vcgtd_s64:
+ Int = Intrinsic::aarch64_neon_vcgt; s = "vcgt";
+ OverloadCmpInt = true; break;
+ case AArch64::BI__builtin_neon_vcgtd_u64:
+ Int = Intrinsic::aarch64_neon_vchi; s = "vcgt";
+ OverloadCmpInt = true; break;
+ // Scalar Compare Greater Than Zero
+ case AArch64::BI__builtin_neon_vcgtzd_s64:
+ Int = Intrinsic::aarch64_neon_vcgt; s = "vcgt";
+ // Add implicit zero operand.
+ Ops.push_back(llvm::Constant::getNullValue(Ops[0]->getType()));
+ OverloadCmpInt = true; break;
+ // Scalar Compare Less Than or Equal
+ case AArch64::BI__builtin_neon_vcled_s64:
+ Int = Intrinsic::aarch64_neon_vcge; s = "vcge";
+ OverloadCmpInt = true; std::swap(Ops[0], Ops[1]); break;
+ case AArch64::BI__builtin_neon_vcled_u64:
+ Int = Intrinsic::aarch64_neon_vchs; s = "vchs";
+ OverloadCmpInt = true; std::swap(Ops[0], Ops[1]); break;
+ // Scalar Compare Less Than or Equal To Zero
+ case AArch64::BI__builtin_neon_vclezd_s64:
+ Int = Intrinsic::aarch64_neon_vclez; s = "vcle";
+ // Add implicit zero operand.
+ Ops.push_back(llvm::Constant::getNullValue(Ops[0]->getType()));
+ OverloadCmpInt = true; break;
+ // Scalar Compare Less Than
+ case AArch64::BI__builtin_neon_vcltd_s64:
+ Int = Intrinsic::aarch64_neon_vcgt; s = "vcgt";
+ OverloadCmpInt = true; std::swap(Ops[0], Ops[1]); break;
+ case AArch64::BI__builtin_neon_vcltd_u64:
+ Int = Intrinsic::aarch64_neon_vchi; s = "vchi";
+ OverloadCmpInt = true; std::swap(Ops[0], Ops[1]); break;
+ // Scalar Compare Less Than Zero
+ case AArch64::BI__builtin_neon_vcltzd_s64:
+ Int = Intrinsic::aarch64_neon_vcltz; s = "vclt";
+ // Add implicit zero operand.
+ Ops.push_back(llvm::Constant::getNullValue(Ops[0]->getType()));
+ OverloadCmpInt = true; break;
+ // Scalar Floating-point Compare Equal
+ case AArch64::BI__builtin_neon_vceqs_f32:
+ case AArch64::BI__builtin_neon_vceqd_f64:
+ Int = Intrinsic::aarch64_neon_vceq; s = "vceq";
+ OverloadCmpInt = true; break;
+ // Scalar Floating-point Compare Equal To Zero
+ case AArch64::BI__builtin_neon_vceqzs_f32:
+ case AArch64::BI__builtin_neon_vceqzd_f64:
+ Int = Intrinsic::aarch64_neon_vceq; s = "vceq";
+ // Add implicit zero operand.
+ Ops.push_back(llvm::Constant::getNullValue(CGF.FloatTy));
+ IsFpCmpZInt = true;
+ OverloadCmpInt = true; break;
+ // Scalar Floating-point Compare Greater Than Or Equal
+ case AArch64::BI__builtin_neon_vcges_f32:
+ case AArch64::BI__builtin_neon_vcged_f64:
+ Int = Intrinsic::aarch64_neon_vcge; s = "vcge";
+ OverloadCmpInt = true; break;
+ // Scalar Floating-point Compare Greater Than Or Equal To Zero
+ case AArch64::BI__builtin_neon_vcgezs_f32:
+ case AArch64::BI__builtin_neon_vcgezd_f64:
+ Int = Intrinsic::aarch64_neon_vcge; s = "vcge";
+ // Add implicit zero operand.
+ Ops.push_back(llvm::Constant::getNullValue(CGF.FloatTy));
+ IsFpCmpZInt = true;
+ OverloadCmpInt = true; break;
+ // Scalar Floating-point Compare Greather Than
+ case AArch64::BI__builtin_neon_vcgts_f32:
+ case AArch64::BI__builtin_neon_vcgtd_f64:
+ Int = Intrinsic::aarch64_neon_vcgt; s = "vcgt";
+ OverloadCmpInt = true; break;
+ // Scalar Floating-point Compare Greather Than Zero
+ case AArch64::BI__builtin_neon_vcgtzs_f32:
+ case AArch64::BI__builtin_neon_vcgtzd_f64:
+ Int = Intrinsic::aarch64_neon_vcgt; s = "vcgt";
+ // Add implicit zero operand.
+ Ops.push_back(llvm::Constant::getNullValue(CGF.FloatTy));
+ IsFpCmpZInt = true;
+ OverloadCmpInt = true; break;
+ // Scalar Floating-point Compare Less Than or Equal
+ case AArch64::BI__builtin_neon_vcles_f32:
+ case AArch64::BI__builtin_neon_vcled_f64:
+ Int = Intrinsic::aarch64_neon_vcge; s = "vcge";
+ OverloadCmpInt = true; break;
+ // Scalar Floating-point Compare Less Than Or Equal To Zero
+ case AArch64::BI__builtin_neon_vclezs_f32:
+ case AArch64::BI__builtin_neon_vclezd_f64:
+ Int = Intrinsic::aarch64_neon_vclez; s = "vcle";
+ // Add implicit zero operand.
+ Ops.push_back(llvm::Constant::getNullValue(CGF.FloatTy));
+ IsFpCmpZInt = true;
+ OverloadCmpInt = true; break;
+ // Scalar Floating-point Compare Less Than Zero
+ case AArch64::BI__builtin_neon_vclts_f32:
+ case AArch64::BI__builtin_neon_vcltd_f64:
+ Int = Intrinsic::aarch64_neon_vcgt; s = "vcgt";
+ OverloadCmpInt = true; std::swap(Ops[0], Ops[1]); break;
+ // Scalar Floating-point Compare Less Than Zero
+ case AArch64::BI__builtin_neon_vcltzs_f32:
+ case AArch64::BI__builtin_neon_vcltzd_f64:
+ Int = Intrinsic::aarch64_neon_vcltz; s = "vclt";
+ // Add implicit zero operand.
+ Ops.push_back(llvm::Constant::getNullValue(CGF.FloatTy));
+ IsFpCmpZInt = true;
+ OverloadCmpInt = true; break;
+ // Scalar Floating-point Absolute Compare Greater Than Or Equal
+ case AArch64::BI__builtin_neon_vcages_f32:
+ case AArch64::BI__builtin_neon_vcaged_f64:
+ Int = Intrinsic::aarch64_neon_vcage; s = "vcage";
+ OverloadCmpInt = true; break;
+ // Scalar Floating-point Absolute Compare Greater Than
+ case AArch64::BI__builtin_neon_vcagts_f32:
+ case AArch64::BI__builtin_neon_vcagtd_f64:
+ Int = Intrinsic::aarch64_neon_vcagt; s = "vcagt";
+ OverloadCmpInt = true; break;
+ // Scalar Floating-point Absolute Compare Less Than Or Equal
+ case AArch64::BI__builtin_neon_vcales_f32:
+ case AArch64::BI__builtin_neon_vcaled_f64:
+ Int = Intrinsic::aarch64_neon_vcage; s = "vcage";
+ OverloadCmpInt = true; std::swap(Ops[0], Ops[1]); break;
+ // Scalar Floating-point Absolute Compare Less Than
+ case AArch64::BI__builtin_neon_vcalts_f32:
+ case AArch64::BI__builtin_neon_vcaltd_f64:
+ Int = Intrinsic::aarch64_neon_vcagt; s = "vcalt";
+ OverloadCmpInt = true; std::swap(Ops[0], Ops[1]); break;
+ // Scalar Compare Bitwise Test Bits
+ case AArch64::BI__builtin_neon_vtstd_s64:
+ case AArch64::BI__builtin_neon_vtstd_u64:
+ Int = Intrinsic::aarch64_neon_vtstd; s = "vtst";
+ OverloadCmpInt = true; break;
+ // Scalar Absolute Value
+ case AArch64::BI__builtin_neon_vabsd_s64:
+ Int = Intrinsic::aarch64_neon_vabs;
+ s = "vabs"; OverloadInt = false; break;
+ // Scalar Absolute Difference
+ case AArch64::BI__builtin_neon_vabds_f32:
+ case AArch64::BI__builtin_neon_vabdd_f64:
+ Int = Intrinsic::aarch64_neon_vabd;
+ s = "vabd"; OverloadInt = true; break;
+ // Scalar Signed Saturating Absolute Value
+ case AArch64::BI__builtin_neon_vqabsb_s8:
+ case AArch64::BI__builtin_neon_vqabsh_s16:
+ case AArch64::BI__builtin_neon_vqabss_s32:
+ case AArch64::BI__builtin_neon_vqabsd_s64:
+ Int = Intrinsic::arm_neon_vqabs;
+ s = "vqabs"; OverloadInt = true; break;
+ // Scalar Negate
+ case AArch64::BI__builtin_neon_vnegd_s64:
+ Int = Intrinsic::aarch64_neon_vneg;
+ s = "vneg"; OverloadInt = false; break;
+ // Scalar Signed Saturating Negate
+ case AArch64::BI__builtin_neon_vqnegb_s8:
+ case AArch64::BI__builtin_neon_vqnegh_s16:
+ case AArch64::BI__builtin_neon_vqnegs_s32:
+ case AArch64::BI__builtin_neon_vqnegd_s64:
+ Int = Intrinsic::arm_neon_vqneg;
+ s = "vqneg"; OverloadInt = true; break;
+ // Scalar Signed Saturating Accumulated of Unsigned Value
+ case AArch64::BI__builtin_neon_vuqaddb_s8:
+ case AArch64::BI__builtin_neon_vuqaddh_s16:
+ case AArch64::BI__builtin_neon_vuqadds_s32:
+ case AArch64::BI__builtin_neon_vuqaddd_s64:
+ Int = Intrinsic::aarch64_neon_vuqadd;
+ s = "vuqadd"; OverloadInt = true; break;
+ // Scalar Unsigned Saturating Accumulated of Signed Value
+ case AArch64::BI__builtin_neon_vsqaddb_u8:
+ case AArch64::BI__builtin_neon_vsqaddh_u16:
+ case AArch64::BI__builtin_neon_vsqadds_u32:
+ case AArch64::BI__builtin_neon_vsqaddd_u64:
+ Int = Intrinsic::aarch64_neon_vsqadd;
+ s = "vsqadd"; OverloadInt = true; break;
+ // Signed Saturating Doubling Multiply-Add Long
+ case AArch64::BI__builtin_neon_vqdmlalh_s16:
+ case AArch64::BI__builtin_neon_vqdmlals_s32:
+ Int = Intrinsic::aarch64_neon_vqdmlal;
+ s = "vqdmlal"; OverloadWideInt = true; break;
+ // Signed Saturating Doubling Multiply-Subtract Long
+ case AArch64::BI__builtin_neon_vqdmlslh_s16:
+ case AArch64::BI__builtin_neon_vqdmlsls_s32:
+ Int = Intrinsic::aarch64_neon_vqdmlsl;
+ s = "vqdmlsl"; OverloadWideInt = true; break;
+ // Signed Saturating Doubling Multiply Long
+ case AArch64::BI__builtin_neon_vqdmullh_s16:
+ case AArch64::BI__builtin_neon_vqdmulls_s32:
+ Int = Intrinsic::arm_neon_vqdmull;
+ s = "vqdmull"; OverloadWideInt = true; break;
+ // Scalar Signed Saturating Extract Unsigned Narrow
+ case AArch64::BI__builtin_neon_vqmovunh_s16:
+ case AArch64::BI__builtin_neon_vqmovuns_s32:
+ case AArch64::BI__builtin_neon_vqmovund_s64:
+ Int = Intrinsic::arm_neon_vqmovnsu;
+ s = "vqmovun"; OverloadNarrowInt = true; break;
+ // Scalar Signed Saturating Extract Narrow
+ case AArch64::BI__builtin_neon_vqmovnh_s16:
+ case AArch64::BI__builtin_neon_vqmovns_s32:
+ case AArch64::BI__builtin_neon_vqmovnd_s64:
+ Int = Intrinsic::arm_neon_vqmovns;
+ s = "vqmovn"; OverloadNarrowInt = true; break;
+ // Scalar Unsigned Saturating Extract Narrow
+ case AArch64::BI__builtin_neon_vqmovnh_u16:
+ case AArch64::BI__builtin_neon_vqmovns_u32:
+ case AArch64::BI__builtin_neon_vqmovnd_u64:
+ Int = Intrinsic::arm_neon_vqmovnu;
+ s = "vqmovn"; OverloadNarrowInt = true; break;
+ // Scalar Signed Shift Right (Immediate)
+ case AArch64::BI__builtin_neon_vshrd_n_s64:
+ Int = Intrinsic::aarch64_neon_vshrds_n;
+ s = "vsshr"; OverloadInt = false; break;
+ // Scalar Unsigned Shift Right (Immediate)
+ case AArch64::BI__builtin_neon_vshrd_n_u64:
+ Int = Intrinsic::aarch64_neon_vshrdu_n;
+ s = "vushr"; OverloadInt = false; break;
+ // Scalar Signed Rounding Shift Right (Immediate)
+ case AArch64::BI__builtin_neon_vrshrd_n_s64:
+ Int = Intrinsic::aarch64_neon_vsrshr;
+ s = "vsrshr"; OverloadInt = true; break;
+ // Scalar Unsigned Rounding Shift Right (Immediate)
+ case AArch64::BI__builtin_neon_vrshrd_n_u64:
+ Int = Intrinsic::aarch64_neon_vurshr;
+ s = "vurshr"; OverloadInt = true; break;
+ // Scalar Signed Shift Right and Accumulate (Immediate)
+ case AArch64::BI__builtin_neon_vsrad_n_s64:
+ Int = Intrinsic::aarch64_neon_vsrads_n;
+ s = "vssra"; OverloadInt = false; break;
+ // Scalar Unsigned Shift Right and Accumulate (Immediate)
+ case AArch64::BI__builtin_neon_vsrad_n_u64:
+ Int = Intrinsic::aarch64_neon_vsradu_n;
+ s = "vusra"; OverloadInt = false; break;
+ // Scalar Signed Rounding Shift Right and Accumulate (Immediate)
+ case AArch64::BI__builtin_neon_vrsrad_n_s64:
+ Int = Intrinsic::aarch64_neon_vrsrads_n;
+ s = "vsrsra"; OverloadInt = false; break;
+ // Scalar Unsigned Rounding Shift Right and Accumulate (Immediate)
+ case AArch64::BI__builtin_neon_vrsrad_n_u64:
+ Int = Intrinsic::aarch64_neon_vrsradu_n;
+ s = "vursra"; OverloadInt = false; break;
+ // Scalar Signed/Unsigned Shift Left (Immediate)
+ case AArch64::BI__builtin_neon_vshld_n_s64:
+ case AArch64::BI__builtin_neon_vshld_n_u64:
+ Int = Intrinsic::aarch64_neon_vshld_n;
+ s = "vshl"; OverloadInt = false; break;
+ // Signed Saturating Shift Left (Immediate)
+ case AArch64::BI__builtin_neon_vqshlb_n_s8:
+ case AArch64::BI__builtin_neon_vqshlh_n_s16:
+ case AArch64::BI__builtin_neon_vqshls_n_s32:
+ case AArch64::BI__builtin_neon_vqshld_n_s64:
+ Int = Intrinsic::aarch64_neon_vqshls_n;
+ s = "vsqshl"; OverloadInt = true; break;
+ // Unsigned Saturating Shift Left (Immediate)
+ case AArch64::BI__builtin_neon_vqshlb_n_u8:
+ case AArch64::BI__builtin_neon_vqshlh_n_u16:
+ case AArch64::BI__builtin_neon_vqshls_n_u32:
+ case AArch64::BI__builtin_neon_vqshld_n_u64:
+ Int = Intrinsic::aarch64_neon_vqshlu_n;
+ s = "vuqshl"; OverloadInt = true; break;
+ // Signed Saturating Shift Left Unsigned (Immediate)
+ case AArch64::BI__builtin_neon_vqshlub_n_s8:
+ case AArch64::BI__builtin_neon_vqshluh_n_s16:
+ case AArch64::BI__builtin_neon_vqshlus_n_s32:
+ case AArch64::BI__builtin_neon_vqshlud_n_s64:
+ Int = Intrinsic::aarch64_neon_vsqshlu;
+ s = "vsqshlu"; OverloadInt = true; break;
+ // Shift Right And Insert (Immediate)
+ case AArch64::BI__builtin_neon_vsrid_n_s64:
+ case AArch64::BI__builtin_neon_vsrid_n_u64:
+ Int = Intrinsic::aarch64_neon_vsri;
+ s = "vsri"; OverloadInt = true; break;
+ // Shift Left And Insert (Immediate)
+ case AArch64::BI__builtin_neon_vslid_n_s64:
+ case AArch64::BI__builtin_neon_vslid_n_u64:
+ Int = Intrinsic::aarch64_neon_vsli;
+ s = "vsli"; OverloadInt = true; break;
+ // Signed Saturating Shift Right Narrow (Immediate)
+ case AArch64::BI__builtin_neon_vqshrnh_n_s16:
+ case AArch64::BI__builtin_neon_vqshrns_n_s32:
+ case AArch64::BI__builtin_neon_vqshrnd_n_s64:
+ Int = Intrinsic::aarch64_neon_vsqshrn;
+ s = "vsqshrn"; OverloadInt = true; break;
+ // Unsigned Saturating Shift Right Narrow (Immediate)
+ case AArch64::BI__builtin_neon_vqshrnh_n_u16:
+ case AArch64::BI__builtin_neon_vqshrns_n_u32:
+ case AArch64::BI__builtin_neon_vqshrnd_n_u64:
+ Int = Intrinsic::aarch64_neon_vuqshrn;
+ s = "vuqshrn"; OverloadInt = true; break;
+ // Signed Saturating Rounded Shift Right Narrow (Immediate)
+ case AArch64::BI__builtin_neon_vqrshrnh_n_s16:
+ case AArch64::BI__builtin_neon_vqrshrns_n_s32:
+ case AArch64::BI__builtin_neon_vqrshrnd_n_s64:
+ Int = Intrinsic::aarch64_neon_vsqrshrn;
+ s = "vsqrshrn"; OverloadInt = true; break;
+ // Unsigned Saturating Rounded Shift Right Narrow (Immediate)
+ case AArch64::BI__builtin_neon_vqrshrnh_n_u16:
+ case AArch64::BI__builtin_neon_vqrshrns_n_u32:
+ case AArch64::BI__builtin_neon_vqrshrnd_n_u64:
+ Int = Intrinsic::aarch64_neon_vuqrshrn;
+ s = "vuqrshrn"; OverloadInt = true; break;
+ // Signed Saturating Shift Right Unsigned Narrow (Immediate)
+ case AArch64::BI__builtin_neon_vqshrunh_n_s16:
+ case AArch64::BI__builtin_neon_vqshruns_n_s32:
+ case AArch64::BI__builtin_neon_vqshrund_n_s64:
+ Int = Intrinsic::aarch64_neon_vsqshrun;
+ s = "vsqshrun"; OverloadInt = true; break;
+ // Signed Saturating Rounded Shift Right Unsigned Narrow (Immediate)
+ case AArch64::BI__builtin_neon_vqrshrunh_n_s16:
+ case AArch64::BI__builtin_neon_vqrshruns_n_s32:
+ case AArch64::BI__builtin_neon_vqrshrund_n_s64:
+ Int = Intrinsic::aarch64_neon_vsqrshrun;
+ s = "vsqrshrun"; OverloadInt = true; break;
+ // Scalar Signed Fixed-point Convert To Floating-Point (Immediate)
+ case AArch64::BI__builtin_neon_vcvts_n_f32_s32:
+ Int = Intrinsic::aarch64_neon_vcvtf32_n_s32;
+ s = "vcvtf"; OverloadInt = false; break;
+ case AArch64::BI__builtin_neon_vcvtd_n_f64_s64:
+ Int = Intrinsic::aarch64_neon_vcvtf64_n_s64;
+ s = "vcvtf"; OverloadInt = false; break;
+ // Scalar Unsigned Fixed-point Convert To Floating-Point (Immediate)
+ case AArch64::BI__builtin_neon_vcvts_n_f32_u32:
+ Int = Intrinsic::aarch64_neon_vcvtf32_n_u32;
+ s = "vcvtf"; OverloadInt = false; break;
+ case AArch64::BI__builtin_neon_vcvtd_n_f64_u64:
+ Int = Intrinsic::aarch64_neon_vcvtf64_n_u64;
+ s = "vcvtf"; OverloadInt = false; break;
+ // Scalar Floating-point Convert To Signed Fixed-point (Immediate)
+ case AArch64::BI__builtin_neon_vcvts_n_s32_f32:
+ Int = Intrinsic::aarch64_neon_vcvts_n_s32_f32;
+ s = "fcvtzs"; OverloadInt = false; break;
+ case AArch64::BI__builtin_neon_vcvtd_n_s64_f64:
+ Int = Intrinsic::aarch64_neon_vcvtd_n_s64_f64;
+ s = "fcvtzs"; OverloadInt = false; break;
+ // Scalar Floating-point Convert To Unsigned Fixed-point (Immediate)
+ case AArch64::BI__builtin_neon_vcvts_n_u32_f32:
+ Int = Intrinsic::aarch64_neon_vcvts_n_u32_f32;
+ s = "fcvtzu"; OverloadInt = false; break;
+ case AArch64::BI__builtin_neon_vcvtd_n_u64_f64:
+ Int = Intrinsic::aarch64_neon_vcvtd_n_u64_f64;
+ s = "fcvtzu"; OverloadInt = false; break;
+ }
+
+ if (!Int)
+ return 0;
+
+ // AArch64 scalar builtin that returns scalar type
+ // and should be mapped to AArch64 intrinsic that returns
+ // one-element vector type.
+ Function *F = 0;
+ if (AcrossVec) {
+ // Gen arg type
+ const Expr *Arg = E->getArg(E->getNumArgs()-1);
+ llvm::Type *Ty = CGF.ConvertType(Arg->getType());
+ llvm::VectorType *VTy = cast<llvm::VectorType>(Ty);
+ llvm::Type *ETy = VTy->getElementType();
+ llvm::VectorType *RTy = llvm::VectorType::get(ETy, 1);
+
+ if (ExtendEle) {
+ assert(!ETy->isFloatingPointTy());
+ RTy = llvm::VectorType::getExtendedElementVectorType(RTy);
+ }
+
+ llvm::Type *Tys[2] = {RTy, VTy};
+ F = CGF.CGM.getIntrinsic(Int, Tys);
+ assert(E->getNumArgs() == 1);
+ } else if (OverloadInt) {
+ // Determine the type of this overloaded AArch64 intrinsic
+ llvm::Type *Ty = CGF.ConvertType(E->getCallReturnType());
+ llvm::VectorType *VTy = llvm::VectorType::get(Ty, 1);
+ assert(VTy);
+
+ F = CGF.CGM.getIntrinsic(Int, VTy);
+ } else if (OverloadWideInt || OverloadNarrowInt) {
+ // Determine the type of this overloaded AArch64 intrinsic
+ const Expr *Arg = E->getArg(E->getNumArgs()-1);
+ llvm::Type *Ty = CGF.ConvertType(Arg->getType());
+ llvm::VectorType *VTy = llvm::VectorType::get(Ty, 1);
+ llvm::VectorType *RTy = OverloadWideInt ?
+ llvm::VectorType::getExtendedElementVectorType(VTy) :
+ llvm::VectorType::getTruncatedElementVectorType(VTy);
+ F = CGF.CGM.getIntrinsic(Int, RTy);
+ } else if (OverloadCmpInt) {
+ // Determine the types of this overloaded AArch64 intrinsic
+ SmallVector<llvm::Type *, 3> Tys;
+ const Expr *Arg = E->getArg(E->getNumArgs()-1);
+ llvm::Type *Ty = CGF.ConvertType(E->getCallReturnType());
+ llvm::VectorType *VTy = llvm::VectorType::get(Ty, 1);
+ Tys.push_back(VTy);
+ Ty = CGF.ConvertType(Arg->getType());
+ VTy = llvm::VectorType::get(Ty, 1);
+ Tys.push_back(VTy);
+ if(IsFpCmpZInt)
+ VTy = llvm::VectorType::get(CGF.FloatTy, 1);
+ Tys.push_back(VTy);
+
+ F = CGF.CGM.getIntrinsic(Int, Tys);
+ } else if (OverloadCvtInt) {
+ // Determine the types of this overloaded AArch64 intrinsic
+ SmallVector<llvm::Type *, 2> Tys;
+ const Expr *Arg = E->getArg(E->getNumArgs()-1);
+ llvm::Type *Ty = CGF.ConvertType(E->getCallReturnType());
+ llvm::VectorType *VTy = llvm::VectorType::get(Ty, 1);
+ Tys.push_back(VTy);
+ Ty = CGF.ConvertType(Arg->getType());
+ VTy = llvm::VectorType::get(Ty, 1);
+ Tys.push_back(VTy);
+
+ F = CGF.CGM.getIntrinsic(Int, Tys);
+ } else
+ F = CGF.CGM.getIntrinsic(Int);
+
+ Value *Result = CGF.EmitNeonCall(F, Ops, s);
+ llvm::Type *ResultType = CGF.ConvertType(E->getType());
+ // AArch64 intrinsic one-element vector type cast to
+ // scalar type expected by the builtin
+ return CGF.Builder.CreateBitCast(Result, ResultType, s);
+}
+
+Value *CodeGenFunction::EmitAArch64CompareBuiltinExpr(
+ Value *Op, llvm::Type *Ty, const CmpInst::Predicate Fp,
+ const CmpInst::Predicate Ip, const Twine &Name) {
+ llvm::Type *OTy = ((llvm::User *)Op)->getOperand(0)->getType();
+ if (OTy->isPointerTy())
+ OTy = Ty;
+ Op = Builder.CreateBitCast(Op, OTy);
+ if (((llvm::VectorType *)OTy)->getElementType()->isFloatingPointTy()) {
+ Op = Builder.CreateFCmp(Fp, Op, ConstantAggregateZero::get(OTy));
+ } else {
+ Op = Builder.CreateICmp(Ip, Op, ConstantAggregateZero::get(OTy));
+ }
+ return Builder.CreateZExt(Op, Ty, Name);
+}
+
+static Value *packTBLDVectorList(CodeGenFunction &CGF, ArrayRef<Value *> Ops,
+ Value *ExtOp, Value *IndexOp,
+ llvm::Type *ResTy, unsigned IntID,
+ const char *Name) {
+ SmallVector<Value *, 2> TblOps;
+ if (ExtOp)
+ TblOps.push_back(ExtOp);
+
+ // Build a vector containing sequential number like (0, 1, 2, ..., 15)
+ SmallVector<Constant*, 16> Indices;
+ llvm::VectorType *TblTy = cast<llvm::VectorType>(Ops[0]->getType());
+ for (unsigned i = 0, e = TblTy->getNumElements(); i != e; ++i) {
+ Indices.push_back(ConstantInt::get(CGF.Int32Ty, 2*i));
+ Indices.push_back(ConstantInt::get(CGF.Int32Ty, 2*i+1));
+ }
+ Value *SV = llvm::ConstantVector::get(Indices);
+
+ int PairPos = 0, End = Ops.size() - 1;
+ while (PairPos < End) {
+ TblOps.push_back(CGF.Builder.CreateShuffleVector(Ops[PairPos],
+ Ops[PairPos+1], SV, Name));
+ PairPos += 2;
+ }
+
+ // If there's an odd number of 64-bit lookup table, fill the high 64-bit
+ // of the 128-bit lookup table with zero.
+ if (PairPos == End) {
+ Value *ZeroTbl = ConstantAggregateZero::get(TblTy);
+ TblOps.push_back(CGF.Builder.CreateShuffleVector(Ops[PairPos],
+ ZeroTbl, SV, Name));
+ }
+
+ TblTy = llvm::VectorType::get(TblTy->getElementType(),
+ 2*TblTy->getNumElements());
+ llvm::Type *Tys[2] = { ResTy, TblTy };
+
+ Function *TblF;
+ TblOps.push_back(IndexOp);
+ TblF = CGF.CGM.getIntrinsic(IntID, Tys);
+
+ return CGF.EmitNeonCall(TblF, TblOps, Name);
+}
+
+static Value *EmitAArch64TblBuiltinExpr(CodeGenFunction &CGF,
+ unsigned BuiltinID,
+ const CallExpr *E) {
+ unsigned int Int = 0;
+ const char *s = NULL;
+
+ unsigned TblPos;
+ switch (BuiltinID) {
+ default:
+ return 0;
+ case AArch64::BI__builtin_neon_vtbl1_v:
+ case AArch64::BI__builtin_neon_vqtbl1_v:
+ case AArch64::BI__builtin_neon_vqtbl1q_v:
+ case AArch64::BI__builtin_neon_vtbl2_v:
+ case AArch64::BI__builtin_neon_vqtbl2_v:
+ case AArch64::BI__builtin_neon_vqtbl2q_v:
+ case AArch64::BI__builtin_neon_vtbl3_v:
+ case AArch64::BI__builtin_neon_vqtbl3_v:
+ case AArch64::BI__builtin_neon_vqtbl3q_v:
+ case AArch64::BI__builtin_neon_vtbl4_v:
+ case AArch64::BI__builtin_neon_vqtbl4_v:
+ case AArch64::BI__builtin_neon_vqtbl4q_v:
+ TblPos = 0;
+ break;
+ case AArch64::BI__builtin_neon_vtbx1_v:
+ case AArch64::BI__builtin_neon_vqtbx1_v:
+ case AArch64::BI__builtin_neon_vqtbx1q_v:
+ case AArch64::BI__builtin_neon_vtbx2_v:
+ case AArch64::BI__builtin_neon_vqtbx2_v:
+ case AArch64::BI__builtin_neon_vqtbx2q_v:
+ case AArch64::BI__builtin_neon_vtbx3_v:
+ case AArch64::BI__builtin_neon_vqtbx3_v:
+ case AArch64::BI__builtin_neon_vqtbx3q_v:
+ case AArch64::BI__builtin_neon_vtbx4_v:
+ case AArch64::BI__builtin_neon_vqtbx4_v:
+ case AArch64::BI__builtin_neon_vqtbx4q_v:
+ TblPos = 1;
+ break;
+ }
+
+ assert(E->getNumArgs() >= 3);
+
+ // Get the last argument, which specifies the vector type.
+ llvm::APSInt Result;
+ const Expr *Arg = E->getArg(E->getNumArgs() - 1);
+ if (!Arg->isIntegerConstantExpr(Result, CGF.getContext()))
+ return 0;
+
+ // Determine the type of this overloaded NEON intrinsic.
+ NeonTypeFlags Type(Result.getZExtValue());
+ llvm::VectorType *VTy = GetNeonType(&CGF, Type);
+ llvm::Type *Ty = VTy;
+ if (!Ty)
+ return 0;
+
+ SmallVector<Value *, 4> Ops;
+ for (unsigned i = 0, e = E->getNumArgs() - 1; i != e; i++) {
+ Ops.push_back(CGF.EmitScalarExpr(E->getArg(i)));
+ }
+
+ Arg = E->getArg(TblPos);
+ llvm::Type *TblTy = CGF.ConvertType(Arg->getType());
+ llvm::VectorType *VTblTy = cast<llvm::VectorType>(TblTy);
+ llvm::Type *Tys[2] = { Ty, VTblTy };
+ unsigned nElts = VTy->getNumElements();
+
+ // AArch64 scalar builtins are not overloaded, they do not have an extra
+ // argument that specifies the vector type, need to handle each case.
+ SmallVector<Value *, 2> TblOps;
+ switch (BuiltinID) {
+ case AArch64::BI__builtin_neon_vtbl1_v: {
+ TblOps.push_back(Ops[0]);
+ return packTBLDVectorList(CGF, TblOps, 0, Ops[1], Ty,
+ Intrinsic::aarch64_neon_vtbl1, "vtbl1");
+ }
+ case AArch64::BI__builtin_neon_vtbl2_v: {
+ TblOps.push_back(Ops[0]);
+ TblOps.push_back(Ops[1]);
+ return packTBLDVectorList(CGF, TblOps, 0, Ops[2], Ty,
+ Intrinsic::aarch64_neon_vtbl1, "vtbl1");
+ }
+ case AArch64::BI__builtin_neon_vtbl3_v: {
+ TblOps.push_back(Ops[0]);
+ TblOps.push_back(Ops[1]);
+ TblOps.push_back(Ops[2]);
+ return packTBLDVectorList(CGF, TblOps, 0, Ops[3], Ty,
+ Intrinsic::aarch64_neon_vtbl2, "vtbl2");
+ }
+ case AArch64::BI__builtin_neon_vtbl4_v: {
+ TblOps.push_back(Ops[0]);
+ TblOps.push_back(Ops[1]);
+ TblOps.push_back(Ops[2]);
+ TblOps.push_back(Ops[3]);
+ return packTBLDVectorList(CGF, TblOps, 0, Ops[4], Ty,
+ Intrinsic::aarch64_neon_vtbl2, "vtbl2");
+ }
+ case AArch64::BI__builtin_neon_vtbx1_v: {
+ TblOps.push_back(Ops[1]);
+ Value *TblRes = packTBLDVectorList(CGF, TblOps, 0, Ops[2], Ty,
+ Intrinsic::aarch64_neon_vtbl1, "vtbl1");
+
+ llvm::Constant *Eight = ConstantInt::get(VTy->getElementType(), 8);
+ Value* EightV = llvm::ConstantVector::getSplat(nElts, Eight);
+ Value *CmpRes = CGF.Builder.CreateICmp(ICmpInst::ICMP_UGE, Ops[2], EightV);
+ CmpRes = CGF.Builder.CreateSExt(CmpRes, Ty);
+
+ SmallVector<Value *, 4> BslOps;
+ BslOps.push_back(CmpRes);
+ BslOps.push_back(Ops[0]);
+ BslOps.push_back(TblRes);
+ Function *BslF = CGF.CGM.getIntrinsic(Intrinsic::arm_neon_vbsl, Ty);
+ return CGF.EmitNeonCall(BslF, BslOps, "vbsl");
+ }
+ case AArch64::BI__builtin_neon_vtbx2_v: {
+ TblOps.push_back(Ops[1]);
+ TblOps.push_back(Ops[2]);
+ return packTBLDVectorList(CGF, TblOps, Ops[0], Ops[3], Ty,
+ Intrinsic::aarch64_neon_vtbx1, "vtbx1");
+ }
+ case AArch64::BI__builtin_neon_vtbx3_v: {
+ TblOps.push_back(Ops[1]);
+ TblOps.push_back(Ops[2]);
+ TblOps.push_back(Ops[3]);
+ Value *TblRes = packTBLDVectorList(CGF, TblOps, 0, Ops[4], Ty,
+ Intrinsic::aarch64_neon_vtbl2, "vtbl2");
+
+ llvm::Constant *TwentyFour = ConstantInt::get(VTy->getElementType(), 24);
+ Value* TwentyFourV = llvm::ConstantVector::getSplat(nElts, TwentyFour);
+ Value *CmpRes = CGF.Builder.CreateICmp(ICmpInst::ICMP_UGE, Ops[4],
+ TwentyFourV);
+ CmpRes = CGF.Builder.CreateSExt(CmpRes, Ty);
+
+ SmallVector<Value *, 4> BslOps;
+ BslOps.push_back(CmpRes);
+ BslOps.push_back(Ops[0]);
+ BslOps.push_back(TblRes);
+ Function *BslF = CGF.CGM.getIntrinsic(Intrinsic::arm_neon_vbsl, Ty);
+ return CGF.EmitNeonCall(BslF, BslOps, "vbsl");
+ }
+ case AArch64::BI__builtin_neon_vtbx4_v: {
+ TblOps.push_back(Ops[1]);
+ TblOps.push_back(Ops[2]);
+ TblOps.push_back(Ops[3]);
+ TblOps.push_back(Ops[4]);
+ return packTBLDVectorList(CGF, TblOps, Ops[0], Ops[5], Ty,
+ Intrinsic::aarch64_neon_vtbx2, "vtbx2");
+ }
+ case AArch64::BI__builtin_neon_vqtbl1_v:
+ case AArch64::BI__builtin_neon_vqtbl1q_v:
+ Int = Intrinsic::aarch64_neon_vtbl1; s = "vtbl1"; break;
+ case AArch64::BI__builtin_neon_vqtbl2_v:
+ case AArch64::BI__builtin_neon_vqtbl2q_v: {
+ Int = Intrinsic::aarch64_neon_vtbl2; s = "vtbl2"; break;
+ case AArch64::BI__builtin_neon_vqtbl3_v:
+ case AArch64::BI__builtin_neon_vqtbl3q_v:
+ Int = Intrinsic::aarch64_neon_vtbl3; s = "vtbl3"; break;
+ case AArch64::BI__builtin_neon_vqtbl4_v:
+ case AArch64::BI__builtin_neon_vqtbl4q_v:
+ Int = Intrinsic::aarch64_neon_vtbl4; s = "vtbl4"; break;
+ case AArch64::BI__builtin_neon_vqtbx1_v:
+ case AArch64::BI__builtin_neon_vqtbx1q_v:
+ Int = Intrinsic::aarch64_neon_vtbx1; s = "vtbx1"; break;
+ case AArch64::BI__builtin_neon_vqtbx2_v:
+ case AArch64::BI__builtin_neon_vqtbx2q_v:
+ Int = Intrinsic::aarch64_neon_vtbx2; s = "vtbx2"; break;
+ case AArch64::BI__builtin_neon_vqtbx3_v:
+ case AArch64::BI__builtin_neon_vqtbx3q_v:
+ Int = Intrinsic::aarch64_neon_vtbx3; s = "vtbx3"; break;
+ case AArch64::BI__builtin_neon_vqtbx4_v:
+ case AArch64::BI__builtin_neon_vqtbx4q_v:
+ Int = Intrinsic::aarch64_neon_vtbx4; s = "vtbx4"; break;
+ }
+ }
+
+ if (!Int)
+ return 0;
+
+ Function *F = CGF.CGM.getIntrinsic(Int, Tys);
+ return CGF.EmitNeonCall(F, Ops, s);
+}
+
Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
const CallExpr *E) {
+ // Process AArch64 scalar builtins
+ if (Value *Result = EmitAArch64ScalarBuiltinExpr(*this, BuiltinID, E))
+ return Result;
+
+ // Process AArch64 table lookup builtins
+ if (Value *Result = EmitAArch64TblBuiltinExpr(*this, BuiltinID, E))
+ return Result;
+
if (BuiltinID == AArch64::BI__clear_cache) {
assert(E->getNumArgs() == 2 &&
"Variadic __clear_cache slipped through on AArch64");
@@ -1639,17 +2897,1039 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
return EmitNounwindRuntimeCall(CGM.CreateRuntimeFunction(FTy, Name), Ops);
}
- return 0;
+ SmallVector<Value *, 4> Ops;
+ llvm::Value *Align = 0; // Alignment for load/store
+ for (unsigned i = 0, e = E->getNumArgs() - 1; i != e; i++) {
+ if (i == 0) {
+ switch (BuiltinID) {
+ case AArch64::BI__builtin_neon_vst1_x2_v:
+ case AArch64::BI__builtin_neon_vst1q_x2_v:
+ case AArch64::BI__builtin_neon_vst1_x3_v:
+ case AArch64::BI__builtin_neon_vst1q_x3_v:
+ case AArch64::BI__builtin_neon_vst1_x4_v:
+ case AArch64::BI__builtin_neon_vst1q_x4_v:
+ // Handle ld1/st1 lane in this function a little different from ARM.
+ case AArch64::BI__builtin_neon_vld1_lane_v:
+ case AArch64::BI__builtin_neon_vld1q_lane_v:
+ case AArch64::BI__builtin_neon_vst1_lane_v:
+ case AArch64::BI__builtin_neon_vst1q_lane_v:
+ // Get the alignment for the argument in addition to the value;
+ // we'll use it later.
+ std::pair<llvm::Value *, unsigned> Src =
+ EmitPointerWithAlignment(E->getArg(0));
+ Ops.push_back(Src.first);
+ Align = Builder.getInt32(Src.second);
+ continue;
+ }
+ }
+ if (i == 1) {
+ switch (BuiltinID) {
+ case AArch64::BI__builtin_neon_vld1_x2_v:
+ case AArch64::BI__builtin_neon_vld1q_x2_v:
+ case AArch64::BI__builtin_neon_vld1_x3_v:
+ case AArch64::BI__builtin_neon_vld1q_x3_v:
+ case AArch64::BI__builtin_neon_vld1_x4_v:
+ case AArch64::BI__builtin_neon_vld1q_x4_v:
+ // Handle ld1/st1 dup lane in this function a little different from ARM.
+ case AArch64::BI__builtin_neon_vld2_dup_v:
+ case AArch64::BI__builtin_neon_vld2q_dup_v:
+ case AArch64::BI__builtin_neon_vld3_dup_v:
+ case AArch64::BI__builtin_neon_vld3q_dup_v:
+ case AArch64::BI__builtin_neon_vld4_dup_v:
+ case AArch64::BI__builtin_neon_vld4q_dup_v:
+ case AArch64::BI__builtin_neon_vld2_lane_v:
+ case AArch64::BI__builtin_neon_vld2q_lane_v:
+ // Get the alignment for the argument in addition to the value;
+ // we'll use it later.
+ std::pair<llvm::Value *, unsigned> Src =
+ EmitPointerWithAlignment(E->getArg(1));
+ Ops.push_back(Src.first);
+ Align = Builder.getInt32(Src.second);
+ continue;
+ }
+ }
+ Ops.push_back(EmitScalarExpr(E->getArg(i)));
+ }
+
+ // Get the last argument, which specifies the vector type.
+ llvm::APSInt Result;
+ const Expr *Arg = E->getArg(E->getNumArgs() - 1);
+ if (!Arg->isIntegerConstantExpr(Result, getContext()))
+ return 0;
+
+ // Determine the type of this overloaded NEON intrinsic.
+ NeonTypeFlags Type(Result.getZExtValue());
+ bool usgn = Type.isUnsigned();
+ bool quad = Type.isQuad();
+
+ llvm::VectorType *VTy = GetNeonType(this, Type);
+ llvm::Type *Ty = VTy;
+ if (!Ty)
+ return 0;
+
+ unsigned Int;
+ switch (BuiltinID) {
+ default:
+ return 0;
+
+ // AArch64 builtins mapping to legacy ARM v7 builtins.
+ // FIXME: the mapped builtins listed correspond to what has been tested
+ // in aarch64-neon-intrinsics.c so far.
+ case AArch64::BI__builtin_neon_vuzp_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vuzp_v, E);
+ case AArch64::BI__builtin_neon_vuzpq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vuzpq_v, E);
+ case AArch64::BI__builtin_neon_vzip_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vzip_v, E);
+ case AArch64::BI__builtin_neon_vzipq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vzipq_v, E);
+ case AArch64::BI__builtin_neon_vtrn_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vtrn_v, E);
+ case AArch64::BI__builtin_neon_vtrnq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vtrnq_v, E);
+ case AArch64::BI__builtin_neon_vext_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vext_v, E);
+ case AArch64::BI__builtin_neon_vextq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vextq_v, E);
+ case AArch64::BI__builtin_neon_vmul_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vmul_v, E);
+ case AArch64::BI__builtin_neon_vmulq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vmulq_v, E);
+ case AArch64::BI__builtin_neon_vabd_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vabd_v, E);
+ case AArch64::BI__builtin_neon_vabdq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vabdq_v, E);
+ case AArch64::BI__builtin_neon_vfma_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vfma_v, E);
+ case AArch64::BI__builtin_neon_vfmaq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vfmaq_v, E);
+ case AArch64::BI__builtin_neon_vbsl_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vbsl_v, E);
+ case AArch64::BI__builtin_neon_vbslq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vbslq_v, E);
+ case AArch64::BI__builtin_neon_vrsqrts_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vrsqrts_v, E);
+ case AArch64::BI__builtin_neon_vrsqrtsq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vrsqrtsq_v, E);
+ case AArch64::BI__builtin_neon_vrecps_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vrecps_v, E);
+ case AArch64::BI__builtin_neon_vrecpsq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vrecpsq_v, E);
+ case AArch64::BI__builtin_neon_vcale_v:
+ if (VTy->getVectorNumElements() == 1) {
+ std::swap(Ops[0], Ops[1]);
+ } else {
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcale_v, E);
+ }
+ case AArch64::BI__builtin_neon_vcage_v:
+ if (VTy->getVectorNumElements() == 1) {
+ // Determine the types of this overloaded AArch64 intrinsic
+ SmallVector<llvm::Type *, 3> Tys;
+ Tys.push_back(VTy);
+ VTy = llvm::VectorType::get(DoubleTy, 1);
+ Tys.push_back(VTy);
+ Tys.push_back(VTy);
+ Function *F = CGM.getIntrinsic(Intrinsic::aarch64_neon_vcage, Tys);
+ return EmitNeonCall(F, Ops, "vcage");
+ }
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcage_v, E);
+ case AArch64::BI__builtin_neon_vcaleq_v:
+ std::swap(Ops[0], Ops[1]);
+ case AArch64::BI__builtin_neon_vcageq_v: {
+ Function *F;
+ if (VTy->getElementType()->isIntegerTy(64))
+ F = CGM.getIntrinsic(Intrinsic::aarch64_neon_vacgeq);
+ else
+ F = CGM.getIntrinsic(Intrinsic::arm_neon_vacgeq);
+ return EmitNeonCall(F, Ops, "vcage");
+ }
+ case AArch64::BI__builtin_neon_vcalt_v:
+ if (VTy->getVectorNumElements() == 1) {
+ std::swap(Ops[0], Ops[1]);
+ } else {
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcalt_v, E);
+ }
+ case AArch64::BI__builtin_neon_vcagt_v:
+ if (VTy->getVectorNumElements() == 1) {
+ // Determine the types of this overloaded AArch64 intrinsic
+ SmallVector<llvm::Type *, 3> Tys;
+ Tys.push_back(VTy);
+ VTy = llvm::VectorType::get(DoubleTy, 1);
+ Tys.push_back(VTy);
+ Tys.push_back(VTy);
+ Function *F = CGM.getIntrinsic(Intrinsic::aarch64_neon_vcagt, Tys);
+ return EmitNeonCall(F, Ops, "vcagt");
+ }
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcagt_v, E);
+ case AArch64::BI__builtin_neon_vcaltq_v:
+ std::swap(Ops[0], Ops[1]);
+ case AArch64::BI__builtin_neon_vcagtq_v: {
+ Function *F;
+ if (VTy->getElementType()->isIntegerTy(64))
+ F = CGM.getIntrinsic(Intrinsic::aarch64_neon_vacgtq);
+ else
+ F = CGM.getIntrinsic(Intrinsic::arm_neon_vacgtq);
+ return EmitNeonCall(F, Ops, "vcagt");
+ }
+ case AArch64::BI__builtin_neon_vtst_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vtst_v, E);
+ case AArch64::BI__builtin_neon_vtstq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vtstq_v, E);
+ case AArch64::BI__builtin_neon_vhadd_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vhadd_v, E);
+ case AArch64::BI__builtin_neon_vhaddq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vhaddq_v, E);
+ case AArch64::BI__builtin_neon_vhsub_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vhsub_v, E);
+ case AArch64::BI__builtin_neon_vhsubq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vhsubq_v, E);
+ case AArch64::BI__builtin_neon_vrhadd_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vrhadd_v, E);
+ case AArch64::BI__builtin_neon_vrhaddq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vrhaddq_v, E);
+ case AArch64::BI__builtin_neon_vqadd_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqadd_v, E);
+ case AArch64::BI__builtin_neon_vqaddq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqaddq_v, E);
+ case AArch64::BI__builtin_neon_vqsub_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqsub_v, E);
+ case AArch64::BI__builtin_neon_vqsubq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqsubq_v, E);
+ case AArch64::BI__builtin_neon_vshl_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vshl_v, E);
+ case AArch64::BI__builtin_neon_vshlq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vshlq_v, E);
+ case AArch64::BI__builtin_neon_vqshl_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqshl_v, E);
+ case AArch64::BI__builtin_neon_vqshlq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqshlq_v, E);
+ case AArch64::BI__builtin_neon_vrshl_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vrshl_v, E);
+ case AArch64::BI__builtin_neon_vrshlq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vrshlq_v, E);
+ case AArch64::BI__builtin_neon_vqrshl_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqrshl_v, E);
+ case AArch64::BI__builtin_neon_vqrshlq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqrshlq_v, E);
+ case AArch64::BI__builtin_neon_vaddhn_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vaddhn_v, E);
+ case AArch64::BI__builtin_neon_vraddhn_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vraddhn_v, E);
+ case AArch64::BI__builtin_neon_vsubhn_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vsubhn_v, E);
+ case AArch64::BI__builtin_neon_vrsubhn_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vrsubhn_v, E);
+ case AArch64::BI__builtin_neon_vmull_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vmull_v, E);
+ case AArch64::BI__builtin_neon_vqdmull_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqdmull_v, E);
+ case AArch64::BI__builtin_neon_vqdmlal_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqdmlal_v, E);
+ case AArch64::BI__builtin_neon_vqdmlsl_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqdmlsl_v, E);
+ case AArch64::BI__builtin_neon_vmax_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vmax_v, E);
+ case AArch64::BI__builtin_neon_vmaxq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vmaxq_v, E);
+ case AArch64::BI__builtin_neon_vmin_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vmin_v, E);
+ case AArch64::BI__builtin_neon_vminq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vminq_v, E);
+ case AArch64::BI__builtin_neon_vpmax_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vpmax_v, E);
+ case AArch64::BI__builtin_neon_vpmin_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vpmin_v, E);
+ case AArch64::BI__builtin_neon_vpadd_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vpadd_v, E);
+ case AArch64::BI__builtin_neon_vqdmulh_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqdmulh_v, E);
+ case AArch64::BI__builtin_neon_vqdmulhq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqdmulhq_v, E);
+ case AArch64::BI__builtin_neon_vqrdmulh_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqrdmulh_v, E);
+ case AArch64::BI__builtin_neon_vqrdmulhq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqrdmulhq_v, E);
+
+ // Shift by immediate
+ case AArch64::BI__builtin_neon_vshr_n_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vshr_n_v, E);
+ case AArch64::BI__builtin_neon_vshrq_n_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vshrq_n_v, E);
+ case AArch64::BI__builtin_neon_vrshr_n_v:
+ case AArch64::BI__builtin_neon_vrshrq_n_v:
+ Int = usgn ? Intrinsic::aarch64_neon_vurshr
+ : Intrinsic::aarch64_neon_vsrshr;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrshr_n");
+ case AArch64::BI__builtin_neon_vsra_n_v:
+ if (VTy->getElementType()->isIntegerTy(64)) {
+ Int = usgn ? Intrinsic::aarch64_neon_vsradu_n
+ : Intrinsic::aarch64_neon_vsrads_n;
+ return EmitNeonCall(CGM.getIntrinsic(Int), Ops, "vsra_n");
+ }
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vsra_n_v, E);
+ case AArch64::BI__builtin_neon_vsraq_n_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vsraq_n_v, E);
+ case AArch64::BI__builtin_neon_vrsra_n_v:
+ if (VTy->getElementType()->isIntegerTy(64)) {
+ Int = usgn ? Intrinsic::aarch64_neon_vrsradu_n
+ : Intrinsic::aarch64_neon_vrsrads_n;
+ return EmitNeonCall(CGM.getIntrinsic(Int), Ops, "vrsra_n");
+ }
+ // fall through
+ case AArch64::BI__builtin_neon_vrsraq_n_v: {
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
+ Int = usgn ? Intrinsic::aarch64_neon_vurshr
+ : Intrinsic::aarch64_neon_vsrshr;
+ Ops[1] = Builder.CreateCall2(CGM.getIntrinsic(Int, Ty), Ops[1], Ops[2]);
+ return Builder.CreateAdd(Ops[0], Ops[1], "vrsra_n");
+ }
+ case AArch64::BI__builtin_neon_vshl_n_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vshl_n_v, E);
+ case AArch64::BI__builtin_neon_vshlq_n_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vshlq_n_v, E);
+ case AArch64::BI__builtin_neon_vqshl_n_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqshl_n_v, E);
+ case AArch64::BI__builtin_neon_vqshlq_n_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqshlq_n_v, E);
+ case AArch64::BI__builtin_neon_vqshlu_n_v:
+ case AArch64::BI__builtin_neon_vqshluq_n_v:
+ Int = Intrinsic::aarch64_neon_vsqshlu;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqshlu_n");
+ case AArch64::BI__builtin_neon_vsri_n_v:
+ case AArch64::BI__builtin_neon_vsriq_n_v:
+ Int = Intrinsic::aarch64_neon_vsri;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vsri_n");
+ case AArch64::BI__builtin_neon_vsli_n_v:
+ case AArch64::BI__builtin_neon_vsliq_n_v:
+ Int = Intrinsic::aarch64_neon_vsli;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vsli_n");
+ case AArch64::BI__builtin_neon_vshll_n_v: {
+ llvm::Type *SrcTy = llvm::VectorType::getTruncatedElementVectorType(VTy);
+ Ops[0] = Builder.CreateBitCast(Ops[0], SrcTy);
+ if (usgn)
+ Ops[0] = Builder.CreateZExt(Ops[0], VTy);
+ else
+ Ops[0] = Builder.CreateSExt(Ops[0], VTy);
+ Ops[1] = EmitNeonShiftVector(Ops[1], VTy, false);
+ return Builder.CreateShl(Ops[0], Ops[1], "vshll_n");
+ }
+ case AArch64::BI__builtin_neon_vshrn_n_v: {
+ llvm::Type *SrcTy = llvm::VectorType::getExtendedElementVectorType(VTy);
+ Ops[0] = Builder.CreateBitCast(Ops[0], SrcTy);
+ Ops[1] = EmitNeonShiftVector(Ops[1], SrcTy, false);
+ if (usgn)
+ Ops[0] = Builder.CreateLShr(Ops[0], Ops[1]);
+ else
+ Ops[0] = Builder.CreateAShr(Ops[0], Ops[1]);
+ return Builder.CreateTrunc(Ops[0], Ty, "vshrn_n");
+ }
+ case AArch64::BI__builtin_neon_vqshrun_n_v:
+ Int = Intrinsic::aarch64_neon_vsqshrun;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqshrun_n");
+ case AArch64::BI__builtin_neon_vrshrn_n_v:
+ Int = Intrinsic::aarch64_neon_vrshrn;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrshrn_n");
+ case AArch64::BI__builtin_neon_vqrshrun_n_v:
+ Int = Intrinsic::aarch64_neon_vsqrshrun;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqrshrun_n");
+ case AArch64::BI__builtin_neon_vqshrn_n_v:
+ Int = usgn ? Intrinsic::aarch64_neon_vuqshrn
+ : Intrinsic::aarch64_neon_vsqshrn;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqshrn_n");
+ case AArch64::BI__builtin_neon_vqrshrn_n_v:
+ Int = usgn ? Intrinsic::aarch64_neon_vuqrshrn
+ : Intrinsic::aarch64_neon_vsqrshrn;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqrshrn_n");
+
+ // Convert
+ case AArch64::BI__builtin_neon_vmovl_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vmovl_v, E);
+ case AArch64::BI__builtin_neon_vcvt_n_f32_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcvt_n_f32_v, E);
+ case AArch64::BI__builtin_neon_vcvtq_n_f32_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcvtq_n_f32_v, E);
+ case AArch64::BI__builtin_neon_vcvt_n_f64_v:
+ case AArch64::BI__builtin_neon_vcvtq_n_f64_v: {
+ llvm::Type *FloatTy =
+ GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float64, false, quad));
+ llvm::Type *Tys[2] = { FloatTy, Ty };
+ Int = usgn ? Intrinsic::arm_neon_vcvtfxu2fp
+ : Intrinsic::arm_neon_vcvtfxs2fp;
+ Function *F = CGM.getIntrinsic(Int, Tys);
+ return EmitNeonCall(F, Ops, "vcvt_n");
+ }
+ case AArch64::BI__builtin_neon_vcvt_n_s32_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcvt_n_s32_v, E);
+ case AArch64::BI__builtin_neon_vcvtq_n_s32_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcvtq_n_s32_v, E);
+ case AArch64::BI__builtin_neon_vcvt_n_u32_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcvt_n_u32_v, E);
+ case AArch64::BI__builtin_neon_vcvtq_n_u32_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcvtq_n_u32_v, E);
+ case AArch64::BI__builtin_neon_vcvt_n_s64_v:
+ case AArch64::BI__builtin_neon_vcvt_n_u64_v:
+ case AArch64::BI__builtin_neon_vcvtq_n_s64_v:
+ case AArch64::BI__builtin_neon_vcvtq_n_u64_v: {
+ llvm::Type *FloatTy =
+ GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float64, false, quad));
+ llvm::Type *Tys[2] = { Ty, FloatTy };
+ Int = usgn ? Intrinsic::arm_neon_vcvtfp2fxu
+ : Intrinsic::arm_neon_vcvtfp2fxs;
+ Function *F = CGM.getIntrinsic(Int, Tys);
+ return EmitNeonCall(F, Ops, "vcvt_n");
+ }
+
+ // Load/Store
+ case AArch64::BI__builtin_neon_vld1_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld1_v, E);
+ case AArch64::BI__builtin_neon_vld1q_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld1q_v, E);
+ case AArch64::BI__builtin_neon_vld2_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld2_v, E);
+ case AArch64::BI__builtin_neon_vld2q_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld2q_v, E);
+ case AArch64::BI__builtin_neon_vld3_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld3_v, E);
+ case AArch64::BI__builtin_neon_vld3q_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld3q_v, E);
+ case AArch64::BI__builtin_neon_vld4_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld4_v, E);
+ case AArch64::BI__builtin_neon_vld4q_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld4q_v, E);
+ case AArch64::BI__builtin_neon_vst1_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vst1_v, E);
+ case AArch64::BI__builtin_neon_vst1q_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vst1q_v, E);
+ case AArch64::BI__builtin_neon_vst2_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vst2_v, E);
+ case AArch64::BI__builtin_neon_vst2q_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vst2q_v, E);
+ case AArch64::BI__builtin_neon_vst3_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vst3_v, E);
+ case AArch64::BI__builtin_neon_vst3q_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vst3q_v, E);
+ case AArch64::BI__builtin_neon_vst4_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vst4_v, E);
+ case AArch64::BI__builtin_neon_vst4q_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vst4q_v, E);
+ case AArch64::BI__builtin_neon_vld1_x2_v:
+ case AArch64::BI__builtin_neon_vld1q_x2_v:
+ case AArch64::BI__builtin_neon_vld1_x3_v:
+ case AArch64::BI__builtin_neon_vld1q_x3_v:
+ case AArch64::BI__builtin_neon_vld1_x4_v:
+ case AArch64::BI__builtin_neon_vld1q_x4_v: {
+ unsigned Int;
+ switch (BuiltinID) {
+ case AArch64::BI__builtin_neon_vld1_x2_v:
+ case AArch64::BI__builtin_neon_vld1q_x2_v:
+ Int = Intrinsic::aarch64_neon_vld1x2;
+ break;
+ case AArch64::BI__builtin_neon_vld1_x3_v:
+ case AArch64::BI__builtin_neon_vld1q_x3_v:
+ Int = Intrinsic::aarch64_neon_vld1x3;
+ break;
+ case AArch64::BI__builtin_neon_vld1_x4_v:
+ case AArch64::BI__builtin_neon_vld1q_x4_v:
+ Int = Intrinsic::aarch64_neon_vld1x4;
+ break;
+ }
+ Function *F = CGM.getIntrinsic(Int, Ty);
+ Ops[1] = Builder.CreateCall2(F, Ops[1], Align, "vld1xN");
+ Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ return Builder.CreateStore(Ops[1], Ops[0]);
+ }
+ case AArch64::BI__builtin_neon_vst1_x2_v:
+ case AArch64::BI__builtin_neon_vst1q_x2_v:
+ case AArch64::BI__builtin_neon_vst1_x3_v:
+ case AArch64::BI__builtin_neon_vst1q_x3_v:
+ case AArch64::BI__builtin_neon_vst1_x4_v:
+ case AArch64::BI__builtin_neon_vst1q_x4_v: {
+ Ops.push_back(Align);
+ unsigned Int;
+ switch (BuiltinID) {
+ case AArch64::BI__builtin_neon_vst1_x2_v:
+ case AArch64::BI__builtin_neon_vst1q_x2_v:
+ Int = Intrinsic::aarch64_neon_vst1x2;
+ break;
+ case AArch64::BI__builtin_neon_vst1_x3_v:
+ case AArch64::BI__builtin_neon_vst1q_x3_v:
+ Int = Intrinsic::aarch64_neon_vst1x3;
+ break;
+ case AArch64::BI__builtin_neon_vst1_x4_v:
+ case AArch64::BI__builtin_neon_vst1q_x4_v:
+ Int = Intrinsic::aarch64_neon_vst1x4;
+ break;
+ }
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "");
+ }
+ case AArch64::BI__builtin_neon_vld1_lane_v:
+ case AArch64::BI__builtin_neon_vld1q_lane_v: {
+ Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
+ Ty = llvm::PointerType::getUnqual(VTy->getElementType());
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ LoadInst *Ld = Builder.CreateLoad(Ops[0]);
+ Ld->setAlignment(cast<ConstantInt>(Align)->getZExtValue());
+ return Builder.CreateInsertElement(Ops[1], Ld, Ops[2], "vld1_lane");
+ }
+ case AArch64::BI__builtin_neon_vld2_lane_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld2q_lane_v, E);
+ case AArch64::BI__builtin_neon_vld2q_lane_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld2q_lane_v, E);
+ case AArch64::BI__builtin_neon_vld3_lane_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld3_lane_v, E);
+ case AArch64::BI__builtin_neon_vld3q_lane_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld3q_lane_v, E);
+ case AArch64::BI__builtin_neon_vld4_lane_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld4_lane_v, E);
+ case AArch64::BI__builtin_neon_vld4q_lane_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld4q_lane_v, E);
+ case AArch64::BI__builtin_neon_vst1_lane_v:
+ case AArch64::BI__builtin_neon_vst1q_lane_v: {
+ Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
+ Ops[1] = Builder.CreateExtractElement(Ops[1], Ops[2]);
+ Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
+ StoreInst *St =
+ Builder.CreateStore(Ops[1], Builder.CreateBitCast(Ops[0], Ty));
+ St->setAlignment(cast<ConstantInt>(Align)->getZExtValue());
+ return St;
+ }
+ case AArch64::BI__builtin_neon_vst2_lane_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vst2_lane_v, E);
+ case AArch64::BI__builtin_neon_vst2q_lane_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vst2q_lane_v, E);
+ case AArch64::BI__builtin_neon_vst3_lane_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vst3_lane_v, E);
+ case AArch64::BI__builtin_neon_vst3q_lane_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vst3q_lane_v, E);
+ case AArch64::BI__builtin_neon_vst4_lane_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vst4_lane_v, E);
+ case AArch64::BI__builtin_neon_vst4q_lane_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vst4q_lane_v, E);
+ case AArch64::BI__builtin_neon_vld1_dup_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld1_dup_v, E);
+ case AArch64::BI__builtin_neon_vld1q_dup_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vld1q_dup_v, E);
+ case AArch64::BI__builtin_neon_vld2_dup_v:
+ case AArch64::BI__builtin_neon_vld2q_dup_v:
+ case AArch64::BI__builtin_neon_vld3_dup_v:
+ case AArch64::BI__builtin_neon_vld3q_dup_v:
+ case AArch64::BI__builtin_neon_vld4_dup_v:
+ case AArch64::BI__builtin_neon_vld4q_dup_v: {
+ // Handle 64-bit x 1 elements as a special-case. There is no "dup" needed.
+ if (VTy->getElementType()->getPrimitiveSizeInBits() == 64 &&
+ VTy->getNumElements() == 1) {
+ switch (BuiltinID) {
+ case AArch64::BI__builtin_neon_vld2_dup_v:
+ Int = Intrinsic::arm_neon_vld2;
+ break;
+ case AArch64::BI__builtin_neon_vld3_dup_v:
+ Int = Intrinsic::arm_neon_vld3;
+ break;
+ case AArch64::BI__builtin_neon_vld4_dup_v:
+ Int = Intrinsic::arm_neon_vld4;
+ break;
+ default:
+ llvm_unreachable("unknown vld_dup intrinsic?");
+ }
+ Function *F = CGM.getIntrinsic(Int, Ty);
+ Ops[1] = Builder.CreateCall2(F, Ops[1], Align, "vld_dup");
+ Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ return Builder.CreateStore(Ops[1], Ops[0]);
+ }
+ switch (BuiltinID) {
+ case AArch64::BI__builtin_neon_vld2_dup_v:
+ case AArch64::BI__builtin_neon_vld2q_dup_v:
+ Int = Intrinsic::arm_neon_vld2lane;
+ break;
+ case AArch64::BI__builtin_neon_vld3_dup_v:
+ case AArch64::BI__builtin_neon_vld3q_dup_v:
+ Int = Intrinsic::arm_neon_vld3lane;
+ break;
+ case AArch64::BI__builtin_neon_vld4_dup_v:
+ case AArch64::BI__builtin_neon_vld4q_dup_v:
+ Int = Intrinsic::arm_neon_vld4lane;
+ break;
+ }
+ Function *F = CGM.getIntrinsic(Int, Ty);
+ llvm::StructType *STy = cast<llvm::StructType>(F->getReturnType());
+
+ SmallVector<Value *, 6> Args;
+ Args.push_back(Ops[1]);
+ Args.append(STy->getNumElements(), UndefValue::get(Ty));
+
+ llvm::Constant *CI = ConstantInt::get(Int32Ty, 0);
+ Args.push_back(CI);
+ Args.push_back(Align);
+
+ Ops[1] = Builder.CreateCall(F, Args, "vld_dup");
+ // splat lane 0 to all elts in each vector of the result.
+ for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
+ Value *Val = Builder.CreateExtractValue(Ops[1], i);
+ Value *Elt = Builder.CreateBitCast(Val, Ty);
+ Elt = EmitNeonSplat(Elt, CI);
+ Elt = Builder.CreateBitCast(Elt, Val->getType());
+ Ops[1] = Builder.CreateInsertValue(Ops[1], Elt, i);
+ }
+ Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ return Builder.CreateStore(Ops[1], Ops[0]);
+ }
+
+ // Crypto
+ case AArch64::BI__builtin_neon_vaeseq_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_aese, Ty),
+ Ops, "aese");
+ case AArch64::BI__builtin_neon_vaesdq_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_aesd, Ty),
+ Ops, "aesd");
+ case AArch64::BI__builtin_neon_vaesmcq_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_aesmc, Ty),
+ Ops, "aesmc");
+ case AArch64::BI__builtin_neon_vaesimcq_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_aesimc, Ty),
+ Ops, "aesimc");
+ case AArch64::BI__builtin_neon_vsha1su1q_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_sha1su1, Ty),
+ Ops, "sha1su1");
+ case AArch64::BI__builtin_neon_vsha256su0q_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_sha256su0, Ty),
+ Ops, "sha256su0");
+ case AArch64::BI__builtin_neon_vsha1su0q_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_sha1su0, Ty),
+ Ops, "sha1su0");
+ case AArch64::BI__builtin_neon_vsha256hq_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_sha256h, Ty),
+ Ops, "sha256h");
+ case AArch64::BI__builtin_neon_vsha256h2q_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_sha256h2, Ty),
+ Ops, "sha256h2");
+ case AArch64::BI__builtin_neon_vsha256su1q_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_sha256su1, Ty),
+ Ops, "sha256su1");
+ case AArch64::BI__builtin_neon_vmul_lane_v:
+ case AArch64::BI__builtin_neon_vmul_laneq_v: {
+ // v1f64 vmul_lane should be mapped to Neon scalar mul lane
+ bool Quad = false;
+ if (BuiltinID == AArch64::BI__builtin_neon_vmul_laneq_v)
+ Quad = true;
+ Ops[0] = Builder.CreateBitCast(Ops[0], DoubleTy);
+ llvm::Type *VTy = GetNeonType(this,
+ NeonTypeFlags(NeonTypeFlags::Float64, false, Quad));
+ Ops[1] = Builder.CreateBitCast(Ops[1], VTy);
+ Ops[1] = Builder.CreateExtractElement(Ops[1], Ops[2], "extract");
+ Value *Result = Builder.CreateFMul(Ops[0], Ops[1]);
+ return Builder.CreateBitCast(Result, Ty);
+ }
+
+ // AArch64-only builtins
+ case AArch64::BI__builtin_neon_vfmaq_laneq_v: {
+ Value *F = CGM.getIntrinsic(Intrinsic::fma, Ty);
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
+
+ Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
+ Ops[2] = EmitNeonSplat(Ops[2], cast<ConstantInt>(Ops[3]));
+ return Builder.CreateCall3(F, Ops[2], Ops[1], Ops[0]);
+ }
+ case AArch64::BI__builtin_neon_vfmaq_lane_v: {
+ Value *F = CGM.getIntrinsic(Intrinsic::fma, Ty);
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
+
+ llvm::VectorType *VTy = cast<llvm::VectorType>(Ty);
+ llvm::Type *STy = llvm::VectorType::get(VTy->getElementType(),
+ VTy->getNumElements() / 2);
+ Ops[2] = Builder.CreateBitCast(Ops[2], STy);
+ Value* SV = llvm::ConstantVector::getSplat(VTy->getNumElements(),
+ cast<ConstantInt>(Ops[3]));
+ Ops[2] = Builder.CreateShuffleVector(Ops[2], Ops[2], SV, "lane");
+
+ return Builder.CreateCall3(F, Ops[2], Ops[1], Ops[0]);
+ }
+ case AArch64::BI__builtin_neon_vfma_lane_v: {
+ llvm::VectorType *VTy = cast<llvm::VectorType>(Ty);
+ // v1f64 fma should be mapped to Neon scalar f64 fma
+ if (VTy && VTy->getElementType() == DoubleTy) {
+ Ops[0] = Builder.CreateBitCast(Ops[0], DoubleTy);
+ Ops[1] = Builder.CreateBitCast(Ops[1], DoubleTy);
+ llvm::Type *VTy = GetNeonType(this,
+ NeonTypeFlags(NeonTypeFlags::Float64, false, false));
+ Ops[2] = Builder.CreateBitCast(Ops[2], VTy);
+ Ops[2] = Builder.CreateExtractElement(Ops[2], Ops[3], "extract");
+ Value *F = CGM.getIntrinsic(Intrinsic::fma, DoubleTy);
+ Value *Result = Builder.CreateCall3(F, Ops[1], Ops[2], Ops[0]);
+ return Builder.CreateBitCast(Result, Ty);
+ }
+ Value *F = CGM.getIntrinsic(Intrinsic::fma, Ty);
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
+
+ Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
+ Ops[2] = EmitNeonSplat(Ops[2], cast<ConstantInt>(Ops[3]));
+ return Builder.CreateCall3(F, Ops[2], Ops[1], Ops[0]);
+ }
+ case AArch64::BI__builtin_neon_vfma_laneq_v: {
+ llvm::VectorType *VTy = cast<llvm::VectorType>(Ty);
+ // v1f64 fma should be mapped to Neon scalar f64 fma
+ if (VTy && VTy->getElementType() == DoubleTy) {
+ Ops[0] = Builder.CreateBitCast(Ops[0], DoubleTy);
+ Ops[1] = Builder.CreateBitCast(Ops[1], DoubleTy);
+ llvm::Type *VTy = GetNeonType(this,
+ NeonTypeFlags(NeonTypeFlags::Float64, false, true));
+ Ops[2] = Builder.CreateBitCast(Ops[2], VTy);
+ Ops[2] = Builder.CreateExtractElement(Ops[2], Ops[3], "extract");
+ Value *F = CGM.getIntrinsic(Intrinsic::fma, DoubleTy);
+ Value *Result = Builder.CreateCall3(F, Ops[1], Ops[2], Ops[0]);
+ return Builder.CreateBitCast(Result, Ty);
+ }
+ Value *F = CGM.getIntrinsic(Intrinsic::fma, Ty);
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
+
+ llvm::Type *STy = llvm::VectorType::get(VTy->getElementType(),
+ VTy->getNumElements() * 2);
+ Ops[2] = Builder.CreateBitCast(Ops[2], STy);
+ Value* SV = llvm::ConstantVector::getSplat(VTy->getNumElements(),
+ cast<ConstantInt>(Ops[3]));
+ Ops[2] = Builder.CreateShuffleVector(Ops[2], Ops[2], SV, "lane");
+
+ return Builder.CreateCall3(F, Ops[2], Ops[1], Ops[0]);
+ }
+ case AArch64::BI__builtin_neon_vfms_v:
+ case AArch64::BI__builtin_neon_vfmsq_v: {
+ Value *F = CGM.getIntrinsic(Intrinsic::fma, Ty);
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
+ Ops[1] = Builder.CreateFNeg(Ops[1]);
+ Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
+
+ // LLVM's fma intrinsic puts the accumulator in the last position, but the
+ // AArch64 intrinsic has it first.
+ return Builder.CreateCall3(F, Ops[1], Ops[2], Ops[0]);
+ }
+ case AArch64::BI__builtin_neon_vmaxnm_v:
+ case AArch64::BI__builtin_neon_vmaxnmq_v: {
+ Int = Intrinsic::aarch64_neon_vmaxnm;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmaxnm");
+ }
+ case AArch64::BI__builtin_neon_vminnm_v:
+ case AArch64::BI__builtin_neon_vminnmq_v: {
+ Int = Intrinsic::aarch64_neon_vminnm;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vminnm");
+ }
+ case AArch64::BI__builtin_neon_vpmaxnm_v:
+ case AArch64::BI__builtin_neon_vpmaxnmq_v: {
+ Int = Intrinsic::aarch64_neon_vpmaxnm;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vpmaxnm");
+ }
+ case AArch64::BI__builtin_neon_vpminnm_v:
+ case AArch64::BI__builtin_neon_vpminnmq_v: {
+ Int = Intrinsic::aarch64_neon_vpminnm;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vpminnm");
+ }
+ case AArch64::BI__builtin_neon_vpmaxq_v: {
+ Int = usgn ? Intrinsic::arm_neon_vpmaxu : Intrinsic::arm_neon_vpmaxs;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vpmax");
+ }
+ case AArch64::BI__builtin_neon_vpminq_v: {
+ Int = usgn ? Intrinsic::arm_neon_vpminu : Intrinsic::arm_neon_vpmins;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vpmin");
+ }
+ case AArch64::BI__builtin_neon_vpaddq_v: {
+ Int = Intrinsic::arm_neon_vpadd;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vpadd");
+ }
+ case AArch64::BI__builtin_neon_vmulx_v:
+ case AArch64::BI__builtin_neon_vmulxq_v: {
+ Int = Intrinsic::aarch64_neon_vmulx;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmulx");
+ }
+ case AArch64::BI__builtin_neon_vpaddl_v:
+ case AArch64::BI__builtin_neon_vpaddlq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vpaddl_v, E);
+ case AArch64::BI__builtin_neon_vpadal_v:
+ case AArch64::BI__builtin_neon_vpadalq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vpadal_v, E);
+ case AArch64::BI__builtin_neon_vqabs_v:
+ case AArch64::BI__builtin_neon_vqabsq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqabs_v, E);
+ case AArch64::BI__builtin_neon_vqneg_v:
+ case AArch64::BI__builtin_neon_vqnegq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqneg_v, E);
+ case AArch64::BI__builtin_neon_vabs_v:
+ case AArch64::BI__builtin_neon_vabsq_v: {
+ if (VTy->getElementType()->isFloatingPointTy()) {
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::fabs, Ty), Ops, "vabs");
+ }
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vabs_v, E);
+ }
+ case AArch64::BI__builtin_neon_vsqadd_v:
+ case AArch64::BI__builtin_neon_vsqaddq_v: {
+ Int = Intrinsic::aarch64_neon_usqadd;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vsqadd");
+ }
+ case AArch64::BI__builtin_neon_vuqadd_v:
+ case AArch64::BI__builtin_neon_vuqaddq_v: {
+ Int = Intrinsic::aarch64_neon_suqadd;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vuqadd");
+ }
+ case AArch64::BI__builtin_neon_vcls_v:
+ case AArch64::BI__builtin_neon_vclsq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcls_v, E);
+ case AArch64::BI__builtin_neon_vclz_v:
+ case AArch64::BI__builtin_neon_vclzq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vclz_v, E);
+ case AArch64::BI__builtin_neon_vcnt_v:
+ case AArch64::BI__builtin_neon_vcntq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcnt_v, E);
+ case AArch64::BI__builtin_neon_vrbit_v:
+ case AArch64::BI__builtin_neon_vrbitq_v:
+ Int = Intrinsic::aarch64_neon_rbit;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrbit");
+ case AArch64::BI__builtin_neon_vmovn_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vmovn_v, E);
+ case AArch64::BI__builtin_neon_vqmovun_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqmovun_v, E);
+ case AArch64::BI__builtin_neon_vqmovn_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vqmovn_v, E);
+ case AArch64::BI__builtin_neon_vcvt_f16_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcvt_f16_v, E);
+ case AArch64::BI__builtin_neon_vcvt_f32_f16:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcvt_f32_f16, E);
+ case AArch64::BI__builtin_neon_vcvt_f32_f64: {
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float32, false, false));
+ return Builder.CreateFPTrunc(Ops[0], Ty, "vcvt");
+ }
+ case AArch64::BI__builtin_neon_vcvtx_f32_v: {
+ llvm::Type *EltTy = FloatTy;
+ llvm::Type *ResTy = llvm::VectorType::get(EltTy, 2);
+ llvm::Type *Tys[2] = { ResTy, Ty };
+ Int = Intrinsic::aarch64_neon_fcvtxn;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtx_f32_f64");
+ }
+ case AArch64::BI__builtin_neon_vcvt_f64_f32: {
+ llvm::Type *OpTy =
+ GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float32, false, false));
+ Ops[0] = Builder.CreateBitCast(Ops[0], OpTy);
+ return Builder.CreateFPExt(Ops[0], Ty, "vcvt");
+ }
+ case AArch64::BI__builtin_neon_vcvt_f64_v:
+ case AArch64::BI__builtin_neon_vcvtq_f64_v: {
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ Ty = GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float64, false, quad));
+ return usgn ? Builder.CreateUIToFP(Ops[0], Ty, "vcvt")
+ : Builder.CreateSIToFP(Ops[0], Ty, "vcvt");
+ }
+ case AArch64::BI__builtin_neon_vrndn_v:
+ case AArch64::BI__builtin_neon_vrndnq_v: {
+ Int = Intrinsic::aarch64_neon_frintn;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndn");
+ }
+ case AArch64::BI__builtin_neon_vrnda_v:
+ case AArch64::BI__builtin_neon_vrndaq_v: {
+ Int = Intrinsic::round;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrnda");
+ }
+ case AArch64::BI__builtin_neon_vrndp_v:
+ case AArch64::BI__builtin_neon_vrndpq_v: {
+ Int = Intrinsic::ceil;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndp");
+ }
+ case AArch64::BI__builtin_neon_vrndm_v:
+ case AArch64::BI__builtin_neon_vrndmq_v: {
+ Int = Intrinsic::floor;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndm");
+ }
+ case AArch64::BI__builtin_neon_vrndx_v:
+ case AArch64::BI__builtin_neon_vrndxq_v: {
+ Int = Intrinsic::rint;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndx");
+ }
+ case AArch64::BI__builtin_neon_vrnd_v:
+ case AArch64::BI__builtin_neon_vrndq_v: {
+ Int = Intrinsic::trunc;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrnd");
+ }
+ case AArch64::BI__builtin_neon_vrndi_v:
+ case AArch64::BI__builtin_neon_vrndiq_v: {
+ Int = Intrinsic::nearbyint;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndi");
+ }
+ case AArch64::BI__builtin_neon_vcvt_s32_v:
+ case AArch64::BI__builtin_neon_vcvt_u32_v:
+ case AArch64::BI__builtin_neon_vcvtq_s32_v:
+ case AArch64::BI__builtin_neon_vcvtq_u32_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcvtq_u32_v, E);
+ case AArch64::BI__builtin_neon_vcvt_s64_v:
+ case AArch64::BI__builtin_neon_vcvt_u64_v:
+ case AArch64::BI__builtin_neon_vcvtq_s64_v:
+ case AArch64::BI__builtin_neon_vcvtq_u64_v: {
+ llvm::Type *DoubleTy =
+ GetNeonType(this, NeonTypeFlags(NeonTypeFlags::Float64, false, quad));
+ Ops[0] = Builder.CreateBitCast(Ops[0], DoubleTy);
+ return usgn ? Builder.CreateFPToUI(Ops[0], Ty, "vcvt")
+ : Builder.CreateFPToSI(Ops[0], Ty, "vcvt");
+ }
+ case AArch64::BI__builtin_neon_vcvtn_s32_v:
+ case AArch64::BI__builtin_neon_vcvtnq_s32_v: {
+ llvm::Type *OpTy = llvm::VectorType::get(FloatTy, VTy->getNumElements());
+ llvm::Type *Tys[2] = { Ty, OpTy };
+ Int = Intrinsic::aarch64_neon_fcvtns;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtns_f32");
+ }
+ case AArch64::BI__builtin_neon_vcvtn_s64_v:
+ case AArch64::BI__builtin_neon_vcvtnq_s64_v: {
+ llvm::Type *OpTy = llvm::VectorType::get(DoubleTy, VTy->getNumElements());
+ llvm::Type *Tys[2] = { Ty, OpTy };
+ Int = Intrinsic::aarch64_neon_fcvtns;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtns_f64");
+ }
+ case AArch64::BI__builtin_neon_vcvtn_u32_v:
+ case AArch64::BI__builtin_neon_vcvtnq_u32_v: {
+ llvm::Type *OpTy = llvm::VectorType::get(FloatTy, VTy->getNumElements());
+ llvm::Type *Tys[2] = { Ty, OpTy };
+ Int = Intrinsic::aarch64_neon_fcvtnu;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtnu_f32");
+ }
+ case AArch64::BI__builtin_neon_vcvtn_u64_v:
+ case AArch64::BI__builtin_neon_vcvtnq_u64_v: {
+ llvm::Type *OpTy = llvm::VectorType::get(DoubleTy, VTy->getNumElements());
+ llvm::Type *Tys[2] = { Ty, OpTy };
+ Int = Intrinsic::aarch64_neon_fcvtnu;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtnu_f64");
+ }
+ case AArch64::BI__builtin_neon_vcvtp_s32_v:
+ case AArch64::BI__builtin_neon_vcvtpq_s32_v: {
+ llvm::Type *OpTy = llvm::VectorType::get(FloatTy, VTy->getNumElements());
+ llvm::Type *Tys[2] = { Ty, OpTy };
+ Int = Intrinsic::aarch64_neon_fcvtps;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtps_f32");
+ }
+ case AArch64::BI__builtin_neon_vcvtp_s64_v:
+ case AArch64::BI__builtin_neon_vcvtpq_s64_v: {
+ llvm::Type *OpTy = llvm::VectorType::get(DoubleTy, VTy->getNumElements());
+ llvm::Type *Tys[2] = { Ty, OpTy };
+ Int = Intrinsic::aarch64_neon_fcvtps;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtps_f64");
+ }
+ case AArch64::BI__builtin_neon_vcvtp_u32_v:
+ case AArch64::BI__builtin_neon_vcvtpq_u32_v: {
+ llvm::Type *OpTy = llvm::VectorType::get(FloatTy, VTy->getNumElements());
+ llvm::Type *Tys[2] = { Ty, OpTy };
+ Int = Intrinsic::aarch64_neon_fcvtpu;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtpu_f32");
+ }
+ case AArch64::BI__builtin_neon_vcvtp_u64_v:
+ case AArch64::BI__builtin_neon_vcvtpq_u64_v: {
+ llvm::Type *OpTy = llvm::VectorType::get(DoubleTy, VTy->getNumElements());
+ llvm::Type *Tys[2] = { Ty, OpTy };
+ Int = Intrinsic::aarch64_neon_fcvtpu;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtpu_f64");
+ }
+ case AArch64::BI__builtin_neon_vcvtm_s32_v:
+ case AArch64::BI__builtin_neon_vcvtmq_s32_v: {
+ llvm::Type *OpTy = llvm::VectorType::get(FloatTy, VTy->getNumElements());
+ llvm::Type *Tys[2] = { Ty, OpTy };
+ Int = Intrinsic::aarch64_neon_fcvtms;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtms_f32");
+ }
+ case AArch64::BI__builtin_neon_vcvtm_s64_v:
+ case AArch64::BI__builtin_neon_vcvtmq_s64_v: {
+ llvm::Type *OpTy = llvm::VectorType::get(DoubleTy, VTy->getNumElements());
+ llvm::Type *Tys[2] = { Ty, OpTy };
+ Int = Intrinsic::aarch64_neon_fcvtms;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtms_f64");
+ }
+ case AArch64::BI__builtin_neon_vcvtm_u32_v:
+ case AArch64::BI__builtin_neon_vcvtmq_u32_v: {
+ llvm::Type *OpTy = llvm::VectorType::get(FloatTy, VTy->getNumElements());
+ llvm::Type *Tys[2] = { Ty, OpTy };
+ Int = Intrinsic::aarch64_neon_fcvtmu;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtmu_f32");
+ }
+ case AArch64::BI__builtin_neon_vcvtm_u64_v:
+ case AArch64::BI__builtin_neon_vcvtmq_u64_v: {
+ llvm::Type *OpTy = llvm::VectorType::get(DoubleTy, VTy->getNumElements());
+ llvm::Type *Tys[2] = { Ty, OpTy };
+ Int = Intrinsic::aarch64_neon_fcvtmu;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtmu_f64");
+ }
+ case AArch64::BI__builtin_neon_vcvta_s32_v:
+ case AArch64::BI__builtin_neon_vcvtaq_s32_v: {
+ llvm::Type *OpTy = llvm::VectorType::get(FloatTy, VTy->getNumElements());
+ llvm::Type *Tys[2] = { Ty, OpTy };
+ Int = Intrinsic::aarch64_neon_fcvtas;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtas_f32");
+ }
+ case AArch64::BI__builtin_neon_vcvta_s64_v:
+ case AArch64::BI__builtin_neon_vcvtaq_s64_v: {
+ llvm::Type *OpTy = llvm::VectorType::get(DoubleTy, VTy->getNumElements());
+ llvm::Type *Tys[2] = { Ty, OpTy };
+ Int = Intrinsic::aarch64_neon_fcvtas;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtas_f64");
+ }
+ case AArch64::BI__builtin_neon_vcvta_u32_v:
+ case AArch64::BI__builtin_neon_vcvtaq_u32_v: {
+ llvm::Type *OpTy = llvm::VectorType::get(FloatTy, VTy->getNumElements());
+ llvm::Type *Tys[2] = { Ty, OpTy };
+ Int = Intrinsic::aarch64_neon_fcvtau;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtau_f32");
+ }
+ case AArch64::BI__builtin_neon_vcvta_u64_v:
+ case AArch64::BI__builtin_neon_vcvtaq_u64_v: {
+ llvm::Type *OpTy = llvm::VectorType::get(DoubleTy, VTy->getNumElements());
+ llvm::Type *Tys[2] = { Ty, OpTy };
+ Int = Intrinsic::aarch64_neon_fcvtau;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtau_f64");
+ }
+ case AArch64::BI__builtin_neon_vrecpe_v:
+ case AArch64::BI__builtin_neon_vrecpeq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vrecpe_v, E);
+ case AArch64::BI__builtin_neon_vrsqrte_v:
+ case AArch64::BI__builtin_neon_vrsqrteq_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vrsqrte_v, E);
+ case AArch64::BI__builtin_neon_vsqrt_v:
+ case AArch64::BI__builtin_neon_vsqrtq_v: {
+ Int = Intrinsic::sqrt;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vsqrt");
+ }
+ case AArch64::BI__builtin_neon_vcvt_f32_v:
+ case AArch64::BI__builtin_neon_vcvtq_f32_v:
+ return EmitARMBuiltinExpr(ARM::BI__builtin_neon_vcvt_f32_v, E);
+ case AArch64::BI__builtin_neon_vceqz_v:
+ case AArch64::BI__builtin_neon_vceqzq_v:
+ return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OEQ,
+ ICmpInst::ICMP_EQ, "vceqz");
+ case AArch64::BI__builtin_neon_vcgez_v:
+ case AArch64::BI__builtin_neon_vcgezq_v:
+ return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OGE,
+ ICmpInst::ICMP_SGE, "vcgez");
+ case AArch64::BI__builtin_neon_vclez_v:
+ case AArch64::BI__builtin_neon_vclezq_v:
+ return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OLE,
+ ICmpInst::ICMP_SLE, "vclez");
+ case AArch64::BI__builtin_neon_vcgtz_v:
+ case AArch64::BI__builtin_neon_vcgtzq_v:
+ return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OGT,
+ ICmpInst::ICMP_SGT, "vcgtz");
+ case AArch64::BI__builtin_neon_vcltz_v:
+ case AArch64::BI__builtin_neon_vcltzq_v:
+ return EmitAArch64CompareBuiltinExpr(Ops[0], Ty, ICmpInst::FCMP_OLT,
+ ICmpInst::ICMP_SLT, "vcltz");
+ }
}
Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
const CallExpr *E) {
if (BuiltinID == ARM::BI__clear_cache) {
+ assert(E->getNumArgs() == 2 && "__clear_cache takes 2 arguments");
const FunctionDecl *FD = E->getDirectCallee();
- // Oddly people write this call without args on occasion and gcc accepts
- // it - it's also marked as varargs in the description file.
SmallVector<Value*, 2> Ops;
- for (unsigned i = 0; i < E->getNumArgs(); i++)
+ for (unsigned i = 0; i < 2; i++)
Ops.push_back(EmitScalarExpr(E->getArg(i)));
llvm::Type *Ty = CGM.getTypes().ConvertType(FD->getType());
llvm::FunctionType *FTy = cast<llvm::FunctionType>(Ty);
@@ -1657,11 +3937,14 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
return EmitNounwindRuntimeCall(CGM.CreateRuntimeFunction(FTy, Name), Ops);
}
- if (BuiltinID == ARM::BI__builtin_arm_ldrexd) {
+ if (BuiltinID == ARM::BI__builtin_arm_ldrexd ||
+ (BuiltinID == ARM::BI__builtin_arm_ldrex &&
+ getContext().getTypeSize(E->getType()) == 64)) {
Function *F = CGM.getIntrinsic(Intrinsic::arm_ldrexd);
Value *LdPtr = EmitScalarExpr(E->getArg(0));
- Value *Val = Builder.CreateCall(F, LdPtr, "ldrexd");
+ Value *Val = Builder.CreateCall(F, Builder.CreateBitCast(LdPtr, Int8PtrTy),
+ "ldrexd");
Value *Val0 = Builder.CreateExtractValue(Val, 1);
Value *Val1 = Builder.CreateExtractValue(Val, 0);
@@ -1670,15 +3953,37 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
Value *ShiftCst = llvm::ConstantInt::get(Int64Ty, 32);
Val = Builder.CreateShl(Val0, ShiftCst, "shl", true /* nuw */);
- return Builder.CreateOr(Val, Val1);
+ Val = Builder.CreateOr(Val, Val1);
+ return Builder.CreateBitCast(Val, ConvertType(E->getType()));
+ }
+
+ if (BuiltinID == ARM::BI__builtin_arm_ldrex) {
+ Value *LoadAddr = EmitScalarExpr(E->getArg(0));
+
+ QualType Ty = E->getType();
+ llvm::Type *RealResTy = ConvertType(Ty);
+ llvm::Type *IntResTy = llvm::IntegerType::get(getLLVMContext(),
+ getContext().getTypeSize(Ty));
+ LoadAddr = Builder.CreateBitCast(LoadAddr, IntResTy->getPointerTo());
+
+ Function *F = CGM.getIntrinsic(Intrinsic::arm_ldrex, LoadAddr->getType());
+ Value *Val = Builder.CreateCall(F, LoadAddr, "ldrex");
+
+ if (RealResTy->isPointerTy())
+ return Builder.CreateIntToPtr(Val, RealResTy);
+ else {
+ Val = Builder.CreateTruncOrBitCast(Val, IntResTy);
+ return Builder.CreateBitCast(Val, RealResTy);
+ }
}
- if (BuiltinID == ARM::BI__builtin_arm_strexd) {
+ if (BuiltinID == ARM::BI__builtin_arm_strexd ||
+ (BuiltinID == ARM::BI__builtin_arm_strex &&
+ getContext().getTypeSize(E->getArg(0)->getType()) == 64)) {
Function *F = CGM.getIntrinsic(Intrinsic::arm_strexd);
llvm::Type *STy = llvm::StructType::get(Int32Ty, Int32Ty, NULL);
- Value *One = llvm::ConstantInt::get(Int32Ty, 1);
- Value *Tmp = Builder.CreateAlloca(Int64Ty, One);
+ Value *Tmp = CreateMemTemp(E->getArg(0)->getType());
Value *Val = EmitScalarExpr(E->getArg(0));
Builder.CreateStore(Val, Tmp);
@@ -1687,10 +3992,83 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
Value *Arg0 = Builder.CreateExtractValue(Val, 0);
Value *Arg1 = Builder.CreateExtractValue(Val, 1);
- Value *StPtr = EmitScalarExpr(E->getArg(1));
+ Value *StPtr = Builder.CreateBitCast(EmitScalarExpr(E->getArg(1)), Int8PtrTy);
return Builder.CreateCall3(F, Arg0, Arg1, StPtr, "strexd");
}
+ if (BuiltinID == ARM::BI__builtin_arm_strex) {
+ Value *StoreVal = EmitScalarExpr(E->getArg(0));
+ Value *StoreAddr = EmitScalarExpr(E->getArg(1));
+
+ QualType Ty = E->getArg(0)->getType();
+ llvm::Type *StoreTy = llvm::IntegerType::get(getLLVMContext(),
+ getContext().getTypeSize(Ty));
+ StoreAddr = Builder.CreateBitCast(StoreAddr, StoreTy->getPointerTo());
+
+ if (StoreVal->getType()->isPointerTy())
+ StoreVal = Builder.CreatePtrToInt(StoreVal, Int32Ty);
+ else {
+ StoreVal = Builder.CreateBitCast(StoreVal, StoreTy);
+ StoreVal = Builder.CreateZExtOrBitCast(StoreVal, Int32Ty);
+ }
+
+ Function *F = CGM.getIntrinsic(Intrinsic::arm_strex, StoreAddr->getType());
+ return Builder.CreateCall2(F, StoreVal, StoreAddr, "strex");
+ }
+
+ if (BuiltinID == ARM::BI__builtin_arm_clrex) {
+ Function *F = CGM.getIntrinsic(Intrinsic::arm_clrex);
+ return Builder.CreateCall(F);
+ }
+
+ if (BuiltinID == ARM::BI__builtin_arm_sevl) {
+ Function *F = CGM.getIntrinsic(Intrinsic::arm_sevl);
+ return Builder.CreateCall(F);
+ }
+
+ // CRC32
+ Intrinsic::ID CRCIntrinsicID = Intrinsic::not_intrinsic;
+ switch (BuiltinID) {
+ case ARM::BI__builtin_arm_crc32b:
+ CRCIntrinsicID = Intrinsic::arm_crc32b; break;
+ case ARM::BI__builtin_arm_crc32cb:
+ CRCIntrinsicID = Intrinsic::arm_crc32cb; break;
+ case ARM::BI__builtin_arm_crc32h:
+ CRCIntrinsicID = Intrinsic::arm_crc32h; break;
+ case ARM::BI__builtin_arm_crc32ch:
+ CRCIntrinsicID = Intrinsic::arm_crc32ch; break;
+ case ARM::BI__builtin_arm_crc32w:
+ case ARM::BI__builtin_arm_crc32d:
+ CRCIntrinsicID = Intrinsic::arm_crc32w; break;
+ case ARM::BI__builtin_arm_crc32cw:
+ case ARM::BI__builtin_arm_crc32cd:
+ CRCIntrinsicID = Intrinsic::arm_crc32cw; break;
+ }
+
+ if (CRCIntrinsicID != Intrinsic::not_intrinsic) {
+ Value *Arg0 = EmitScalarExpr(E->getArg(0));
+ Value *Arg1 = EmitScalarExpr(E->getArg(1));
+
+ // crc32{c,}d intrinsics are implemnted as two calls to crc32{c,}w
+ // intrinsics, hence we need different codegen for these cases.
+ if (BuiltinID == ARM::BI__builtin_arm_crc32d ||
+ BuiltinID == ARM::BI__builtin_arm_crc32cd) {
+ Value *C1 = llvm::ConstantInt::get(Int64Ty, 32);
+ Value *Arg1a = Builder.CreateTruncOrBitCast(Arg1, Int32Ty);
+ Value *Arg1b = Builder.CreateLShr(Arg1, C1);
+ Arg1b = Builder.CreateTruncOrBitCast(Arg1b, Int32Ty);
+
+ Function *F = CGM.getIntrinsic(CRCIntrinsicID);
+ Value *Res = Builder.CreateCall2(F, Arg0, Arg1a);
+ return Builder.CreateCall2(F, Res, Arg1b);
+ } else {
+ Arg1 = Builder.CreateZExtOrBitCast(Arg1, Int32Ty);
+
+ Function *F = CGM.getIntrinsic(CRCIntrinsicID);
+ return Builder.CreateCall2(F, Arg0, Arg1);
+ }
+ }
+
SmallVector<Value*, 4> Ops;
llvm::Value *Align = 0;
for (unsigned i = 0, e = E->getNumArgs() - 1; i != e; i++) {
@@ -1836,9 +4214,24 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
case ARM::BI__builtin_neon_vabsq_v:
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vabs, Ty),
Ops, "vabs");
- case ARM::BI__builtin_neon_vaddhn_v:
- return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vaddhn, Ty),
- Ops, "vaddhn");
+ case ARM::BI__builtin_neon_vaddhn_v: {
+ llvm::VectorType *SrcTy =
+ llvm::VectorType::getExtendedElementVectorType(VTy);
+
+ // %sum = add <4 x i32> %lhs, %rhs
+ Ops[0] = Builder.CreateBitCast(Ops[0], SrcTy);
+ Ops[1] = Builder.CreateBitCast(Ops[1], SrcTy);
+ Ops[0] = Builder.CreateAdd(Ops[0], Ops[1], "vaddhn");
+
+ // %high = lshr <4 x i32> %sum, <i32 16, i32 16, i32 16, i32 16>
+ Constant *ShiftAmt = ConstantInt::get(SrcTy->getElementType(),
+ SrcTy->getScalarSizeInBits() / 2);
+ ShiftAmt = ConstantVector::getSplat(VTy->getNumElements(), ShiftAmt);
+ Ops[0] = Builder.CreateLShr(Ops[0], ShiftAmt, "vaddhn");
+
+ // %res = trunc <4 x i32> %high to <4 x i16>
+ return Builder.CreateTrunc(Ops[0], VTy, "vaddhn");
+ }
case ARM::BI__builtin_neon_vcale_v:
std::swap(Ops[0], Ops[1]);
case ARM::BI__builtin_neon_vcage_v: {
@@ -2142,6 +4535,11 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vmulp, Ty),
Ops, "vmul");
case ARM::BI__builtin_neon_vmull_v:
+ // FIXME: the integer vmull operations could be emitted in terms of pure
+ // LLVM IR (2 exts followed by a mul). Unfortunately LLVM has a habit of
+ // hoisting the exts outside loops. Until global ISel comes along that can
+ // see through such movement this leads to bad CodeGen. So we need an
+ // intrinsic for now.
Int = usgn ? Intrinsic::arm_neon_vmullu : Intrinsic::arm_neon_vmulls;
Int = Type.isPoly() ? (unsigned)Intrinsic::arm_neon_vmullp : Int;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmull");
@@ -2195,12 +4593,28 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
case ARM::BI__builtin_neon_vqaddq_v:
Int = usgn ? Intrinsic::arm_neon_vqaddu : Intrinsic::arm_neon_vqadds;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vqadd");
- case ARM::BI__builtin_neon_vqdmlal_v:
- return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqdmlal, Ty),
- Ops, "vqdmlal");
- case ARM::BI__builtin_neon_vqdmlsl_v:
- return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqdmlsl, Ty),
- Ops, "vqdmlsl");
+ case ARM::BI__builtin_neon_vqdmlal_v: {
+ SmallVector<Value *, 2> MulOps(Ops.begin() + 1, Ops.end());
+ Value *Mul = EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqdmull, Ty),
+ MulOps, "vqdmlal");
+
+ SmallVector<Value *, 2> AddOps;
+ AddOps.push_back(Ops[0]);
+ AddOps.push_back(Mul);
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqadds, Ty),
+ AddOps, "vqdmlal");
+ }
+ case ARM::BI__builtin_neon_vqdmlsl_v: {
+ SmallVector<Value *, 2> MulOps(Ops.begin() + 1, Ops.end());
+ Value *Mul = EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqdmull, Ty),
+ MulOps, "vqdmlsl");
+
+ SmallVector<Value *, 2> SubOps;
+ SubOps.push_back(Ops[0]);
+ SubOps.push_back(Mul);
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqsubs, Ty),
+ SubOps, "vqdmlsl");
+ }
case ARM::BI__builtin_neon_vqdmulh_v:
case ARM::BI__builtin_neon_vqdmulhq_v:
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqdmulh, Ty),
@@ -2320,12 +4734,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
Ops, "vshrn_n", 1, true);
case ARM::BI__builtin_neon_vshr_n_v:
case ARM::BI__builtin_neon_vshrq_n_v:
- Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- Ops[1] = EmitNeonShiftVector(Ops[1], Ty, false);
- if (usgn)
- return Builder.CreateLShr(Ops[0], Ops[1], "vshr_n");
- else
- return Builder.CreateAShr(Ops[0], Ops[1], "vshr_n");
+ return EmitNeonRShiftImm(Ops[0], Ops[1], Ty, usgn, "vshr_n");
case ARM::BI__builtin_neon_vsri_n_v:
case ARM::BI__builtin_neon_vsriq_n_v:
rightShift = true;
@@ -2337,12 +4746,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
case ARM::BI__builtin_neon_vsra_n_v:
case ARM::BI__builtin_neon_vsraq_n_v:
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
- Ops[2] = EmitNeonShiftVector(Ops[2], Ty, false);
- if (usgn)
- Ops[1] = Builder.CreateLShr(Ops[1], Ops[2], "vsra_n");
- else
- Ops[1] = Builder.CreateAShr(Ops[1], Ops[2], "vsra_n");
+ Ops[1] = EmitNeonRShiftImm(Ops[1], Ops[2], Ty, usgn, "vsra_n");
return Builder.CreateAdd(Ops[0], Ops[1]);
case ARM::BI__builtin_neon_vst1_v:
case ARM::BI__builtin_neon_vst1q_v:
@@ -2400,9 +4804,24 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
Ops.push_back(Align);
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vst4lane, Ty),
Ops, "");
- case ARM::BI__builtin_neon_vsubhn_v:
- return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vsubhn, Ty),
- Ops, "vsubhn");
+ case ARM::BI__builtin_neon_vsubhn_v: {
+ llvm::VectorType *SrcTy =
+ llvm::VectorType::getExtendedElementVectorType(VTy);
+
+ // %sum = add <4 x i32> %lhs, %rhs
+ Ops[0] = Builder.CreateBitCast(Ops[0], SrcTy);
+ Ops[1] = Builder.CreateBitCast(Ops[1], SrcTy);
+ Ops[0] = Builder.CreateSub(Ops[0], Ops[1], "vsubhn");
+
+ // %high = lshr <4 x i32> %sum, <i32 16, i32 16, i32 16, i32 16>
+ Constant *ShiftAmt = ConstantInt::get(SrcTy->getElementType(),
+ SrcTy->getScalarSizeInBits() / 2);
+ ShiftAmt = ConstantVector::getSplat(VTy->getNumElements(), ShiftAmt);
+ Ops[0] = Builder.CreateLShr(Ops[0], ShiftAmt, "vsubhn");
+
+ // %res = trunc <4 x i32> %high to <4 x i16>
+ return Builder.CreateTrunc(Ops[0], VTy, "vsubhn");
+ }
case ARM::BI__builtin_neon_vtbl1_v:
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbl1),
Ops, "vtbl1");
@@ -2560,19 +4979,15 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
return Builder.CreateExtractElement(Ops[0],
llvm::ConstantInt::get(Ops[1]->getType(), 0));
case X86::BI__builtin_ia32_ldmxcsr: {
- llvm::Type *PtrTy = Int8PtrTy;
- Value *One = llvm::ConstantInt::get(Int32Ty, 1);
- Value *Tmp = Builder.CreateAlloca(Int32Ty, One);
+ Value *Tmp = CreateMemTemp(E->getArg(0)->getType());
Builder.CreateStore(Ops[0], Tmp);
return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_ldmxcsr),
- Builder.CreateBitCast(Tmp, PtrTy));
+ Builder.CreateBitCast(Tmp, Int8PtrTy));
}
case X86::BI__builtin_ia32_stmxcsr: {
- llvm::Type *PtrTy = Int8PtrTy;
- Value *One = llvm::ConstantInt::get(Int32Ty, 1);
- Value *Tmp = Builder.CreateAlloca(Int32Ty, One);
+ Value *Tmp = CreateMemTemp(E->getType());
Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_stmxcsr),
- Builder.CreateBitCast(Tmp, PtrTy));
+ Builder.CreateBitCast(Tmp, Int8PtrTy));
return Builder.CreateLoad(Tmp, "stmxcsr");
}
case X86::BI__builtin_ia32_storehps:
@@ -2697,7 +5112,8 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
case X86::BI__builtin_ia32_movntpd256:
case X86::BI__builtin_ia32_movntdq:
case X86::BI__builtin_ia32_movntdq256:
- case X86::BI__builtin_ia32_movnti: {
+ case X86::BI__builtin_ia32_movnti:
+ case X86::BI__builtin_ia32_movnti64: {
llvm::MDNode *Node = llvm::MDNode::get(getLLVMContext(),
Builder.getInt32(1));
@@ -2707,7 +5123,16 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
"cast");
StoreInst *SI = Builder.CreateStore(Ops[1], BC);
SI->setMetadata(CGM.getModule().getMDKindID("nontemporal"), Node);
- SI->setAlignment(16);
+
+ // If the operand is an integer, we can't assume alignment. Otherwise,
+ // assume natural alignment.
+ QualType ArgTy = E->getArg(1)->getType();
+ unsigned Align;
+ if (ArgTy->isIntegerType())
+ Align = 1;
+ else
+ Align = getContext().getTypeSizeInChars(ArgTy).getQuantity();
+ SI->setAlignment(Align);
return SI;
}
// 3DNow!
@@ -2761,6 +5186,13 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
Builder.CreateStore(Builder.CreateExtractValue(Call, 0), Ops[0]);
return Builder.CreateExtractValue(Call, 1);
}
+ // AVX2 broadcast
+ case X86::BI__builtin_ia32_vbroadcastsi256: {
+ Value *VecTmp = CreateMemTemp(E->getArg(0)->getType());
+ Builder.CreateStore(Ops[0], VecTmp);
+ Value *F = CGM.getIntrinsic(Intrinsic::x86_avx2_vbroadcasti128);
+ return Builder.CreateCall(F, Builder.CreateBitCast(VecTmp, Int8PtrTy));
+ }
}
}
diff --git a/lib/CodeGen/CGCUDARuntime.cpp b/lib/CodeGen/CGCUDARuntime.cpp
index fc72008..eaf31bb 100644
--- a/lib/CodeGen/CGCUDARuntime.cpp
+++ b/lib/CodeGen/CGCUDARuntime.cpp
@@ -44,8 +44,8 @@ RValue CGCUDARuntime::EmitCUDAKernelCallExpr(CodeGenFunction &CGF,
}
llvm::Value *Callee = CGF.EmitScalarExpr(E->getCallee());
- CGF.EmitCall(E->getCallee()->getType(), Callee, ReturnValue,
- E->arg_begin(), E->arg_end(), TargetDecl);
+ CGF.EmitCall(E->getCallee()->getType(), Callee, E->getLocStart(),
+ ReturnValue, E->arg_begin(), E->arg_end(), TargetDecl);
CGF.EmitBranch(ContBlock);
CGF.EmitBlock(ContBlock);
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index 983cb92..cfb2d62 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -34,6 +34,11 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
if (!getCodeGenOpts().CXXCtorDtorAliases)
return true;
+ // Producing an alias to a base class ctor/dtor can degrade debug quality
+ // as the debugger cannot tell them appart.
+ if (getCodeGenOpts().OptimizationLevel == 0)
+ return true;
+
// If the destructor doesn't have a trivial body, we have to emit it
// separately.
if (!D->hasTrivialBody())
@@ -82,60 +87,44 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
if (!UniqueBase)
return true;
- /// If we don't have a definition for the destructor yet, don't
- /// emit. We can't emit aliases to declarations; that's just not
- /// how aliases work.
- const CXXDestructorDecl *BaseD = UniqueBase->getDestructor();
- if (!BaseD->isImplicit() && !BaseD->hasBody())
- return true;
-
// If the base is at a non-zero offset, give up.
const ASTRecordLayout &ClassLayout = Context.getASTRecordLayout(Class);
if (!ClassLayout.getBaseClassOffset(UniqueBase).isZero())
return true;
+ const CXXDestructorDecl *BaseD = UniqueBase->getDestructor();
return TryEmitDefinitionAsAlias(GlobalDecl(D, Dtor_Base),
- GlobalDecl(BaseD, Dtor_Base));
+ GlobalDecl(BaseD, Dtor_Base),
+ false);
}
/// Try to emit a definition as a global alias for another definition.
+/// If \p InEveryTU is true, we know that an equivalent alias can be produced
+/// in every translation unit.
bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
- GlobalDecl TargetDecl) {
+ GlobalDecl TargetDecl,
+ bool InEveryTU) {
if (!getCodeGenOpts().CXXCtorDtorAliases)
return true;
// The alias will use the linkage of the referrent. If we can't
// support aliases with that linkage, fail.
- llvm::GlobalValue::LinkageTypes Linkage
- = getFunctionLinkage(cast<FunctionDecl>(AliasDecl.getDecl()));
-
- switch (Linkage) {
- // We can definitely emit aliases to definitions with external linkage.
- case llvm::GlobalValue::ExternalLinkage:
- case llvm::GlobalValue::ExternalWeakLinkage:
- break;
-
- // Same with local linkage.
- case llvm::GlobalValue::InternalLinkage:
- case llvm::GlobalValue::PrivateLinkage:
- case llvm::GlobalValue::LinkerPrivateLinkage:
- break;
-
- // We should try to support linkonce linkages.
- case llvm::GlobalValue::LinkOnceAnyLinkage:
- case llvm::GlobalValue::LinkOnceODRLinkage:
- return true;
+ llvm::GlobalValue::LinkageTypes Linkage = getFunctionLinkage(AliasDecl);
- // Other linkages will probably never be supported.
- default:
+ // We can't use an alias if the linkage is not valid for one.
+ if (!llvm::GlobalAlias::isValidLinkage(Linkage))
return true;
- }
- llvm::GlobalValue::LinkageTypes TargetLinkage
- = getFunctionLinkage(cast<FunctionDecl>(TargetDecl.getDecl()));
+ llvm::GlobalValue::LinkageTypes TargetLinkage =
+ getFunctionLinkage(TargetDecl);
- if (llvm::GlobalValue::isWeakForLinker(TargetLinkage))
- return true;
+ // Check if we have it already.
+ StringRef MangledName = getMangledName(AliasDecl);
+ llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
+ if (Entry && !Entry->isDeclaration())
+ return false;
+ if (Replacements.count(MangledName))
+ return false;
// Derive the type for the alias.
llvm::PointerType *AliasType
@@ -149,15 +138,41 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
if (Ref->getType() != AliasType)
Aliasee = llvm::ConstantExpr::getBitCast(Ref, AliasType);
+ // Instead of creating as alias to a linkonce_odr, replace all of the uses
+ // of the aliassee.
+ if (llvm::GlobalValue::isDiscardableIfUnused(Linkage) &&
+ (TargetLinkage != llvm::GlobalValue::AvailableExternallyLinkage ||
+ !TargetDecl.getDecl()->hasAttr<AlwaysInlineAttr>())) {
+ // FIXME: An extern template instanciation will create functions with
+ // linkage "AvailableExternally". In libc++, some classes also define
+ // members with attribute "AlwaysInline" and expect no reference to
+ // be generated. It is desirable to reenable this optimisation after
+ // corresponding LLVM changes.
+ Replacements[MangledName] = Aliasee;
+ return false;
+ }
+
+ if (!InEveryTU) {
+ /// If we don't have a definition for the destructor yet, don't
+ /// emit. We can't emit aliases to declarations; that's just not
+ /// how aliases work.
+ if (Ref->isDeclaration())
+ return true;
+ }
+
+ // Don't create an alias to a linker weak symbol. This avoids producing
+ // different COMDATs in different TUs. Another option would be to
+ // output the alias both for weak_odr and linkonce_odr, but that
+ // requires explicit comdat support in the IL.
+ if (llvm::GlobalValue::isWeakForLinker(TargetLinkage))
+ return true;
+
// Create the alias with no name.
llvm::GlobalAlias *Alias =
new llvm::GlobalAlias(AliasType, Linkage, "", Aliasee, &getModule());
// Switch any previous uses to the alias.
- StringRef MangledName = getMangledName(AliasDecl);
- llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
if (Entry) {
- assert(Entry->isDeclaration() && "definition already exists for alias");
assert(Entry->getType() == AliasType &&
"declaration exists with different type");
Alias->takeName(Entry);
@@ -173,37 +188,26 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
return false;
}
-void CodeGenModule::EmitCXXConstructors(const CXXConstructorDecl *D) {
- // The constructor used for constructing this as a complete class;
- // constucts the virtual bases, then calls the base constructor.
- if (!D->getParent()->isAbstract()) {
- // We don't need to emit the complete ctor if the class is abstract.
- EmitGlobal(GlobalDecl(D, Ctor_Complete));
- }
-
- // The constructor used for constructing this as a base class;
- // ignores virtual bases.
- if (getTarget().getCXXABI().hasConstructorVariants())
- EmitGlobal(GlobalDecl(D, Ctor_Base));
-}
-
void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *ctor,
CXXCtorType ctorType) {
// The complete constructor is equivalent to the base constructor
// for classes with no virtual bases. Try to emit it as an alias.
if (getTarget().getCXXABI().hasConstructorVariants() &&
- ctorType == Ctor_Complete &&
!ctor->getParent()->getNumVBases() &&
- !TryEmitDefinitionAsAlias(GlobalDecl(ctor, Ctor_Complete),
- GlobalDecl(ctor, Ctor_Base)))
- return;
+ (ctorType == Ctor_Complete || ctorType == Ctor_Base)) {
+ bool ProducedAlias =
+ !TryEmitDefinitionAsAlias(GlobalDecl(ctor, Ctor_Complete),
+ GlobalDecl(ctor, Ctor_Base), true);
+ if (ctorType == Ctor_Complete && ProducedAlias)
+ return;
+ }
const CGFunctionInfo &fnInfo =
getTypes().arrangeCXXConstructorDeclaration(ctor, ctorType);
llvm::Function *fn =
cast<llvm::Function>(GetAddrOfCXXConstructor(ctor, ctorType, &fnInfo));
- setFunctionLinkage(ctor, fn);
+ setFunctionLinkage(GlobalDecl(ctor, ctorType), fn);
CodeGenFunction(*this).GenerateCode(GlobalDecl(ctor, ctorType), fn, fnInfo);
@@ -229,31 +233,22 @@ CodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *ctor,
/*ForVTable=*/false));
}
-void CodeGenModule::EmitCXXDestructors(const CXXDestructorDecl *D) {
- // The destructor in a virtual table is always a 'deleting'
- // destructor, which calls the complete destructor and then uses the
- // appropriate operator delete.
- if (D->isVirtual())
- EmitGlobal(GlobalDecl(D, Dtor_Deleting));
-
- // The destructor used for destructing this as a most-derived class;
- // call the base destructor and then destructs any virtual bases.
- EmitGlobal(GlobalDecl(D, Dtor_Complete));
-
- // The destructor used for destructing this as a base class; ignores
- // virtual bases.
- EmitGlobal(GlobalDecl(D, Dtor_Base));
-}
-
void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *dtor,
CXXDtorType dtorType) {
// The complete destructor is equivalent to the base destructor for
// classes with no virtual bases, so try to emit it as an alias.
- if (dtorType == Dtor_Complete &&
- !dtor->getParent()->getNumVBases() &&
- !TryEmitDefinitionAsAlias(GlobalDecl(dtor, Dtor_Complete),
- GlobalDecl(dtor, Dtor_Base)))
- return;
+ if (!dtor->getParent()->getNumVBases() &&
+ (dtorType == Dtor_Complete || dtorType == Dtor_Base)) {
+ bool ProducedAlias =
+ !TryEmitDefinitionAsAlias(GlobalDecl(dtor, Dtor_Complete),
+ GlobalDecl(dtor, Dtor_Base), true);
+ if (ProducedAlias) {
+ if (dtorType == Dtor_Complete)
+ return;
+ if (dtor->isVirtual())
+ getVTables().EmitThunks(GlobalDecl(dtor, Dtor_Complete));
+ }
+ }
// The base destructor is equivalent to the base destructor of its
// base class if there is exactly one non-virtual base class with a
@@ -267,7 +262,7 @@ void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *dtor,
llvm::Function *fn =
cast<llvm::Function>(GetAddrOfCXXDestructor(dtor, dtorType, &fnInfo));
- setFunctionLinkage(dtor, fn);
+ setFunctionLinkage(GlobalDecl(dtor, dtorType), fn);
CodeGenFunction(*this).GenerateCode(GlobalDecl(dtor, dtorType), fn, fnInfo);
@@ -278,47 +273,51 @@ void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *dtor,
llvm::GlobalValue *
CodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *dtor,
CXXDtorType dtorType,
- const CGFunctionInfo *fnInfo) {
+ const CGFunctionInfo *fnInfo,
+ llvm::FunctionType *fnType) {
GlobalDecl GD(dtor, dtorType);
StringRef name = getMangledName(GD);
if (llvm::GlobalValue *existing = GetGlobalValue(name))
return existing;
- if (!fnInfo) fnInfo = &getTypes().arrangeCXXDestructor(dtor, dtorType);
-
- llvm::FunctionType *fnType = getTypes().GetFunctionType(*fnInfo);
+ if (!fnType) {
+ if (!fnInfo) fnInfo = &getTypes().arrangeCXXDestructor(dtor, dtorType);
+ fnType = getTypes().GetFunctionType(*fnInfo);
+ }
return cast<llvm::Function>(GetOrCreateLLVMFunction(name, fnType, GD,
/*ForVTable=*/false));
}
-static llvm::Value *BuildVirtualCall(CodeGenFunction &CGF, uint64_t VTableIndex,
- llvm::Value *This, llvm::Type *Ty) {
+static llvm::Value *BuildAppleKextVirtualCall(CodeGenFunction &CGF,
+ GlobalDecl GD,
+ llvm::Type *Ty,
+ const CXXRecordDecl *RD) {
+ assert(!CGF.CGM.getTarget().getCXXABI().isMicrosoft() &&
+ "No kext in Microsoft ABI");
+ GD = GD.getCanonicalDecl();
+ CodeGenModule &CGM = CGF.CGM;
+ llvm::Value *VTable = CGM.getCXXABI().getAddrOfVTable(RD, CharUnits());
Ty = Ty->getPointerTo()->getPointerTo();
-
- llvm::Value *VTable = CGF.GetVTablePtr(This, Ty);
- llvm::Value *VFuncPtr =
- CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfn");
+ VTable = CGF.Builder.CreateBitCast(VTable, Ty);
+ assert(VTable && "BuildVirtualCall = kext vtbl pointer is null");
+ uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD);
+ uint64_t AddressPoint =
+ CGM.getItaniumVTableContext().getVTableLayout(RD)
+ .getAddressPoint(BaseSubobject(RD, CharUnits::Zero()));
+ VTableIndex += AddressPoint;
+ llvm::Value *VFuncPtr =
+ CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt");
return CGF.Builder.CreateLoad(VFuncPtr);
}
-llvm::Value *
-CodeGenFunction::BuildVirtualCall(const CXXMethodDecl *MD, llvm::Value *This,
- llvm::Type *Ty) {
- MD = MD->getCanonicalDecl();
- uint64_t VTableIndex = CGM.getVTableContext().getMethodVTableIndex(MD);
-
- return ::BuildVirtualCall(*this, VTableIndex, This, Ty);
-}
-
-/// BuildVirtualCall - This routine is to support gcc's kext ABI making
+/// BuildAppleKextVirtualCall - This routine is to support gcc's kext ABI making
/// indirect call to virtual functions. It makes the call through indexing
/// into the vtable.
llvm::Value *
CodeGenFunction::BuildAppleKextVirtualCall(const CXXMethodDecl *MD,
NestedNameSpecifier *Qual,
llvm::Type *Ty) {
- llvm::Value *VTable = 0;
assert((Qual->getKind() == NestedNameSpecifier::TypeSpec) &&
"BuildAppleKextVirtualCall - bad Qual kind");
@@ -330,20 +329,8 @@ CodeGenFunction::BuildAppleKextVirtualCall(const CXXMethodDecl *MD,
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD))
return BuildAppleKextVirtualDestructorCall(DD, Dtor_Complete, RD);
-
- VTable = CGM.getVTables().GetAddrOfVTable(RD);
- Ty = Ty->getPointerTo()->getPointerTo();
- VTable = Builder.CreateBitCast(VTable, Ty);
- assert(VTable && "BuildVirtualCall = kext vtbl pointer is null");
- MD = MD->getCanonicalDecl();
- uint64_t VTableIndex = CGM.getVTableContext().getMethodVTableIndex(MD);
- uint64_t AddressPoint =
- CGM.getVTableContext().getVTableLayout(RD)
- .getAddressPoint(BaseSubobject(RD, CharUnits::Zero()));
- VTableIndex += AddressPoint;
- llvm::Value *VFuncPtr =
- Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt");
- return Builder.CreateLoad(VFuncPtr);
+
+ return ::BuildAppleKextVirtualCall(*this, MD, Ty, RD);
}
/// BuildVirtualCall - This routine makes indirect vtable call for
@@ -353,42 +340,16 @@ CodeGenFunction::BuildAppleKextVirtualDestructorCall(
const CXXDestructorDecl *DD,
CXXDtorType Type,
const CXXRecordDecl *RD) {
- llvm::Value * Callee = 0;
const CXXMethodDecl *MD = cast<CXXMethodDecl>(DD);
// FIXME. Dtor_Base dtor is always direct!!
// It need be somehow inline expanded into the caller.
// -O does that. But need to support -O0 as well.
if (MD->isVirtual() && Type != Dtor_Base) {
// Compute the function type we're calling.
- const CGFunctionInfo &FInfo =
- CGM.getTypes().arrangeCXXDestructor(cast<CXXDestructorDecl>(MD),
- Dtor_Complete);
+ const CGFunctionInfo &FInfo =
+ CGM.getTypes().arrangeCXXDestructor(DD, Dtor_Complete);
llvm::Type *Ty = CGM.getTypes().GetFunctionType(FInfo);
-
- llvm::Value *VTable = CGM.getVTables().GetAddrOfVTable(RD);
- Ty = Ty->getPointerTo()->getPointerTo();
- VTable = Builder.CreateBitCast(VTable, Ty);
- DD = cast<CXXDestructorDecl>(DD->getCanonicalDecl());
- uint64_t VTableIndex =
- CGM.getVTableContext().getMethodVTableIndex(GlobalDecl(DD, Type));
- uint64_t AddressPoint =
- CGM.getVTableContext().getVTableLayout(RD)
- .getAddressPoint(BaseSubobject(RD, CharUnits::Zero()));
- VTableIndex += AddressPoint;
- llvm::Value *VFuncPtr =
- Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt");
- Callee = Builder.CreateLoad(VFuncPtr);
+ return ::BuildAppleKextVirtualCall(*this, GlobalDecl(DD, Type), Ty, RD);
}
- return Callee;
+ return 0;
}
-
-llvm::Value *
-CodeGenFunction::BuildVirtualCall(const CXXDestructorDecl *DD, CXXDtorType Type,
- llvm::Value *This, llvm::Type *Ty) {
- DD = cast<CXXDestructorDecl>(DD->getCanonicalDecl());
- uint64_t VTableIndex =
- CGM.getVTableContext().getMethodVTableIndex(GlobalDecl(DD, Type));
-
- return ::BuildVirtualCall(*this, VTableIndex, This, Ty);
-}
-
diff --git a/lib/CodeGen/CGCXXABI.cpp b/lib/CodeGen/CGCXXABI.cpp
index 68fecb2..412b278 100644
--- a/lib/CodeGen/CGCXXABI.cpp
+++ b/lib/CodeGen/CGCXXABI.cpp
@@ -1,4 +1,4 @@
-//===----- CGCXXABI.cpp - Interface to C++ ABIs -----------------*- C++ -*-===//
+//===----- CGCXXABI.cpp - Interface to C++ ABIs ---------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -212,13 +212,6 @@ llvm::Value *CGCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
return llvm::ConstantInt::get(CGF.SizeTy, 0);
}
-void CGCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
- const VarDecl &D,
- llvm::GlobalVariable *GV,
- bool PerformInit) {
- ErrorUnsupportedABI(CGF, "static local variable initialization");
-}
-
void CGCXXABI::registerGlobalDtor(CodeGenFunction &CGF,
const VarDecl &D,
llvm::Constant *dtor,
@@ -227,7 +220,7 @@ void CGCXXABI::registerGlobalDtor(CodeGenFunction &CGF,
CGM.ErrorUnsupported(&D, "non-trivial TLS destruction");
// The default behavior is to use atexit.
- CGF.registerGlobalDtorWithAtExit(dtor, addr);
+ CGF.registerGlobalDtorWithAtExit(D, dtor, addr);
}
/// Returns the adjustment, in bytes, required for the given
@@ -251,8 +244,31 @@ llvm::Constant *CGCXXABI::getMemberPointerAdjustment(const CastExpr *E) {
E->path_end());
}
-llvm::BasicBlock *CGCXXABI::EmitCtorCompleteObjectHandler(
- CodeGenFunction &CGF) {
+CharUnits CGCXXABI::getMemberPointerPathAdjustment(const APValue &MP) {
+ // TODO: Store base specifiers in APValue member pointer paths so we can
+ // easily reuse CGM.GetNonVirtualBaseClassOffset().
+ const ValueDecl *MPD = MP.getMemberPointerDecl();
+ CharUnits ThisAdjustment = CharUnits::Zero();
+ ArrayRef<const CXXRecordDecl*> Path = MP.getMemberPointerPath();
+ bool DerivedMember = MP.isMemberPointerToDerivedMember();
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(MPD->getDeclContext());
+ for (unsigned I = 0, N = Path.size(); I != N; ++I) {
+ const CXXRecordDecl *Base = RD;
+ const CXXRecordDecl *Derived = Path[I];
+ if (DerivedMember)
+ std::swap(Base, Derived);
+ ThisAdjustment +=
+ getContext().getASTRecordLayout(Derived).getBaseClassOffset(Base);
+ RD = Path[I];
+ }
+ if (DerivedMember)
+ ThisAdjustment = -ThisAdjustment;
+ return ThisAdjustment;
+}
+
+llvm::BasicBlock *
+CGCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
+ const CXXRecordDecl *RD) {
if (CGM.getTarget().getCXXABI().hasConstructorVariants())
llvm_unreachable("shouldn't be called in this ABI");
@@ -270,3 +286,7 @@ LValue CGCXXABI::EmitThreadLocalDeclRefExpr(CodeGenFunction &CGF,
ErrorUnsupportedABI(CGF, "odr-use of thread_local global");
return LValue();
}
+
+bool CGCXXABI::NeedsVTTParameter(GlobalDecl GD) {
+ return false;
+}
diff --git a/lib/CodeGen/CGCXXABI.h b/lib/CodeGen/CGCXXABI.h
index 1e4da63..9e9a2a7 100644
--- a/lib/CodeGen/CGCXXABI.h
+++ b/lib/CodeGen/CGCXXABI.h
@@ -97,8 +97,12 @@ public:
return *MangleCtx;
}
- /// Returns true if the given instance method is one of the
- /// kinds that the ABI says returns 'this'.
+ /// Returns true if the given constructor or destructor is one of the
+ /// kinds that the ABI says returns 'this' (only applies when called
+ /// non-virtually for destructors).
+ ///
+ /// There currently is no way to indicate if a destructor returns 'this'
+ /// when called virtually, and code generation does not support the case.
virtual bool HasThisReturn(GlobalDecl GD) const { return false; }
/// Returns true if the given record type should be returned indirectly.
@@ -192,6 +196,12 @@ protected:
/// is required.
llvm::Constant *getMemberPointerAdjustment(const CastExpr *E);
+ /// \brief Computes the non-virtual adjustment needed for a member pointer
+ /// conversion along an inheritance path stored in an APValue. Unlike
+ /// getMemberPointerAdjustment(), the adjustment can be negative if the path
+ /// is from a derived type to a base type.
+ CharUnits getMemberPointerPathAdjustment(const APValue &MP);
+
public:
/// Adjust the given non-null pointer to an object of polymorphic
/// type to point to the complete object.
@@ -202,11 +212,16 @@ public:
llvm::Value *ptr,
QualType type) = 0;
+ virtual llvm::Value *GetVirtualBaseClassOffset(CodeGenFunction &CGF,
+ llvm::Value *This,
+ const CXXRecordDecl *ClassDecl,
+ const CXXRecordDecl *BaseClassDecl) = 0;
+
/// Build the signature of the given constructor variant by adding
- /// any required parameters. For convenience, ResTy has been
- /// initialized to 'void', and ArgTys has been initialized with the
- /// type of 'this' (although this may be changed by the ABI) and
- /// will have the formal parameters added to it afterwards.
+ /// any required parameters. For convenience, ArgTys has been initialized
+ /// with the type of 'this' and ResTy has been initialized with the type of
+ /// 'this' if HasThisReturn(GlobalDecl(Ctor, T)) is true or 'void' otherwise
+ /// (although both may be changed by the ABI).
///
/// If there are ever any ABIs where the implicit parameters are
/// intermixed with the formal parameters, we can address those
@@ -216,46 +231,138 @@ public:
CanQualType &ResTy,
SmallVectorImpl<CanQualType> &ArgTys) = 0;
- virtual llvm::BasicBlock *EmitCtorCompleteObjectHandler(CodeGenFunction &CGF);
+ virtual llvm::BasicBlock *EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
+ const CXXRecordDecl *RD);
+
+ /// Emit the code to initialize hidden members required
+ /// to handle virtual inheritance, if needed by the ABI.
+ virtual void
+ initializeHiddenVirtualInheritanceMembers(CodeGenFunction &CGF,
+ const CXXRecordDecl *RD) {}
+
+ /// Emit constructor variants required by this ABI.
+ virtual void EmitCXXConstructors(const CXXConstructorDecl *D) = 0;
/// Build the signature of the given destructor variant by adding
- /// any required parameters. For convenience, ResTy has been
- /// initialized to 'void' and ArgTys has been initialized with the
- /// type of 'this' (although this may be changed by the ABI).
+ /// any required parameters. For convenience, ArgTys has been initialized
+ /// with the type of 'this' and ResTy has been initialized with the type of
+ /// 'this' if HasThisReturn(GlobalDecl(Dtor, T)) is true or 'void' otherwise
+ /// (although both may be changed by the ABI).
virtual void BuildDestructorSignature(const CXXDestructorDecl *Dtor,
CXXDtorType T,
CanQualType &ResTy,
SmallVectorImpl<CanQualType> &ArgTys) = 0;
+ /// Returns true if the given destructor type should be emitted as a linkonce
+ /// delegating thunk, regardless of whether the dtor is defined in this TU or
+ /// not.
+ virtual bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor,
+ CXXDtorType DT) const = 0;
+
+ /// Emit destructor variants required by this ABI.
+ virtual void EmitCXXDestructors(const CXXDestructorDecl *D) = 0;
+
+ /// Get the type of the implicit "this" parameter used by a method. May return
+ /// zero if no specific type is applicable, e.g. if the ABI expects the "this"
+ /// parameter to point to some artificial offset in a complete object due to
+ /// vbases being reordered.
+ virtual const CXXRecordDecl *
+ getThisArgumentTypeForMethod(const CXXMethodDecl *MD) {
+ return MD->getParent();
+ }
+
+ /// Perform ABI-specific "this" argument adjustment required prior to
+ /// a virtual function call.
+ virtual llvm::Value *adjustThisArgumentForVirtualCall(CodeGenFunction &CGF,
+ GlobalDecl GD,
+ llvm::Value *This) {
+ return This;
+ }
+
/// Build the ABI-specific portion of the parameter list for a
/// function. This generally involves a 'this' parameter and
/// possibly some extra data for constructors and destructors.
///
/// ABIs may also choose to override the return type, which has been
- /// initialized with the formal return type of the function.
+ /// initialized with the type of 'this' if HasThisReturn(CGF.CurGD) is true or
+ /// the formal return type of the function otherwise.
virtual void BuildInstanceFunctionParams(CodeGenFunction &CGF,
QualType &ResTy,
FunctionArgList &Params) = 0;
+ /// Perform ABI-specific "this" parameter adjustment in a virtual function
+ /// prologue.
+ virtual llvm::Value *adjustThisParameterInVirtualFunctionPrologue(
+ CodeGenFunction &CGF, GlobalDecl GD, llvm::Value *This) {
+ return This;
+ }
+
/// Emit the ABI-specific prolog for the function.
virtual void EmitInstanceFunctionProlog(CodeGenFunction &CGF) = 0;
/// Emit the constructor call. Return the function that is called.
- virtual llvm::Value *EmitConstructorCall(CodeGenFunction &CGF,
+ virtual void EmitConstructorCall(CodeGenFunction &CGF,
const CXXConstructorDecl *D,
- CXXCtorType Type, bool ForVirtualBase,
- bool Delegating,
+ CXXCtorType Type,
+ bool ForVirtualBase, bool Delegating,
llvm::Value *This,
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd) = 0;
+ /// Emits the VTable definitions required for the given record type.
+ virtual void emitVTableDefinitions(CodeGenVTables &CGVT,
+ const CXXRecordDecl *RD) = 0;
+
+ /// Get the address point of the vtable for the given base subobject while
+ /// building a constructor or a destructor. On return, NeedsVirtualOffset
+ /// tells if a virtual base adjustment is needed in order to get the offset
+ /// of the base subobject.
+ virtual llvm::Value *getVTableAddressPointInStructor(
+ CodeGenFunction &CGF, const CXXRecordDecl *RD, BaseSubobject Base,
+ const CXXRecordDecl *NearestVBase, bool &NeedsVirtualOffset) = 0;
+
+ /// Get the address point of the vtable for the given base subobject while
+ /// building a constexpr.
+ virtual llvm::Constant *
+ getVTableAddressPointForConstExpr(BaseSubobject Base,
+ const CXXRecordDecl *VTableClass) = 0;
+
+ /// Get the address of the vtable for the given record decl which should be
+ /// used for the vptr at the given offset in RD.
+ virtual llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD,
+ CharUnits VPtrOffset) = 0;
+
+ /// Build a virtual function pointer in the ABI-specific way.
+ virtual llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF,
+ GlobalDecl GD,
+ llvm::Value *This,
+ llvm::Type *Ty) = 0;
+
/// Emit the ABI-specific virtual destructor call.
- virtual RValue EmitVirtualDestructorCall(CodeGenFunction &CGF,
- const CXXDestructorDecl *Dtor,
- CXXDtorType DtorType,
- SourceLocation CallLoc,
- ReturnValueSlot ReturnValue,
- llvm::Value *This) = 0;
+ virtual void EmitVirtualDestructorCall(CodeGenFunction &CGF,
+ const CXXDestructorDecl *Dtor,
+ CXXDtorType DtorType,
+ SourceLocation CallLoc,
+ llvm::Value *This) = 0;
+
+ virtual void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF,
+ GlobalDecl GD,
+ CallArgList &CallArgs) {}
+
+ /// Emit any tables needed to implement virtual inheritance. For Itanium,
+ /// this emits virtual table tables. For the MSVC++ ABI, this emits virtual
+ /// base tables.
+ virtual void emitVirtualInheritanceTables(const CXXRecordDecl *RD) = 0;
+
+ virtual void setThunkLinkage(llvm::Function *Thunk, bool ForVTable) = 0;
+
+ virtual llvm::Value *performThisAdjustment(CodeGenFunction &CGF,
+ llvm::Value *This,
+ const ThisAdjustment &TA) = 0;
+
+ virtual llvm::Value *performReturnAdjustment(CodeGenFunction &CGF,
+ llvm::Value *Ret,
+ const ReturnAdjustment &RA) = 0;
virtual void EmitReturnFromThunk(CodeGenFunction &CGF,
RValue RV, QualType ResultType);
@@ -266,6 +373,10 @@ public:
/// Gets the deleted virtual member call name.
virtual StringRef GetDeletedVirtualCallName() = 0;
+ /// \brief Returns true iff static data members that are initialized in the
+ /// class definition should have linkonce linkage.
+ virtual bool isInlineInitializedStaticDataMemberLinkOnce() { return false; }
+
/**************************** Array cookies ******************************/
/// Returns the extra size required in order to store the array
@@ -312,6 +423,9 @@ public:
QualType ElementType, llvm::Value *&NumElements,
llvm::Value *&AllocPtr, CharUnits &CookieSize);
+ /// Return whether the given global decl needs a VTT parameter.
+ virtual bool NeedsVTTParameter(GlobalDecl GD);
+
protected:
/// Returns the extra size required in order to store the array
/// cookie for the given type. Assumes that an array cookie is
@@ -344,7 +458,8 @@ public:
/// - a static local variable
/// - a static data member of a class template instantiation
virtual void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
- llvm::GlobalVariable *DeclPtr, bool PerformInit);
+ llvm::GlobalVariable *DeclPtr,
+ bool PerformInit) = 0;
/// Emit code to force the execution of a destructor during global
/// teardown. The default implementation of this uses atexit.
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index b0f460e..22f2467 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -1,4 +1,4 @@
-//===--- CGCall.cpp - Encapsulate calling convention details ----*- C++ -*-===//
+//===--- CGCall.cpp - Encapsulate calling convention details --------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -22,6 +22,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/CodeGen/CGFunctionInfo.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/Attributes.h"
@@ -41,6 +42,8 @@ static unsigned ClangCallConvToLLVMCallConv(CallingConv CC) {
case CC_X86StdCall: return llvm::CallingConv::X86_StdCall;
case CC_X86FastCall: return llvm::CallingConv::X86_FastCall;
case CC_X86ThisCall: return llvm::CallingConv::X86_ThisCall;
+ case CC_X86_64Win64: return llvm::CallingConv::X86_64_Win64;
+ case CC_X86_64SysV: return llvm::CallingConv::X86_64_SysV;
case CC_AAPCS: return llvm::CallingConv::ARM_AAPCS;
case CC_AAPCS_VFP: return llvm::CallingConv::ARM_AAPCS_VFP;
case CC_IntelOclBicc: return llvm::CallingConv::Intel_OCL_BI;
@@ -103,24 +106,12 @@ static const CGFunctionInfo &arrangeFreeFunctionType(CodeGenTypes &CGT,
return arrangeLLVMFunctionInfo(CGT, prefix, FTP, FTP->getExtInfo());
}
-/// Given the formal ext-info of a C++ instance method, adjust it
-/// according to the C++ ABI in effect.
-static void adjustCXXMethodInfo(CodeGenTypes &CGT,
- FunctionType::ExtInfo &extInfo,
- bool isVariadic) {
- if (extInfo.getCC() == CC_Default) {
- CallingConv CC = CGT.getContext().getDefaultCXXMethodCallConv(isVariadic);
- extInfo = extInfo.withCallingConv(CC);
- }
-}
-
/// Arrange the argument and result information for a free function (i.e.
/// not a C++ or ObjC instance method) of the given type.
static const CGFunctionInfo &arrangeCXXMethodType(CodeGenTypes &CGT,
SmallVectorImpl<CanQualType> &prefix,
CanQual<FunctionProtoType> FTP) {
FunctionType::ExtInfo extInfo = FTP->getExtInfo();
- adjustCXXMethodInfo(CGT, extInfo, FTP->isVariadic());
return arrangeLLVMFunctionInfo(CGT, prefix, FTP, extInfo);
}
@@ -160,6 +151,8 @@ static CallingConv getCallingConventionForDecl(const Decl *D) {
/// Arrange the argument and result information for a call to an
/// unknown C++ non-static member function of the given abstract type.
+/// (Zero value of RD means we don't have any meaningful "this" argument type,
+/// so fall back to a generic pointer type).
/// The member function must be an ordinary function, i.e. not a
/// constructor or destructor.
const CGFunctionInfo &
@@ -168,7 +161,10 @@ CodeGenTypes::arrangeCXXMethodType(const CXXRecordDecl *RD,
SmallVector<CanQualType, 16> argTypes;
// Add the 'this' pointer.
- argTypes.push_back(GetThisType(Context, RD));
+ if (RD)
+ argTypes.push_back(GetThisType(Context, RD));
+ else
+ argTypes.push_back(Context.VoidPtrTy);
return ::arrangeCXXMethodType(*this, argTypes,
FTP->getCanonicalTypeUnqualified().getAs<FunctionProtoType>());
@@ -180,14 +176,15 @@ CodeGenTypes::arrangeCXXMethodType(const CXXRecordDecl *RD,
/// constructor or destructor.
const CGFunctionInfo &
CodeGenTypes::arrangeCXXMethodDeclaration(const CXXMethodDecl *MD) {
- assert(!isa<CXXConstructorDecl>(MD) && "wrong method for contructors!");
+ assert(!isa<CXXConstructorDecl>(MD) && "wrong method for constructors!");
assert(!isa<CXXDestructorDecl>(MD) && "wrong method for destructors!");
CanQual<FunctionProtoType> prototype = GetFormalType(MD);
if (MD->isInstance()) {
// The abstract case is perfectly fine.
- return arrangeCXXMethodType(MD->getParent(), prototype.getTypePtr());
+ const CXXRecordDecl *ThisType = TheCXXABI.getThisArgumentTypeForMethod(MD);
+ return arrangeCXXMethodType(ThisType, prototype.getTypePtr());
}
return arrangeFreeFunctionType(prototype);
@@ -200,7 +197,10 @@ CodeGenTypes::arrangeCXXConstructorDeclaration(const CXXConstructorDecl *D,
CXXCtorType ctorKind) {
SmallVector<CanQualType, 16> argTypes;
argTypes.push_back(GetThisType(Context, D->getParent()));
- CanQualType resultType = Context.VoidTy;
+
+ GlobalDecl GD(D, ctorKind);
+ CanQualType resultType =
+ TheCXXABI.HasThisReturn(GD) ? argTypes.front() : Context.VoidTy;
TheCXXABI.BuildConstructorSignature(D, ctorKind, resultType, argTypes);
@@ -213,7 +213,6 @@ CodeGenTypes::arrangeCXXConstructorDeclaration(const CXXConstructorDecl *D,
argTypes.push_back(FTP->getArgType(i));
FunctionType::ExtInfo extInfo = FTP->getExtInfo();
- adjustCXXMethodInfo(*this, extInfo, FTP->isVariadic());
return arrangeLLVMFunctionInfo(resultType, argTypes, extInfo, required);
}
@@ -225,7 +224,10 @@ CodeGenTypes::arrangeCXXDestructor(const CXXDestructorDecl *D,
CXXDtorType dtorKind) {
SmallVector<CanQualType, 2> argTypes;
argTypes.push_back(GetThisType(Context, D->getParent()));
- CanQualType resultType = Context.VoidTy;
+
+ GlobalDecl GD(D, dtorKind);
+ CanQualType resultType =
+ TheCXXABI.HasThisReturn(GD) ? argTypes.front() : Context.VoidTy;
TheCXXABI.BuildDestructorSignature(D, dtorKind, resultType, argTypes);
@@ -234,7 +236,6 @@ CodeGenTypes::arrangeCXXDestructor(const CXXDestructorDecl *D,
assert(FTP->isVariadic() == 0 && "dtor with formal parameters");
FunctionType::ExtInfo extInfo = FTP->getExtInfo();
- adjustCXXMethodInfo(*this, extInfo, false);
return arrangeLLVMFunctionInfo(resultType, argTypes, extInfo,
RequiredArgs::All);
}
@@ -322,6 +323,7 @@ CodeGenTypes::arrangeGlobalDeclaration(GlobalDecl GD) {
/// additional number of formal parameters considered required.
static const CGFunctionInfo &
arrangeFreeFunctionLikeCall(CodeGenTypes &CGT,
+ CodeGenModule &CGM,
const CallArgList &args,
const FunctionType *fnType,
unsigned numExtraRequiredArgs) {
@@ -340,8 +342,9 @@ arrangeFreeFunctionLikeCall(CodeGenTypes &CGT,
// explicitly use the variadic convention for unprototyped calls,
// treat all of the arguments as required but preserve the nominal
// possibility of variadics.
- } else if (CGT.CGM.getTargetCodeGenInfo()
- .isNoProtoCallVariadic(args, cast<FunctionNoProtoType>(fnType))) {
+ } else if (CGM.getTargetCodeGenInfo()
+ .isNoProtoCallVariadic(args,
+ cast<FunctionNoProtoType>(fnType))) {
required = RequiredArgs(args.size());
}
@@ -356,7 +359,7 @@ arrangeFreeFunctionLikeCall(CodeGenTypes &CGT,
const CGFunctionInfo &
CodeGenTypes::arrangeFreeFunctionCall(const CallArgList &args,
const FunctionType *fnType) {
- return arrangeFreeFunctionLikeCall(*this, args, fnType, 0);
+ return arrangeFreeFunctionLikeCall(*this, CGM, args, fnType, 0);
}
/// A block function call is essentially a free-function call with an
@@ -364,7 +367,7 @@ CodeGenTypes::arrangeFreeFunctionCall(const CallArgList &args,
const CGFunctionInfo &
CodeGenTypes::arrangeBlockFunctionCall(const CallArgList &args,
const FunctionType *fnType) {
- return arrangeFreeFunctionLikeCall(*this, args, fnType, 1);
+ return arrangeFreeFunctionLikeCall(*this, CGM, args, fnType, 1);
}
const CGFunctionInfo &
@@ -393,7 +396,6 @@ CodeGenTypes::arrangeCXXMethodCall(const CallArgList &args,
argTypes.push_back(Context.getCanonicalParamType(i->Ty));
FunctionType::ExtInfo info = FPT->getExtInfo();
- adjustCXXMethodInfo(*this, info, FPT->isVariadic());
return arrangeLLVMFunctionInfo(GetReturnType(FPT->getResultType()),
argTypes, info, required);
}
@@ -642,6 +644,10 @@ EnterStructPointerForCoercedAccess(llvm::Value *SrcPtr,
/// CoerceIntOrPtrToIntOrPtr - Convert a value Val to the specific Ty where both
/// are either integers or pointers. This does a truncation of the value if it
/// is too large or a zero extension if it is too small.
+///
+/// This behaves as if the value were coerced through memory, so on big-endian
+/// targets the high bits are preserved in a truncation, while little-endian
+/// targets preserve the low bits.
static llvm::Value *CoerceIntOrPtrToIntOrPtr(llvm::Value *Val,
llvm::Type *Ty,
CodeGenFunction &CGF) {
@@ -661,8 +667,25 @@ static llvm::Value *CoerceIntOrPtrToIntOrPtr(llvm::Value *Val,
if (isa<llvm::PointerType>(DestIntTy))
DestIntTy = CGF.IntPtrTy;
- if (Val->getType() != DestIntTy)
- Val = CGF.Builder.CreateIntCast(Val, DestIntTy, false, "coerce.val.ii");
+ if (Val->getType() != DestIntTy) {
+ const llvm::DataLayout &DL = CGF.CGM.getDataLayout();
+ if (DL.isBigEndian()) {
+ // Preserve the high bits on big-endian targets.
+ // That is what memory coercion does.
+ uint64_t SrcSize = DL.getTypeAllocSizeInBits(Val->getType());
+ uint64_t DstSize = DL.getTypeAllocSizeInBits(DestIntTy);
+ if (SrcSize > DstSize) {
+ Val = CGF.Builder.CreateLShr(Val, SrcSize - DstSize, "coerce.highbits");
+ Val = CGF.Builder.CreateTrunc(Val, DestIntTy, "coerce.val.ii");
+ } else {
+ Val = CGF.Builder.CreateZExt(Val, DestIntTy, "coerce.val.ii");
+ Val = CGF.Builder.CreateShl(Val, DstSize - SrcSize, "coerce.highbits");
+ }
+ } else {
+ // Little-endian targets preserve the low bits. No shifts required.
+ Val = CGF.Builder.CreateIntCast(Val, DestIntTy, false, "coerce.val.ii");
+ }
+ }
if (isa<llvm::PointerType>(Ty))
Val = CGF.Builder.CreateIntToPtr(Val, Ty, "coerce.val.ip");
@@ -1024,25 +1047,29 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
// Attributes that should go on the function, but not the call site.
if (!CodeGenOpts.DisableFPElim) {
FuncAttrs.addAttribute("no-frame-pointer-elim", "false");
- FuncAttrs.addAttribute("no-frame-pointer-elim-non-leaf", "false");
} else if (CodeGenOpts.OmitLeafFramePointer) {
FuncAttrs.addAttribute("no-frame-pointer-elim", "false");
- FuncAttrs.addAttribute("no-frame-pointer-elim-non-leaf", "true");
+ FuncAttrs.addAttribute("no-frame-pointer-elim-non-leaf");
} else {
FuncAttrs.addAttribute("no-frame-pointer-elim", "true");
- FuncAttrs.addAttribute("no-frame-pointer-elim-non-leaf", "true");
+ FuncAttrs.addAttribute("no-frame-pointer-elim-non-leaf");
}
FuncAttrs.addAttribute("less-precise-fpmad",
- CodeGenOpts.LessPreciseFPMAD ? "true" : "false");
+ llvm::toStringRef(CodeGenOpts.LessPreciseFPMAD));
FuncAttrs.addAttribute("no-infs-fp-math",
- CodeGenOpts.NoInfsFPMath ? "true" : "false");
+ llvm::toStringRef(CodeGenOpts.NoInfsFPMath));
FuncAttrs.addAttribute("no-nans-fp-math",
- CodeGenOpts.NoNaNsFPMath ? "true" : "false");
+ llvm::toStringRef(CodeGenOpts.NoNaNsFPMath));
FuncAttrs.addAttribute("unsafe-fp-math",
- CodeGenOpts.UnsafeFPMath ? "true" : "false");
+ llvm::toStringRef(CodeGenOpts.UnsafeFPMath));
FuncAttrs.addAttribute("use-soft-float",
- CodeGenOpts.SoftFloat ? "true" : "false");
+ llvm::toStringRef(CodeGenOpts.SoftFloat));
+ FuncAttrs.addAttribute("stack-protector-buffer-size",
+ llvm::utostr(CodeGenOpts.SSPBufferSize));
+
+ if (!CodeGenOpts.StackRealignment)
+ FuncAttrs.addAttribute("no-realign-stack");
}
QualType RetTy = FI.getReturnType();
@@ -1050,12 +1077,15 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
const ABIArgInfo &RetAI = FI.getReturnInfo();
switch (RetAI.getKind()) {
case ABIArgInfo::Extend:
- if (RetTy->hasSignedIntegerRepresentation())
- RetAttrs.addAttribute(llvm::Attribute::SExt);
- else if (RetTy->hasUnsignedIntegerRepresentation())
- RetAttrs.addAttribute(llvm::Attribute::ZExt);
- break;
+ if (RetTy->hasSignedIntegerRepresentation())
+ RetAttrs.addAttribute(llvm::Attribute::SExt);
+ else if (RetTy->hasUnsignedIntegerRepresentation())
+ RetAttrs.addAttribute(llvm::Attribute::ZExt);
+ // FALL THROUGH
case ABIArgInfo::Direct:
+ if (RetAI.getInReg())
+ RetAttrs.addAttribute(llvm::Attribute::InReg);
+ break;
case ABIArgInfo::Ignore:
break;
@@ -1263,7 +1293,8 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
} else {
// Load scalar value from indirect argument.
CharUnits Alignment = getContext().getTypeAlignInChars(Ty);
- V = EmitLoadOfScalar(V, false, Alignment.getQuantity(), Ty);
+ V = EmitLoadOfScalar(V, false, Alignment.getQuantity(), Ty,
+ Arg->getLocStart());
if (isPromoted)
V = emitArgumentDemotion(*this, Arg, V);
@@ -1294,6 +1325,13 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
if (isPromoted)
V = emitArgumentDemotion(*this, Arg, V);
+ if (const CXXMethodDecl *MD =
+ dyn_cast_or_null<CXXMethodDecl>(CurCodeDecl)) {
+ if (MD->isVirtual() && Arg == CXXABIThisDecl)
+ V = CGM.getCXXABI().
+ adjustThisParameterInVirtualFunctionPrologue(*this, CurGD, V);
+ }
+
// Because of merging of function types from multiple decls it is
// possible for the type of an argument to not match the corresponding
// type in the function type. Since we are codegening the callee
@@ -1371,7 +1409,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
// Match to what EmitParmDecl is expecting for this type.
if (CodeGenFunction::hasScalarEvaluationKind(Ty)) {
- V = EmitLoadOfScalar(V, false, AlignmentToUse, Ty);
+ V = EmitLoadOfScalar(V, false, AlignmentToUse, Ty, Arg->getLocStart());
if (isPromoted)
V = emitArgumentDemotion(*this, Arg, V);
}
@@ -1609,20 +1647,9 @@ static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) {
return store;
}
-/// Check whether 'this' argument of a callsite matches 'this' of the caller.
-static bool checkThisPointer(llvm::Value *ThisArg, llvm::Value *This) {
- if (ThisArg == This)
- return true;
- // Check whether ThisArg is a bitcast of This.
- llvm::BitCastInst *Bitcast;
- if ((Bitcast = dyn_cast<llvm::BitCastInst>(ThisArg)) &&
- Bitcast->getOperand(0) == This)
- return true;
- return false;
-}
-
void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
- bool EmitRetDbgLoc) {
+ bool EmitRetDbgLoc,
+ SourceLocation EndLoc) {
// Functions with no result always return void.
if (ReturnValue == 0) {
Builder.CreateRetVoid();
@@ -1639,7 +1666,8 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
switch (getEvaluationKind(RetTy)) {
case TEK_Complex: {
ComplexPairTy RT =
- EmitLoadOfComplex(MakeNaturalAlignAddrLValue(ReturnValue, RetTy));
+ EmitLoadOfComplex(MakeNaturalAlignAddrLValue(ReturnValue, RetTy),
+ EndLoc);
EmitStoreOfComplex(RT,
MakeNaturalAlignAddrLValue(CurFn->arg_begin(), RetTy),
/*isInit*/ true);
@@ -1667,8 +1695,10 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
// If there is a dominating store to ReturnValue, we can elide
// the load, zap the store, and usually zap the alloca.
if (llvm::StoreInst *SI = findDominatingStoreToReturnValue(*this)) {
- // Reuse the debug location from the store unless we're told not to.
- if (EmitRetDbgLoc)
+ // Reuse the debug location from the store unless there is
+ // cleanup code to be emitted between the store and return
+ // instruction.
+ if (EmitRetDbgLoc && !AutoreleaseResult)
RetDbgLoc = SI->getDebugLoc();
// Get the stored value and nuke the now-dead store.
RV = SI->getValueOperand();
@@ -1715,26 +1745,14 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
llvm_unreachable("Invalid ABI kind for return argument");
}
- // If this function returns 'this', the last instruction is a CallInst
- // that returns 'this', and 'this' argument of the CallInst points to
- // the same object as CXXThisValue, use the return value from the CallInst.
- // We will not need to keep 'this' alive through the callsite. It also enables
- // optimizations in the backend, such as tail call optimization.
- if (CalleeWithThisReturn && CGM.getCXXABI().HasThisReturn(CurGD)) {
- llvm::BasicBlock *IP = Builder.GetInsertBlock();
- llvm::CallInst *Callsite;
- if (!IP->empty() && (Callsite = dyn_cast<llvm::CallInst>(&IP->back())) &&
- Callsite->getCalledFunction() == CalleeWithThisReturn &&
- checkThisPointer(Callsite->getOperand(0), CXXThisValue))
- RV = Builder.CreateBitCast(Callsite, RetAI.getCoerceToType());
- }
llvm::Instruction *Ret = RV ? Builder.CreateRet(RV) : Builder.CreateRetVoid();
if (!RetDbgLoc.isUnknown())
Ret->setDebugLoc(RetDbgLoc);
}
void CodeGenFunction::EmitDelegateCallArg(CallArgList &args,
- const VarDecl *param) {
+ const VarDecl *param,
+ SourceLocation loc) {
// StartFunction converted the ABI-lowered parameter(s) into a
// local alloca. We need to turn that into an r-value suitable
// for EmitCall.
@@ -1755,7 +1773,7 @@ void CodeGenFunction::EmitDelegateCallArg(CallArgList &args,
return args.add(RValue::get(Builder.CreateLoad(local)), type);
}
- args.add(convertTempToRValue(local, type), type);
+ args.add(convertTempToRValue(local, type, loc), type);
}
static bool isProvablyNull(llvm::Value *addr) {
@@ -1814,7 +1832,7 @@ static void emitWriteback(CodeGenFunction &CGF,
CGF.EmitARCIntrinsicUse(writeback.ToUse);
// Load the old value (primitively).
- llvm::Value *oldValue = CGF.EmitLoadOfScalar(srcLV);
+ llvm::Value *oldValue = CGF.EmitLoadOfScalar(srcLV, SourceLocation());
// Put the new value in place (primitively).
CGF.EmitStoreOfScalar(value, srcLV, /*init*/ false);
@@ -1839,6 +1857,19 @@ static void emitWritebacks(CodeGenFunction &CGF,
emitWriteback(CGF, *i);
}
+static void deactivateArgCleanupsBeforeCall(CodeGenFunction &CGF,
+ const CallArgList &CallArgs) {
+ assert(CGF.getTarget().getCXXABI().isArgumentDestroyedByCallee());
+ ArrayRef<CallArgList::CallArgCleanup> Cleanups =
+ CallArgs.getCleanupsToDeactivate();
+ // Iterate in reverse to increase the likelihood of popping the cleanup.
+ for (ArrayRef<CallArgList::CallArgCleanup>::reverse_iterator
+ I = Cleanups.rbegin(), E = Cleanups.rend(); I != E; ++I) {
+ CGF.DeactivateCleanupBlock(I->Cleanup, I->IsActiveIP);
+ I->IsActiveIP->eraseFromParent();
+ }
+}
+
static const Expr *maybeGetUnaryAddrOfOperand(const Expr *E) {
if (const UnaryOperator *uop = dyn_cast<UnaryOperator>(E->IgnoreParens()))
if (uop->getOpcode() == UO_AddrOf)
@@ -1930,7 +1961,7 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args,
// Perform a copy if necessary.
if (shouldCopy) {
- RValue srcRV = CGF.EmitLoadOfLValue(srcLV);
+ RValue srcRV = CGF.EmitLoadOfLValue(srcLV, SourceLocation());
assert(srcRV.isScalar());
llvm::Value *src = srcRV.getScalarVal();
@@ -1987,16 +2018,47 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
if (E->isGLValue()) {
assert(E->getObjectKind() == OK_Ordinary);
- return args.add(EmitReferenceBindingToExpr(E, /*InitializedDecl=*/0),
- type);
+ return args.add(EmitReferenceBindingToExpr(E), type);
+ }
+
+ bool HasAggregateEvalKind = hasAggregateEvaluationKind(type);
+
+ // In the Microsoft C++ ABI, aggregate arguments are destructed by the callee.
+ // However, we still have to push an EH-only cleanup in case we unwind before
+ // we make it to the call.
+ if (HasAggregateEvalKind &&
+ CGM.getTarget().getCXXABI().isArgumentDestroyedByCallee()) {
+ const CXXRecordDecl *RD = type->getAsCXXRecordDecl();
+ if (RD && RD->hasNonTrivialDestructor()) {
+ AggValueSlot Slot = CreateAggTemp(type, "agg.arg.tmp");
+ Slot.setExternallyDestructed();
+ EmitAggExpr(E, Slot);
+ RValue RV = Slot.asRValue();
+ args.add(RV, type);
+
+ pushDestroy(EHCleanup, RV.getAggregateAddr(), type, destroyCXXObject,
+ /*useEHCleanupForArray*/ true);
+ // This unreachable is a temporary marker which will be removed later.
+ llvm::Instruction *IsActive = Builder.CreateUnreachable();
+ args.addArgCleanupDeactivation(EHStack.getInnermostEHScope(), IsActive);
+ return;
+ }
}
- if (hasAggregateEvaluationKind(type) &&
- isa<ImplicitCastExpr>(E) &&
+ if (HasAggregateEvalKind && isa<ImplicitCastExpr>(E) &&
cast<CastExpr>(E)->getCastKind() == CK_LValueToRValue) {
LValue L = EmitLValue(cast<CastExpr>(E)->getSubExpr());
assert(L.isSimple());
- args.add(L.asAggregateRValue(), type, /*NeedsCopy*/true);
+ if (L.getAlignment() >= getContext().getTypeAlignInChars(type)) {
+ args.add(L.asAggregateRValue(), type, /*NeedsCopy*/true);
+ } else {
+ // We can't represent a misaligned lvalue in the CallArgList, so copy
+ // to an aligned temporary now.
+ llvm::Value *tmp = CreateMemTemp(type);
+ EmitAggregateCopy(tmp, L.getAddress(), type, L.isVolatile(),
+ L.getAlignment());
+ args.add(RValue::getAggregate(tmp), type);
+ }
return;
}
@@ -2127,7 +2189,7 @@ static void checkArgMatches(llvm::Value *Elt, unsigned &ArgNo,
}
void CodeGenFunction::ExpandTypeToArgs(QualType Ty, RValue RV,
- SmallVector<llvm::Value*,16> &Args,
+ SmallVectorImpl<llvm::Value *> &Args,
llvm::FunctionType *IRFuncTy) {
if (const ConstantArrayType *AT = getContext().getAsConstantArrayType(Ty)) {
unsigned NumElts = AT->getSize().getZExtValue();
@@ -2135,7 +2197,7 @@ void CodeGenFunction::ExpandTypeToArgs(QualType Ty, RValue RV,
llvm::Value *Addr = RV.getAggregateAddr();
for (unsigned Elt = 0; Elt < NumElts; ++Elt) {
llvm::Value *EltAddr = Builder.CreateConstGEP2_32(Addr, 0, Elt);
- RValue EltRV = convertTempToRValue(EltAddr, EltTy);
+ RValue EltRV = convertTempToRValue(EltAddr, EltTy, SourceLocation());
ExpandTypeToArgs(EltTy, EltRV, Args, IRFuncTy);
}
} else if (const RecordType *RT = Ty->getAs<RecordType>()) {
@@ -2159,7 +2221,7 @@ void CodeGenFunction::ExpandTypeToArgs(QualType Ty, RValue RV,
}
}
if (LargestFD) {
- RValue FldRV = EmitRValueForField(LV, LargestFD);
+ RValue FldRV = EmitRValueForField(LV, LargestFD, SourceLocation());
ExpandTypeToArgs(LargestFD->getType(), FldRV, Args, IRFuncTy);
}
} else {
@@ -2167,7 +2229,7 @@ void CodeGenFunction::ExpandTypeToArgs(QualType Ty, RValue RV,
i != e; ++i) {
FieldDecl *FD = *i;
- RValue FldRV = EmitRValueForField(LV, FD);
+ RValue FldRV = EmitRValueForField(LV, FD, SourceLocation());
ExpandTypeToArgs(FD->getType(), FldRV, Args, IRFuncTy);
}
}
@@ -2394,6 +2456,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
}
}
+ if (!CallArgs.getCleanupsToDeactivate().empty())
+ deactivateArgCleanupsBeforeCall(*this, CallArgs);
+
// If the callee is a bitcast of a function to a varargs pointer to function
// type, check to see if we can remove the bitcast. This handles some cases
// with unprototyped functions.
@@ -2482,7 +2547,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
switch (RetAI.getKind()) {
case ABIArgInfo::Indirect:
- return convertTempToRValue(Args[0], RetTy);
+ return convertTempToRValue(Args[0], RetTy, SourceLocation());
case ABIArgInfo::Ignore:
// If we are ignoring an argument that had a result, make sure to
@@ -2540,7 +2605,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
}
CreateCoercedStore(CI, StorePtr, DestIsVolatile, *this);
- return convertTempToRValue(DestPtr, RetTy);
+ return convertTempToRValue(DestPtr, RetTy, SourceLocation());
}
case ABIArgInfo::Expand:
diff --git a/lib/CodeGen/CGCall.h b/lib/CodeGen/CGCall.h
index 85c3320..532cb59c 100644
--- a/lib/CodeGen/CGCall.h
+++ b/lib/CodeGen/CGCall.h
@@ -16,6 +16,7 @@
#define CLANG_CODEGEN_CGCALL_H
#include "CGValue.h"
+#include "EHScopeStack.h"
#include "clang/AST/CanonicalType.h"
#include "clang/AST/Type.h"
#include "llvm/ADT/FoldingSet.h"
@@ -67,6 +68,14 @@ namespace CodeGen {
llvm::Value *ToUse;
};
+ struct CallArgCleanup {
+ EHScopeStack::stable_iterator Cleanup;
+
+ /// The "is active" insertion point. This instruction is temporary and
+ /// will be removed after insertion.
+ llvm::Instruction *IsActiveIP;
+ };
+
void add(RValue rvalue, QualType type, bool needscopy = false) {
push_back(CallArg(rvalue, type, needscopy));
}
@@ -92,57 +101,25 @@ namespace CodeGen {
writeback_iterator writeback_begin() const { return Writebacks.begin(); }
writeback_iterator writeback_end() const { return Writebacks.end(); }
- private:
- SmallVector<Writeback, 1> Writebacks;
- };
-
- /// A class for recording the number of arguments that a function
- /// signature requires.
- class RequiredArgs {
- /// The number of required arguments, or ~0 if the signature does
- /// not permit optional arguments.
- unsigned NumRequired;
- public:
- enum All_t { All };
-
- RequiredArgs(All_t _) : NumRequired(~0U) {}
- explicit RequiredArgs(unsigned n) : NumRequired(n) {
- assert(n != ~0U);
- }
-
- /// Compute the arguments required by the given formal prototype,
- /// given that there may be some additional, non-formal arguments
- /// in play.
- static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype,
- unsigned additional) {
- if (!prototype->isVariadic()) return All;
- return RequiredArgs(prototype->getNumArgs() + additional);
- }
-
- static RequiredArgs forPrototype(const FunctionProtoType *prototype) {
- return forPrototypePlus(prototype, 0);
- }
-
- static RequiredArgs forPrototype(CanQual<FunctionProtoType> prototype) {
- return forPrototype(prototype.getTypePtr());
+ void addArgCleanupDeactivation(EHScopeStack::stable_iterator Cleanup,
+ llvm::Instruction *IsActiveIP) {
+ CallArgCleanup ArgCleanup;
+ ArgCleanup.Cleanup = Cleanup;
+ ArgCleanup.IsActiveIP = IsActiveIP;
+ CleanupsToDeactivate.push_back(ArgCleanup);
}
- static RequiredArgs forPrototypePlus(CanQual<FunctionProtoType> prototype,
- unsigned additional) {
- return forPrototypePlus(prototype.getTypePtr(), additional);
+ ArrayRef<CallArgCleanup> getCleanupsToDeactivate() const {
+ return CleanupsToDeactivate;
}
- bool allowsOptionalArgs() const { return NumRequired != ~0U; }
- unsigned getNumRequiredArgs() const {
- assert(allowsOptionalArgs());
- return NumRequired;
- }
+ private:
+ SmallVector<Writeback, 1> Writebacks;
- unsigned getOpaqueData() const { return NumRequired; }
- static RequiredArgs getFromOpaqueData(unsigned value) {
- if (value == ~0U) return All;
- return RequiredArgs(value);
- }
+ /// Deactivate these cleanups immediately before making the call. This
+ /// is used to cleanup objects that are owned by the callee once the call
+ /// occurs.
+ SmallVector<CallArgCleanup, 1> CleanupsToDeactivate;
};
/// FunctionArgList - Type for representing both the decl and type
@@ -151,137 +128,6 @@ namespace CodeGen {
class FunctionArgList : public SmallVector<const VarDecl*, 16> {
};
- /// CGFunctionInfo - Class to encapsulate the information about a
- /// function definition.
- class CGFunctionInfo : public llvm::FoldingSetNode {
- struct ArgInfo {
- CanQualType type;
- ABIArgInfo info;
- };
-
- /// The LLVM::CallingConv to use for this function (as specified by the
- /// user).
- unsigned CallingConvention : 8;
-
- /// The LLVM::CallingConv to actually use for this function, which may
- /// depend on the ABI.
- unsigned EffectiveCallingConvention : 8;
-
- /// The clang::CallingConv that this was originally created with.
- unsigned ASTCallingConvention : 8;
-
- /// Whether this function is noreturn.
- unsigned NoReturn : 1;
-
- /// Whether this function is returns-retained.
- unsigned ReturnsRetained : 1;
-
- /// How many arguments to pass inreg.
- unsigned HasRegParm : 1;
- unsigned RegParm : 4;
-
- RequiredArgs Required;
-
- unsigned NumArgs;
- ArgInfo *getArgsBuffer() {
- return reinterpret_cast<ArgInfo*>(this+1);
- }
- const ArgInfo *getArgsBuffer() const {
- return reinterpret_cast<const ArgInfo*>(this + 1);
- }
-
- CGFunctionInfo() : Required(RequiredArgs::All) {}
-
- public:
- static CGFunctionInfo *create(unsigned llvmCC,
- const FunctionType::ExtInfo &extInfo,
- CanQualType resultType,
- ArrayRef<CanQualType> argTypes,
- RequiredArgs required);
-
- typedef const ArgInfo *const_arg_iterator;
- typedef ArgInfo *arg_iterator;
-
- const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; }
- const_arg_iterator arg_end() const { return getArgsBuffer() + 1 + NumArgs; }
- arg_iterator arg_begin() { return getArgsBuffer() + 1; }
- arg_iterator arg_end() { return getArgsBuffer() + 1 + NumArgs; }
-
- unsigned arg_size() const { return NumArgs; }
-
- bool isVariadic() const { return Required.allowsOptionalArgs(); }
- RequiredArgs getRequiredArgs() const { return Required; }
-
- bool isNoReturn() const { return NoReturn; }
-
- /// In ARC, whether this function retains its return value. This
- /// is not always reliable for call sites.
- bool isReturnsRetained() const { return ReturnsRetained; }
-
- /// getASTCallingConvention() - Return the AST-specified calling
- /// convention.
- CallingConv getASTCallingConvention() const {
- return CallingConv(ASTCallingConvention);
- }
-
- /// getCallingConvention - Return the user specified calling
- /// convention, which has been translated into an LLVM CC.
- unsigned getCallingConvention() const { return CallingConvention; }
-
- /// getEffectiveCallingConvention - Return the actual calling convention to
- /// use, which may depend on the ABI.
- unsigned getEffectiveCallingConvention() const {
- return EffectiveCallingConvention;
- }
- void setEffectiveCallingConvention(unsigned Value) {
- EffectiveCallingConvention = Value;
- }
-
- bool getHasRegParm() const { return HasRegParm; }
- unsigned getRegParm() const { return RegParm; }
-
- FunctionType::ExtInfo getExtInfo() const {
- return FunctionType::ExtInfo(isNoReturn(),
- getHasRegParm(), getRegParm(),
- getASTCallingConvention(),
- isReturnsRetained());
- }
-
- CanQualType getReturnType() const { return getArgsBuffer()[0].type; }
-
- ABIArgInfo &getReturnInfo() { return getArgsBuffer()[0].info; }
- const ABIArgInfo &getReturnInfo() const { return getArgsBuffer()[0].info; }
-
- void Profile(llvm::FoldingSetNodeID &ID) {
- ID.AddInteger(getASTCallingConvention());
- ID.AddBoolean(NoReturn);
- ID.AddBoolean(ReturnsRetained);
- ID.AddBoolean(HasRegParm);
- ID.AddInteger(RegParm);
- ID.AddInteger(Required.getOpaqueData());
- getReturnType().Profile(ID);
- for (arg_iterator it = arg_begin(), ie = arg_end(); it != ie; ++it)
- it->type.Profile(ID);
- }
- static void Profile(llvm::FoldingSetNodeID &ID,
- const FunctionType::ExtInfo &info,
- RequiredArgs required,
- CanQualType resultType,
- ArrayRef<CanQualType> argTypes) {
- ID.AddInteger(info.getCC());
- ID.AddBoolean(info.getNoReturn());
- ID.AddBoolean(info.getProducesResult());
- ID.AddBoolean(info.getHasRegParm());
- ID.AddInteger(info.getRegParm());
- ID.AddInteger(required.getOpaqueData());
- resultType.Profile(ID);
- for (ArrayRef<CanQualType>::iterator
- i = argTypes.begin(), e = argTypes.end(); i != e; ++i) {
- i->Profile(ID);
- }
- }
- };
-
/// ReturnValueSlot - Contains the address where the return value of a
/// function can be stored, and whether the address is volatile or not.
class ReturnValueSlot {
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index 3fd0757..4848d75 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -17,10 +17,12 @@
#include "CodeGenFunction.h"
#include "CGCXXABI.h"
#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtCXX.h"
#include "clang/Basic/TargetBuiltins.h"
+#include "clang/CodeGen/CGFunctionInfo.h"
#include "clang/Frontend/CodeGenOptions.h"
using namespace clang;
@@ -198,7 +200,8 @@ CodeGenFunction::GetAddressOfBaseClass(llvm::Value *Value,
// Compute the virtual offset.
llvm::Value *VirtualOffset = 0;
if (VBase) {
- VirtualOffset = GetVirtualBaseClassOffset(Value, Derived, VBase);
+ VirtualOffset =
+ CGM.getCXXABI().GetVirtualBaseClassOffset(*this, Value, Derived, VBase);
}
// Apply both offsets.
@@ -285,7 +288,7 @@ CodeGenFunction::GetAddressOfDerivedClass(llvm::Value *Value,
llvm::Value *CodeGenFunction::GetVTTParameter(GlobalDecl GD,
bool ForVirtualBase,
bool Delegating) {
- if (!CodeGenVTables::needsVTTParameter(GD)) {
+ if (!CGM.getCXXABI().NeedsVTTParameter(GD)) {
// This constructor/destructor does not need a VTT parameter.
return 0;
}
@@ -303,7 +306,7 @@ llvm::Value *CodeGenFunction::GetVTTParameter(GlobalDecl GD,
} else if (RD == Base) {
// If the record matches the base, this is the complete ctor/dtor
// variant calling the base variant in a class with virtual bases.
- assert(!CodeGenVTables::needsVTTParameter(CurGD) &&
+ assert(!CGM.getCXXABI().NeedsVTTParameter(CurGD) &&
"doing no-op VTT offset in base dtor/ctor?");
assert(!ForVirtualBase && "Can't have same class as virtual base!");
SubVTTIndex = 0;
@@ -318,7 +321,7 @@ llvm::Value *CodeGenFunction::GetVTTParameter(GlobalDecl GD,
assert(SubVTTIndex != 0 && "Sub-VTT index must be greater than zero!");
}
- if (CodeGenVTables::needsVTTParameter(CurGD)) {
+ if (CGM.getCXXABI().NeedsVTTParameter(CurGD)) {
// A VTT parameter was passed to the constructor, use it.
VTT = LoadCXXVTT();
VTT = Builder.CreateConstInBoundsGEP1_64(VTT, SubVTTIndex);
@@ -432,52 +435,45 @@ static void EmitAggMemberInitializer(CodeGenFunction &CGF,
unsigned Index) {
if (Index == ArrayIndexes.size()) {
LValue LV = LHS;
- { // Scope for Cleanups.
- CodeGenFunction::RunCleanupsScope Cleanups(CGF);
-
- if (ArrayIndexVar) {
- // If we have an array index variable, load it and use it as an offset.
- // Then, increment the value.
- llvm::Value *Dest = LHS.getAddress();
- llvm::Value *ArrayIndex = CGF.Builder.CreateLoad(ArrayIndexVar);
- Dest = CGF.Builder.CreateInBoundsGEP(Dest, ArrayIndex, "destaddress");
- llvm::Value *Next = llvm::ConstantInt::get(ArrayIndex->getType(), 1);
- Next = CGF.Builder.CreateAdd(ArrayIndex, Next, "inc");
- CGF.Builder.CreateStore(Next, ArrayIndexVar);
-
- // Update the LValue.
- LV.setAddress(Dest);
- CharUnits Align = CGF.getContext().getTypeAlignInChars(T);
- LV.setAlignment(std::min(Align, LV.getAlignment()));
- }
- switch (CGF.getEvaluationKind(T)) {
- case TEK_Scalar:
- CGF.EmitScalarInit(Init, /*decl*/ 0, LV, false);
- break;
- case TEK_Complex:
- CGF.EmitComplexExprIntoLValue(Init, LV, /*isInit*/ true);
- break;
- case TEK_Aggregate: {
- AggValueSlot Slot =
- AggValueSlot::forLValue(LV,
- AggValueSlot::IsDestructed,
- AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased);
-
- CGF.EmitAggExpr(Init, Slot);
- break;
- }
- }
+ if (ArrayIndexVar) {
+ // If we have an array index variable, load it and use it as an offset.
+ // Then, increment the value.
+ llvm::Value *Dest = LHS.getAddress();
+ llvm::Value *ArrayIndex = CGF.Builder.CreateLoad(ArrayIndexVar);
+ Dest = CGF.Builder.CreateInBoundsGEP(Dest, ArrayIndex, "destaddress");
+ llvm::Value *Next = llvm::ConstantInt::get(ArrayIndex->getType(), 1);
+ Next = CGF.Builder.CreateAdd(ArrayIndex, Next, "inc");
+ CGF.Builder.CreateStore(Next, ArrayIndexVar);
+
+ // Update the LValue.
+ LV.setAddress(Dest);
+ CharUnits Align = CGF.getContext().getTypeAlignInChars(T);
+ LV.setAlignment(std::min(Align, LV.getAlignment()));
}
- // Now, outside of the initializer cleanup scope, destroy the backing array
- // for a std::initializer_list member.
- CGF.MaybeEmitStdInitializerListCleanup(LV.getAddress(), Init);
+ switch (CGF.getEvaluationKind(T)) {
+ case TEK_Scalar:
+ CGF.EmitScalarInit(Init, /*decl*/ 0, LV, false);
+ break;
+ case TEK_Complex:
+ CGF.EmitComplexExprIntoLValue(Init, LV, /*isInit*/ true);
+ break;
+ case TEK_Aggregate: {
+ AggValueSlot Slot =
+ AggValueSlot::forLValue(LV,
+ AggValueSlot::IsDestructed,
+ AggValueSlot::DoesNotNeedGCBarriers,
+ AggValueSlot::IsNotAliased);
+
+ CGF.EmitAggExpr(Init, Slot);
+ break;
+ }
+ }
return;
}
-
+
const ConstantArrayType *Array = CGF.getContext().getAsConstantArrayType(T);
assert(Array && "Array initialization without the array type?");
llvm::Value *IndexVar
@@ -511,16 +507,12 @@ static void EmitAggMemberInitializer(CodeGenFunction &CGF,
CGF.EmitBlock(ForBody);
llvm::BasicBlock *ContinueBlock = CGF.createBasicBlock("for.inc");
-
- {
- CodeGenFunction::RunCleanupsScope Cleanups(CGF);
-
- // Inside the loop body recurse to emit the inner loop or, eventually, the
- // constructor call.
- EmitAggMemberInitializer(CGF, LHS, Init, ArrayIndexVar,
- Array->getElementType(), ArrayIndexes, Index + 1);
- }
-
+
+ // Inside the loop body recurse to emit the inner loop or, eventually, the
+ // constructor call.
+ EmitAggMemberInitializer(CGF, LHS, Init, ArrayIndexVar,
+ Array->getElementType(), ArrayIndexes, Index + 1);
+
CGF.EmitBlock(ContinueBlock);
// Emit the increment of the loop counter.
@@ -573,7 +565,7 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
// in the AST, we could generalize it more easily.
const ConstantArrayType *Array
= CGF.getContext().getAsConstantArrayType(FieldType);
- if (Array && Constructor->isImplicitlyDefined() &&
+ if (Array && Constructor->isDefaulted() &&
Constructor->isCopyOrMoveConstructor()) {
QualType BaseElementTy = CGF.getContext().getBaseElementType(Array);
CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(MemberInit->getInit());
@@ -713,7 +705,7 @@ void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) {
CGM.getTarget().getCXXABI().hasConstructorVariants()) {
if (CGDebugInfo *DI = getDebugInfo())
DI->EmitLocation(Builder, Ctor->getLocEnd());
- EmitDelegateCXXConstructorCall(Ctor, Ctor_Base, Args);
+ EmitDelegateCXXConstructorCall(Ctor, Ctor_Base, Args, Ctor->getLocEnd());
return;
}
@@ -725,7 +717,7 @@ void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) {
if (IsTryBody)
EnterCXXTryStmt(*cast<CXXTryStmt>(Body), true);
- EHScopeStack::stable_iterator CleanupDepth = EHStack.stable_begin();
+ RunCleanupsScope RunCleanups(*this);
// TODO: in restricted cases, we can emit the vbase initializers of
// a complete ctor and then delegate to the base ctor.
@@ -744,13 +736,36 @@ void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) {
// initializers, which includes (along the exceptional path) the
// destructors for those members and bases that were fully
// constructed.
- PopCleanupBlocks(CleanupDepth);
+ RunCleanups.ForceCleanup();
if (IsTryBody)
ExitCXXTryStmt(*cast<CXXTryStmt>(Body), true);
}
namespace {
+ /// RAII object to indicate that codegen is copying the value representation
+ /// instead of the object representation. Useful when copying a struct or
+ /// class which has uninitialized members and we're only performing
+ /// lvalue-to-rvalue conversion on the object but not its members.
+ class CopyingValueRepresentation {
+ public:
+ explicit CopyingValueRepresentation(CodeGenFunction &CGF)
+ : CGF(CGF), SO(*CGF.SanOpts), OldSanOpts(CGF.SanOpts) {
+ SO.Bool = false;
+ SO.Enum = false;
+ CGF.SanOpts = &SO;
+ }
+ ~CopyingValueRepresentation() {
+ CGF.SanOpts = OldSanOpts;
+ }
+ private:
+ CodeGenFunction &CGF;
+ SanitizerOptions SO;
+ const SanitizerOptions *OldSanOpts;
+ };
+}
+
+namespace {
class FieldMemcpyizer {
public:
FieldMemcpyizer(CodeGenFunction &CGF, const CXXRecordDecl *ClassDecl,
@@ -859,8 +874,12 @@ namespace {
}
void addNextField(FieldDecl *F) {
- assert(F->getFieldIndex() == LastAddedFieldIndex + 1 &&
- "Cannot aggregate non-contiguous fields.");
+ // For the most part, the following invariant will hold:
+ // F->getFieldIndex() == LastAddedFieldIndex + 1
+ // The one exception is that Sema won't add a copy-initializer for an
+ // unnamed bitfield, which will show up here as a gap in the sequence.
+ assert(F->getFieldIndex() >= LastAddedFieldIndex + 1 &&
+ "Cannot aggregate fields out of order.");
LastAddedFieldIndex = F->getFieldIndex();
// The 'first' and 'last' fields are chosen by offset, rather than field
@@ -891,7 +910,7 @@ namespace {
/// constructor.
static const VarDecl* getTrivialCopySource(const CXXConstructorDecl *CD,
FunctionArgList &Args) {
- if (CD->isCopyOrMoveConstructor() && CD->isImplicitlyDefined())
+ if (CD->isCopyOrMoveConstructor() && CD->isDefaulted())
return Args[Args.size() - 1];
return 0;
}
@@ -925,7 +944,7 @@ namespace {
FunctionArgList &Args)
: FieldMemcpyizer(CGF, CD->getParent(), getTrivialCopySource(CD, Args)),
ConstructorDecl(CD),
- MemcpyableCtor(CD->isImplicitlyDefined() &&
+ MemcpyableCtor(CD->isDefaulted() &&
CD->isCopyOrMoveConstructor() &&
CGF.getLangOpts().getGC() == LangOptions::NonGC),
Args(Args) { }
@@ -945,9 +964,10 @@ namespace {
if (AggregatedInits.size() <= 1) {
// This memcpy is too small to be worthwhile. Fall back on default
// codegen.
- for (unsigned i = 0; i < AggregatedInits.size(); ++i) {
+ if (!AggregatedInits.empty()) {
+ CopyingValueRepresentation CVR(CGF);
EmitMemberInitializer(CGF, ConstructorDecl->getParent(),
- AggregatedInits[i], ConstructorDecl, Args);
+ AggregatedInits[0], ConstructorDecl, Args);
}
reset();
return;
@@ -986,8 +1006,8 @@ namespace {
private:
// Returns the memcpyable field copied by the given statement, if one
- // exists. Otherwise r
- FieldDecl* getMemcpyableField(Stmt *S) {
+ // exists. Otherwise returns null.
+ FieldDecl *getMemcpyableField(Stmt *S) {
if (!AssignmentsMemcpyable)
return 0;
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(S)) {
@@ -1081,8 +1101,10 @@ namespace {
void emitAggregatedStmts() {
if (AggregatedStmts.size() <= 1) {
- for (unsigned i = 0; i < AggregatedStmts.size(); ++i)
- CGF.EmitStmt(AggregatedStmts[i]);
+ if (!AggregatedStmts.empty()) {
+ CopyingValueRepresentation CVR(CGF);
+ CGF.EmitStmt(AggregatedStmts[0]);
+ }
reset();
}
@@ -1115,7 +1137,8 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
!CGM.getTarget().getCXXABI().hasConstructorVariants()) {
// The ABIs that don't have constructor variants need to put a branch
// before the virtual base initialization code.
- BaseCtorContinueBB = CGM.getCXXABI().EmitCtorCompleteObjectHandler(*this);
+ BaseCtorContinueBB =
+ CGM.getCXXABI().EmitCtorCompleteObjectHandler(*this, ClassDecl);
assert(BaseCtorContinueBB);
}
@@ -1270,16 +1293,19 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
// If this is the complete variant, just invoke the base variant;
// the epilogue will destruct the virtual bases. But we can't do
// this optimization if the body is a function-try-block, because
- // we'd introduce *two* handler blocks.
+ // we'd introduce *two* handler blocks. In the Microsoft ABI, we
+ // always delegate because we might not have a definition in this TU.
switch (DtorType) {
case Dtor_Deleting: llvm_unreachable("already handled deleting case");
case Dtor_Complete:
+ assert((Body || getTarget().getCXXABI().isMicrosoft()) &&
+ "can't emit a dtor without a body for non-Microsoft ABIs");
+
// Enter the cleanup scopes for virtual bases.
EnterDtorCleanups(Dtor, Dtor_Complete);
- if (!isTryBody &&
- CGM.getTarget().getCXXABI().hasDestructorVariants()) {
+ if (!isTryBody) {
EmitCXXDestructorCall(Dtor, Dtor_Base, /*ForVirtualBase=*/false,
/*Delegating=*/false, LoadCXXThis());
break;
@@ -1287,6 +1313,8 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
// Fallthrough: act like we're in the base variant.
case Dtor_Base:
+ assert(Body);
+
// Enter the cleanup scopes for fields and non-virtual bases.
EnterDtorCleanups(Dtor, Dtor_Base);
@@ -1635,17 +1663,6 @@ 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().getDebugInfo() == CodeGenOptions::LimitedDebugInfo) {
- // If debug info for this class has not 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 this is a trivial constructor, just emit what's needed.
if (D->isTrivial()) {
if (ArgBeg == ArgEnd) {
@@ -1667,11 +1684,8 @@ CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
}
// Non-trivial constructors are handled in an ABI-specific manner.
- llvm::Value *Callee = CGM.getCXXABI().EmitConstructorCall(*this, D, Type,
- ForVirtualBase, Delegating, This, ArgBeg, ArgEnd);
- if (CGM.getCXXABI().HasThisReturn(CurGD) &&
- CGM.getCXXABI().HasThisReturn(GlobalDecl(D, Type)))
- CalleeWithThisReturn = Callee;
+ CGM.getCXXABI().EmitConstructorCall(*this, D, Type, ForVirtualBase,
+ Delegating, This, ArgBeg, ArgEnd);
}
void
@@ -1686,8 +1700,7 @@ CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D,
EmitAggregateCopy(This, Src, (*ArgBeg)->getType());
return;
}
- llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D,
- clang::Ctor_Complete);
+ llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, clang::Ctor_Complete);
assert(D->isInstance() &&
"Trying to emit a member call expr on a static method!");
@@ -1730,7 +1743,8 @@ CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D,
void
CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,
CXXCtorType CtorType,
- const FunctionArgList &Args) {
+ const FunctionArgList &Args,
+ SourceLocation Loc) {
CallArgList DelegateArgs;
FunctionArgList::const_iterator I = Args.begin(), E = Args.end();
@@ -1747,7 +1761,7 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,
QualType VoidPP = getContext().getPointerType(getContext().VoidPtrTy);
DelegateArgs.add(RValue::get(VTT), VoidPP);
- if (CodeGenVTables::needsVTTParameter(CurGD)) {
+ if (CGM.getCXXABI().NeedsVTTParameter(CurGD)) {
assert(I != E && "cannot skip vtt parameter, already done with args");
assert((*I)->getType() == VoidPP && "skipping parameter not of vtt type");
++I;
@@ -1757,15 +1771,13 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,
// Explicit arguments.
for (; I != E; ++I) {
const VarDecl *param = *I;
- EmitDelegateCallArg(DelegateArgs, param);
+ // FIXME: per-argument source location
+ EmitDelegateCallArg(DelegateArgs, param, Loc);
}
llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(Ctor, CtorType);
EmitCall(CGM.getTypes().arrangeCXXConstructorDeclaration(Ctor, CtorType),
Callee, ReturnValueSlot(), DelegateArgs, Ctor);
- if (CGM.getCXXABI().HasThisReturn(CurGD) &&
- CGM.getCXXABI().HasThisReturn(GlobalDecl(Ctor, CtorType)))
- CalleeWithThisReturn = Callee;
}
namespace {
@@ -1818,8 +1830,8 @@ void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD,
bool ForVirtualBase,
bool Delegating,
llvm::Value *This) {
- llvm::Value *VTT = GetVTTParameter(GlobalDecl(DD, Type),
- ForVirtualBase, Delegating);
+ GlobalDecl GD(DD, Type);
+ llvm::Value *VTT = GetVTTParameter(GD, ForVirtualBase, Delegating);
llvm::Value *Callee = 0;
if (getLangOpts().AppleKext)
Callee = BuildAppleKextVirtualDestructorCall(DD, Type,
@@ -1827,14 +1839,14 @@ void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD,
if (!Callee)
Callee = CGM.GetAddrOfCXXDestructor(DD, Type);
-
+
+ if (DD->isVirtual())
+ This = CGM.getCXXABI().adjustThisArgumentForVirtualCall(*this, GD, This);
+
// FIXME: Provide a source location here.
EmitCXXMemberCall(DD, SourceLocation(), Callee, ReturnValueSlot(), This,
VTT, getContext().getPointerType(getContext().VoidPtrTy),
0, 0);
- if (CGM.getCXXABI().HasThisReturn(CurGD) &&
- CGM.getCXXABI().HasThisReturn(GlobalDecl(DD, Type)))
- CalleeWithThisReturn = Callee;
}
namespace {
@@ -1868,69 +1880,30 @@ void CodeGenFunction::PushDestructorCleanup(QualType T, llvm::Value *Addr) {
PushDestructorCleanup(D, Addr);
}
-llvm::Value *
-CodeGenFunction::GetVirtualBaseClassOffset(llvm::Value *This,
- const CXXRecordDecl *ClassDecl,
- const CXXRecordDecl *BaseClassDecl) {
- llvm::Value *VTablePtr = GetVTablePtr(This, Int8PtrTy);
- CharUnits VBaseOffsetOffset =
- CGM.getVTableContext().getVirtualBaseOffsetOffset(ClassDecl, BaseClassDecl);
-
- llvm::Value *VBaseOffsetPtr =
- Builder.CreateConstGEP1_64(VTablePtr, VBaseOffsetOffset.getQuantity(),
- "vbase.offset.ptr");
- llvm::Type *PtrDiffTy =
- ConvertType(getContext().getPointerDiffType());
-
- VBaseOffsetPtr = Builder.CreateBitCast(VBaseOffsetPtr,
- PtrDiffTy->getPointerTo());
-
- llvm::Value *VBaseOffset = Builder.CreateLoad(VBaseOffsetPtr, "vbase.offset");
-
- return VBaseOffset;
-}
-
void
CodeGenFunction::InitializeVTablePointer(BaseSubobject Base,
const CXXRecordDecl *NearestVBase,
CharUnits OffsetFromNearestVBase,
- llvm::Constant *VTable,
const CXXRecordDecl *VTableClass) {
- const CXXRecordDecl *RD = Base.getBase();
-
// Compute the address point.
- llvm::Value *VTableAddressPoint;
-
- // Check if we need to use a vtable from the VTT.
- if (CodeGenVTables::needsVTTParameter(CurGD) &&
- (RD->getNumVBases() || NearestVBase)) {
- // Get the secondary vpointer index.
- uint64_t VirtualPointerIndex =
- CGM.getVTables().getSecondaryVirtualPointerIndex(VTableClass, Base);
-
- /// Load the VTT.
- llvm::Value *VTT = LoadCXXVTT();
- if (VirtualPointerIndex)
- VTT = Builder.CreateConstInBoundsGEP1_64(VTT, VirtualPointerIndex);
-
- // And load the address point from the VTT.
- VTableAddressPoint = Builder.CreateLoad(VTT);
- } else {
- uint64_t AddressPoint =
- CGM.getVTableContext().getVTableLayout(VTableClass).getAddressPoint(Base);
- VTableAddressPoint =
- Builder.CreateConstInBoundsGEP2_64(VTable, 0, AddressPoint);
- }
+ bool NeedsVirtualOffset;
+ llvm::Value *VTableAddressPoint =
+ CGM.getCXXABI().getVTableAddressPointInStructor(
+ *this, VTableClass, Base, NearestVBase, NeedsVirtualOffset);
+ if (!VTableAddressPoint)
+ return;
// Compute where to store the address point.
llvm::Value *VirtualOffset = 0;
CharUnits NonVirtualOffset = CharUnits::Zero();
- if (CodeGenVTables::needsVTTParameter(CurGD) && NearestVBase) {
+ if (NeedsVirtualOffset) {
// We need to use the virtual base offset offset because the virtual base
// might have a different offset in the most derived class.
- VirtualOffset = GetVirtualBaseClassOffset(LoadCXXThis(), VTableClass,
- NearestVBase);
+ VirtualOffset = CGM.getCXXABI().GetVirtualBaseClassOffset(*this,
+ LoadCXXThis(),
+ VTableClass,
+ NearestVBase);
NonVirtualOffset = OffsetFromNearestVBase;
} else {
// We can just use the base offset in the complete class.
@@ -1958,7 +1931,6 @@ CodeGenFunction::InitializeVTablePointers(BaseSubobject Base,
const CXXRecordDecl *NearestVBase,
CharUnits OffsetFromNearestVBase,
bool BaseIsNonVirtualPrimaryBase,
- llvm::Constant *VTable,
const CXXRecordDecl *VTableClass,
VisitedVirtualBasesSetTy& VBases) {
// If this base is a non-virtual primary base the address point has already
@@ -1966,7 +1938,7 @@ CodeGenFunction::InitializeVTablePointers(BaseSubobject Base,
if (!BaseIsNonVirtualPrimaryBase) {
// Initialize the vtable pointer for this base.
InitializeVTablePointer(Base, NearestVBase, OffsetFromNearestVBase,
- VTable, VTableClass);
+ VTableClass);
}
const CXXRecordDecl *RD = Base.getBase();
@@ -2009,7 +1981,7 @@ CodeGenFunction::InitializeVTablePointers(BaseSubobject Base,
I->isVirtual() ? BaseDecl : NearestVBase,
BaseOffsetFromNearestVBase,
BaseDeclIsNonVirtualPrimaryBase,
- VTable, VTableClass, VBases);
+ VTableClass, VBases);
}
}
@@ -2018,16 +1990,15 @@ void CodeGenFunction::InitializeVTablePointers(const CXXRecordDecl *RD) {
if (!RD->isDynamicClass())
return;
- // Get the VTable.
- llvm::Constant *VTable = CGM.getVTables().GetAddrOfVTable(RD);
-
// Initialize the vtable pointers for this class and all of its bases.
VisitedVirtualBasesSetTy VBases;
InitializeVTablePointers(BaseSubobject(RD, CharUnits::Zero()),
/*NearestVBase=*/0,
/*OffsetFromNearestVBase=*/CharUnits::Zero(),
- /*BaseIsNonVirtualPrimaryBase=*/false,
- VTable, RD, VBases);
+ /*BaseIsNonVirtualPrimaryBase=*/false, RD, VBases);
+
+ if (RD->getNumVBases())
+ CGM.getCXXABI().initializeHiddenVirtualInheritanceMembers(*this, RD);
}
llvm::Value *CodeGenFunction::GetVTablePtr(llvm::Value *This,
@@ -2038,29 +2009,6 @@ llvm::Value *CodeGenFunction::GetVTablePtr(llvm::Value *This,
return VTable;
}
-static const CXXRecordDecl *getMostDerivedClassDecl(const Expr *Base) {
- const Expr *E = Base;
-
- while (true) {
- E = E->IgnoreParens();
- if (const CastExpr *CE = dyn_cast<CastExpr>(E)) {
- if (CE->getCastKind() == CK_DerivedToBase ||
- CE->getCastKind() == CK_UncheckedDerivedToBase ||
- CE->getCastKind() == CK_NoOp) {
- E = CE->getSubExpr();
- continue;
- }
- }
-
- break;
- }
-
- QualType DerivedType = E->getType();
- if (const PointerType *PTy = DerivedType->getAs<PointerType>())
- DerivedType = PTy->getPointeeType();
-
- return cast<CXXRecordDecl>(DerivedType->castAs<RecordType>()->getDecl());
-}
// FIXME: Ideally Expr::IgnoreParenNoopCasts should do this, but it doesn't do
// quite what we want.
@@ -2087,10 +2035,14 @@ static const Expr *skipNoOpCastsAndParens(const Expr *E) {
}
}
-/// canDevirtualizeMemberFunctionCall - Checks whether the given virtual member
-/// function call on the given expr can be devirtualized.
-static bool canDevirtualizeMemberFunctionCall(const Expr *Base,
- const CXXMethodDecl *MD) {
+bool
+CodeGenFunction::CanDevirtualizeMemberFunctionCall(const Expr *Base,
+ const CXXMethodDecl *MD) {
+ // When building with -fapple-kext, all calls must go through the vtable since
+ // the kernel linker can do runtime patching of vtables.
+ if (getLangOpts().AppleKext)
+ return false;
+
// If the most derived class is marked final, we know that no subclass can
// override this member function and so we can devirtualize it. For example:
//
@@ -2101,7 +2053,7 @@ static bool canDevirtualizeMemberFunctionCall(const Expr *Base,
// b->f();
// }
//
- const CXXRecordDecl *MostDerivedClassDecl = getMostDerivedClassDecl(Base);
+ const CXXRecordDecl *MostDerivedClassDecl = Base->getBestDynamicClassType();
if (MostDerivedClassDecl->hasAttr<FinalAttr>())
return true;
@@ -2124,7 +2076,14 @@ static bool canDevirtualizeMemberFunctionCall(const Expr *Base,
return false;
}
-
+
+ // We can devirtualize calls on an object accessed by a class member access
+ // expression, since by C++11 [basic.life]p6 we know that it can't refer to
+ // a derived class object constructed in the same location.
+ if (const MemberExpr *ME = dyn_cast<MemberExpr>(Base))
+ if (const ValueDecl *VD = dyn_cast<ValueDecl>(ME->getMemberDecl()))
+ return VD->getType()->isRecordType();
+
// We can always devirtualize calls on temporary object expressions.
if (isa<CXXConstructExpr>(Base))
return true;
@@ -2141,20 +2100,6 @@ static bool canDevirtualizeMemberFunctionCall(const Expr *Base,
return false;
}
-static bool UseVirtualCall(ASTContext &Context,
- const CXXOperatorCallExpr *CE,
- const CXXMethodDecl *MD) {
- if (!MD->isVirtual())
- return false;
-
- // When building with -fapple-kext, all calls must go through the vtable since
- // the kernel linker can do runtime patching of vtables.
- if (Context.getLangOpts().AppleKext)
- return true;
-
- return !canDevirtualizeMemberFunctionCall(CE->getArg(0), MD);
-}
-
llvm::Value *
CodeGenFunction::EmitCXXOperatorMemberCallee(const CXXOperatorCallExpr *E,
const CXXMethodDecl *MD,
@@ -2163,20 +2108,15 @@ CodeGenFunction::EmitCXXOperatorMemberCallee(const CXXOperatorCallExpr *E,
CGM.getTypes().GetFunctionType(
CGM.getTypes().arrangeCXXMethodDeclaration(MD));
- if (UseVirtualCall(getContext(), E, MD))
- return BuildVirtualCall(MD, This, fnType);
+ if (MD->isVirtual() && !CanDevirtualizeMemberFunctionCall(E->getArg(0), MD))
+ return CGM.getCXXABI().getVirtualFunctionPointer(*this, MD, This, fnType);
return CGM.GetAddrOfFunction(MD, fnType);
}
-void CodeGenFunction::EmitForwardingCallToLambda(const CXXRecordDecl *lambda,
- CallArgList &callArgs) {
- // Lookup the call operator
- DeclarationName operatorName
- = getContext().DeclarationNames.getCXXOperatorName(OO_Call);
- CXXMethodDecl *callOperator =
- cast<CXXMethodDecl>(lambda->lookup(operatorName).front());
-
+void CodeGenFunction::EmitForwardingCallToLambda(
+ const CXXMethodDecl *callOperator,
+ CallArgList &callArgs) {
// Get the address of the call operator.
const CGFunctionInfo &calleeFnInfo =
CGM.getTypes().arrangeCXXMethodDeclaration(callOperator);
@@ -2225,10 +2165,11 @@ void CodeGenFunction::EmitLambdaBlockInvokeBody() {
for (BlockDecl::param_const_iterator I = BD->param_begin(),
E = BD->param_end(); I != E; ++I) {
ParmVarDecl *param = *I;
- EmitDelegateCallArg(CallArgs, param);
+ EmitDelegateCallArg(CallArgs, param, param->getLocStart());
}
-
- EmitForwardingCallToLambda(Lambda, CallArgs);
+ assert(!Lambda->isGenericLambda() &&
+ "generic lambda interconversion to block not implemented");
+ EmitForwardingCallToLambda(Lambda->getLambdaCallOperator(), CallArgs);
}
void CodeGenFunction::EmitLambdaToBlockPointerBody(FunctionArgList &Args) {
@@ -2239,7 +2180,7 @@ void CodeGenFunction::EmitLambdaToBlockPointerBody(FunctionArgList &Args) {
return;
}
- EmitFunctionBody(Args);
+ EmitFunctionBody(Args, cast<FunctionDecl>(CurGD.getDecl())->getBody());
}
void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD) {
@@ -2256,10 +2197,22 @@ void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD) {
for (FunctionDecl::param_const_iterator I = MD->param_begin(),
E = MD->param_end(); I != E; ++I) {
ParmVarDecl *param = *I;
- EmitDelegateCallArg(CallArgs, param);
+ EmitDelegateCallArg(CallArgs, param, param->getLocStart());
}
-
- EmitForwardingCallToLambda(Lambda, CallArgs);
+ const CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator();
+ // For a generic lambda, find the corresponding call operator specialization
+ // to which the call to the static-invoker shall be forwarded.
+ if (Lambda->isGenericLambda()) {
+ assert(MD->isFunctionTemplateSpecialization());
+ const TemplateArgumentList *TAL = MD->getTemplateSpecializationArgs();
+ FunctionTemplateDecl *CallOpTemplate = CallOp->getDescribedFunctionTemplate();
+ void *InsertPos = 0;
+ FunctionDecl *CorrespondingCallOpSpecialization =
+ CallOpTemplate->findSpecialization(TAL->data(), TAL->size(), InsertPos);
+ assert(CorrespondingCallOpSpecialization);
+ CallOp = cast<CXXMethodDecl>(CorrespondingCallOpSpecialization);
+ }
+ EmitForwardingCallToLambda(CallOp, CallArgs);
}
void CodeGenFunction::EmitLambdaStaticInvokeFunction(const CXXMethodDecl *MD) {
diff --git a/lib/CodeGen/CGCleanup.cpp b/lib/CodeGen/CGCleanup.cpp
index ba6b56c..65de4d4 100644
--- a/lib/CodeGen/CGCleanup.cpp
+++ b/lib/CodeGen/CGCleanup.cpp
@@ -17,8 +17,8 @@
//
//===----------------------------------------------------------------------===//
-#include "CodeGenFunction.h"
#include "CGCleanup.h"
+#include "CodeGenFunction.h"
using namespace clang;
using namespace CodeGen;
@@ -371,8 +371,7 @@ void CodeGenFunction::ResolveBranchFixups(llvm::BasicBlock *Block) {
}
/// Pops cleanup blocks until the given savepoint is reached.
-void CodeGenFunction::PopCleanupBlocks(EHScopeStack::stable_iterator Old,
- SourceLocation EHLoc) {
+void CodeGenFunction::PopCleanupBlocks(EHScopeStack::stable_iterator Old) {
assert(Old.isValid());
while (EHStack.stable_begin() != Old) {
@@ -384,8 +383,35 @@ void CodeGenFunction::PopCleanupBlocks(EHScopeStack::stable_iterator Old,
bool FallThroughIsBranchThrough =
Old.strictlyEncloses(Scope.getEnclosingNormalCleanup());
- PopCleanupBlock(FallThroughIsBranchThrough, EHLoc);
+ PopCleanupBlock(FallThroughIsBranchThrough);
+ }
+}
+
+/// Pops cleanup blocks until the given savepoint is reached, then add the
+/// cleanups from the given savepoint in the lifetime-extended cleanups stack.
+void
+CodeGenFunction::PopCleanupBlocks(EHScopeStack::stable_iterator Old,
+ size_t OldLifetimeExtendedSize) {
+ PopCleanupBlocks(Old);
+
+ // Move our deferred cleanups onto the EH stack.
+ for (size_t I = OldLifetimeExtendedSize,
+ E = LifetimeExtendedCleanupStack.size(); I != E; /**/) {
+ // Alignment should be guaranteed by the vptrs in the individual cleanups.
+ assert((I % llvm::alignOf<LifetimeExtendedCleanupHeader>() == 0) &&
+ "misaligned cleanup stack entry");
+
+ LifetimeExtendedCleanupHeader &Header =
+ reinterpret_cast<LifetimeExtendedCleanupHeader&>(
+ LifetimeExtendedCleanupStack[I]);
+ I += sizeof(Header);
+
+ EHStack.pushCopyOfCleanup(Header.getKind(),
+ &LifetimeExtendedCleanupStack[I],
+ Header.getSize());
+ I += Header.getSize();
}
+ LifetimeExtendedCleanupStack.resize(OldLifetimeExtendedSize);
}
static llvm::BasicBlock *CreateNormalEntry(CodeGenFunction &CGF,
@@ -533,8 +559,7 @@ static void destroyOptimisticNormalEntry(CodeGenFunction &CGF,
/// Pops a cleanup block. If the block includes a normal cleanup, the
/// current insertion point is threaded through the cleanup, as are
/// any branch fixups on the cleanup.
-void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough,
- SourceLocation EHLoc) {
+void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
assert(!EHStack.empty() && "cleanup stack is empty!");
assert(isa<EHCleanupScope>(*EHStack.begin()) && "top not a cleanup!");
EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.begin());
@@ -836,7 +861,7 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough,
// Emit the EH cleanup if required.
if (RequiresEHCleanup) {
if (CGDebugInfo *DI = getDebugInfo())
- DI->EmitLocation(Builder, EHLoc);
+ DI->EmitLocation(Builder, CurEHLocation);
CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
diff --git a/lib/CodeGen/CGCleanup.h b/lib/CodeGen/CGCleanup.h
index d8dbe41..1bd6bba 100644
--- a/lib/CodeGen/CGCleanup.h
+++ b/lib/CodeGen/CGCleanup.h
@@ -14,13 +14,15 @@
#ifndef CLANG_CODEGEN_CGCLEANUP_H
#define CLANG_CODEGEN_CGCLEANUP_H
-/// EHScopeStack is defined in CodeGenFunction.h, but its
-/// implementation is in this file and in CGCleanup.cpp.
-#include "CodeGenFunction.h"
+#include "EHScopeStack.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
namespace llvm {
- class Value;
- class BasicBlock;
+class BasicBlock;
+class Value;
+class ConstantInt;
+class AllocaInst;
}
namespace clang {
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index ddcb931..fcb26f0 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -13,6 +13,7 @@
#include "CGDebugInfo.h"
#include "CGBlocks.h"
+#include "CGCXXABI.h"
#include "CGObjCRuntime.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
@@ -36,12 +37,13 @@
#include "llvm/IR/Module.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
using namespace clang;
using namespace clang::CodeGen;
CGDebugInfo::CGDebugInfo(CodeGenModule &CGM)
- : CGM(CGM), DBuilder(CGM.getModule()),
- BlockLiteralGenericSet(false) {
+ : CGM(CGM), DebugKind(CGM.getCodeGenOpts().getDebugInfo()),
+ DBuilder(CGM.getModule()) {
CreateCompileUnit();
}
@@ -50,9 +52,54 @@ CGDebugInfo::~CGDebugInfo() {
"Region stack mismatch, stack not empty!");
}
+
+NoLocation::NoLocation(CodeGenFunction &CGF, CGBuilderTy &B)
+ : DI(CGF.getDebugInfo()), Builder(B) {
+ if (DI) {
+ SavedLoc = DI->getLocation();
+ DI->CurLoc = SourceLocation();
+ Builder.SetCurrentDebugLocation(llvm::DebugLoc());
+ }
+}
+
+NoLocation::~NoLocation() {
+ if (DI) {
+ assert(Builder.getCurrentDebugLocation().isUnknown());
+ DI->CurLoc = SavedLoc;
+ }
+}
+
+ArtificialLocation::ArtificialLocation(CodeGenFunction &CGF, CGBuilderTy &B)
+ : DI(CGF.getDebugInfo()), Builder(B) {
+ if (DI) {
+ SavedLoc = DI->getLocation();
+ DI->CurLoc = SourceLocation();
+ Builder.SetCurrentDebugLocation(llvm::DebugLoc());
+ }
+}
+
+void ArtificialLocation::Emit() {
+ if (DI) {
+ // Sync the Builder.
+ DI->EmitLocation(Builder, SavedLoc);
+ DI->CurLoc = SourceLocation();
+ // Construct a location that has a valid scope, but no line info.
+ assert(!DI->LexicalBlockStack.empty());
+ llvm::DIDescriptor Scope(DI->LexicalBlockStack.back());
+ Builder.SetCurrentDebugLocation(llvm::DebugLoc::get(0, 0, Scope));
+ }
+}
+
+ArtificialLocation::~ArtificialLocation() {
+ if (DI) {
+ assert(Builder.getCurrentDebugLocation().getLine() == 0);
+ DI->CurLoc = SavedLoc;
+ }
+}
+
void CGDebugInfo::setLocation(SourceLocation Loc) {
// If the new location isn't valid return.
- if (!Loc.isValid()) return;
+ if (Loc.isInvalid()) return;
CurLoc = CGM.getContext().getSourceManager().getExpansionLoc(Loc);
@@ -112,7 +159,7 @@ llvm::DIScope CGDebugInfo::getContextDescriptor(const Decl *Context) {
}
/// getFunctionName - Get function name for the given FunctionDecl. If the
-/// name is constructred on demand (e.g. C++ destructor) then the name
+/// name is constructed on demand (e.g. C++ destructor) then the name
/// is stored on the side.
StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) {
assert (FD && "Invalid FunctionDecl!");
@@ -138,10 +185,7 @@ StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) {
}
// Copy this name on the side and use its reference.
- OS.flush();
- char *StrPtr = DebugInfoNames.Allocate<char>(NS.size());
- memcpy(StrPtr, NS.data(), NS.size());
- return StringRef(StrPtr, NS.size());
+ return internString(OS.str());
}
StringRef CGDebugInfo::getObjCMethodName(const ObjCMethodDecl *OMD) {
@@ -149,35 +193,37 @@ StringRef CGDebugInfo::getObjCMethodName(const ObjCMethodDecl *OMD) {
llvm::raw_svector_ostream OS(MethodName);
OS << (OMD->isInstanceMethod() ? '-' : '+') << '[';
const DeclContext *DC = OMD->getDeclContext();
- if (const ObjCImplementationDecl *OID =
+ if (const ObjCImplementationDecl *OID =
dyn_cast<const ObjCImplementationDecl>(DC)) {
OS << OID->getName();
- } else if (const ObjCInterfaceDecl *OID =
+ } else if (const ObjCInterfaceDecl *OID =
dyn_cast<const ObjCInterfaceDecl>(DC)) {
OS << OID->getName();
- } else if (const ObjCCategoryImplDecl *OCD =
+ } else if (const ObjCCategoryImplDecl *OCD =
dyn_cast<const ObjCCategoryImplDecl>(DC)){
OS << ((const NamedDecl *)OCD)->getIdentifier()->getNameStart() << '(' <<
OCD->getIdentifier()->getNameStart() << ')';
+ } else if (isa<ObjCProtocolDecl>(DC)) {
+ // We can extract the type of the class from the self pointer.
+ if (ImplicitParamDecl* SelfDecl = OMD->getSelfDecl()) {
+ QualType ClassTy =
+ cast<ObjCObjectPointerType>(SelfDecl->getType())->getPointeeType();
+ ClassTy.print(OS, PrintingPolicy(LangOptions()));
+ }
}
OS << ' ' << OMD->getSelector().getAsString() << ']';
- char *StrPtr = DebugInfoNames.Allocate<char>(OS.tell());
- memcpy(StrPtr, MethodName.begin(), OS.tell());
- return StringRef(StrPtr, OS.tell());
+ return internString(OS.str());
}
/// getSelectorName - Return selector name. This is used for debugging
/// info.
StringRef CGDebugInfo::getSelectorName(Selector S) {
- const std::string &SName = S.getAsString();
- char *StrPtr = DebugInfoNames.Allocate<char>(SName.size());
- memcpy(StrPtr, SName.data(), SName.size());
- return StringRef(StrPtr, SName.size());
+ return internString(S.getAsString());
}
/// getClassName - Get class name including template argument list.
-StringRef
+StringRef
CGDebugInfo::getClassName(const RecordDecl *RD) {
const ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(RD);
@@ -206,11 +252,7 @@ CGDebugInfo::getClassName(const RecordDecl *RD) {
}
// Copy this name on the side and use its reference.
- size_t Length = Name.size() + TemplateArgList.size();
- char *StrPtr = DebugInfoNames.Allocate<char>(Length);
- memcpy(StrPtr, Name.data(), Name.size());
- memcpy(StrPtr + Name.size(), TemplateArgList.data(), TemplateArgList.size());
- return StringRef(StrPtr, Length);
+ return internString(Name, TemplateArgList);
}
/// getOrCreateFile - Get the file debug info descriptor for the input location.
@@ -280,9 +322,7 @@ StringRef CGDebugInfo::getCurrentDirname() {
return CWDName;
SmallString<256> CWD;
llvm::sys::fs::current_path(CWD);
- char *CompDirnamePtr = DebugInfoNames.Allocate<char>(CWD.size());
- memcpy(CompDirnamePtr, CWD.data(), CWD.size());
- return CWDName = StringRef(CompDirnamePtr, CWD.size());
+ return CWDName = internString(CWD);
}
/// CreateCompileUnit - Create new compile unit.
@@ -301,21 +341,20 @@ void CGDebugInfo::CreateCompileUnit() {
std::string MainFileDir;
if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
MainFileDir = MainFile->getDir()->getName();
- if (MainFileDir != ".")
- MainFileName = MainFileDir + "/" + MainFileName;
+ if (MainFileDir != ".") {
+ llvm::SmallString<1024> MainFileDirSS(MainFileDir);
+ llvm::sys::path::append(MainFileDirSS, MainFileName);
+ MainFileName = MainFileDirSS.str();
+ }
}
// Save filename string.
- char *FilenamePtr = DebugInfoNames.Allocate<char>(MainFileName.length());
- memcpy(FilenamePtr, MainFileName.c_str(), MainFileName.length());
- StringRef Filename(FilenamePtr, MainFileName.length());
+ StringRef Filename = internString(MainFileName);
// Save split dwarf file string.
std::string SplitDwarfFile = CGM.getCodeGenOpts().SplitDwarfFile;
- char *SplitDwarfPtr = DebugInfoNames.Allocate<char>(SplitDwarfFile.length());
- memcpy(SplitDwarfPtr, SplitDwarfFile.c_str(), SplitDwarfFile.length());
- StringRef SplitDwarfFilename(SplitDwarfPtr, SplitDwarfFile.length());
-
+ StringRef SplitDwarfFilename = internString(SplitDwarfFile);
+
unsigned LangTag;
const LangOptions &LO = CGM.getLangOpts();
if (LO.CPlusPlus) {
@@ -339,12 +378,11 @@ void CGDebugInfo::CreateCompileUnit() {
RuntimeVers = LO.ObjCRuntime.isNonFragile() ? 2 : 1;
// Create new compile unit.
- DBuilder.createCompileUnit(LangTag, Filename, getCurrentDirname(),
- Producer, LO.Optimize,
- CGM.getCodeGenOpts().DwarfDebugFlags,
- RuntimeVers, SplitDwarfFilename);
// FIXME - Eliminate TheCU.
- TheCU = llvm::DICompileUnit(DBuilder.getCU());
+ TheCU = DBuilder.createCompileUnit(LangTag, Filename, getCurrentDirname(),
+ Producer, LO.Optimize,
+ CGM.getCodeGenOpts().DwarfDebugFlags,
+ RuntimeVers, SplitDwarfFilename);
}
/// CreateType - Get the Basic type from the cache or create a new
@@ -360,12 +398,11 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
case BuiltinType::Dependent:
llvm_unreachable("Unexpected builtin type");
case BuiltinType::NullPtr:
- return DBuilder.
- createNullPtrType(BT->getName(CGM.getLangOpts()));
+ return DBuilder.createNullPtrType();
case BuiltinType::Void:
return llvm::DIType();
case BuiltinType::ObjCClass:
- if (ClassTy.Verify())
+ if (ClassTy)
return ClassTy;
ClassTy = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
"objc_class", TheCU,
@@ -377,16 +414,16 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
// Class isa;
// } *id;
- if (ObjTy.Verify())
+ if (ObjTy)
return ObjTy;
- if (!ClassTy.Verify())
+ if (!ClassTy)
ClassTy = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
"objc_class", TheCU,
getOrCreateMainFile(), 0);
unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
-
+
llvm::DIType ISATy = DBuilder.createPointerType(ClassTy, Size);
ObjTy =
@@ -398,7 +435,7 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
return ObjTy;
}
case BuiltinType::ObjCSel: {
- if (SelTy.Verify())
+ if (SelTy)
return SelTy;
SelTy =
DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
@@ -411,7 +448,7 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
return getOrCreateStructPtrType("opencl_image1d_t",
OCLImage1dDITy);
case BuiltinType::OCLImage1dArray:
- return getOrCreateStructPtrType("opencl_image1d_array_t",
+ return getOrCreateStructPtrType("opencl_image1d_array_t",
OCLImage1dArrayDITy);
case BuiltinType::OCLImage1dBuffer:
return getOrCreateStructPtrType("opencl_image1d_buffer_t",
@@ -471,7 +508,7 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
// Bit size, align and offset of the type.
uint64_t Size = CGM.getContext().getTypeSize(BT);
uint64_t Align = CGM.getContext().getTypeAlign(BT);
- llvm::DIType DbgTy =
+ llvm::DIType DbgTy =
DBuilder.createBasicType(BTName, Size, Align, Encoding);
return DbgTy;
}
@@ -484,7 +521,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 =
+ llvm::DIType DbgTy =
DBuilder.createBasicType("complex", Size, Align, Encoding);
return DbgTy;
@@ -523,7 +560,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);
-
+
return DbgTy;
}
@@ -537,20 +574,48 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty,
return getOrCreateType(CGM.getContext().getObjCIdType(), Unit);
llvm::DIType DbgTy =
- CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty,
+ CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty,
Ty->getPointeeType(), Unit);
return DbgTy;
}
llvm::DIType CGDebugInfo::CreateType(const PointerType *Ty,
llvm::DIFile Unit) {
- return CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty,
+ return CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty,
Ty->getPointeeType(), Unit);
}
+/// In C++ mode, types have linkage, so we can rely on the ODR and
+/// on their mangled names, if they're external.
+static SmallString<256>
+getUniqueTagTypeName(const TagType *Ty, CodeGenModule &CGM,
+ llvm::DICompileUnit TheCU) {
+ SmallString<256> FullName;
+ // FIXME: ODR should apply to ObjC++ exactly the same wasy it does to C++.
+ // For now, only apply ODR with C++.
+ const TagDecl *TD = Ty->getDecl();
+ if (TheCU.getLanguage() != llvm::dwarf::DW_LANG_C_plus_plus ||
+ !TD->isExternallyVisible())
+ return FullName;
+ // Microsoft Mangler does not have support for mangleCXXRTTIName yet.
+ if (CGM.getTarget().getCXXABI().isMicrosoft())
+ return FullName;
+
+ // TODO: This is using the RTTI name. Is there a better way to get
+ // a unique string for a type?
+ llvm::raw_svector_ostream Out(FullName);
+ CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(QualType(Ty, 0), Out);
+ Out.flush();
+ return FullName;
+}
+
// Creates a forward declaration for a RecordDecl in the given context.
-llvm::DIType CGDebugInfo::createRecordFwdDecl(const RecordDecl *RD,
- llvm::DIDescriptor Ctx) {
+llvm::DICompositeType
+CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty,
+ llvm::DIDescriptor Ctx) {
+ const RecordDecl *RD = Ty->getDecl();
+ if (llvm::DIType T = getTypeOrNull(CGM.getContext().getRecordType(RD)))
+ return llvm::DICompositeType(T);
llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());
unsigned Line = getLineNumber(RD->getLocation());
StringRef RDName = getClassName(RD);
@@ -566,74 +631,18 @@ llvm::DIType CGDebugInfo::createRecordFwdDecl(const RecordDecl *RD,
}
// Create the type.
- return DBuilder.createForwardDecl(Tag, RDName, Ctx, DefUnit, Line);
-}
-
-// Walk up the context chain and create forward decls for record decls,
-// and normal descriptors for namespaces.
-llvm::DIDescriptor CGDebugInfo::createContextChain(const Decl *Context) {
- if (!Context)
- return TheCU;
-
- // See if we already have the parent.
- llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator
- I = RegionMap.find(Context);
- if (I != RegionMap.end()) {
- llvm::Value *V = I->second;
- return llvm::DIDescriptor(dyn_cast_or_null<llvm::MDNode>(V));
- }
-
- // Check namespace.
- if (const NamespaceDecl *NSDecl = dyn_cast<NamespaceDecl>(Context))
- return llvm::DIDescriptor(getOrCreateNameSpace(NSDecl));
-
- if (const RecordDecl *RD = dyn_cast<RecordDecl>(Context)) {
- if (!RD->isDependentType()) {
- llvm::DIType Ty = getOrCreateLimitedType(CGM.getContext().getTypeDeclType(RD),
- getOrCreateMainFile());
- return llvm::DIDescriptor(Ty);
- }
- }
- return TheCU;
-}
-
-/// CreatePointeeType - Create Pointee type. If Pointee is a record
-/// then emit record's fwd if debug info size reduction is enabled.
-llvm::DIType CGDebugInfo::CreatePointeeType(QualType PointeeTy,
- llvm::DIFile Unit) {
- if (CGM.getCodeGenOpts().getDebugInfo() != CodeGenOptions::LimitedDebugInfo)
- return getOrCreateType(PointeeTy, Unit);
-
- // Limit debug info for the pointee type.
-
- // If we have an existing type, use that, it's still smaller than creating
- // a new type.
- llvm::DIType Ty = getTypeOrNull(PointeeTy);
- if (Ty.Verify()) return Ty;
-
- // Handle qualifiers.
- if (PointeeTy.hasLocalQualifiers())
- return CreateQualifiedType(PointeeTy, Unit);
-
- if (const RecordType *RTy = dyn_cast<RecordType>(PointeeTy)) {
- RecordDecl *RD = RTy->getDecl();
- llvm::DIDescriptor FDContext =
- getContextDescriptor(cast<Decl>(RD->getDeclContext()));
- llvm::DIType RetTy = createRecordFwdDecl(RD, FDContext);
- TypeCache[QualType(RTy, 0).getAsOpaquePtr()] = RetTy;
- return RetTy;
- }
- return getOrCreateType(PointeeTy, Unit);
+ SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
+ return DBuilder.createForwardDecl(Tag, RDName, Ctx, DefUnit, Line, 0, 0, 0,
+ FullName);
}
llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag,
- const Type *Ty,
+ const Type *Ty,
QualType PointeeTy,
llvm::DIFile Unit) {
if (Tag == llvm::dwarf::DW_TAG_reference_type ||
Tag == llvm::dwarf::DW_TAG_rvalue_reference_type)
- return DBuilder.createReferenceType(Tag,
- CreatePointeeType(PointeeTy, Unit));
+ return DBuilder.createReferenceType(Tag, getOrCreateType(PointeeTy, Unit));
// Bit size, align and offset of the type.
// Size is always the size of a pointer. We can't use getTypeSize here
@@ -642,25 +651,24 @@ llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag,
uint64_t Size = CGM.getTarget().getPointerWidth(AS);
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
- return DBuilder.createPointerType(CreatePointeeType(PointeeTy, Unit),
- Size, Align);
+ return DBuilder.createPointerType(getOrCreateType(PointeeTy, Unit), Size,
+ Align);
}
-llvm::DIType CGDebugInfo::getOrCreateStructPtrType(StringRef Name, llvm::DIType &Cache) {
- if (Cache.Verify())
- return Cache;
- Cache =
- DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
- Name, TheCU, getOrCreateMainFile(),
- 0);
- unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
- Cache = DBuilder.createPointerType(Cache, Size);
+llvm::DIType CGDebugInfo::getOrCreateStructPtrType(StringRef Name,
+ llvm::DIType &Cache) {
+ if (Cache)
return Cache;
+ Cache = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, Name,
+ TheCU, getOrCreateMainFile(), 0);
+ unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
+ Cache = DBuilder.createPointerType(Cache, Size);
+ return Cache;
}
llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
llvm::DIFile Unit) {
- if (BlockLiteralGenericSet)
+ if (BlockLiteralGeneric)
return BlockLiteralGeneric;
SmallVector<llvm::Value *, 8> EltTys;
@@ -716,7 +724,6 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
Unit, LineNo, FieldOffset, 0,
Flags, llvm::DIType(), Elements);
- BlockLiteralGenericSet = true;
BlockLiteralGeneric = DBuilder.createPointerType(EltTy, Size);
return BlockLiteralGeneric;
}
@@ -725,16 +732,16 @@ llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty, llvm::DIFile Unit) {
// Typedefs are derived from some other type. If we have a typedef of a
// typedef, make sure to emit the whole chain.
llvm::DIType Src = getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit);
- if (!Src.Verify())
+ if (!Src)
return llvm::DIType();
// We don't set size information, but do specify where the typedef was
// declared.
unsigned Line = getLineNumber(Ty->getDecl()->getLocation());
const TypedefNameDecl *TyDecl = Ty->getDecl();
-
+
llvm::DIDescriptor TypedefContext =
getContextDescriptor(cast<Decl>(Ty->getDecl()->getDeclContext()));
-
+
return
DBuilder.createTypedef(Src, TyDecl->getName(), Unit, Line, TypedefContext);
}
@@ -767,7 +774,7 @@ llvm::DIType CGDebugInfo::createFieldType(StringRef name,
AccessSpecifier AS,
uint64_t offsetInBits,
llvm::DIFile tunit,
- llvm::DIDescriptor scope) {
+ llvm::DIScope scope) {
llvm::DIType debugType = getOrCreateType(type, tunit);
// Get the location for the field.
@@ -839,20 +846,15 @@ CollectRecordLambdaFields(const CXXRecordDecl *CXXDecl,
}
}
-/// CollectRecordStaticField - Helper for CollectRecordFields.
-void CGDebugInfo::
-CollectRecordStaticField(const VarDecl *Var,
- SmallVectorImpl<llvm::Value *> &elements,
- llvm::DIType RecordTy) {
+/// Helper for CollectRecordFields.
+llvm::DIDerivedType
+CGDebugInfo::CreateRecordStaticField(const VarDecl *Var,
+ llvm::DIType RecordTy) {
// Create the descriptor for the static variable, with or without
// constant initializers.
llvm::DIFile VUnit = getOrCreateFile(Var->getLocation());
llvm::DIType VTy = getOrCreateType(Var->getType(), VUnit);
- // Do not describe enums as static members.
- if (VTy.getTag() == llvm::dwarf::DW_TAG_enumeration_type)
- return;
-
unsigned LineNumber = getLineNumber(Var->getLocation());
StringRef VName = Var->getName();
llvm::Constant *C = NULL;
@@ -873,10 +875,10 @@ CollectRecordStaticField(const VarDecl *Var,
else if (Access == clang::AS_protected)
Flags |= llvm::DIDescriptor::FlagProtected;
- llvm::DIType GV = DBuilder.createStaticMemberType(RecordTy, VName, VUnit,
- LineNumber, VTy, Flags, C);
- elements.push_back(GV);
+ llvm::DIDerivedType GV = DBuilder.createStaticMemberType(
+ RecordTy, VName, VUnit, LineNumber, VTy, Flags, C);
StaticDataMemberCache[Var->getCanonicalDecl()] = llvm::WeakVH(GV);
+ return GV;
}
/// CollectRecordNormalField - Helper for CollectRecordFields.
@@ -908,10 +910,10 @@ CollectRecordNormalField(const FieldDecl *field, uint64_t OffsetInBits,
/// 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 *record, llvm::DIFile tunit,
- SmallVectorImpl<llvm::Value *> &elements,
- llvm::DIType RecordTy) {
+void CGDebugInfo::CollectRecordFields(const RecordDecl *record,
+ llvm::DIFile tunit,
+ SmallVectorImpl<llvm::Value *> &elements,
+ llvm::DICompositeType RecordTy) {
const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(record);
if (CXXDecl && CXXDecl->isLambda())
@@ -922,24 +924,22 @@ CollectRecordFields(const RecordDecl *record, llvm::DIFile tunit,
// Field number for non-static fields.
unsigned fieldNo = 0;
- // Bookkeeping for an ms struct, which ignores certain fields.
- bool IsMsStruct = record->isMsStruct(CGM.getContext());
- const FieldDecl *LastFD = 0;
-
// Static and non-static members should appear in the same order as
// the corresponding declarations in the source program.
for (RecordDecl::decl_iterator I = record->decls_begin(),
E = record->decls_end(); I != E; ++I)
- if (const VarDecl *V = dyn_cast<VarDecl>(*I))
- CollectRecordStaticField(V, elements, RecordTy);
- else if (FieldDecl *field = dyn_cast<FieldDecl>(*I)) {
- if (IsMsStruct) {
- // Zero-length bitfields following non-bitfield members are
- // completely ignored; we don't even count them.
- if (CGM.getContext().ZeroBitfieldFollowsNonBitfield((field), LastFD))
- continue;
- LastFD = field;
- }
+ if (const VarDecl *V = dyn_cast<VarDecl>(*I)) {
+ // Reuse the existing static member declaration if one exists
+ llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator MI =
+ StaticDataMemberCache.find(V->getCanonicalDecl());
+ if (MI != StaticDataMemberCache.end()) {
+ assert(MI->second &&
+ "Static data member declaration should still exist");
+ elements.push_back(
+ llvm::DIDerivedType(cast<llvm::MDNode>(MI->second)));
+ } else
+ elements.push_back(CreateRecordStaticField(V, RecordTy));
+ } else if (FieldDecl *field = dyn_cast<FieldDecl>(*I)) {
CollectRecordNormalField(field, layout.getFieldOffset(fieldNo),
tunit, elements, RecordTy);
@@ -952,17 +952,17 @@ CollectRecordFields(const RecordDecl *record, llvm::DIFile tunit,
/// getOrCreateMethodType - CXXMethodDecl's type is a FunctionType. This
/// function type is not updated to include implicit "this" pointer. Use this
/// routine to get a method type which includes "this" pointer.
-llvm::DIType
+llvm::DICompositeType
CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method,
llvm::DIFile Unit) {
const FunctionProtoType *Func = Method->getType()->getAs<FunctionProtoType>();
if (Method->isStatic())
- return getOrCreateType(QualType(Func, 0), Unit);
+ return llvm::DICompositeType(getOrCreateType(QualType(Func, 0), Unit));
return getOrCreateInstanceMethodType(Method->getThisType(CGM.getContext()),
Func, Unit);
}
-llvm::DIType CGDebugInfo::getOrCreateInstanceMethodType(
+llvm::DICompositeType CGDebugInfo::getOrCreateInstanceMethodType(
QualType ThisPtr, const FunctionProtoType *Func, llvm::DIFile Unit) {
// Add "this" pointer.
llvm::DIArray Args = llvm::DICompositeType(
@@ -984,7 +984,8 @@ llvm::DIType CGDebugInfo::getOrCreateInstanceMethodType(
uint64_t Size = CGM.getTarget().getPointerWidth(AS);
uint64_t Align = CGM.getContext().getTypeAlign(ThisPtrTy);
llvm::DIType PointeeType = getOrCreateType(PointeeTy, Unit);
- llvm::DIType ThisPtrType = DBuilder.createPointerType(PointeeType, Size, Align);
+ llvm::DIType ThisPtrType =
+ DBuilder.createPointerType(PointeeType, Size, Align);
TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType;
// TODO: This and the artificial type below are misleading, the
// types aren't artificial the argument is, but the current
@@ -1007,7 +1008,7 @@ llvm::DIType CGDebugInfo::getOrCreateInstanceMethodType(
return DBuilder.createSubroutineType(Unit, EltTypeArray);
}
-/// isFunctionLocalClass - Return true if CXXRecordDecl is defined
+/// isFunctionLocalClass - Return true if CXXRecordDecl is defined
/// inside a function.
static bool isFunctionLocalClass(const CXXRecordDecl *RD) {
if (const CXXRecordDecl *NRD = dyn_cast<CXXRecordDecl>(RD->getDeclContext()))
@@ -1023,11 +1024,11 @@ llvm::DISubprogram
CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method,
llvm::DIFile Unit,
llvm::DIType RecordTy) {
- bool IsCtorOrDtor =
+ bool IsCtorOrDtor =
isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method);
-
+
StringRef MethodName = getFunctionName(Method);
- llvm::DIType MethodTy = getOrCreateMethodType(Method, Unit);
+ llvm::DICompositeType MethodTy = getOrCreateMethodType(Method, Unit);
// Since a single ctor/dtor corresponds to multiple functions, it doesn't
// make sense to give a single ctor/dtor a linkage name.
@@ -1036,24 +1037,32 @@ CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method,
MethodLinkageName = CGM.getMangledName(Method);
// Get the location for the method.
- llvm::DIFile MethodDefUnit = getOrCreateFile(Method->getLocation());
- unsigned MethodLine = getLineNumber(Method->getLocation());
+ llvm::DIFile MethodDefUnit;
+ unsigned MethodLine = 0;
+ if (!Method->isImplicit()) {
+ MethodDefUnit = getOrCreateFile(Method->getLocation());
+ MethodLine = getLineNumber(Method->getLocation());
+ }
// Collect virtual method info.
llvm::DIType ContainingType;
- unsigned Virtuality = 0;
+ unsigned Virtuality = 0;
unsigned VIndex = 0;
-
+
if (Method->isVirtual()) {
if (Method->isPure())
Virtuality = llvm::dwarf::DW_VIRTUALITY_pure_virtual;
else
Virtuality = llvm::dwarf::DW_VIRTUALITY_virtual;
-
+
// It doesn't make sense to give a virtual destructor a vtable index,
// since a single destructor has two entries in the vtable.
- if (!isa<CXXDestructorDecl>(Method))
- VIndex = CGM.getVTableContext().getMethodVTableIndex(Method);
+ // FIXME: Add proper support for debug info for virtual calls in
+ // the Microsoft ABI, where we may use multiple vptrs to make a vftable
+ // lookup if we have multiple or virtual inheritance.
+ if (!isa<CXXDestructorDecl>(Method) &&
+ !CGM.getTarget().getCXXABI().isMicrosoft())
+ VIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(Method);
ContainingType = RecordTy;
}
@@ -1068,7 +1077,7 @@ CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method,
if (const CXXConstructorDecl *CXXC = dyn_cast<CXXConstructorDecl>(Method)) {
if (CXXC->isExplicit())
Flags |= llvm::DIDescriptor::FlagExplicit;
- } else if (const CXXConversionDecl *CXXC =
+ } else if (const CXXConversionDecl *CXXC =
dyn_cast<CXXConversionDecl>(Method)) {
if (CXXC->isExplicit())
Flags |= llvm::DIDescriptor::FlagExplicit;
@@ -1078,21 +1087,21 @@ CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method,
llvm::DIArray TParamsArray = CollectFunctionTemplateParams(Method, Unit);
llvm::DISubprogram SP =
- DBuilder.createMethod(RecordTy, MethodName, MethodLinkageName,
+ DBuilder.createMethod(RecordTy, MethodName, MethodLinkageName,
MethodDefUnit, MethodLine,
- MethodTy, /*isLocalToUnit=*/false,
+ MethodTy, /*isLocalToUnit=*/false,
/* isDefinition=*/ false,
Virtuality, VIndex, ContainingType,
Flags, CGM.getLangOpts().Optimize, NULL,
TParamsArray);
-
+
SPCache[Method->getCanonicalDecl()] = llvm::WeakVH(SP);
return SP;
}
/// CollectCXXMemberFunctions - A helper function to collect debug info for
-/// C++ member functions. This is used while creating debug info entry for
+/// C++ member functions. This is used while creating debug info entry for
/// a Record.
void CGDebugInfo::
CollectCXXMemberFunctions(const CXXRecordDecl *RD, llvm::DIFile Unit,
@@ -1104,40 +1113,42 @@ CollectCXXMemberFunctions(const CXXRecordDecl *RD, llvm::DIFile Unit,
// the functions.
for(DeclContext::decl_iterator I = RD->decls_begin(),
E = RD->decls_end(); I != E; ++I) {
- Decl *D = *I;
- if (D->isImplicit() && !D->isUsed())
- continue;
-
- if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))
- EltTys.push_back(CreateCXXMemberFunction(Method, Unit, RecordTy));
- else if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(D))
+ if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*I)) {
+ // Reuse the existing member function declaration if it exists.
+ // It may be associated with the declaration of the type & should be
+ // reused as we're building the definition.
+ //
+ // This situation can arise in the vtable-based debug info reduction where
+ // implicit members are emitted in a non-vtable TU.
+ llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator MI =
+ SPCache.find(Method->getCanonicalDecl());
+ if (MI == SPCache.end()) {
+ // If the member is implicit, lazily create it when we see the
+ // definition, not before. (an ODR-used implicit default ctor that's
+ // never actually code generated should not produce debug info)
+ if (!Method->isImplicit())
+ EltTys.push_back(CreateCXXMemberFunction(Method, Unit, RecordTy));
+ } else
+ EltTys.push_back(MI->second);
+ } else if (const FunctionTemplateDecl *FTD =
+ dyn_cast<FunctionTemplateDecl>(*I)) {
+ // Add any template specializations that have already been seen. Like
+ // implicit member functions, these may have been added to a declaration
+ // in the case of vtable-based debug info reduction.
for (FunctionTemplateDecl::spec_iterator SI = FTD->spec_begin(),
- SE = FTD->spec_end(); SI != SE; ++SI)
- EltTys.push_back(CreateCXXMemberFunction(cast<CXXMethodDecl>(*SI), Unit,
- RecordTy));
- }
-}
-
-/// CollectCXXFriends - A helper function to collect debug info for
-/// C++ base classes. This is used while creating debug info entry for
-/// a Record.
-void CGDebugInfo::
-CollectCXXFriends(const CXXRecordDecl *RD, llvm::DIFile Unit,
- SmallVectorImpl<llvm::Value *> &EltTys,
- llvm::DIType RecordTy) {
- for (CXXRecordDecl::friend_iterator BI = RD->friend_begin(),
- BE = RD->friend_end(); BI != BE; ++BI) {
- if ((*BI)->isUnsupportedFriend())
- continue;
- if (TypeSourceInfo *TInfo = (*BI)->getFriendType())
- EltTys.push_back(DBuilder.createFriend(RecordTy,
- getOrCreateType(TInfo->getType(),
- Unit)));
+ SE = FTD->spec_end();
+ SI != SE; ++SI) {
+ llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator MI =
+ SPCache.find(cast<CXXMethodDecl>(*SI)->getCanonicalDecl());
+ if (MI != SPCache.end())
+ EltTys.push_back(MI->second);
+ }
+ }
}
}
/// CollectCXXBases - A helper function to collect debug info for
-/// C++ base classes. This is used while creating debug info entry for
+/// C++ base classes. This is used while creating debug info entry for
/// a Record.
void CGDebugInfo::
CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile Unit,
@@ -1149,30 +1160,30 @@ CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile Unit,
BE = RD->bases_end(); BI != BE; ++BI) {
unsigned BFlags = 0;
uint64_t BaseOffset;
-
+
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(BI->getType()->getAs<RecordType>()->getDecl());
-
+
if (BI->isVirtual()) {
// virtual base offset offset is -ve. The code generator emits dwarf
// expression where it expects +ve number.
- BaseOffset =
- 0 - CGM.getVTableContext()
+ BaseOffset =
+ 0 - CGM.getItaniumVTableContext()
.getVirtualBaseOffsetOffset(RD, Base).getQuantity();
BFlags = llvm::DIDescriptor::FlagVirtual;
} else
BaseOffset = CGM.getContext().toBits(RL.getBaseClassOffset(Base));
// FIXME: Inconsistent units for BaseOffset. It is in bytes when
// BI->isVirtual() and bits when not.
-
+
AccessSpecifier Access = BI->getAccessSpecifier();
if (Access == clang::AS_private)
BFlags |= llvm::DIDescriptor::FlagPrivate;
else if (Access == clang::AS_protected)
BFlags |= llvm::DIDescriptor::FlagProtected;
-
- llvm::DIType DTy =
- DBuilder.createInheritance(RecordTy,
+
+ llvm::DIType DTy =
+ DBuilder.createInheritance(RecordTy,
getOrCreateType(BI->getType(), Unit),
BaseOffset, BFlags);
EltTys.push_back(DTy);
@@ -1182,23 +1193,119 @@ CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile Unit,
/// CollectTemplateParams - A helper function to collect template parameters.
llvm::DIArray CGDebugInfo::
CollectTemplateParams(const TemplateParameterList *TPList,
- const TemplateArgumentList &TAList,
+ ArrayRef<TemplateArgument> TAList,
llvm::DIFile Unit) {
- SmallVector<llvm::Value *, 16> TemplateParams;
+ SmallVector<llvm::Value *, 16> TemplateParams;
for (unsigned i = 0, e = TAList.size(); i != e; ++i) {
const TemplateArgument &TA = TAList[i];
- const NamedDecl *ND = TPList->getParam(i);
- if (TA.getKind() == TemplateArgument::Type) {
+ StringRef Name;
+ if (TPList)
+ Name = TPList->getParam(i)->getName();
+ switch (TA.getKind()) {
+ case TemplateArgument::Type: {
llvm::DIType TTy = getOrCreateType(TA.getAsType(), Unit);
llvm::DITemplateTypeParameter TTP =
- DBuilder.createTemplateTypeParameter(TheCU, ND->getName(), TTy);
+ DBuilder.createTemplateTypeParameter(TheCU, Name, TTy);
TemplateParams.push_back(TTP);
- } else if (TA.getKind() == TemplateArgument::Integral) {
+ } break;
+ case TemplateArgument::Integral: {
llvm::DIType TTy = getOrCreateType(TA.getIntegralType(), Unit);
llvm::DITemplateValueParameter TVP =
- DBuilder.createTemplateValueParameter(TheCU, ND->getName(), TTy,
- TA.getAsIntegral().getZExtValue());
- TemplateParams.push_back(TVP);
+ DBuilder.createTemplateValueParameter(
+ TheCU, Name, TTy,
+ llvm::ConstantInt::get(CGM.getLLVMContext(), TA.getAsIntegral()));
+ TemplateParams.push_back(TVP);
+ } break;
+ case TemplateArgument::Declaration: {
+ const ValueDecl *D = TA.getAsDecl();
+ bool InstanceMember = D->isCXXInstanceMember();
+ QualType T = InstanceMember
+ ? CGM.getContext().getMemberPointerType(
+ D->getType(), cast<RecordDecl>(D->getDeclContext())
+ ->getTypeForDecl())
+ : CGM.getContext().getPointerType(D->getType());
+ llvm::DIType TTy = getOrCreateType(T, Unit);
+ llvm::Value *V = 0;
+ // Variable pointer template parameters have a value that is the address
+ // of the variable.
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D))
+ V = CGM.GetAddrOfGlobalVar(VD);
+ // Member function pointers have special support for building them, though
+ // this is currently unsupported in LLVM CodeGen.
+ if (InstanceMember) {
+ if (const CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(D))
+ V = CGM.getCXXABI().EmitMemberPointer(method);
+ } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ V = CGM.GetAddrOfFunction(FD);
+ // Member data pointers have special handling too to compute the fixed
+ // offset within the object.
+ if (isa<FieldDecl>(D)) {
+ // These five lines (& possibly the above member function pointer
+ // handling) might be able to be refactored to use similar code in
+ // CodeGenModule::getMemberPointerConstant
+ uint64_t fieldOffset = CGM.getContext().getFieldOffset(D);
+ CharUnits chars =
+ CGM.getContext().toCharUnitsFromBits((int64_t) fieldOffset);
+ V = CGM.getCXXABI().EmitMemberDataPointer(
+ cast<MemberPointerType>(T.getTypePtr()), chars);
+ }
+ llvm::DITemplateValueParameter TVP =
+ DBuilder.createTemplateValueParameter(TheCU, Name, TTy,
+ V->stripPointerCasts());
+ TemplateParams.push_back(TVP);
+ } break;
+ case TemplateArgument::NullPtr: {
+ QualType T = TA.getNullPtrType();
+ llvm::DIType TTy = getOrCreateType(T, Unit);
+ llvm::Value *V = 0;
+ // Special case member data pointer null values since they're actually -1
+ // instead of zero.
+ if (const MemberPointerType *MPT =
+ dyn_cast<MemberPointerType>(T.getTypePtr()))
+ // But treat member function pointers as simple zero integers because
+ // it's easier than having a special case in LLVM's CodeGen. If LLVM
+ // CodeGen grows handling for values of non-null member function
+ // pointers then perhaps we could remove this special case and rely on
+ // EmitNullMemberPointer for member function pointers.
+ if (MPT->isMemberDataPointer())
+ V = CGM.getCXXABI().EmitNullMemberPointer(MPT);
+ if (!V)
+ V = llvm::ConstantInt::get(CGM.Int8Ty, 0);
+ llvm::DITemplateValueParameter TVP =
+ DBuilder.createTemplateValueParameter(TheCU, Name, TTy, V);
+ TemplateParams.push_back(TVP);
+ } break;
+ case TemplateArgument::Template: {
+ llvm::DITemplateValueParameter TVP =
+ DBuilder.createTemplateTemplateParameter(
+ TheCU, Name, llvm::DIType(),
+ TA.getAsTemplate().getAsTemplateDecl()
+ ->getQualifiedNameAsString());
+ TemplateParams.push_back(TVP);
+ } break;
+ case TemplateArgument::Pack: {
+ llvm::DITemplateValueParameter TVP =
+ DBuilder.createTemplateParameterPack(
+ TheCU, Name, llvm::DIType(),
+ CollectTemplateParams(NULL, TA.getPackAsArray(), Unit));
+ TemplateParams.push_back(TVP);
+ } break;
+ case TemplateArgument::Expression: {
+ const Expr *E = TA.getAsExpr();
+ QualType T = E->getType();
+ llvm::Value *V = CGM.EmitConstantExpr(E, T);
+ assert(V && "Expression in template argument isn't constant");
+ llvm::DIType TTy = getOrCreateType(T, Unit);
+ llvm::DITemplateValueParameter TVP =
+ DBuilder.createTemplateValueParameter(TheCU, Name, TTy,
+ V->stripPointerCasts());
+ TemplateParams.push_back(TVP);
+ } break;
+ // And the following should never occur:
+ case TemplateArgument::TemplateExpansion:
+ case TemplateArgument::Null:
+ llvm_unreachable(
+ "These argument types shouldn't exist in concrete types");
}
}
return DBuilder.getOrCreateArray(TemplateParams);
@@ -1213,8 +1320,8 @@ CollectFunctionTemplateParams(const FunctionDecl *FD, llvm::DIFile Unit) {
const TemplateParameterList *TList =
FD->getTemplateSpecializationInfo()->getTemplate()
->getTemplateParameters();
- return
- CollectTemplateParams(TList, *FD->getTemplateSpecializationArgs(), Unit);
+ return CollectTemplateParams(
+ TList, FD->getTemplateSpecializationArgs()->asArray(), Unit);
}
return llvm::DIArray();
}
@@ -1227,12 +1334,12 @@ CollectCXXTemplateParams(const ClassTemplateSpecializationDecl *TSpecial,
llvm::PointerUnion<ClassTemplateDecl *,
ClassTemplatePartialSpecializationDecl *>
PU = TSpecial->getSpecializedTemplateOrPartial();
-
+
TemplateParameterList *TPList = PU.is<ClassTemplateDecl *>() ?
PU.get<ClassTemplateDecl *>()->getTemplateParameters() :
PU.get<ClassTemplatePartialSpecializationDecl *>()->getTemplateParameters();
const TemplateArgumentList &TAList = TSpecial->getTemplateInstantiationArgs();
- return CollectTemplateParams(TPList, TAList, Unit);
+ return CollectTemplateParams(TPList, TAList.asArray(), Unit);
}
/// getOrCreateVTablePtrType - Return debug info descriptor for vtable.
@@ -1255,13 +1362,8 @@ llvm::DIType CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile Unit) {
/// getVTableName - Get vtable name for the given Class.
StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) {
- // Construct gdb compatible name name.
- std::string Name = "_vptr$" + RD->getNameAsString();
-
- // Copy this name on the side and use its reference.
- char *StrPtr = DebugInfoNames.Allocate<char>(Name.length());
- memcpy(StrPtr, Name.data(), Name.length());
- return StringRef(StrPtr, Name.length());
+ // Copy the gdb compatible name on the side and use its reference.
+ return internString("_vptr$", RD->getNameAsString());
}
@@ -1283,15 +1385,16 @@ CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile Unit,
unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
llvm::DIType VPTR
= DBuilder.createMemberType(Unit, getVTableName(RD), Unit,
- 0, Size, 0, 0, llvm::DIDescriptor::FlagArtificial,
+ 0, Size, 0, 0,
+ llvm::DIDescriptor::FlagArtificial,
getOrCreateVTablePtrType(Unit));
EltTys.push_back(VPTR);
}
-/// getOrCreateRecordType - Emit record type's standalone debug info.
-llvm::DIType CGDebugInfo::getOrCreateRecordType(QualType RTy,
+/// getOrCreateRecordType - Emit record type's standalone debug info.
+llvm::DIType CGDebugInfo::getOrCreateRecordType(QualType RTy,
SourceLocation Loc) {
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
+ assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
llvm::DIType T = getOrCreateType(RTy, getOrCreateFile(Loc));
return T;
}
@@ -1300,15 +1403,76 @@ llvm::DIType CGDebugInfo::getOrCreateRecordType(QualType RTy,
/// debug info.
llvm::DIType CGDebugInfo::getOrCreateInterfaceType(QualType D,
SourceLocation Loc) {
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
+ assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
llvm::DIType T = getOrCreateType(D, getOrCreateFile(Loc));
RetainedTypes.push_back(D.getAsOpaquePtr());
return T;
}
+void CGDebugInfo::completeType(const RecordDecl *RD) {
+ if (DebugKind > CodeGenOptions::LimitedDebugInfo ||
+ !CGM.getLangOpts().CPlusPlus)
+ completeRequiredType(RD);
+}
+
+void CGDebugInfo::completeRequiredType(const RecordDecl *RD) {
+ if (const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD))
+ if (CXXDecl->isDynamicClass())
+ return;
+
+ QualType Ty = CGM.getContext().getRecordType(RD);
+ llvm::DIType T = getTypeOrNull(Ty);
+ if (T && T.isForwardDecl())
+ completeClassData(RD);
+}
+
+void CGDebugInfo::completeClassData(const RecordDecl *RD) {
+ if (DebugKind <= CodeGenOptions::DebugLineTablesOnly)
+ return;
+ QualType Ty = CGM.getContext().getRecordType(RD);
+ void* TyPtr = Ty.getAsOpaquePtr();
+ if (CompletedTypeCache.count(TyPtr))
+ return;
+ llvm::DIType Res = CreateTypeDefinition(Ty->castAs<RecordType>());
+ assert(!Res.isForwardDecl());
+ CompletedTypeCache[TyPtr] = Res;
+ TypeCache[TyPtr] = Res;
+}
+
/// CreateType - get structure or union type.
llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
RecordDecl *RD = Ty->getDecl();
+ const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD);
+ // Always emit declarations for types that aren't required to be complete when
+ // in limit-debug-info mode. If the type is later found to be required to be
+ // complete this declaration will be upgraded to a definition by
+ // `completeRequiredType`.
+ // If the type is dynamic, only emit the definition in TUs that require class
+ // data. This is handled by `completeClassData`.
+ llvm::DICompositeType T(getTypeOrNull(QualType(Ty, 0)));
+ // If we've already emitted the type, just use that, even if it's only a
+ // declaration. The completeType, completeRequiredType, and completeClassData
+ // callbacks will handle promoting the declaration to a definition.
+ if (T ||
+ (DebugKind <= CodeGenOptions::LimitedDebugInfo &&
+ // Under -flimit-debug-info, emit only a declaration unless the type is
+ // required to be complete.
+ !RD->isCompleteDefinitionRequired() && CGM.getLangOpts().CPlusPlus) ||
+ // If the class is dynamic, only emit a declaration. A definition will be
+ // emitted whenever the vtable is emitted.
+ (CXXDecl && CXXDecl->hasDefinition() && CXXDecl->isDynamicClass()) || T) {
+ llvm::DIDescriptor FDContext =
+ getContextDescriptor(cast<Decl>(RD->getDeclContext()));
+ if (!T)
+ T = getOrCreateRecordFwdDecl(Ty, FDContext);
+ return T;
+ }
+
+ return CreateTypeDefinition(Ty);
+}
+
+llvm::DIType CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) {
+ RecordDecl *RD = Ty->getDecl();
// Get overall information about the record type for the debug info.
llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());
@@ -1320,14 +1484,16 @@ 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::DICompositeType FwdDecl(
- getOrCreateLimitedType(QualType(Ty, 0), DefUnit));
- assert(FwdDecl.Verify() &&
- "The debug type of a RecordType should be a DICompositeType");
+ llvm::DICompositeType FwdDecl(getOrCreateLimitedType(Ty, DefUnit));
+ assert(FwdDecl.isCompositeType() &&
+ "The debug type of a RecordType should be a llvm::DICompositeType");
if (FwdDecl.isForwardDecl())
return FwdDecl;
+ if (const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD))
+ CollectContainingType(CXXDecl, FwdDecl);
+
// Push the struct on region stack.
LexicalBlockStack.push_back(&*FwdDecl);
RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl);
@@ -1337,6 +1503,7 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
// Convert all the elements.
SmallVector<llvm::Value *, 16> EltTys;
+ // what about nested types?
// Note: The split of CXXDecl information here is intentional, the
// gdb tests will depend on a certain ordering at printout. The debug
@@ -1350,20 +1517,14 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
// Collect data fields (including static variables and any initializers).
CollectRecordFields(RD, DefUnit, EltTys, FwdDecl);
- llvm::DIArray TParamsArray;
- if (CXXDecl) {
+ if (CXXDecl)
CollectCXXMemberFunctions(CXXDecl, DefUnit, EltTys, FwdDecl);
- CollectCXXFriends(CXXDecl, DefUnit, EltTys, FwdDecl);
- if (const ClassTemplateSpecializationDecl *TSpecial
- = dyn_cast<ClassTemplateSpecializationDecl>(RD))
- TParamsArray = CollectCXXTemplateParams(TSpecial, DefUnit);
- }
LexicalBlockStack.pop_back();
RegionMap.erase(Ty->getDecl());
llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);
- FwdDecl.setTypeArray(Elements, TParamsArray);
+ FwdDecl.setTypeArray(Elements);
RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl);
return FwdDecl;
@@ -1376,6 +1537,31 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCObjectType *Ty,
return getOrCreateType(Ty->getBaseType(), Unit);
}
+
+/// \return true if Getter has the default name for the property PD.
+static bool hasDefaultGetterName(const ObjCPropertyDecl *PD,
+ const ObjCMethodDecl *Getter) {
+ assert(PD);
+ if (!Getter)
+ return true;
+
+ assert(Getter->getDeclName().isObjCZeroArgSelector());
+ return PD->getName() ==
+ Getter->getDeclName().getObjCSelector().getNameForSlot(0);
+}
+
+/// \return true if Setter has the default name for the property PD.
+static bool hasDefaultSetterName(const ObjCPropertyDecl *PD,
+ const ObjCMethodDecl *Setter) {
+ assert(PD);
+ if (!Setter)
+ return true;
+
+ assert(Setter->getDeclName().isObjCOneArgSelector());
+ return SelectorTable::constructSetterName(PD->getName()) ==
+ Setter->getDeclName().getObjCSelector().getNameForSlot(0);
+}
+
/// CreateType - get objective-c interface type.
llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
llvm::DIFile Unit) {
@@ -1418,8 +1604,8 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
// will find it and we're emitting the complete type.
QualType QualTy = QualType(Ty, 0);
CompletedTypeCache[QualTy.getAsOpaquePtr()] = RealDecl;
- // Push the struct on region stack.
+ // Push the struct on region stack.
LexicalBlockStack.push_back(static_cast<llvm::MDNode*>(RealDecl));
RegionMap[Ty->getDecl()] = llvm::WeakVH(RealDecl);
@@ -1432,12 +1618,13 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
getOrCreateType(CGM.getContext().getObjCInterfaceType(SClass), Unit);
if (!SClassTy.isValid())
return llvm::DIType();
-
+
llvm::DIType InhTag =
DBuilder.createInheritance(RealDecl, SClassTy, 0, 0);
EltTys.push_back(InhTag);
}
+ // Create entries for all of the properties.
for (ObjCContainerDecl::prop_iterator I = ID->prop_begin(),
E = ID->prop_end(); I != E; ++I) {
const ObjCPropertyDecl *PD = *I;
@@ -1449,9 +1636,9 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
llvm::MDNode *PropertyNode =
DBuilder.createObjCProperty(PD->getName(),
PUnit, PLine,
- (Getter && Getter->isImplicit()) ? "" :
+ hasDefaultGetterName(PD, Getter) ? "" :
getSelectorName(PD->getGetterName()),
- (Setter && Setter->isImplicit()) ? "" :
+ hasDefaultSetterName(PD, Setter) ? "" :
getSelectorName(PD->getSetterName()),
PD->getPropertyAttributes(),
getOrCreateType(PD->getType(), PUnit));
@@ -1465,7 +1652,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
if (!FieldTy.isValid())
return llvm::DIType();
-
+
StringRef FieldName = Field->getName();
// Ignore unnamed fields.
@@ -1483,8 +1670,8 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
// Bit size, align and offset of the type.
FieldSize = Field->isBitField()
- ? Field->getBitWidthValue(CGM.getContext())
- : CGM.getContext().getTypeSize(FType);
+ ? Field->getBitWidthValue(CGM.getContext())
+ : CGM.getContext().getTypeSize(FType);
FieldAlign = CGM.getContext().getTypeAlign(FType);
}
@@ -1512,7 +1699,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
llvm::MDNode *PropertyNode = NULL;
if (ObjCImplementationDecl *ImpD = ID->getImplementation()) {
- if (ObjCPropertyImplDecl *PImpD =
+ if (ObjCPropertyImplDecl *PImpD =
ImpD->FindPropertyImplIvarDecl(Field->getIdentifier())) {
if (ObjCPropertyDecl *PD = PImpD->getPropertyDecl()) {
SourceLocation Loc = PD->getLocation();
@@ -1523,9 +1710,9 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
PropertyNode =
DBuilder.createObjCProperty(PD->getName(),
PUnit, PLine,
- (Getter && Getter->isImplicit()) ? "" :
+ hasDefaultGetterName(PD, Getter) ? "" :
getSelectorName(PD->getGetterName()),
- (Setter && Setter->isImplicit()) ? "" :
+ hasDefaultSetterName(PD, Setter) ? "" :
getSelectorName(PD->getSetterName()),
PD->getPropertyAttributes(),
getOrCreateType(PD->getType(), PUnit));
@@ -1547,7 +1734,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
// private ivars that we would miss otherwise.
if (ID->getImplementation() == 0)
CompletedTypeCache.erase(QualTy.getAsOpaquePtr());
-
+
LexicalBlockStack.pop_back();
return RealDecl;
}
@@ -1585,7 +1772,7 @@ llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty,
Align = 0;
else
Align = CGM.getContext().getTypeAlign(Ty->getElementType());
- } else if (Ty->isDependentSizedArrayType() || Ty->isIncompleteType()) {
+ } else if (Ty->isIncompleteType()) {
Size = 0;
Align = 0;
} else {
@@ -1610,7 +1797,7 @@ llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty,
int64_t Count = -1; // Count == -1 is an unbounded array.
if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(Ty))
Count = CAT->getSize().getZExtValue();
-
+
// FIXME: Verify this is right for VLAs.
Subscripts.push_back(DBuilder.getOrCreateSubrange(0, Count));
EltTy = Ty->getElementType();
@@ -1618,30 +1805,30 @@ llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty,
llvm::DIArray SubscriptArray = DBuilder.getOrCreateArray(Subscripts);
- llvm::DIType DbgTy =
+ llvm::DIType DbgTy =
DBuilder.createArrayType(Size, Align, getOrCreateType(EltTy, Unit),
SubscriptArray);
return DbgTy;
}
-llvm::DIType CGDebugInfo::CreateType(const LValueReferenceType *Ty,
+llvm::DIType CGDebugInfo::CreateType(const LValueReferenceType *Ty,
llvm::DIFile Unit) {
- return CreatePointerLikeType(llvm::dwarf::DW_TAG_reference_type,
+ return CreatePointerLikeType(llvm::dwarf::DW_TAG_reference_type,
Ty, Ty->getPointeeType(), Unit);
}
-llvm::DIType CGDebugInfo::CreateType(const RValueReferenceType *Ty,
+llvm::DIType CGDebugInfo::CreateType(const RValueReferenceType *Ty,
llvm::DIFile Unit) {
- return CreatePointerLikeType(llvm::dwarf::DW_TAG_rvalue_reference_type,
+ return CreatePointerLikeType(llvm::dwarf::DW_TAG_rvalue_reference_type,
Ty, Ty->getPointeeType(), Unit);
}
-llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty,
+llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty,
llvm::DIFile U) {
llvm::DIType ClassType = getOrCreateType(QualType(Ty->getClass(), 0), U);
if (!Ty->getPointeeType()->isFunctionType())
return DBuilder.createMemberPointerType(
- CreatePointeeType(Ty->getPointeeType(), U), ClassType);
+ getOrCreateType(Ty->getPointeeType(), U), ClassType);
return DBuilder.createMemberPointerType(getOrCreateInstanceMethodType(
CGM.getContext().getPointerType(
QualType(Ty->getClass(), Ty->getPointeeType().getCVRQualifiers())),
@@ -1649,7 +1836,7 @@ llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty,
ClassType);
}
-llvm::DIType CGDebugInfo::CreateType(const AtomicType *Ty,
+llvm::DIType CGDebugInfo::CreateType(const AtomicType *Ty,
llvm::DIFile U) {
// Ignore the atomic wrapping
// FIXME: What is the correct representation?
@@ -1657,7 +1844,8 @@ llvm::DIType CGDebugInfo::CreateType(const AtomicType *Ty,
}
/// CreateEnumType - get enumeration type.
-llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED) {
+llvm::DIType CGDebugInfo::CreateEnumType(const EnumType *Ty) {
+ const EnumDecl *ED = Ty->getDecl();
uint64_t Size = 0;
uint64_t Align = 0;
if (!ED->getTypeForDecl()->isIncompleteType()) {
@@ -1665,6 +1853,8 @@ llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED) {
Align = CGM.getContext().getTypeAlign(ED->getTypeForDecl());
}
+ SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
+
// If this is just a forward declaration, construct an appropriately
// marked node and just return it.
if (!ED->getDefinition()) {
@@ -1675,7 +1865,7 @@ llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED) {
StringRef EDName = ED->getName();
return DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_enumeration_type,
EDName, EDContext, DefUnit, Line, 0,
- Size, Align);
+ Size, Align, FullName);
}
// Create DIEnumerator elements for each enumerator.
@@ -1686,7 +1876,7 @@ llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED) {
Enum != EnumEnd; ++Enum) {
Enumerators.push_back(
DBuilder.createEnumerator(Enum->getName(),
- Enum->getInitVal().getZExtValue()));
+ Enum->getInitVal().getSExtValue()));
}
// Return a CompositeType for the enum itself.
@@ -1694,21 +1884,25 @@ llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED) {
llvm::DIFile DefUnit = getOrCreateFile(ED->getLocation());
unsigned Line = getLineNumber(ED->getLocation());
- llvm::DIDescriptor EnumContext =
+ llvm::DIDescriptor EnumContext =
getContextDescriptor(cast<Decl>(ED->getDeclContext()));
llvm::DIType ClassTy = ED->isFixed() ?
getOrCreateType(ED->getIntegerType(), DefUnit) : llvm::DIType();
- llvm::DIType DbgTy =
+ llvm::DIType DbgTy =
DBuilder.createEnumerationType(EnumContext, ED->getName(), DefUnit, Line,
Size, Align, EltArray,
- ClassTy);
+ ClassTy, FullName);
return DbgTy;
}
static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
Qualifiers Quals;
do {
- Quals += T.getLocalQualifiers();
+ Qualifiers InnerQuals = T.getLocalQualifiers();
+ // Qualifiers::operator+() doesn't like it if you add a Qualifier
+ // that is already there.
+ Quals += Qualifiers::removeCommonQualifiers(Quals, InnerQuals);
+ Quals += InnerQuals;
QualType LastT = T;
switch (T->getTypeClass()) {
default:
@@ -1741,21 +1935,25 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
T = cast<SubstTemplateTypeParmType>(T)->getReplacementType();
break;
case Type::Auto:
- T = cast<AutoType>(T)->getDeducedType();
+ QualType DT = cast<AutoType>(T)->getDeducedType();
+ if (DT.isNull())
+ return T;
+ T = DT;
break;
}
-
+
assert(T != LastT && "Type unwrapping failed to unwrap!");
(void)LastT;
} while (true);
}
-/// getType - Get the type from the cache or return null type if it doesn't exist.
+/// getType - Get the type from the cache or return null type if it doesn't
+/// exist.
llvm::DIType CGDebugInfo::getTypeOrNull(QualType Ty) {
// Unwrap the type as needed for debug information.
Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext());
-
+
// Check for existing entry.
if (Ty->getTypeClass() == Type::ObjCInterface) {
llvm::Value *V = getCachedInterfaceTypeOrNull(Ty);
@@ -1793,10 +1991,7 @@ llvm::DIType CGDebugInfo::getCompletedTypeOrNull(QualType Ty) {
}
// Verify that any cached debug info still exists.
- if (V != 0)
- return llvm::DIType(cast<llvm::MDNode>(V));
-
- return llvm::DIType();
+ return llvm::DIType(cast_or_null<llvm::MDNode>(V));
}
/// getCachedInterfaceTypeOrNull - Get the type from the interface
@@ -1824,9 +2019,7 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile Unit) {
// Unwrap the type as needed for debug information.
Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext());
- llvm::DIType T = getCompletedTypeOrNull(Ty);
-
- if (T.Verify())
+ if (llvm::DIType T = getCompletedTypeOrNull(Ty))
return T;
// Otherwise create the type.
@@ -1836,29 +2029,33 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile Unit) {
// And update the type cache.
TypeCache[TyPtr] = Res;
+ // FIXME: this getTypeOrNull call seems silly when we just inserted the type
+ // into the cache - but getTypeOrNull has a special case for cached interface
+ // types. We should probably just pull that out as a special case for the
+ // "else" block below & skip the otherwise needless lookup.
llvm::DIType TC = getTypeOrNull(Ty);
- if (TC.Verify() && TC.isForwardDecl())
+ if (TC && TC.isForwardDecl())
ReplaceMap.push_back(std::make_pair(TyPtr, static_cast<llvm::Value*>(TC)));
else if (ObjCInterfaceDecl* Decl = getObjCInterfaceDecl(Ty)) {
// Interface types may have elements added to them by a
// subsequent implementation or extension, so we keep them in
// the ObjCInterfaceCache together with a checksum. Instead of
- // the (possibly) incomplete interace type, we return a forward
+ // the (possibly) incomplete interface type, we return a forward
// declaration that gets RAUW'd in CGDebugInfo::finalize().
- llvm::DenseMap<void *, std::pair<llvm::WeakVH, unsigned > >
- ::iterator it = ObjCInterfaceCache.find(TyPtr);
- if (it != ObjCInterfaceCache.end())
- TC = llvm::DIType(cast<llvm::MDNode>(it->second.first));
- else
- TC = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
- Decl->getName(), TheCU, Unit,
- getLineNumber(Decl->getLocation()),
- TheCU.getLanguage());
+ std::pair<llvm::WeakVH, unsigned> &V = ObjCInterfaceCache[TyPtr];
+ if (V.first)
+ return llvm::DIType(cast<llvm::MDNode>(V.first));
+ TC = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
+ Decl->getName(), TheCU, Unit,
+ getLineNumber(Decl->getLocation()),
+ TheCU.getLanguage());
// Store the forward declaration in the cache.
- ObjCInterfaceCache[TyPtr] = std::make_pair(TC, Checksum(Decl));
+ V.first = TC;
+ V.second = Checksum(Decl);
// Register the type for replacement in finalize().
ReplaceMap.push_back(std::make_pair(TyPtr, static_cast<llvm::Value*>(TC)));
+
return TC;
}
@@ -1868,19 +2065,25 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile Unit) {
return Res;
}
-/// Currently the checksum merely consists of the number of ivars.
-unsigned CGDebugInfo::Checksum(const ObjCInterfaceDecl
- *InterfaceDecl) {
- unsigned IvarNo = 0;
- for (const ObjCIvarDecl *Ivar = InterfaceDecl->all_declared_ivar_begin();
- Ivar != 0; Ivar = Ivar->getNextIvar()) ++IvarNo;
- return IvarNo;
+/// Currently the checksum of an interface includes the number of
+/// ivars and property accessors.
+unsigned CGDebugInfo::Checksum(const ObjCInterfaceDecl *ID) {
+ // The assumption is that the number of ivars can only increase
+ // monotonically, so it is safe to just use their current number as
+ // a checksum.
+ unsigned Sum = 0;
+ for (const ObjCIvarDecl *Ivar = ID->all_declared_ivar_begin();
+ Ivar != 0; Ivar = Ivar->getNextIvar())
+ ++Sum;
+
+ return Sum;
}
ObjCInterfaceDecl *CGDebugInfo::getObjCInterfaceDecl(QualType Ty) {
switch (Ty->getTypeClass()) {
case Type::ObjCObjectPointer:
- return getObjCInterfaceDecl(cast<ObjCObjectPointerType>(Ty)->getPointeeType());
+ return getObjCInterfaceDecl(cast<ObjCObjectPointerType>(Ty)
+ ->getPointeeType());
case Type::ObjCInterface:
return cast<ObjCInterfaceType>(Ty)->getDecl();
default:
@@ -1895,7 +2098,7 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit) {
return CreateQualifiedType(Ty, Unit);
const char *Diag = 0;
-
+
// Work out details of type.
switch (Ty->getTypeClass()) {
#define TYPE(Class, Base)
@@ -1920,6 +2123,10 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit) {
return CreateType(cast<ComplexType>(Ty));
case Type::Pointer:
return CreateType(cast<PointerType>(Ty), Unit);
+ case Type::Decayed:
+ // Decayed types are just pointers in LLVM and DWARF.
+ return CreateType(
+ cast<PointerType>(cast<DecayedType>(Ty)->getDecayedType()), Unit);
case Type::BlockPointer:
return CreateType(cast<BlockPointerType>(Ty), Unit);
case Type::Typedef:
@@ -1927,7 +2134,7 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit) {
case Type::Record:
return CreateType(cast<RecordType>(Ty));
case Type::Enum:
- return CreateEnumType(cast<EnumType>(Ty)->getDecl());
+ return CreateEnumType(cast<EnumType>(Ty));
case Type::FunctionProto:
case Type::FunctionNoProto:
return CreateType(cast<FunctionType>(Ty), Unit);
@@ -1956,10 +2163,13 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit) {
case Type::TypeOf:
case Type::Decltype:
case Type::UnaryTransform:
- case Type::Auto:
+ case Type::PackExpansion:
llvm_unreachable("type should have been unwrapped!");
+ case Type::Auto:
+ Diag = "auto";
+ break;
}
-
+
assert(Diag && "Fall through without a diagnostic?");
unsigned DiagID = CGM.getDiags().getCustomDiagID(DiagnosticsEngine::Error,
"debug information for %0 is not yet supported");
@@ -1970,117 +2180,119 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit) {
/// getOrCreateLimitedType - Get the type from the cache or create a new
/// limited type if necessary.
-llvm::DIType CGDebugInfo::getOrCreateLimitedType(QualType Ty,
+llvm::DIType CGDebugInfo::getOrCreateLimitedType(const RecordType *Ty,
llvm::DIFile Unit) {
- if (Ty.isNull())
- return llvm::DIType();
+ QualType QTy(Ty, 0);
- // Unwrap the type as needed for debug information.
- Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext());
-
- llvm::DIType T = getTypeOrNull(Ty);
+ llvm::DICompositeType T(getTypeOrNull(QTy));
// We may have cached a forward decl when we could have created
// a non-forward decl. Go ahead and create a non-forward decl
// now.
- if (T.Verify() && !T.isForwardDecl()) return T;
+ if (T && !T.isForwardDecl()) return T;
// Otherwise create the type.
- llvm::DIType Res = CreateLimitedTypeNode(Ty, Unit);
+ llvm::DICompositeType Res = CreateLimitedType(Ty);
- if (T.Verify() && T.isForwardDecl())
- ReplaceMap.push_back(std::make_pair(Ty.getAsOpaquePtr(),
- static_cast<llvm::Value*>(T)));
+ // Propagate members from the declaration to the definition
+ // CreateType(const RecordType*) will overwrite this with the members in the
+ // correct order if the full type is needed.
+ Res.setTypeArray(T.getTypeArray());
+
+ if (T && T.isForwardDecl())
+ ReplaceMap.push_back(
+ std::make_pair(QTy.getAsOpaquePtr(), static_cast<llvm::Value *>(T)));
// And update the type cache.
- TypeCache[Ty.getAsOpaquePtr()] = Res;
+ TypeCache[QTy.getAsOpaquePtr()] = Res;
return Res;
}
// TODO: Currently used for context chains when limiting debug info.
-llvm::DIType CGDebugInfo::CreateLimitedType(const RecordType *Ty) {
+llvm::DICompositeType CGDebugInfo::CreateLimitedType(const RecordType *Ty) {
RecordDecl *RD = Ty->getDecl();
-
+
// Get overall information about the record type for the debug info.
llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());
unsigned Line = getLineNumber(RD->getLocation());
StringRef RDName = getClassName(RD);
- llvm::DIDescriptor RDContext;
- if (CGM.getCodeGenOpts().getDebugInfo() == CodeGenOptions::LimitedDebugInfo)
- RDContext = createContextChain(cast<Decl>(RD->getDeclContext()));
- else
- RDContext = getContextDescriptor(cast<Decl>(RD->getDeclContext()));
+ llvm::DIDescriptor RDContext =
+ getContextDescriptor(cast<Decl>(RD->getDeclContext()));
+
+ // If we ended up creating the type during the context chain construction,
+ // just return that.
+ // FIXME: this could be dealt with better if the type was recorded as
+ // completed before we started this (see the CompletedTypeCache usage in
+ // CGDebugInfo::CreateTypeDefinition(const RecordType*) - that would need to
+ // be pushed to before context creation, but after it was known to be
+ // destined for completion (might still have an issue if this caller only
+ // required a declaration but the context construction ended up creating a
+ // definition)
+ llvm::DICompositeType T(getTypeOrNull(CGM.getContext().getRecordType(RD)));
+ if (T && (!T.isForwardDecl() || !RD->getDefinition()))
+ return T;
// If this is just a forward declaration, construct an appropriately
// marked node and just return it.
if (!RD->getDefinition())
- return createRecordFwdDecl(RD, RDContext);
+ return getOrCreateRecordFwdDecl(Ty, RDContext);
uint64_t Size = CGM.getContext().getTypeSize(Ty);
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
- const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD);
llvm::DICompositeType RealDecl;
-
+
+ SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
+
if (RD->isUnion())
RealDecl = DBuilder.createUnionType(RDContext, RDName, DefUnit, Line,
- Size, Align, 0, llvm::DIArray());
+ Size, Align, 0, llvm::DIArray(), 0,
+ FullName);
else if (RD->isClass()) {
// FIXME: This could be a struct type giving a default visibility different
// than C++ class type, but needs llvm metadata changes first.
RealDecl = DBuilder.createClassType(RDContext, RDName, DefUnit, Line,
Size, Align, 0, 0, llvm::DIType(),
llvm::DIArray(), llvm::DIType(),
- llvm::DIArray());
+ llvm::DIArray(), FullName);
} else
RealDecl = DBuilder.createStructType(RDContext, RDName, DefUnit, Line,
- Size, Align, 0, llvm::DIType(), llvm::DIArray());
+ Size, Align, 0, llvm::DIType(),
+ llvm::DIArray(), 0, llvm::DIType(),
+ FullName);
RegionMap[Ty->getDecl()] = llvm::WeakVH(RealDecl);
TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = RealDecl;
- if (CXXDecl) {
- // A class's primary base or the class itself contains the vtable.
- llvm::DICompositeType ContainingType;
- const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
- if (const CXXRecordDecl *PBase = RL.getPrimaryBase()) {
- // Seek non virtual primary base root.
- while (1) {
- const ASTRecordLayout &BRL = CGM.getContext().getASTRecordLayout(PBase);
- const CXXRecordDecl *PBT = BRL.getPrimaryBase();
- if (PBT && !BRL.isPrimaryBaseVirtual())
- PBase = PBT;
- else
- break;
- }
- ContainingType = llvm::DICompositeType(
- getOrCreateType(QualType(PBase->getTypeForDecl(), 0), DefUnit));
- } else if (CXXDecl->isDynamicClass())
- ContainingType = RealDecl;
-
- RealDecl.setContainingType(ContainingType);
- }
- return llvm::DIType(RealDecl);
+ if (const ClassTemplateSpecializationDecl *TSpecial =
+ dyn_cast<ClassTemplateSpecializationDecl>(RD))
+ RealDecl.setTypeArray(llvm::DIArray(),
+ CollectCXXTemplateParams(TSpecial, DefUnit));
+ return RealDecl;
}
-/// CreateLimitedTypeNode - Create a new debug type node, but only forward
-/// declare composite types that haven't been processed yet.
-llvm::DIType CGDebugInfo::CreateLimitedTypeNode(QualType Ty,llvm::DIFile Unit) {
-
- // Work out details of type.
- switch (Ty->getTypeClass()) {
-#define TYPE(Class, Base)
-#define ABSTRACT_TYPE(Class, Base)
-#define NON_CANONICAL_TYPE(Class, Base)
-#define DEPENDENT_TYPE(Class, Base) case Type::Class:
- #include "clang/AST/TypeNodes.def"
- llvm_unreachable("Dependent types cannot show up in debug information");
+void CGDebugInfo::CollectContainingType(const CXXRecordDecl *RD,
+ llvm::DICompositeType RealDecl) {
+ // A class's primary base or the class itself contains the vtable.
+ llvm::DICompositeType ContainingType;
+ const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
+ if (const CXXRecordDecl *PBase = RL.getPrimaryBase()) {
+ // Seek non virtual primary base root.
+ while (1) {
+ const ASTRecordLayout &BRL = CGM.getContext().getASTRecordLayout(PBase);
+ const CXXRecordDecl *PBT = BRL.getPrimaryBase();
+ if (PBT && !BRL.isPrimaryBaseVirtual())
+ PBase = PBT;
+ else
+ break;
+ }
+ ContainingType = llvm::DICompositeType(
+ getOrCreateType(QualType(PBase->getTypeForDecl(), 0),
+ getOrCreateFile(RD->getLocation())));
+ } else if (RD->isDynamicClass())
+ ContainingType = RealDecl;
- case Type::Record:
- return CreateLimitedType(cast<RecordType>(Ty));
- default:
- return CreateTypeNode(Ty, Unit);
- }
+ RealDecl.setContainingType(ContainingType);
}
/// CreateMemberType - Create new member and increase Offset by FType's size.
@@ -2097,21 +2309,57 @@ llvm::DIType CGDebugInfo::CreateMemberType(llvm::DIFile Unit, QualType FType,
return Ty;
}
+llvm::DIDescriptor CGDebugInfo::getDeclarationOrDefinition(const Decl *D) {
+ // We only need a declaration (not a definition) of the type - so use whatever
+ // we would otherwise do to get a type for a pointee. (forward declarations in
+ // limited debug info, full definitions (if the type definition is available)
+ // in unlimited debug info)
+ if (const TypeDecl *TD = dyn_cast<TypeDecl>(D))
+ return getOrCreateType(CGM.getContext().getTypeDeclType(TD),
+ getOrCreateFile(TD->getLocation()));
+ // Otherwise fall back to a fairly rudimentary cache of existing declarations.
+ // This doesn't handle providing declarations (for functions or variables) for
+ // entities without definitions in this TU, nor when the definition proceeds
+ // the call to this function.
+ // FIXME: This should be split out into more specific maps with support for
+ // emitting forward declarations and merging definitions with declarations,
+ // the same way as we do for types.
+ llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator I =
+ DeclCache.find(D->getCanonicalDecl());
+ if (I == DeclCache.end())
+ return llvm::DIDescriptor();
+ llvm::Value *V = I->second;
+ return llvm::DIDescriptor(dyn_cast_or_null<llvm::MDNode>(V));
+}
+
/// getFunctionDeclaration - Return debug info descriptor to describe method
/// declaration for the given method definition.
llvm::DISubprogram CGDebugInfo::getFunctionDeclaration(const Decl *D) {
+ if (!D || DebugKind == CodeGenOptions::DebugLineTablesOnly)
+ return llvm::DISubprogram();
+
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
if (!FD) return llvm::DISubprogram();
// Setup context.
- getContextDescriptor(cast<Decl>(D->getDeclContext()));
+ llvm::DIScope S = getContextDescriptor(cast<Decl>(D->getDeclContext()));
llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator
MI = SPCache.find(FD->getCanonicalDecl());
+ if (MI == SPCache.end()) {
+ if (const CXXMethodDecl *MD =
+ dyn_cast<CXXMethodDecl>(FD->getCanonicalDecl())) {
+ llvm::DICompositeType T(S);
+ llvm::DISubprogram SP =
+ CreateCXXMemberFunction(MD, getOrCreateFile(MD->getLocation()), T);
+ T.addMember(SP);
+ return SP;
+ }
+ }
if (MI != SPCache.end()) {
llvm::Value *V = MI->second;
llvm::DISubprogram SP(dyn_cast_or_null<llvm::MDNode>(V));
- if (SP.isSubprogram() && !llvm::DISubprogram(SP).isDefinition())
+ if (SP.isSubprogram() && !SP.isDefinition())
return SP;
}
@@ -2123,7 +2371,7 @@ llvm::DISubprogram CGDebugInfo::getFunctionDeclaration(const Decl *D) {
if (MI != SPCache.end()) {
llvm::Value *V = MI->second;
llvm::DISubprogram SP(dyn_cast_or_null<llvm::MDNode>(V));
- if (SP.isSubprogram() && !llvm::DISubprogram(SP).isDefinition())
+ if (SP.isSubprogram() && !SP.isDefinition())
return SP;
}
}
@@ -2132,9 +2380,15 @@ llvm::DISubprogram CGDebugInfo::getFunctionDeclaration(const Decl *D) {
// getOrCreateFunctionType - Construct DIType. If it is a c++ method, include
// implicit parameter "this".
-llvm::DIType CGDebugInfo::getOrCreateFunctionType(const Decl *D,
- QualType FnType,
- llvm::DIFile F) {
+llvm::DICompositeType CGDebugInfo::getOrCreateFunctionType(const Decl *D,
+ QualType FnType,
+ llvm::DIFile F) {
+ if (!D || DebugKind == CodeGenOptions::DebugLineTablesOnly)
+ // Create fake but valid subroutine type. Otherwise
+ // llvm::DISubprogram::Verify() would return false, and
+ // subprogram DIE will miss DW_AT_decl_file and
+ // DW_AT_decl_line fields.
+ return DBuilder.createSubroutineType(F, DBuilder.getOrCreateArray(None));
if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))
return getOrCreateMethodType(Method, F);
@@ -2143,7 +2397,14 @@ llvm::DIType CGDebugInfo::getOrCreateFunctionType(const Decl *D,
SmallVector<llvm::Value *, 16> Elts;
// First element is always return type. For 'void' functions it is NULL.
- Elts.push_back(getOrCreateType(OMethod->getResultType(), F));
+ QualType ResultTy = OMethod->getResultType();
+
+ // Replace the instancetype keyword with the actual type.
+ if (ResultTy == CGM.getContext().getObjCInstanceType())
+ ResultTy = CGM.getContext().getPointerType(
+ QualType(OMethod->getClassInterface()->getTypeForDecl(), 0));
+
+ Elts.push_back(getOrCreateType(ResultTy, F));
// "self" pointer is always first argument.
QualType SelfDeclTy = OMethod->getSelfDecl()->getType();
llvm::DIType SelfTy = getOrCreateType(SelfDeclTy, F);
@@ -2152,14 +2413,14 @@ llvm::DIType CGDebugInfo::getOrCreateFunctionType(const Decl *D,
llvm::DIType CmdTy = getOrCreateType(OMethod->getCmdDecl()->getType(), F);
Elts.push_back(DBuilder.createArtificialType(CmdTy));
// Get rest of the arguments.
- for (ObjCMethodDecl::param_const_iterator PI = OMethod->param_begin(),
+ for (ObjCMethodDecl::param_const_iterator PI = OMethod->param_begin(),
PE = OMethod->param_end(); PI != PE; ++PI)
Elts.push_back(getOrCreateType((*PI)->getType(), F));
llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(Elts);
return DBuilder.createSubroutineType(F, EltTypeArray);
}
- return getOrCreateType(FnType, F);
+ return llvm::DICompositeType(getOrCreateType(FnType, F));
}
/// EmitFunctionStart - Constructs the debug code for entering a function.
@@ -2187,7 +2448,7 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType,
llvm::DIArray TParamsArray;
if (!HasDecl) {
// Use llvm function name.
- Name = Fn->getName();
+ LinkageName = Fn->getName();
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
// If there is a DISubprogram for this function available then use it.
llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator
@@ -2214,16 +2475,16 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType,
if (LinkageName == Name ||
(!CGM.getCodeGenOpts().EmitGcovArcs &&
!CGM.getCodeGenOpts().EmitGcovNotes &&
- CGM.getCodeGenOpts().getDebugInfo() <= CodeGenOptions::DebugLineTablesOnly))
+ DebugKind <= CodeGenOptions::DebugLineTablesOnly))
LinkageName = StringRef();
- if (CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo) {
+ if (DebugKind >= CodeGenOptions::LimitedDebugInfo) {
if (const NamespaceDecl *NSDecl =
- dyn_cast_or_null<NamespaceDecl>(FD->getDeclContext()))
+ dyn_cast_or_null<NamespaceDecl>(FD->getDeclContext()))
FDContext = getOrCreateNameSpace(NSDecl);
else if (const RecordDecl *RDecl =
- dyn_cast_or_null<RecordDecl>(FD->getDeclContext()))
- FDContext = getContextDescriptor(cast<Decl>(RDecl->getDeclContext()));
+ dyn_cast_or_null<RecordDecl>(FD->getDeclContext()))
+ FDContext = getContextDescriptor(cast<Decl>(RDecl));
// Collect template parameters.
TParamsArray = CollectFunctionTemplateParams(FD, Unit);
@@ -2243,28 +2504,15 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType,
if (!HasDecl || D->isImplicit())
Flags |= llvm::DIDescriptor::FlagArtificial;
- llvm::DIType DIFnType;
- llvm::DISubprogram SPDecl;
- if (HasDecl &&
- CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo) {
- DIFnType = getOrCreateFunctionType(D, FnType, Unit);
- SPDecl = getFunctionDeclaration(D);
- } else {
- // Create fake but valid subroutine type. Otherwise
- // llvm::DISubprogram::Verify() would return false, and
- // subprogram DIE will miss DW_AT_decl_file and
- // DW_AT_decl_line fields.
- SmallVector<llvm::Value*, 16> Elts;
- llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(Elts);
- DIFnType = DBuilder.createSubroutineType(Unit, EltTypeArray);
- }
- llvm::DISubprogram SP;
- SP = DBuilder.createFunction(FDContext, Name, LinkageName, Unit,
- LineNo, DIFnType,
- Fn->hasInternalLinkage(), true/*definition*/,
- getLineNumber(CurLoc), Flags,
- CGM.getLangOpts().Optimize,
- Fn, TParamsArray, SPDecl);
+ llvm::DISubprogram SP =
+ DBuilder.createFunction(FDContext, Name, LinkageName, Unit, LineNo,
+ getOrCreateFunctionType(D, FnType, Unit),
+ Fn->hasInternalLinkage(), true /*definition*/,
+ getLineNumber(CurLoc), Flags,
+ CGM.getLangOpts().Optimize, Fn, TParamsArray,
+ getFunctionDeclaration(D));
+ if (HasDecl)
+ DeclCache.insert(std::make_pair(D->getCanonicalDecl(), llvm::WeakVH(SP)));
// Push function on region stack.
llvm::MDNode *SPN = SP;
@@ -2274,10 +2522,10 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType,
}
/// EmitLocation - Emit metadata to indicate a change in line/column
-/// information in the source file.
+/// information in the source file. If the location is invalid, the
+/// previous location will be reused.
void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc,
bool ForceColumnInfo) {
-
// Update our current location
setLocation(Loc);
@@ -2292,7 +2540,7 @@ void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc,
Builder.getCurrentDebugLocation().getScope(CGM.getLLVMContext()) ==
LexicalBlockStack.back())
return;
-
+
// Update last state.
PrevLoc = CurLoc;
@@ -2319,7 +2567,8 @@ void CGDebugInfo::CreateLexicalBlock(SourceLocation Loc) {
/// EmitLexicalBlockStart - Constructs the debug code for entering a declarative
/// region - beginning of a DW_TAG_lexical_block.
-void CGDebugInfo::EmitLexicalBlockStart(CGBuilderTy &Builder, SourceLocation Loc) {
+void CGDebugInfo::EmitLexicalBlockStart(CGBuilderTy &Builder,
+ SourceLocation Loc) {
// Set our current location.
setLocation(Loc);
@@ -2334,7 +2583,8 @@ void CGDebugInfo::EmitLexicalBlockStart(CGBuilderTy &Builder, SourceLocation Loc
/// EmitLexicalBlockEnd - Constructs the debug code for exiting a declarative
/// region - end of a DW_TAG_lexical_block.
-void CGDebugInfo::EmitLexicalBlockEnd(CGBuilderTy &Builder, SourceLocation Loc) {
+void CGDebugInfo::EmitLexicalBlockEnd(CGBuilderTy &Builder,
+ SourceLocation Loc) {
assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
// Provide an entry in the line table for the end of the block.
@@ -2355,7 +2605,7 @@ void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder) {
FnBeginRegionCount.pop_back();
}
-// EmitTypeForVarWithBlocksAttr - Build up structure info for the byref.
+// EmitTypeForVarWithBlocksAttr - Build up structure info for the byref.
// See BuildByRefType.
llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
uint64_t *XOffset) {
@@ -2364,9 +2614,9 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
QualType FType;
uint64_t FieldSize, FieldOffset;
unsigned FieldAlign;
-
+
llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
- QualType Type = VD->getType();
+ QualType Type = VD->getType();
FieldOffset = 0;
FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
@@ -2388,21 +2638,23 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
Qualifiers::ObjCLifetime Lifetime;
if (CGM.getContext().getByrefLifetime(Type,
Lifetime, HasByrefExtendedLayout)
- && HasByrefExtendedLayout)
+ && HasByrefExtendedLayout) {
+ FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
EltTys.push_back(CreateMemberType(Unit, FType,
"__byref_variable_layout",
&FieldOffset));
-
+ }
+
CharUnits Align = CGM.getContext().getDeclAlign(VD);
if (Align > CGM.getContext().toCharUnitsFromBits(
CGM.getTarget().getPointerAlign(0))) {
- CharUnits FieldOffsetInBytes
+ CharUnits FieldOffsetInBytes
= CGM.getContext().toCharUnitsFromBits(FieldOffset);
CharUnits AlignedOffsetInBytes
= FieldOffsetInBytes.RoundUpToAlignment(Align);
CharUnits NumPaddingBytes
= AlignedOffsetInBytes - FieldOffsetInBytes;
-
+
if (NumPaddingBytes.isPositive()) {
llvm::APInt pad(32, NumPaddingBytes.getQuantity());
FType = CGM.getContext().getConstantArrayType(CGM.getContext().CharTy,
@@ -2410,40 +2662,45 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
EltTys.push_back(CreateMemberType(Unit, FType, "", &FieldOffset));
}
}
-
+
FType = Type;
llvm::DIType FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
FieldSize = CGM.getContext().getTypeSize(FType);
FieldAlign = CGM.getContext().toBits(Align);
- *XOffset = FieldOffset;
+ *XOffset = FieldOffset;
FieldTy = DBuilder.createMemberType(Unit, VD->getName(), Unit,
0, FieldSize, FieldAlign,
FieldOffset, 0, FieldTy);
EltTys.push_back(FieldTy);
FieldOffset += FieldSize;
-
+
llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);
-
+
unsigned Flags = llvm::DIDescriptor::FlagBlockByrefStruct;
-
+
return DBuilder.createStructType(Unit, "", Unit, 0, FieldOffset, 0, Flags,
llvm::DIType(), Elements);
}
/// EmitDeclare - Emit local variable declaration debug info.
void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
- llvm::Value *Storage,
+ llvm::Value *Storage,
unsigned ArgNo, CGBuilderTy &Builder) {
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
+ assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
- llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
+ bool Unwritten =
+ VD->isImplicit() || (isa<Decl>(VD->getDeclContext()) &&
+ cast<Decl>(VD->getDeclContext())->isImplicit());
+ llvm::DIFile Unit;
+ if (!Unwritten)
+ Unit = getOrCreateFile(VD->getLocation());
llvm::DIType Ty;
uint64_t XOffset = 0;
if (VD->hasAttr<BlocksAttr>())
Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset);
- else
+ else
Ty = getOrCreateType(VD->getType(), Unit);
// If there is no debug info for this type then do not emit debug info
@@ -2451,24 +2708,13 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
if (!Ty)
return;
- if (llvm::Argument *Arg = dyn_cast<llvm::Argument>(Storage)) {
- // If Storage is an aggregate returned as 'sret' then let debugger know
- // about this.
- if (Arg->hasStructRetAttr())
- Ty = DBuilder.createReferenceType(llvm::dwarf::DW_TAG_reference_type, 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->hasNonTrivialCopyConstructor() ||
- !Record->hasTrivialDestructor())
- Ty = DBuilder.createReferenceType(llvm::dwarf::DW_TAG_reference_type, Ty);
- }
- }
-
// Get location information.
- unsigned Line = getLineNumber(VD->getLocation());
- unsigned Column = getColumnNumber(VD->getLocation());
+ unsigned Line = 0;
+ unsigned Column = 0;
+ if (!Unwritten) {
+ Line = getLineNumber(VD->getLocation());
+ Column = getColumnNumber(VD->getLocation());
+ }
unsigned Flags = 0;
if (VD->isImplicit())
Flags |= llvm::DIDescriptor::FlagArtificial;
@@ -2479,6 +2725,10 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
// otherwise it is 'self' or 'this'.
if (isa<ImplicitParamDecl>(VD) && ArgNo == 1)
Flags |= llvm::DIDescriptor::FlagObjectPointer;
+ if (llvm::Argument *Arg = dyn_cast<llvm::Argument>(Storage))
+ if (Arg->getType()->isPointerTy() && !Arg->hasByValAttr() &&
+ !VD->getType()->isPointerType())
+ Flags |= llvm::DIDescriptor::FlagIndirectVariable;
llvm::MDNode *Scope = LexicalBlockStack.back();
@@ -2501,33 +2751,18 @@ 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(Scope),
VD->getName(), Unit, Line, Ty,
addr, ArgNo);
-
- // 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));
- return;
- } else if (isa<VariableArrayType>(VD->getType())) {
- // These are "complex" variables in that they need an op_deref.
- // Create the descriptor for the variable.
- llvm::Value *Addr = llvm::ConstantInt::get(CGM.Int64Ty,
- llvm::DIBuilder::OpDeref);
- llvm::DIVariable D =
- DBuilder.createComplexVariable(Tag,
- llvm::DIDescriptor(Scope),
- Name, Unit, Line, Ty,
- Addr, ArgNo);
// 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));
return;
- }
+ } else if (isa<VariableArrayType>(VD->getType()))
+ Flags |= llvm::DIDescriptor::FlagIndirectVariable;
} else if (const RecordType *RT = dyn_cast<RecordType>(VD->getType())) {
// If VD is an anonymous union then Storage represents value for
// all union fields.
@@ -2539,18 +2774,18 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
FieldDecl *Field = *I;
llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
StringRef FieldName = Field->getName();
-
+
// 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,
+ FieldName, Unit, Line, FieldTy,
CGM.getLangOpts().Optimize, Flags,
ArgNo);
-
+
// Insert an llvm.dbg.declare into the current block.
llvm::Instruction *Call =
DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());
@@ -2575,7 +2810,7 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD,
llvm::Value *Storage,
CGBuilderTy &Builder) {
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
+ assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
EmitDeclare(VD, llvm::dwarf::DW_TAG_auto_variable, Storage, 0, Builder);
}
@@ -2585,9 +2820,10 @@ void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD,
/// never happen though, since creating a type for the implicit self
/// argument implies that we already parsed the interface definition
/// and the ivar declarations in the implementation.
-llvm::DIType CGDebugInfo::CreateSelfType(const QualType &QualTy, llvm::DIType Ty) {
+llvm::DIType CGDebugInfo::CreateSelfType(const QualType &QualTy,
+ llvm::DIType Ty) {
llvm::DIType CachedTy = getTypeOrNull(QualTy);
- if (CachedTy.Verify()) Ty = CachedTy;
+ if (CachedTy) Ty = CachedTy;
else DEBUG(llvm::dbgs() << "No cached type for self.");
return DBuilder.createObjectPointerType(Ty);
}
@@ -2596,20 +2832,20 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(const VarDecl *VD,
llvm::Value *Storage,
CGBuilderTy &Builder,
const CGBlockInfo &blockInfo) {
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
+ assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
-
+
if (Builder.GetInsertBlock() == 0)
return;
-
+
bool isByRef = VD->hasAttr<BlocksAttr>();
-
+
uint64_t XOffset = 0;
llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
llvm::DIType Ty;
if (isByRef)
Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset);
- else
+ else
Ty = getOrCreateType(VD->getType(), Unit);
// Self is passed along as an implicit non-arg variable in a
@@ -2649,7 +2885,7 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(const VarDecl *VD,
// Create the descriptor for the variable.
llvm::DIVariable D =
- DBuilder.createComplexVariable(llvm::dwarf::DW_TAG_auto_variable,
+ DBuilder.createComplexVariable(llvm::dwarf::DW_TAG_auto_variable,
llvm::DIDescriptor(LexicalBlockStack.back()),
VD->getName(), Unit, Line, Ty, addr);
@@ -2665,7 +2901,7 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(const VarDecl *VD,
void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *VD, llvm::Value *AI,
unsigned ArgNo,
CGBuilderTy &Builder) {
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
+ assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
EmitDeclare(VD, llvm::dwarf::DW_TAG_arg_variable, AI, ArgNo, Builder);
}
@@ -2683,7 +2919,7 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
llvm::Value *Arg,
llvm::Value *LocalAddr,
CGBuilderTy &Builder) {
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
+ assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
ASTContext &C = CGM.getContext();
const BlockDecl *blockDecl = block.getBlockDecl();
@@ -2692,7 +2928,7 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
llvm::DIFile tunit = getOrCreateFile(loc);
unsigned line = getLineNumber(loc);
unsigned column = getColumnNumber(loc);
-
+
// Build the debug-info type for the block literal.
getContextDescriptor(cast<Decl>(blockDecl->getDeclContext()));
@@ -2812,7 +3048,7 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
// Create the descriptor for the parameter.
llvm::DIVariable debugVar =
DBuilder.createLocalVariable(llvm::dwarf::DW_TAG_arg_variable,
- llvm::DIDescriptor(scope),
+ llvm::DIDescriptor(scope),
Arg->getName(), tunit, line, type,
CGM.getLangOpts().Optimize, flags,
cast<llvm::Argument>(Arg)->getArgNo() + 1);
@@ -2831,25 +3067,32 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
DbgDecl->setDebugLoc(llvm::DebugLoc::get(line, column, scope));
}
-/// getStaticDataMemberDeclaration - If D is an out-of-class definition of
-/// a static data member of a class, find its corresponding in-class
-/// declaration.
-llvm::DIDerivedType CGDebugInfo::getStaticDataMemberDeclaration(const Decl *D) {
- if (cast<VarDecl>(D)->isStaticDataMember()) {
- llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator
- MI = StaticDataMemberCache.find(D->getCanonicalDecl());
- if (MI != StaticDataMemberCache.end())
- // Verify the info still exists.
- if (llvm::Value *V = MI->second)
- return llvm::DIDerivedType(cast<llvm::MDNode>(V));
- }
- return llvm::DIDerivedType();
+/// If D is an out-of-class definition of a static data member of a class, find
+/// its corresponding in-class declaration.
+llvm::DIDerivedType
+CGDebugInfo::getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D) {
+ if (!D->isStaticDataMember())
+ return llvm::DIDerivedType();
+ llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator MI =
+ StaticDataMemberCache.find(D->getCanonicalDecl());
+ if (MI != StaticDataMemberCache.end()) {
+ assert(MI->second && "Static data member declaration should still exist");
+ return llvm::DIDerivedType(cast<llvm::MDNode>(MI->second));
+ }
+
+ // If the member wasn't found in the cache, lazily construct and add it to the
+ // type (used when a limited form of the type is emitted).
+ llvm::DICompositeType Ctxt(
+ getContextDescriptor(cast<Decl>(D->getDeclContext())));
+ llvm::DIDerivedType T = CreateRecordStaticField(D, Ctxt);
+ Ctxt.addMember(T);
+ return T;
}
/// EmitGlobalVariable - Emit information about a global variable.
void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
const VarDecl *D) {
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
+ assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
// Create global variable debug descriptor.
llvm::DIFile Unit = getOrCreateFile(D->getLocation());
unsigned LineNo = getLineNumber(D->getLocation());
@@ -2873,18 +3116,19 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
LinkageName = Var->getName();
if (LinkageName == DeclName)
LinkageName = StringRef();
- llvm::DIDescriptor DContext =
+ llvm::DIDescriptor DContext =
getContextDescriptor(dyn_cast<Decl>(D->getDeclContext()));
- DBuilder.createStaticVariable(DContext, DeclName, LinkageName,
- Unit, LineNo, getOrCreateType(T, Unit),
- Var->hasInternalLinkage(), Var,
- getStaticDataMemberDeclaration(D));
+ llvm::DIGlobalVariable GV = DBuilder.createStaticVariable(
+ DContext, DeclName, LinkageName, Unit, LineNo, getOrCreateType(T, Unit),
+ Var->hasInternalLinkage(), Var,
+ getOrCreateStaticDataMemberDeclarationOrNull(D));
+ DeclCache.insert(std::make_pair(D->getCanonicalDecl(), llvm::WeakVH(GV)));
}
/// EmitGlobalVariable - Emit information about an objective-c interface.
void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
ObjCInterfaceDecl *ID) {
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
+ assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
// Create global variable debug descriptor.
llvm::DIFile Unit = getOrCreateFile(ID->getLocation());
unsigned LineNo = getLineNumber(ID->getLocation());
@@ -2908,9 +3152,9 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
}
/// EmitGlobalVariable - Emit global variable's debug info.
-void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD,
+void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD,
llvm::Constant *Init) {
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
+ assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
// Create the descriptor for the variable.
llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
StringRef Name = VD->getName();
@@ -2923,34 +3167,79 @@ 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,
- getLineNumber(VD->getLocation()),
- Ty, true, Init,
- getStaticDataMemberDeclaration(VD));
+ llvm::DIGlobalVariable GV = DBuilder.createStaticVariable(
+ Unit, Name, Name, Unit, getLineNumber(VD->getLocation()), Ty, true, Init,
+ getOrCreateStaticDataMemberDeclarationOrNull(cast<VarDecl>(VD)));
+ DeclCache.insert(std::make_pair(VD->getCanonicalDecl(), llvm::WeakVH(GV)));
+}
+
+llvm::DIScope CGDebugInfo::getCurrentContextDescriptor(const Decl *D) {
+ if (!LexicalBlockStack.empty())
+ return llvm::DIScope(LexicalBlockStack.back());
+ return getContextDescriptor(D);
}
void CGDebugInfo::EmitUsingDirective(const UsingDirectiveDecl &UD) {
- llvm::DIScope Scope =
- LexicalBlockStack.empty()
- ? getContextDescriptor(cast<Decl>(UD.getDeclContext()))
- : llvm::DIScope(LexicalBlockStack.back());
+ if (CGM.getCodeGenOpts().getDebugInfo() < CodeGenOptions::LimitedDebugInfo)
+ return;
DBuilder.createImportedModule(
- Scope, getOrCreateNameSpace(UD.getNominatedNamespace()),
+ getCurrentContextDescriptor(cast<Decl>(UD.getDeclContext())),
+ getOrCreateNameSpace(UD.getNominatedNamespace()),
getLineNumber(UD.getLocation()));
}
+void CGDebugInfo::EmitUsingDecl(const UsingDecl &UD) {
+ if (CGM.getCodeGenOpts().getDebugInfo() < CodeGenOptions::LimitedDebugInfo)
+ return;
+ assert(UD.shadow_size() &&
+ "We shouldn't be codegening an invalid UsingDecl containing no decls");
+ // Emitting one decl is sufficient - debuggers can detect that this is an
+ // overloaded name & provide lookup for all the overloads.
+ const UsingShadowDecl &USD = **UD.shadow_begin();
+ if (llvm::DIDescriptor Target =
+ getDeclarationOrDefinition(USD.getUnderlyingDecl()))
+ DBuilder.createImportedDeclaration(
+ getCurrentContextDescriptor(cast<Decl>(USD.getDeclContext())), Target,
+ getLineNumber(USD.getLocation()));
+}
+
+llvm::DIImportedEntity
+CGDebugInfo::EmitNamespaceAlias(const NamespaceAliasDecl &NA) {
+ if (CGM.getCodeGenOpts().getDebugInfo() < CodeGenOptions::LimitedDebugInfo)
+ return llvm::DIImportedEntity(0);
+ llvm::WeakVH &VH = NamespaceAliasCache[&NA];
+ if (VH)
+ return llvm::DIImportedEntity(cast<llvm::MDNode>(VH));
+ llvm::DIImportedEntity R(0);
+ if (const NamespaceAliasDecl *Underlying =
+ dyn_cast<NamespaceAliasDecl>(NA.getAliasedNamespace()))
+ // This could cache & dedup here rather than relying on metadata deduping.
+ R = DBuilder.createImportedModule(
+ getCurrentContextDescriptor(cast<Decl>(NA.getDeclContext())),
+ EmitNamespaceAlias(*Underlying), getLineNumber(NA.getLocation()),
+ NA.getName());
+ else
+ R = DBuilder.createImportedModule(
+ getCurrentContextDescriptor(cast<Decl>(NA.getDeclContext())),
+ getOrCreateNameSpace(cast<NamespaceDecl>(NA.getAliasedNamespace())),
+ getLineNumber(NA.getLocation()), NA.getName());
+ VH = R;
+ return R;
+}
+
/// getOrCreateNamesSpace - Return namespace descriptor for the given
/// namespace decl.
-llvm::DINameSpace
+llvm::DINameSpace
CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl) {
- llvm::DenseMap<const NamespaceDecl *, llvm::WeakVH>::iterator I =
+ NSDecl = NSDecl->getCanonicalDecl();
+ llvm::DenseMap<const NamespaceDecl *, llvm::WeakVH>::iterator I =
NameSpaceCache.find(NSDecl);
if (I != NameSpaceCache.end())
return llvm::DINameSpace(cast<llvm::MDNode>(I->second));
-
+
unsigned LineNo = getLineNumber(NSDecl->getLocation());
llvm::DIFile FileD = getOrCreateFile(NSDecl->getLocation());
- llvm::DIDescriptor Context =
+ llvm::DIDescriptor Context =
getContextDescriptor(dyn_cast<Decl>(NSDecl->getDeclContext()));
llvm::DINameSpace NS =
DBuilder.createNameSpace(Context, NSDecl->getName(), FileD, LineNo);
@@ -2965,7 +3254,7 @@ void CGDebugInfo::finalize() {
// Verify that the debug info still exists.
if (llvm::Value *V = VI->second)
Ty = llvm::DIType(cast<llvm::MDNode>(V));
-
+
llvm::DenseMap<void *, llvm::WeakVH>::iterator it =
TypeCache.find(VI->first);
if (it != TypeCache.end()) {
@@ -2974,7 +3263,7 @@ void CGDebugInfo::finalize() {
RepTy = llvm::DIType(cast<llvm::MDNode>(V));
}
- if (Ty.Verify() && Ty.isForwardDecl() && RepTy.Verify())
+ if (Ty && Ty.isForwardDecl() && RepTy)
Ty.replaceAllUsesWith(RepTy);
}
diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h
index 4080492..0ca274f 100644
--- a/lib/CodeGen/CGDebugInfo.h
+++ b/lib/CodeGen/CGDebugInfo.h
@@ -18,6 +18,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
#include "clang/Basic/SourceLocation.h"
+#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/DIBuilder.h"
#include "llvm/DebugInfo.h"
@@ -35,6 +36,7 @@ namespace clang {
class ObjCIvarDecl;
class ClassTemplateSpecializationDecl;
class GlobalDecl;
+ class UsingDecl;
namespace CodeGen {
class CodeGenModule;
@@ -45,7 +47,10 @@ namespace CodeGen {
/// and is responsible for emitting to llvm globals or pass directly to
/// the backend.
class CGDebugInfo {
+ friend class NoLocation;
+ friend class ArtificialLocation;
CodeGenModule &CGM;
+ const CodeGenOptions::DebugInfoKind DebugKind;
llvm::DIBuilder DBuilder;
llvm::DICompileUnit TheCU;
SourceLocation CurLoc, PrevLoc;
@@ -57,14 +62,14 @@ class CGDebugInfo {
llvm::DIType OCLImage2dDITy, OCLImage2dArrayDITy;
llvm::DIType OCLImage3dDITy;
llvm::DIType OCLEventDITy;
-
+ llvm::DIType BlockLiteralGeneric;
+
/// TypeCache - Cache of previously constructed Types.
llvm::DenseMap<void *, llvm::WeakVH> TypeCache;
/// ObjCInterfaceCache - Cache of previously constructed interfaces
/// which may change. Storing a pair of DIType and checksum.
- llvm::DenseMap<void *, std::pair<llvm::WeakVH, unsigned > >
- ObjCInterfaceCache;
+ llvm::DenseMap<void *, std::pair<llvm::WeakVH, unsigned> > ObjCInterfaceCache;
/// RetainedTypes - list of interfaces we want to keep even if orphaned.
std::vector<void *> RetainedTypes;
@@ -76,9 +81,6 @@ class CGDebugInfo {
/// compilation.
std::vector<std::pair<void *, llvm::WeakVH> >ReplaceMap;
- bool BlockLiteralGenericSet;
- llvm::DIType BlockLiteralGeneric;
-
// LexicalBlockStack - Keep track of our current nested lexical block.
std::vector<llvm::TrackingVH<llvm::MDNode> > LexicalBlockStack;
llvm::DenseMap<const Decl *, llvm::WeakVH> RegionMap;
@@ -94,22 +96,28 @@ class CGDebugInfo {
llvm::DenseMap<const char *, llvm::WeakVH> DIFileCache;
llvm::DenseMap<const FunctionDecl *, llvm::WeakVH> SPCache;
+ /// \brief Cache declarations relevant to DW_TAG_imported_declarations (C++
+ /// using declarations) that aren't covered by other more specific caches.
+ llvm::DenseMap<const Decl *, llvm::WeakVH> DeclCache;
llvm::DenseMap<const NamespaceDecl *, llvm::WeakVH> NameSpaceCache;
+ llvm::DenseMap<const NamespaceAliasDecl *, llvm::WeakVH> NamespaceAliasCache;
llvm::DenseMap<const Decl *, llvm::WeakVH> StaticDataMemberCache;
/// Helper functions for getOrCreateType.
unsigned Checksum(const ObjCInterfaceDecl *InterfaceDecl);
llvm::DIType CreateType(const BuiltinType *Ty);
llvm::DIType CreateType(const ComplexType *Ty);
- llvm::DIType CreateQualifiedType(QualType Ty, llvm::DIFile F);
- llvm::DIType CreateType(const TypedefType *Ty, llvm::DIFile F);
+ llvm::DIType CreateQualifiedType(QualType Ty, llvm::DIFile Fg);
+ llvm::DIType CreateType(const TypedefType *Ty, llvm::DIFile Fg);
llvm::DIType CreateType(const ObjCObjectPointerType *Ty,
llvm::DIFile F);
llvm::DIType CreateType(const PointerType *Ty, llvm::DIFile F);
llvm::DIType CreateType(const BlockPointerType *Ty, llvm::DIFile F);
llvm::DIType CreateType(const FunctionType *Ty, llvm::DIFile F);
- llvm::DIType CreateType(const RecordType *Ty);
- llvm::DIType CreateLimitedType(const RecordType *Ty);
+ llvm::DIType CreateType(const RecordType *Tyg);
+ llvm::DIType CreateTypeDefinition(const RecordType *Ty);
+ llvm::DICompositeType CreateLimitedType(const RecordType *Ty);
+ void CollectContainingType(const CXXRecordDecl *RD, llvm::DICompositeType CT);
llvm::DIType CreateType(const ObjCInterfaceType *Ty, llvm::DIFile F);
llvm::DIType CreateType(const ObjCObjectType *Ty, llvm::DIFile F);
llvm::DIType CreateType(const VectorType *Ty, llvm::DIFile F);
@@ -118,19 +126,19 @@ class CGDebugInfo {
llvm::DIType CreateType(const RValueReferenceType *Ty, llvm::DIFile Unit);
llvm::DIType CreateType(const MemberPointerType *Ty, llvm::DIFile F);
llvm::DIType CreateType(const AtomicType *Ty, llvm::DIFile F);
- llvm::DIType CreateEnumType(const EnumDecl *ED);
+ llvm::DIType CreateEnumType(const EnumType *Ty);
llvm::DIType CreateSelfType(const QualType &QualTy, llvm::DIType Ty);
llvm::DIType getTypeOrNull(const QualType);
llvm::DIType getCompletedTypeOrNull(const QualType);
- llvm::DIType getOrCreateMethodType(const CXXMethodDecl *Method,
- llvm::DIFile F);
- llvm::DIType getOrCreateInstanceMethodType(
+ llvm::DICompositeType getOrCreateMethodType(const CXXMethodDecl *Method,
+ llvm::DIFile F);
+ llvm::DICompositeType getOrCreateInstanceMethodType(
QualType ThisPtr, const FunctionProtoType *Func, llvm::DIFile Unit);
- llvm::DIType getOrCreateFunctionType(const Decl *D, QualType FnType,
- llvm::DIFile F);
+ llvm::DICompositeType getOrCreateFunctionType(const Decl *D, QualType FnType,
+ llvm::DIFile F);
llvm::DIType getOrCreateVTablePtrType(llvm::DIFile F);
llvm::DINameSpace getOrCreateNameSpace(const NamespaceDecl *N);
- llvm::DIType CreatePointeeType(QualType PointeeTy, llvm::DIFile F);
+ llvm::DIType getOrCreateTypeDeclaration(QualType PointeeTy, llvm::DIFile F);
llvm::DIType CreatePointerLikeType(unsigned Tag,
const Type *Ty, QualType PointeeTy,
llvm::DIFile F);
@@ -141,29 +149,24 @@ class CGDebugInfo {
llvm::DISubprogram CreateCXXMemberFunction(const CXXMethodDecl *Method,
llvm::DIFile F,
llvm::DIType RecordTy);
-
+
void CollectCXXMemberFunctions(const CXXRecordDecl *Decl,
llvm::DIFile F,
SmallVectorImpl<llvm::Value *> &E,
llvm::DIType T);
- void CollectCXXFriends(const CXXRecordDecl *Decl,
- llvm::DIFile F,
- SmallVectorImpl<llvm::Value *> &EltTys,
- llvm::DIType RecordTy);
-
void CollectCXXBases(const CXXRecordDecl *Decl,
llvm::DIFile F,
SmallVectorImpl<llvm::Value *> &EltTys,
llvm::DIType RecordTy);
-
+
llvm::DIArray
CollectTemplateParams(const TemplateParameterList *TPList,
- const TemplateArgumentList &TAList,
+ ArrayRef<TemplateArgument> TAList,
llvm::DIFile Unit);
llvm::DIArray
CollectFunctionTemplateParams(const FunctionDecl *FD, llvm::DIFile Unit);
- llvm::DIArray
+ llvm::DIArray
CollectCXXTemplateParams(const ClassTemplateSpecializationDecl *TS,
llvm::DIFile F);
@@ -171,22 +174,21 @@ class CGDebugInfo {
uint64_t sizeInBitsOverride, SourceLocation loc,
AccessSpecifier AS, uint64_t offsetInBits,
llvm::DIFile tunit,
- llvm::DIDescriptor scope);
+ llvm::DIScope scope);
// Helpers for collecting fields of a record.
void CollectRecordLambdaFields(const CXXRecordDecl *CXXDecl,
SmallVectorImpl<llvm::Value *> &E,
llvm::DIType RecordTy);
- void CollectRecordStaticField(const VarDecl *Var,
- SmallVectorImpl<llvm::Value *> &E,
- llvm::DIType RecordTy);
+ llvm::DIDerivedType CreateRecordStaticField(const VarDecl *Var,
+ llvm::DIType RecordTy);
void CollectRecordNormalField(const FieldDecl *Field, uint64_t OffsetInBits,
llvm::DIFile F,
SmallVectorImpl<llvm::Value *> &E,
llvm::DIType RecordTy);
void CollectRecordFields(const RecordDecl *Decl, llvm::DIFile F,
SmallVectorImpl<llvm::Value *> &E,
- llvm::DIType RecordTy);
+ llvm::DICompositeType RecordTy);
void CollectVTableInfo(const CXXRecordDecl *Decl,
llvm::DIFile F,
@@ -195,7 +197,7 @@ class CGDebugInfo {
// CreateLexicalBlock - Create a new lexical block node and push it on
// the stack.
void CreateLexicalBlock(SourceLocation Loc);
-
+
public:
CGDebugInfo(CodeGenModule &CGM);
~CGDebugInfo();
@@ -206,6 +208,9 @@ public:
/// invalid it is ignored.
void setLocation(SourceLocation Loc);
+ /// getLocation - Return the current source location.
+ SourceLocation getLocation() const { return CurLoc; }
+
/// EmitLocation - Emit metadata to indicate a change in line/column
/// information in the source file.
/// \param ForceColumnInfo Assume DebugColumnInfo option is true.
@@ -265,20 +270,30 @@ public:
/// \brief - Emit C++ using directive.
void EmitUsingDirective(const UsingDirectiveDecl &UD);
- /// getOrCreateRecordType - Emit record type's standalone debug info.
+ /// \brief - Emit C++ using declaration.
+ void EmitUsingDecl(const UsingDecl &UD);
+
+ /// \brief - Emit C++ namespace alias.
+ llvm::DIImportedEntity EmitNamespaceAlias(const NamespaceAliasDecl &NA);
+
+ /// getOrCreateRecordType - Emit record type's standalone debug info.
llvm::DIType getOrCreateRecordType(QualType Ty, SourceLocation L);
/// getOrCreateInterfaceType - Emit an objective c interface type standalone
/// debug info.
llvm::DIType getOrCreateInterfaceType(QualType Ty,
- SourceLocation Loc);
+ SourceLocation Loc);
+
+ void completeType(const RecordDecl *RD);
+ void completeRequiredType(const RecordDecl *RD);
+ void completeClassData(const RecordDecl *RD);
private:
/// EmitDeclare - Emit call to llvm.dbg.declare for a variable declaration.
void EmitDeclare(const VarDecl *decl, unsigned Tag, llvm::Value *AI,
unsigned ArgNo, CGBuilderTy &Builder);
- // EmitTypeForVarWithBlocksAttr - Build up structure info for the byref.
+ // EmitTypeForVarWithBlocksAttr - Build up structure info for the byref.
// See BuildByRefType.
llvm::DIType EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
uint64_t *OffSet);
@@ -286,10 +301,12 @@ private:
/// getContextDescriptor - Get context info for the decl.
llvm::DIScope getContextDescriptor(const Decl *Decl);
- /// createRecordFwdDecl - Create a forward decl for a RecordType in a given
- /// context.
- llvm::DIType createRecordFwdDecl(const RecordDecl *, llvm::DIDescriptor);
-
+ llvm::DIScope getCurrentContextDescriptor(const Decl *Decl);
+
+ /// \brief Create a forward decl for a RecordType in a given context.
+ llvm::DICompositeType getOrCreateRecordFwdDecl(const RecordType *,
+ llvm::DIDescriptor);
+
/// createContextChain - Create a set of decls for the context chain.
llvm::DIDescriptor createContextChain(const Decl *Decl);
@@ -299,7 +316,7 @@ private:
/// CreateCompileUnit - Create new compile unit.
void CreateCompileUnit();
- /// getOrCreateFile - Get the file debug info descriptor for the input
+ /// getOrCreateFile - Get the file debug info descriptor for the input
/// location.
llvm::DIFile getOrCreateFile(SourceLocation Loc);
@@ -308,43 +325,43 @@ private:
/// getOrCreateType - Get the type from the cache or create a new type if
/// necessary.
- llvm::DIType getOrCreateType(QualType Ty, llvm::DIFile F);
+ llvm::DIType getOrCreateType(QualType Ty, llvm::DIFile Fg);
/// getOrCreateLimitedType - Get the type from the cache or create a new
/// partial type if necessary.
- llvm::DIType getOrCreateLimitedType(QualType Ty, llvm::DIFile F);
+ llvm::DIType getOrCreateLimitedType(const RecordType *Ty, llvm::DIFile F);
/// CreateTypeNode - Create type metadata for a source language type.
- llvm::DIType CreateTypeNode(QualType Ty, llvm::DIFile F);
+ llvm::DIType CreateTypeNode(QualType Ty, llvm::DIFile Fg);
/// getObjCInterfaceDecl - return the underlying ObjCInterfaceDecl
/// if Ty is an ObjCInterface or a pointer to one.
ObjCInterfaceDecl* getObjCInterfaceDecl(QualType Ty);
- /// CreateLimitedTypeNode - Create type metadata for a source language
- /// type, but only partial types for records.
- llvm::DIType CreateLimitedTypeNode(QualType Ty, llvm::DIFile F);
-
/// CreateMemberType - Create new member and increase Offset by FType's size.
llvm::DIType CreateMemberType(llvm::DIFile Unit, QualType FType,
StringRef Name, uint64_t *Offset);
+ /// \brief Retrieve the DIDescriptor, if any, for the canonical form of this
+ /// declaration.
+ llvm::DIDescriptor getDeclarationOrDefinition(const Decl *D);
+
/// getFunctionDeclaration - Return debug info descriptor to describe method
/// declaration for the given method definition.
llvm::DISubprogram getFunctionDeclaration(const Decl *D);
- /// getStaticDataMemberDeclaration - Return debug info descriptor to
- /// describe in-class static data member declaration for the given
- /// out-of-class definition.
- llvm::DIDerivedType getStaticDataMemberDeclaration(const Decl *D);
+ /// Return debug info descriptor to describe in-class static data member
+ /// declaration for the given out-of-class definition.
+ llvm::DIDerivedType
+ getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D);
/// getFunctionName - Get function name for the given FunctionDecl. If the
- /// name is constructred on demand (e.g. C++ destructor) then the name
+ /// name is constructed on demand (e.g. C++ destructor) then the name
/// is stored on the side.
StringRef getFunctionName(const FunctionDecl *FD);
/// getObjCMethodName - Returns the unmangled name of an Objective-C method.
- /// This is the display name for the debugging info.
+ /// This is the display name for the debugging info.
StringRef getObjCMethodName(const ObjCMethodDecl *FD);
/// getSelectorName - Return selector name. This is used for debugging
@@ -361,11 +378,62 @@ private:
/// then use current location.
unsigned getLineNumber(SourceLocation Loc);
- /// getColumnNumber - Get column number for the location. If location is
+ /// getColumnNumber - Get column number for the location. If location is
/// invalid then use current location.
/// \param Force Assume DebugColumnInfo option is true.
unsigned getColumnNumber(SourceLocation Loc, bool Force=false);
+
+ /// internString - Allocate a copy of \p A using the DebugInfoNames allocator
+ /// and return a reference to it. If multiple arguments are given the strings
+ /// are concatenated.
+ StringRef internString(StringRef A, StringRef B = StringRef()) {
+ char *Data = DebugInfoNames.Allocate<char>(A.size() + B.size());
+ std::memcpy(Data, A.data(), A.size());
+ std::memcpy(Data + A.size(), B.data(), B.size());
+ return StringRef(Data, A.size() + B.size());
+ }
};
+
+/// NoLocation - An RAII object that temporarily disables debug
+/// locations. This is useful for emitting instructions that should be
+/// counted towards the function prologue.
+class NoLocation {
+ SourceLocation SavedLoc;
+ CGDebugInfo *DI;
+ CGBuilderTy &Builder;
+public:
+ NoLocation(CodeGenFunction &CGF, CGBuilderTy &B);
+ /// ~NoLocation - Autorestore everything back to normal.
+ ~NoLocation();
+};
+
+/// ArtificialLocation - An RAII object that temporarily switches to
+/// an artificial debug location that has a valid scope, but no line
+/// information. This is useful when emitting compiler-generated
+/// helper functions that have no source location associated with
+/// them. The DWARF specification allows the compiler to use the
+/// special line number 0 to indicate code that can not be attributed
+/// to any source location.
+///
+/// This is necessary because passing an empty SourceLocation to
+/// CGDebugInfo::setLocation() will result in the last valid location
+/// being reused.
+class ArtificialLocation {
+ SourceLocation SavedLoc;
+ CGDebugInfo *DI;
+ CGBuilderTy &Builder;
+public:
+ ArtificialLocation(CodeGenFunction &CGF, CGBuilderTy &B);
+
+ /// Set the current location to line 0, but within the current scope
+ /// (= the top of the LexicalBlockStack).
+ void Emit();
+
+ /// ~ArtificialLocation - Autorestore everything back to normal.
+ ~ArtificialLocation();
+};
+
+
} // namespace CodeGen
} // namespace clang
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 3ce6dec..66d6b33 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -21,6 +21,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/CodeGen/CGFunctionInfo.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/GlobalVariable.h"
@@ -37,6 +38,8 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
case Decl::UnresolvedUsingTypename:
case Decl::ClassTemplateSpecialization:
case Decl::ClassTemplatePartialSpecialization:
+ case Decl::VarTemplateSpecialization:
+ case Decl::VarTemplatePartialSpecialization:
case Decl::TemplateTypeParm:
case Decl::UnresolvedUsingValue:
case Decl::NonTypeTemplateParm:
@@ -52,6 +55,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
case Decl::ParmVar:
case Decl::ImplicitParam:
case Decl::ClassTemplate:
+ case Decl::VarTemplate:
case Decl::FunctionTemplate:
case Decl::TypeAliasTemplate:
case Decl::TemplateTemplateParm:
@@ -72,15 +76,13 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
case Decl::Block:
case Decl::Captured:
case Decl::ClassScopeFunctionSpecialization:
+ case Decl::UsingShadow:
llvm_unreachable("Declaration should not be in declstmts!");
case Decl::Function: // void X();
case Decl::Record: // struct/union/class X;
case Decl::Enum: // enum X;
case Decl::EnumConstant: // enum ? { X = ? }
case Decl::CXXRecord: // struct/union/class X; [C++]
- case Decl::Using: // using X; [C++]
- case Decl::UsingShadow:
- case Decl::NamespaceAlias:
case Decl::StaticAssert: // static_assert(X, ""); [C++0x]
case Decl::Label: // __label__ x;
case Decl::Import:
@@ -89,6 +91,14 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
// None of these decls require codegen support.
return;
+ case Decl::NamespaceAlias:
+ if (CGDebugInfo *DI = getDebugInfo())
+ DI->EmitNamespaceAlias(cast<NamespaceAliasDecl>(D));
+ return;
+ case Decl::Using: // using X; [C++]
+ if (CGDebugInfo *DI = getDebugInfo())
+ DI->EmitUsingDecl(cast<UsingDecl>(D));
+ return;
case Decl::UsingDirective: // using namespace X; [C++]
if (CGDebugInfo *DI = getDebugInfo())
DI->EmitUsingDirective(cast<UsingDirectiveDecl>(D));
@@ -114,35 +124,32 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
/// EmitVarDecl - This method handles emission of any variable declaration
/// inside a function, including static vars etc.
void CodeGenFunction::EmitVarDecl(const VarDecl &D) {
- switch (D.getStorageClass()) {
- case SC_None:
- case SC_Auto:
- case SC_Register:
- return EmitAutoVarDecl(D);
- case SC_Static: {
+ if (D.isStaticLocal()) {
llvm::GlobalValue::LinkageTypes Linkage =
llvm::GlobalValue::InternalLinkage;
- // If the function definition has some sort of weak linkage, its
- // static variables should also be weak so that they get properly
- // uniqued. We can't do this in C, though, because there's no
- // standard way to agree on which variables are the same (i.e.
- // there's no mangling).
- if (getLangOpts().CPlusPlus)
- if (llvm::GlobalValue::isWeakForLinker(CurFn->getLinkage()))
- Linkage = CurFn->getLinkage();
+ // If the variable is externally visible, it must have weak linkage so it
+ // can be uniqued.
+ if (D.isExternallyVisible()) {
+ Linkage = llvm::GlobalValue::LinkOnceODRLinkage;
+
+ // FIXME: We need to force the emission/use of a guard variable for
+ // some variables even if we can constant-evaluate them because
+ // we can't guarantee every translation unit will constant-evaluate them.
+ }
return EmitStaticVarDecl(D, Linkage);
}
- case SC_Extern:
- case SC_PrivateExtern:
+
+ if (D.hasExternalStorage())
// Don't emit it now, allow it to be emitted lazily on its first use.
return;
- case SC_OpenCLWorkGroupLocal:
+
+ if (D.getStorageClass() == SC_OpenCLWorkGroupLocal)
return CGM.getOpenCLRuntime().EmitWorkGroupLocalVarDecl(*this, D);
- }
- llvm_unreachable("Unknown storage class");
+ assert(D.hasLocalStorage());
+ return EmitAutoVarDecl(D);
}
static std::string GetStaticDeclName(CodeGenFunction &CGF, const VarDecl &D,
@@ -200,8 +207,7 @@ CodeGenFunction::CreateStaticVarDecl(const VarDecl &D,
llvm::GlobalVariable::NotThreadLocal,
AddrSpace);
GV->setAlignment(getContext().getDeclAlign(&D).getQuantity());
- if (Linkage != llvm::GlobalValue::InternalLinkage)
- GV->setVisibility(CurFn->getVisibility());
+ CGM.setGlobalVisibility(GV, &D);
if (D.getTLSKind())
CGM.setTLSMode(GV, D);
@@ -420,7 +426,8 @@ namespace {
// byref or something.
DeclRefExpr DRE(const_cast<VarDecl*>(&Var), false,
Var.getType(), VK_LValue, SourceLocation());
- llvm::Value *value = CGF.EmitLoadOfScalar(CGF.EmitDeclRefLValue(&DRE));
+ llvm::Value *value = CGF.EmitLoadOfScalar(CGF.EmitDeclRefLValue(&DRE),
+ SourceLocation());
CGF.EmitExtendGCLifetime(value);
}
};
@@ -647,7 +654,7 @@ void CodeGenFunction::EmitScalarInit(const Expr *init,
// might have to initialize with a barrier. We have to do this for
// both __weak and __strong, but __weak got filtered out above.
if (accessedByInit && lifetime == Qualifiers::OCL_Strong) {
- llvm::Value *oldValue = EmitLoadOfScalar(lvalue);
+ llvm::Value *oldValue = EmitLoadOfScalar(lvalue, init->getExprLoc());
EmitStoreOfScalar(value, lvalue, /* isInitialization */ true);
EmitARCRelease(oldValue, ARCImpreciseLifetime);
return;
@@ -838,19 +845,19 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
bool NRVO = getLangOpts().ElideConstructors &&
D.isNRVOVariable();
- // If this value is a POD array or struct with a statically
- // determinable constant initializer, there are optimizations we can do.
+ // If this value is an array or struct with a statically determinable
+ // constant initializer, there are optimizations we can do.
//
// TODO: We should constant-evaluate the initializer of any variable,
// as long as it is initialized by a constant expression. Currently,
// isConstantInitializer produces wrong answers for structs with
// reference or bitfield members, and a few other cases, and checking
// for POD-ness protects us from some of these.
- if (D.getInit() &&
- (Ty->isArrayType() || Ty->isRecordType()) &&
- (Ty.isPODType(getContext()) ||
- getContext().getBaseElementType(Ty)->isObjCObjectPointerType()) &&
- D.getInit()->isConstantInitializer(getContext(), false)) {
+ if (D.getInit() && (Ty->isArrayType() || Ty->isRecordType()) &&
+ (D.isConstexpr() ||
+ ((Ty.isPODType(getContext()) ||
+ getContext().getBaseElementType(Ty)->isObjCObjectPointerType()) &&
+ D.getInit()->isConstantInitializer(getContext(), false)))) {
// If the variable's a const type, and it's neither an NRVO
// candidate nor a __block variable and has no mutable members,
@@ -1078,7 +1085,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
capturedByInit ? emission.Address : emission.getObjectAddress(*this);
llvm::Constant *constant = 0;
- if (emission.IsConstantAggregate) {
+ if (emission.IsConstantAggregate || D.isConstexpr()) {
assert(!capturedByInit && "constant init contains a capturing block?");
constant = CGM.EmitConstantInit(D, this);
}
@@ -1089,6 +1096,13 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
return EmitExprAsInit(Init, &D, lv, capturedByInit);
}
+ if (!emission.IsConstantAggregate) {
+ // For simple scalar/complex initialization, store the value directly.
+ LValue lv = MakeAddrLValue(Loc, type, alignment);
+ lv.setNonGC(true);
+ return EmitStoreThroughLValue(RValue::get(constant), lv, true);
+ }
+
// If this is a simple aggregate initialization, we can optimize it
// in various ways.
bool isVolatile = type.isVolatileQualified();
@@ -1151,7 +1165,7 @@ void CodeGenFunction::EmitExprAsInit(const Expr *init,
QualType type = D->getType();
if (type->isReferenceType()) {
- RValue rvalue = EmitReferenceBindingToExpr(init, D);
+ RValue rvalue = EmitReferenceBindingToExpr(init);
if (capturedByInit)
drillIntoBlockVariable(*this, lvalue, cast<VarDecl>(D));
EmitStoreThroughLValue(rvalue, lvalue, true);
@@ -1178,7 +1192,6 @@ void CodeGenFunction::EmitExprAsInit(const Expr *init,
AggValueSlot::DoesNotNeedGCBarriers,
AggValueSlot::IsNotAliased));
}
- MaybeEmitStdInitializerListCleanup(lvalue.getAddress(), init);
return;
}
llvm_unreachable("bad evaluation kind");
@@ -1331,6 +1344,26 @@ void CodeGenFunction::pushDestroy(CleanupKind cleanupKind, llvm::Value *addr,
destroyer, useEHCleanupForArray);
}
+void CodeGenFunction::pushLifetimeExtendedDestroy(
+ CleanupKind cleanupKind, llvm::Value *addr, QualType type,
+ Destroyer *destroyer, bool useEHCleanupForArray) {
+ assert(!isInConditionalBranch() &&
+ "performing lifetime extension from within conditional");
+
+ // Push an EH-only cleanup for the object now.
+ // FIXME: When popping normal cleanups, we need to keep this EH cleanup
+ // around in case a temporary's destructor throws an exception.
+ if (cleanupKind & EHCleanup)
+ EHStack.pushCleanup<DestroyObject>(
+ static_cast<CleanupKind>(cleanupKind & ~NormalCleanup), addr, type,
+ destroyer, useEHCleanupForArray);
+
+ // Remember that we need to push a full cleanup for the object at the
+ // end of the full-expression.
+ pushCleanupAfterFullExpr<DestroyObject>(
+ cleanupKind, addr, type, destroyer, useEHCleanupForArray);
+}
+
/// emitDestroy - Immediately perform the destruction of the given
/// object.
///
@@ -1608,10 +1641,18 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg,
}
llvm::Value *DeclPtr;
+ bool HasNonScalarEvalKind = !CodeGenFunction::hasScalarEvaluationKind(Ty);
// If this is an aggregate or variable sized value, reuse the input pointer.
- if (!Ty->isConstantSizeType() ||
- !CodeGenFunction::hasScalarEvaluationKind(Ty)) {
+ if (HasNonScalarEvalKind || !Ty->isConstantSizeType()) {
DeclPtr = Arg;
+ // Push a destructor cleanup for this parameter if the ABI requires it.
+ if (HasNonScalarEvalKind &&
+ getTarget().getCXXABI().isArgumentDestroyedByCallee()) {
+ if (const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl()) {
+ if (RD->hasNonTrivialDestructor())
+ pushDestroy(QualType::DK_cxx_destructor, DeclPtr, Ty);
+ }
+ }
} else {
// Otherwise, create a temporary to hold the value.
llvm::AllocaInst *Alloc = CreateTempAlloca(ConvertTypeForMem(Ty),
@@ -1649,7 +1690,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg,
// use objc_storeStrong(&dest, value) for retaining the
// object. But first, store a null into 'dest' because
// objc_storeStrong attempts to release its old value.
- llvm::Value * Null = CGM.EmitNullConstant(D.getType());
+ llvm::Value *Null = CGM.EmitNullConstant(D.getType());
EmitStoreOfScalar(Null, lv, /* isInitialization */ true);
EmitARCStoreStrongCall(lv.getAddress(), Arg, true);
doStore = false;
diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp
index 9ffcff2..7bdb9eb 100644
--- a/lib/CodeGen/CGDeclCXX.cpp
+++ b/lib/CodeGen/CGDeclCXX.cpp
@@ -96,13 +96,14 @@ static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
CXXDestructorDecl *dtor = record->getDestructor();
function = CGM.GetAddrOfCXXDestructor(dtor, Dtor_Complete);
- argument = addr;
+ argument = llvm::ConstantExpr::getBitCast(
+ addr, CGF.getTypes().ConvertType(type)->getPointerTo());
// Otherwise, the standard logic requires a helper function.
} else {
- function = CodeGenFunction(CGM).generateDestroyHelper(addr, type,
- CGF.getDestroyer(dtorKind),
- CGF.needsEHCleanup(dtorKind));
+ function = CodeGenFunction(CGM)
+ .generateDestroyHelper(addr, type, CGF.getDestroyer(dtorKind),
+ CGF.needsEHCleanup(dtorKind), &D);
argument = llvm::Constant::getNullValue(CGF.Int8PtrTy);
}
@@ -149,7 +150,7 @@ void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
assert(PerformInit && "cannot have constant initializer which needs "
"destruction for reference");
unsigned Alignment = getContext().getDeclAlign(&D).getQuantity();
- RValue RV = EmitReferenceBindingToExpr(Init, &D);
+ RValue RV = EmitReferenceBindingToExpr(Init);
EmitStoreOfScalar(RV.getScalarVal(), DeclPtr, false, Alignment, T);
}
@@ -161,23 +162,24 @@ CreateGlobalInitOrDestructFunction(CodeGenModule &CGM,
/// Create a stub function, suitable for being passed to atexit,
/// which passes the given address to the given destructor function.
-static llvm::Constant *createAtExitStub(CodeGenModule &CGM,
+static llvm::Constant *createAtExitStub(CodeGenModule &CGM, const VarDecl &VD,
llvm::Constant *dtor,
llvm::Constant *addr) {
// Get the destructor function type, void(*)(void).
llvm::FunctionType *ty = llvm::FunctionType::get(CGM.VoidTy, false);
+ SmallString<256> FnName;
+ {
+ llvm::raw_svector_ostream Out(FnName);
+ CGM.getCXXABI().getMangleContext().mangleDynamicAtExitDestructor(&VD, Out);
+ }
llvm::Function *fn =
- CreateGlobalInitOrDestructFunction(CGM, ty,
- Twine("__dtor_", addr->getName()));
+ CreateGlobalInitOrDestructFunction(CGM, ty, FnName.str());
CodeGenFunction CGF(CGM);
- // Initialize debug info if needed.
- CGF.maybeInitializeDebugInfo();
-
- CGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, fn,
- CGM.getTypes().arrangeNullaryFunction(),
- FunctionArgList(), SourceLocation());
+ CGF.StartFunction(&VD, CGM.getContext().VoidTy, fn,
+ CGM.getTypes().arrangeNullaryFunction(), FunctionArgList(),
+ SourceLocation());
llvm::CallInst *call = CGF.Builder.CreateCall(dtor, addr);
@@ -192,10 +194,11 @@ static llvm::Constant *createAtExitStub(CodeGenModule &CGM,
}
/// Register a global destructor using the C atexit runtime function.
-void CodeGenFunction::registerGlobalDtorWithAtExit(llvm::Constant *dtor,
+void CodeGenFunction::registerGlobalDtorWithAtExit(const VarDecl &VD,
+ llvm::Constant *dtor,
llvm::Constant *addr) {
// Create a function which calls the destructor.
- llvm::Constant *dtorStub = createAtExitStub(CGM, dtor, addr);
+ llvm::Constant *dtorStub = createAtExitStub(CGM, VD, dtor, addr);
// extern "C" int atexit(void (*f)(void));
llvm::FunctionType *atexitTy =
@@ -257,10 +260,15 @@ CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
llvm::GlobalVariable *Addr,
bool PerformInit) {
llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
+ SmallString<256> FnName;
+ {
+ llvm::raw_svector_ostream Out(FnName);
+ getCXXABI().getMangleContext().mangleDynamicInitializer(D, Out);
+ }
// Create a variable initialization function.
llvm::Function *Fn =
- CreateGlobalInitOrDestructFunction(*this, FTy, "__cxx_global_var_init");
+ CreateGlobalInitOrDestructFunction(*this, FTy, FnName.str());
CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D, Addr,
PerformInit);
@@ -278,6 +286,20 @@ CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
OrderGlobalInits Key(order, PrioritizedCXXGlobalInits.size());
PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn));
DelayedCXXInitPosition.erase(D);
+ } else if (D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization &&
+ D->getTemplateSpecializationKind() != TSK_Undeclared) {
+ // C++ [basic.start.init]p2:
+ // Definitions of explicitly specialized class template static data
+ // members have ordered initialization. Other class template static data
+ // members (i.e., implicitly or explicitly instantiated specializations)
+ // have unordered initialization.
+ //
+ // As a consequence, we can put them into their own llvm.global_ctors entry.
+ // This should allow GlobalOpt to fire more often, and allow us to implement
+ // the Microsoft C++ ABI, which uses COMDAT elimination to avoid double
+ // initializaiton.
+ AddGlobalCtor(Fn);
+ DelayedCXXInitPosition.erase(D);
} else {
llvm::DenseMap<const Decl *, unsigned>::iterator I =
DelayedCXXInitPosition.find(D);
@@ -386,8 +408,8 @@ void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
llvm::GlobalVariable *Addr,
bool PerformInit) {
// Check if we need to emit debug info for variable initializer.
- if (!D->hasAttr<NoDebugAttr>())
- maybeInitializeDebugInfo();
+ if (D->hasAttr<NoDebugAttr>())
+ DebugInfo = NULL; // disable debug info indefinitely for this function
StartFunction(GlobalDecl(D), getContext().VoidTy, Fn,
getTypes().arrangeNullaryFunction(),
@@ -410,9 +432,6 @@ void
CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
ArrayRef<llvm::Constant *> Decls,
llvm::GlobalVariable *Guard) {
- // Initialize debug info if needed.
- maybeInitializeDebugInfo();
-
StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
getTypes().arrangeNullaryFunction(),
FunctionArgList(), SourceLocation());
@@ -459,9 +478,6 @@ CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
void CodeGenFunction::GenerateCXXGlobalDtorsFunc(llvm::Function *Fn,
const std::vector<std::pair<llvm::WeakVH, llvm::Constant*> >
&DtorsAndObjects) {
- // Initialize debug info if needed.
- maybeInitializeDebugInfo();
-
StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
getTypes().arrangeNullaryFunction(),
FunctionArgList(), SourceLocation());
@@ -481,11 +497,9 @@ void CodeGenFunction::GenerateCXXGlobalDtorsFunc(llvm::Function *Fn,
/// generateDestroyHelper - Generates a helper function which, when
/// invoked, destroys the given object.
-llvm::Function *
-CodeGenFunction::generateDestroyHelper(llvm::Constant *addr,
- QualType type,
- Destroyer *destroyer,
- bool useEHCleanupForArray) {
+llvm::Function *CodeGenFunction::generateDestroyHelper(
+ llvm::Constant *addr, QualType type, Destroyer *destroyer,
+ bool useEHCleanupForArray, const VarDecl *VD) {
FunctionArgList args;
ImplicitParamDecl dst(0, SourceLocation(), 0, getContext().VoidPtrTy);
args.push_back(&dst);
@@ -498,11 +512,7 @@ CodeGenFunction::generateDestroyHelper(llvm::Constant *addr,
llvm::Function *fn =
CreateGlobalInitOrDestructFunction(CGM, FTy, "__cxx_global_array_dtor");
- // Initialize debug info if needed.
- maybeInitializeDebugInfo();
-
- StartFunction(GlobalDecl(), getContext().VoidTy, fn, FI, args,
- SourceLocation());
+ StartFunction(VD, getContext().VoidTy, fn, FI, args, SourceLocation());
emitDestroy(addr, type, destroyer, useEHCleanupForArray);
diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp
index a088d78..39a992a 100644
--- a/lib/CodeGen/CGException.cpp
+++ b/lib/CodeGen/CGException.cpp
@@ -89,7 +89,7 @@ static llvm::Constant *getEndCatchFn(CodeGenModule &CGM) {
}
static llvm::Constant *getUnexpectedFn(CodeGenModule &CGM) {
- // void __cxa_call_unexepcted(void *thrown_exception);
+ // void __cxa_call_unexpected(void *thrown_exception);
llvm::FunctionType *FTy =
llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, /*IsVarArgs=*/false);
@@ -766,6 +766,11 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
// Save the current IR generation state.
CGBuilderTy::InsertPoint savedIP = Builder.saveAndClearIP();
+ SourceLocation SavedLocation;
+ if (CGDebugInfo *DI = getDebugInfo()) {
+ SavedLocation = DI->getLocation();
+ DI->EmitLocation(Builder, CurEHLocation);
+ }
const EHPersonality &personality = EHPersonality::get(getLangOpts());
@@ -887,6 +892,8 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
// Restore the old IR generation state.
Builder.restoreIP(savedIP);
+ if (CGDebugInfo *DI = getDebugInfo())
+ DI->EmitLocation(Builder, SavedLocation);
return lpad;
}
@@ -938,7 +945,8 @@ static llvm::Value *CallBeginCatch(CodeGenFunction &CGF,
/// parameter during catch initialization.
static void InitCatchParam(CodeGenFunction &CGF,
const VarDecl &CatchParam,
- llvm::Value *ParamAddr) {
+ llvm::Value *ParamAddr,
+ SourceLocation Loc) {
// Load the exception from where the landing pad saved it.
llvm::Value *Exn = CGF.getExceptionFromSlot();
@@ -1045,11 +1053,11 @@ static void InitCatchParam(CodeGenFunction &CGF,
CGF.getContext().getDeclAlign(&CatchParam));
switch (TEK) {
case TEK_Complex:
- CGF.EmitStoreOfComplex(CGF.EmitLoadOfComplex(srcLV), destLV,
+ CGF.EmitStoreOfComplex(CGF.EmitLoadOfComplex(srcLV, Loc), destLV,
/*init*/ true);
return;
case TEK_Scalar: {
- llvm::Value *ExnLoad = CGF.EmitLoadOfScalar(srcLV);
+ llvm::Value *ExnLoad = CGF.EmitLoadOfScalar(srcLV, Loc);
CGF.EmitStoreOfScalar(ExnLoad, destLV, /*init*/ true);
return;
}
@@ -1143,7 +1151,7 @@ static void BeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *S) {
// Emit the local.
CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam);
- InitCatchParam(CGF, *CatchParam, var.getObjectAddress(CGF));
+ InitCatchParam(CGF, *CatchParam, var.getObjectAddress(CGF), S->getLocStart());
CGF.EmitAutoVarCleanups(var);
}
@@ -1612,8 +1620,15 @@ llvm::BasicBlock *CodeGenFunction::getTerminateHandler() {
// end of the function by FinishFunction.
TerminateHandler = createBasicBlock("terminate.handler");
Builder.SetInsertPoint(TerminateHandler);
- llvm::CallInst *TerminateCall = EmitNounwindRuntimeCall(getTerminateFn(CGM));
- TerminateCall->setDoesNotReturn();
+ llvm::CallInst *terminateCall;
+ if (useClangCallTerminate(CGM)) {
+ // Load the exception pointer.
+ llvm::Value *exn = getExceptionFromSlot();
+ terminateCall = EmitNounwindRuntimeCall(getClangCallTerminateFn(CGM), exn);
+ } else {
+ terminateCall = EmitNounwindRuntimeCall(getTerminateFn(CGM));
+ }
+ terminateCall->setDoesNotReturn();
Builder.CreateUnreachable();
// Restore the saved insertion state.
@@ -1683,3 +1698,7 @@ llvm::BasicBlock *CodeGenFunction::getEHResumeBlock(bool isCleanup) {
return EHResumeBlock;
}
+
+void CodeGenFunction::EmitSEHTryStmt(const SEHTryStmt &S) {
+ CGM.ErrorUnsupported(&S, "SEH __try");
+}
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 64670c5..cb990b2 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -171,244 +171,240 @@ void CodeGenFunction::EmitAnyExprToMem(const Expr *E,
llvm_unreachable("bad evaluation kind");
}
-static llvm::Value *
-CreateReferenceTemporary(CodeGenFunction &CGF, QualType Type,
- const NamedDecl *InitializedDecl) {
- if (const VarDecl *VD = dyn_cast_or_null<VarDecl>(InitializedDecl)) {
- if (VD->hasGlobalStorage()) {
- SmallString<256> Name;
- llvm::raw_svector_ostream Out(Name);
- CGF.CGM.getCXXABI().getMangleContext().mangleReferenceTemporary(VD, Out);
- Out.flush();
-
- llvm::Type *RefTempTy = CGF.ConvertTypeForMem(Type);
-
- // Create the reference temporary.
- llvm::GlobalVariable *RefTemp =
- new llvm::GlobalVariable(CGF.CGM.getModule(),
- RefTempTy, /*isConstant=*/false,
- llvm::GlobalValue::InternalLinkage,
- llvm::Constant::getNullValue(RefTempTy),
- Name.str());
- // If we're binding to a thread_local variable, the temporary is also
- // thread local.
- if (VD->getTLSKind())
- CGF.CGM.setTLSMode(RefTemp, *VD);
- return RefTemp;
- }
- }
-
- return CGF.CreateMemTemp(Type, "ref.tmp");
-}
-
-static llvm::Value *
-EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E,
- llvm::Value *&ReferenceTemporary,
- const CXXDestructorDecl *&ReferenceTemporaryDtor,
- const InitListExpr *&ReferenceInitializerList,
- QualType &ObjCARCReferenceLifetimeType,
- const NamedDecl *InitializedDecl) {
- const MaterializeTemporaryExpr *M = NULL;
- E = E->findMaterializedTemporary(M);
+static void
+pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M,
+ const Expr *E, llvm::Value *ReferenceTemporary) {
// Objective-C++ ARC:
// If we are binding a reference to a temporary that has ownership, we
// need to perform retain/release operations on the temporary.
- if (M && CGF.getLangOpts().ObjCAutoRefCount &&
- M->getType()->isObjCLifetimeType() &&
- (M->getType().getObjCLifetime() == Qualifiers::OCL_Strong ||
- M->getType().getObjCLifetime() == Qualifiers::OCL_Weak ||
- M->getType().getObjCLifetime() == Qualifiers::OCL_Autoreleasing))
- ObjCARCReferenceLifetimeType = M->getType();
-
- if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(E)) {
- CGF.enterFullExpression(EWC);
- CodeGenFunction::RunCleanupsScope Scope(CGF);
-
- return EmitExprForReferenceBinding(CGF, EWC->getSubExpr(),
- ReferenceTemporary,
- ReferenceTemporaryDtor,
- ReferenceInitializerList,
- ObjCARCReferenceLifetimeType,
- InitializedDecl);
- }
-
- if (E->isGLValue()) {
- // Emit the expression as an lvalue.
- LValue LV = CGF.EmitLValue(E);
- assert(LV.isSimple());
- return LV.getAddress();
- }
-
- if (!ObjCARCReferenceLifetimeType.isNull()) {
- ReferenceTemporary = CreateReferenceTemporary(CGF,
- ObjCARCReferenceLifetimeType,
- InitializedDecl);
-
-
- LValue RefTempDst = CGF.MakeAddrLValue(ReferenceTemporary,
- ObjCARCReferenceLifetimeType);
-
- CGF.EmitScalarInit(E, dyn_cast_or_null<ValueDecl>(InitializedDecl),
- RefTempDst, false);
-
- bool ExtendsLifeOfTemporary = false;
- if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(InitializedDecl)) {
- if (Var->extendsLifetimeOfTemporary())
- ExtendsLifeOfTemporary = true;
- } else if (InitializedDecl && isa<FieldDecl>(InitializedDecl)) {
- ExtendsLifeOfTemporary = true;
- }
-
- if (!ExtendsLifeOfTemporary) {
- // Since the lifetime of this temporary isn't going to be extended,
- // we need to clean it up ourselves at the end of the full expression.
- switch (ObjCARCReferenceLifetimeType.getObjCLifetime()) {
- case Qualifiers::OCL_None:
- case Qualifiers::OCL_ExplicitNone:
- case Qualifiers::OCL_Autoreleasing:
- break;
-
- case Qualifiers::OCL_Strong: {
- assert(!ObjCARCReferenceLifetimeType->isArrayType());
- CleanupKind cleanupKind = CGF.getARCCleanupKind();
- CGF.pushDestroy(cleanupKind,
- ReferenceTemporary,
- ObjCARCReferenceLifetimeType,
- CodeGenFunction::destroyARCStrongImprecise,
- cleanupKind & EHCleanup);
- break;
- }
-
- case Qualifiers::OCL_Weak:
+ //
+ // FIXME: This should be looking at E, not M.
+ if (CGF.getLangOpts().ObjCAutoRefCount &&
+ M->getType()->isObjCLifetimeType()) {
+ QualType ObjCARCReferenceLifetimeType = M->getType();
+ switch (Qualifiers::ObjCLifetime Lifetime =
+ ObjCARCReferenceLifetimeType.getObjCLifetime()) {
+ case Qualifiers::OCL_None:
+ case Qualifiers::OCL_ExplicitNone:
+ // Carry on to normal cleanup handling.
+ break;
+
+ case Qualifiers::OCL_Autoreleasing:
+ // Nothing to do; cleaned up by an autorelease pool.
+ return;
+
+ case Qualifiers::OCL_Strong:
+ case Qualifiers::OCL_Weak:
+ switch (StorageDuration Duration = M->getStorageDuration()) {
+ case SD_Static:
+ // Note: we intentionally do not register a cleanup to release
+ // the object on program termination.
+ return;
+
+ case SD_Thread:
+ // FIXME: We should probably register a cleanup in this case.
+ return;
+
+ case SD_Automatic:
+ case SD_FullExpression:
assert(!ObjCARCReferenceLifetimeType->isArrayType());
- CGF.pushDestroy(NormalAndEHCleanup,
- ReferenceTemporary,
- ObjCARCReferenceLifetimeType,
- CodeGenFunction::destroyARCWeak,
- /*useEHCleanupForArray*/ true);
- break;
+ CodeGenFunction::Destroyer *Destroy;
+ CleanupKind CleanupKind;
+ if (Lifetime == Qualifiers::OCL_Strong) {
+ const ValueDecl *VD = M->getExtendingDecl();
+ bool Precise =
+ VD && isa<VarDecl>(VD) && VD->hasAttr<ObjCPreciseLifetimeAttr>();
+ CleanupKind = CGF.getARCCleanupKind();
+ Destroy = Precise ? &CodeGenFunction::destroyARCStrongPrecise
+ : &CodeGenFunction::destroyARCStrongImprecise;
+ } else {
+ // __weak objects always get EH cleanups; otherwise, exceptions
+ // could cause really nasty crashes instead of mere leaks.
+ CleanupKind = NormalAndEHCleanup;
+ Destroy = &CodeGenFunction::destroyARCWeak;
+ }
+ if (Duration == SD_FullExpression)
+ CGF.pushDestroy(CleanupKind, ReferenceTemporary,
+ ObjCARCReferenceLifetimeType, *Destroy,
+ CleanupKind & EHCleanup);
+ else
+ CGF.pushLifetimeExtendedDestroy(CleanupKind, ReferenceTemporary,
+ ObjCARCReferenceLifetimeType,
+ *Destroy, CleanupKind & EHCleanup);
+ return;
+
+ case SD_Dynamic:
+ llvm_unreachable("temporary cannot have dynamic storage duration");
}
-
- ObjCARCReferenceLifetimeType = QualType();
+ llvm_unreachable("unknown storage duration");
}
-
- return ReferenceTemporary;
}
- SmallVector<SubobjectAdjustment, 2> Adjustments;
- E = E->skipRValueSubobjectAdjustments(Adjustments);
- if (const OpaqueValueExpr *opaque = dyn_cast<OpaqueValueExpr>(E))
- if (opaque->getType()->isRecordType())
- return CGF.EmitOpaqueValueLValue(opaque).getAddress();
+ CXXDestructorDecl *ReferenceTemporaryDtor = 0;
+ if (const RecordType *RT =
+ E->getType()->getBaseElementTypeUnsafe()->getAs<RecordType>()) {
+ // Get the destructor for the reference temporary.
+ CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+ if (!ClassDecl->hasTrivialDestructor())
+ ReferenceTemporaryDtor = ClassDecl->getDestructor();
+ }
- // Create a reference temporary if necessary.
- AggValueSlot AggSlot = AggValueSlot::ignored();
- if (CGF.hasAggregateEvaluationKind(E->getType())) {
- ReferenceTemporary = CreateReferenceTemporary(CGF, E->getType(),
- InitializedDecl);
- CharUnits Alignment = CGF.getContext().getTypeAlignInChars(E->getType());
- AggValueSlot::IsDestructed_t isDestructed
- = AggValueSlot::IsDestructed_t(InitializedDecl != 0);
- AggSlot = AggValueSlot::forAddr(ReferenceTemporary, Alignment,
- Qualifiers(), isDestructed,
- AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased);
- }
-
- if (InitializedDecl) {
- if (const InitListExpr *ILE = dyn_cast<InitListExpr>(E)) {
- if (ILE->initializesStdInitializerList()) {
- ReferenceInitializerList = ILE;
- }
- }
- else if (const RecordType *RT =
- E->getType()->getBaseElementTypeUnsafe()->getAs<RecordType>()){
- // Get the destructor for the reference temporary.
- CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RT->getDecl());
- if (!ClassDecl->hasTrivialDestructor())
- ReferenceTemporaryDtor = ClassDecl->getDestructor();
+ if (!ReferenceTemporaryDtor)
+ return;
+
+ // Call the destructor for the temporary.
+ switch (M->getStorageDuration()) {
+ case SD_Static:
+ case SD_Thread: {
+ llvm::Constant *CleanupFn;
+ llvm::Constant *CleanupArg;
+ if (E->getType()->isArrayType()) {
+ CleanupFn = CodeGenFunction(CGF.CGM).generateDestroyHelper(
+ cast<llvm::Constant>(ReferenceTemporary), E->getType(),
+ CodeGenFunction::destroyCXXObject, CGF.getLangOpts().Exceptions,
+ dyn_cast_or_null<VarDecl>(M->getExtendingDecl()));
+ CleanupArg = llvm::Constant::getNullValue(CGF.Int8PtrTy);
+ } else {
+ CleanupFn =
+ CGF.CGM.GetAddrOfCXXDestructor(ReferenceTemporaryDtor, Dtor_Complete);
+ CleanupArg = cast<llvm::Constant>(ReferenceTemporary);
}
+ CGF.CGM.getCXXABI().registerGlobalDtor(
+ CGF, *cast<VarDecl>(M->getExtendingDecl()), CleanupFn, CleanupArg);
+ break;
}
- RValue RV = CGF.EmitAnyExpr(E, AggSlot);
-
- // Check if need to perform derived-to-base casts and/or field accesses, to
- // get from the temporary object we created (and, potentially, for which we
- // extended the lifetime) to the subobject we're binding the reference to.
- if (!Adjustments.empty()) {
- llvm::Value *Object = RV.getAggregateAddr();
- for (unsigned I = Adjustments.size(); I != 0; --I) {
- SubobjectAdjustment &Adjustment = Adjustments[I-1];
- switch (Adjustment.Kind) {
- case SubobjectAdjustment::DerivedToBaseAdjustment:
- Object =
- CGF.GetAddressOfBaseClass(Object,
- Adjustment.DerivedToBase.DerivedClass,
- Adjustment.DerivedToBase.BasePath->path_begin(),
- Adjustment.DerivedToBase.BasePath->path_end(),
- /*NullCheckValue=*/false);
- break;
-
- case SubobjectAdjustment::FieldAdjustment: {
- LValue LV = CGF.MakeAddrLValue(Object, E->getType());
- LV = CGF.EmitLValueForField(LV, Adjustment.Field);
- if (LV.isSimple()) {
- Object = LV.getAddress();
- break;
- }
-
- // For non-simple lvalues, we actually have to create a copy of
- // the object we're binding to.
- QualType T = Adjustment.Field->getType().getNonReferenceType()
- .getUnqualifiedType();
- Object = CreateReferenceTemporary(CGF, T, InitializedDecl);
- LValue TempLV = CGF.MakeAddrLValue(Object,
- Adjustment.Field->getType());
- CGF.EmitStoreThroughLValue(CGF.EmitLoadOfLValue(LV), TempLV);
- break;
- }
+ case SD_FullExpression:
+ CGF.pushDestroy(NormalAndEHCleanup, ReferenceTemporary, E->getType(),
+ CodeGenFunction::destroyCXXObject,
+ CGF.getLangOpts().Exceptions);
+ break;
- case SubobjectAdjustment::MemberPointerAdjustment: {
- llvm::Value *Ptr = CGF.EmitScalarExpr(Adjustment.Ptr.RHS);
- Object = CGF.CGM.getCXXABI().EmitMemberDataPointerAddress(
- CGF, Object, Ptr, Adjustment.Ptr.MPT);
- break;
- }
- }
+ case SD_Automatic:
+ CGF.pushLifetimeExtendedDestroy(NormalAndEHCleanup,
+ ReferenceTemporary, E->getType(),
+ CodeGenFunction::destroyCXXObject,
+ CGF.getLangOpts().Exceptions);
+ break;
+
+ case SD_Dynamic:
+ llvm_unreachable("temporary cannot have dynamic storage duration");
+ }
+}
+
+static llvm::Value *
+createReferenceTemporary(CodeGenFunction &CGF,
+ const MaterializeTemporaryExpr *M, const Expr *Inner) {
+ switch (M->getStorageDuration()) {
+ case SD_FullExpression:
+ case SD_Automatic:
+ return CGF.CreateMemTemp(Inner->getType(), "ref.tmp");
+
+ case SD_Thread:
+ case SD_Static:
+ return CGF.CGM.GetAddrOfGlobalTemporary(M, Inner);
+
+ case SD_Dynamic:
+ llvm_unreachable("temporary can't have dynamic storage duration");
+ }
+ llvm_unreachable("unknown storage duration");
+}
+
+LValue CodeGenFunction::EmitMaterializeTemporaryExpr(
+ const MaterializeTemporaryExpr *M) {
+ const Expr *E = M->GetTemporaryExpr();
+
+ if (getLangOpts().ObjCAutoRefCount &&
+ M->getType()->isObjCLifetimeType() &&
+ M->getType().getObjCLifetime() != Qualifiers::OCL_None &&
+ M->getType().getObjCLifetime() != Qualifiers::OCL_ExplicitNone) {
+ // FIXME: Fold this into the general case below.
+ llvm::Value *Object = createReferenceTemporary(*this, M, E);
+ LValue RefTempDst = MakeAddrLValue(Object, M->getType());
+
+ if (llvm::GlobalVariable *Var = dyn_cast<llvm::GlobalVariable>(Object)) {
+ // We should not have emitted the initializer for this temporary as a
+ // constant.
+ assert(!Var->hasInitializer());
+ Var->setInitializer(CGM.EmitNullConstant(E->getType()));
}
- return Object;
+ EmitScalarInit(E, M->getExtendingDecl(), RefTempDst, false);
+
+ pushTemporaryCleanup(*this, M, E, Object);
+ return RefTempDst;
}
- if (RV.isAggregate())
- return RV.getAggregateAddr();
+ SmallVector<const Expr *, 2> CommaLHSs;
+ SmallVector<SubobjectAdjustment, 2> Adjustments;
+ E = E->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments);
+
+ for (unsigned I = 0, N = CommaLHSs.size(); I != N; ++I)
+ EmitIgnoredExpr(CommaLHSs[I]);
- // Create a temporary variable that we can bind the reference to.
- ReferenceTemporary = CreateReferenceTemporary(CGF, E->getType(),
- InitializedDecl);
+ if (const OpaqueValueExpr *opaque = dyn_cast<OpaqueValueExpr>(E)) {
+ if (opaque->getType()->isRecordType()) {
+ assert(Adjustments.empty());
+ return EmitOpaqueValueLValue(opaque);
+ }
+ }
+ // Create and initialize the reference temporary.
+ llvm::Value *Object = createReferenceTemporary(*this, M, E);
+ if (llvm::GlobalVariable *Var = dyn_cast<llvm::GlobalVariable>(Object)) {
+ // If the temporary is a global and has a constant initializer, we may
+ // have already initialized it.
+ if (!Var->hasInitializer()) {
+ Var->setInitializer(CGM.EmitNullConstant(E->getType()));
+ EmitAnyExprToMem(E, Object, Qualifiers(), /*IsInit*/true);
+ }
+ } else {
+ EmitAnyExprToMem(E, Object, Qualifiers(), /*IsInit*/true);
+ }
+ pushTemporaryCleanup(*this, M, E, Object);
+
+ // Perform derived-to-base casts and/or field accesses, to get from the
+ // temporary object we created (and, potentially, for which we extended
+ // the lifetime) to the subobject we're binding the reference to.
+ for (unsigned I = Adjustments.size(); I != 0; --I) {
+ SubobjectAdjustment &Adjustment = Adjustments[I-1];
+ switch (Adjustment.Kind) {
+ case SubobjectAdjustment::DerivedToBaseAdjustment:
+ Object =
+ GetAddressOfBaseClass(Object, Adjustment.DerivedToBase.DerivedClass,
+ Adjustment.DerivedToBase.BasePath->path_begin(),
+ Adjustment.DerivedToBase.BasePath->path_end(),
+ /*NullCheckValue=*/ false);
+ break;
- LValue tempLV = CGF.MakeNaturalAlignAddrLValue(ReferenceTemporary,
- E->getType());
- if (RV.isScalar())
- CGF.EmitStoreOfScalar(RV.getScalarVal(), tempLV, /*init*/ true);
- else
- CGF.EmitStoreOfComplex(RV.getComplexVal(), tempLV, /*init*/ true);
- return ReferenceTemporary;
+ case SubobjectAdjustment::FieldAdjustment: {
+ LValue LV = MakeAddrLValue(Object, E->getType());
+ LV = EmitLValueForField(LV, Adjustment.Field);
+ assert(LV.isSimple() &&
+ "materialized temporary field is not a simple lvalue");
+ Object = LV.getAddress();
+ break;
+ }
+
+ case SubobjectAdjustment::MemberPointerAdjustment: {
+ llvm::Value *Ptr = EmitScalarExpr(Adjustment.Ptr.RHS);
+ Object = CGM.getCXXABI().EmitMemberDataPointerAddress(
+ *this, Object, Ptr, Adjustment.Ptr.MPT);
+ break;
+ }
+ }
+ }
+
+ return MakeAddrLValue(Object, M->getType());
}
RValue
-CodeGenFunction::EmitReferenceBindingToExpr(const Expr *E,
- const NamedDecl *InitializedDecl) {
- llvm::Value *ReferenceTemporary = 0;
- const CXXDestructorDecl *ReferenceTemporaryDtor = 0;
- const InitListExpr *ReferenceInitializerList = 0;
- QualType ObjCARCReferenceLifetimeType;
- llvm::Value *Value = EmitExprForReferenceBinding(*this, E, ReferenceTemporary,
- ReferenceTemporaryDtor,
- ReferenceInitializerList,
- ObjCARCReferenceLifetimeType,
- InitializedDecl);
+CodeGenFunction::EmitReferenceBindingToExpr(const Expr *E) {
+ // Emit the expression as an lvalue.
+ LValue LV = EmitLValue(E);
+ assert(LV.isSimple());
+ llvm::Value *Value = LV.getAddress();
+
if (SanitizePerformTypeCheck && !E->getType()->isFunctionType()) {
// C++11 [dcl.ref]p5 (as amended by core issue 453):
// If a glvalue to which a reference is directly bound designates neither
@@ -418,80 +414,7 @@ CodeGenFunction::EmitReferenceBindingToExpr(const Expr *E,
QualType Ty = E->getType();
EmitTypeCheck(TCK_ReferenceBinding, E->getExprLoc(), Value, Ty);
}
- if (!ReferenceTemporaryDtor && !ReferenceInitializerList &&
- ObjCARCReferenceLifetimeType.isNull())
- return RValue::get(Value);
-
- // Make sure to call the destructor for the reference temporary.
- const VarDecl *VD = dyn_cast_or_null<VarDecl>(InitializedDecl);
- if (VD && VD->hasGlobalStorage()) {
- if (ReferenceTemporaryDtor) {
- llvm::Constant *CleanupFn;
- llvm::Constant *CleanupArg;
- if (E->getType()->isArrayType()) {
- CleanupFn = CodeGenFunction(CGM).generateDestroyHelper(
- cast<llvm::Constant>(ReferenceTemporary), E->getType(),
- destroyCXXObject, getLangOpts().Exceptions);
- CleanupArg = llvm::Constant::getNullValue(Int8PtrTy);
- } else {
- CleanupFn =
- CGM.GetAddrOfCXXDestructor(ReferenceTemporaryDtor, Dtor_Complete);
- CleanupArg = cast<llvm::Constant>(ReferenceTemporary);
- }
- CGM.getCXXABI().registerGlobalDtor(*this, *VD, CleanupFn, CleanupArg);
- } else if (ReferenceInitializerList) {
- // FIXME: This is wrong. We need to register a global destructor to clean
- // up the initializer_list object, rather than adding it as a local
- // cleanup.
- EmitStdInitializerListCleanup(ReferenceTemporary,
- ReferenceInitializerList);
- } else {
- assert(!ObjCARCReferenceLifetimeType.isNull() && !VD->getTLSKind());
- // Note: We intentionally do not register a global "destructor" to
- // release the object.
- }
-
- return RValue::get(Value);
- }
- if (ReferenceTemporaryDtor) {
- if (E->getType()->isArrayType())
- pushDestroy(NormalAndEHCleanup, ReferenceTemporary, E->getType(),
- destroyCXXObject, getLangOpts().Exceptions);
- else
- PushDestructorCleanup(ReferenceTemporaryDtor, ReferenceTemporary);
- } else if (ReferenceInitializerList) {
- EmitStdInitializerListCleanup(ReferenceTemporary,
- ReferenceInitializerList);
- } else {
- switch (ObjCARCReferenceLifetimeType.getObjCLifetime()) {
- case Qualifiers::OCL_None:
- llvm_unreachable(
- "Not a reference temporary that needs to be deallocated");
- case Qualifiers::OCL_ExplicitNone:
- case Qualifiers::OCL_Autoreleasing:
- // Nothing to do.
- break;
-
- case Qualifiers::OCL_Strong: {
- bool precise = VD && VD->hasAttr<ObjCPreciseLifetimeAttr>();
- CleanupKind cleanupKind = getARCCleanupKind();
- pushDestroy(cleanupKind, ReferenceTemporary, ObjCARCReferenceLifetimeType,
- precise ? destroyARCStrongPrecise : destroyARCStrongImprecise,
- cleanupKind & EHCleanup);
- break;
- }
-
- case Qualifiers::OCL_Weak: {
- // __weak objects always get EH cleanups; otherwise, exceptions
- // could cause really nasty crashes instead of mere leaks.
- pushDestroy(NormalAndEHCleanup, ReferenceTemporary,
- ObjCARCReferenceLifetimeType, destroyARCWeak, true);
- break;
- }
- }
- }
-
return RValue::get(Value);
}
@@ -553,7 +476,9 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
// The glvalue must refer to a large enough storage region.
// FIXME: If Address Sanitizer is enabled, insert dynamic instrumentation
// to check this.
- llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::objectsize, IntPtrTy);
+ // FIXME: Get object address space
+ llvm::Type *Tys[2] = { IntPtrTy, Int8PtrTy };
+ llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::objectsize, Tys);
llvm::Value *Min = Builder.getFalse();
llvm::Value *CastAddr = Builder.CreateBitCast(Address, Int8PtrTy);
llvm::Value *LargeEnough =
@@ -716,7 +641,8 @@ static llvm::Value *getArrayIndexingBound(
void CodeGenFunction::EmitBoundsCheck(const Expr *E, const Expr *Base,
llvm::Value *Index, QualType IndexType,
bool Accessed) {
- assert(SanOpts->Bounds && "should not be called unless adding bounds checks");
+ assert(SanOpts->ArrayBounds &&
+ "should not be called unless adding bounds checks");
QualType IndexedType;
llvm::Value *Bound = getArrayIndexingBound(*this, Base, IndexedType);
@@ -741,13 +667,13 @@ void CodeGenFunction::EmitBoundsCheck(const Expr *E, const Expr *Base,
CodeGenFunction::ComplexPairTy CodeGenFunction::
EmitComplexPrePostIncDec(const UnaryOperator *E, LValue LV,
bool isInc, bool isPre) {
- ComplexPairTy InVal = EmitLoadOfComplex(LV);
-
+ ComplexPairTy InVal = EmitLoadOfComplex(LV, E->getExprLoc());
+
llvm::Value *NextVal;
if (isa<llvm::IntegerType>(InVal.first->getType())) {
uint64_t AmountVal = isInc ? 1 : -1;
NextVal = llvm::ConstantInt::get(InVal.first->getType(), AmountVal, true);
-
+
// Add the inc/dec to the real part.
NextVal = Builder.CreateAdd(InVal.first, NextVal, isInc ? "inc" : "dec");
} else {
@@ -756,16 +682,16 @@ EmitComplexPrePostIncDec(const UnaryOperator *E, LValue LV,
if (!isInc)
FVal.changeSign();
NextVal = llvm::ConstantFP::get(getLLVMContext(), FVal);
-
+
// Add the inc/dec to the real part.
NextVal = Builder.CreateFAdd(InVal.first, NextVal, isInc ? "inc" : "dec");
}
-
+
ComplexPairTy IncVal(NextVal, InVal.second);
-
+
// Store the updated result through the lvalue.
EmitStoreOfComplex(IncVal, LV, /*init*/ false);
-
+
// If this is a postinc, return the value read from memory, otherwise use the
// updated value.
return isPre ? IncVal : InVal;
@@ -787,7 +713,7 @@ RValue CodeGenFunction::GetUndefRValue(QualType Ty) {
llvm::Value *U = llvm::UndefValue::get(EltTy);
return RValue::getComplex(std::make_pair(U, U));
}
-
+
// If this is a use of an undefined aggregate type, the aggregate must have an
// identifiable address. Just because the contents of the value are undefined
// doesn't mean that the address can't be taken and compared.
@@ -817,7 +743,7 @@ LValue CodeGenFunction::EmitUnsupportedLValue(const Expr *E,
LValue CodeGenFunction::EmitCheckedLValue(const Expr *E, TypeCheckKind TCK) {
LValue LV;
- if (SanOpts->Bounds && isa<ArraySubscriptExpr>(E))
+ if (SanOpts->ArrayBounds && isa<ArraySubscriptExpr>(E))
LV = EmitArraySubscriptExpr(cast<ArraySubscriptExpr>(E), /*Accessed*/true);
else
LV = EmitLValue(E);
@@ -899,8 +825,6 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
return EmitLValue(cleanups->getSubExpr());
}
- case Expr::CXXScalarValueInitExprClass:
- return EmitNullInitializationLValue(cast<CXXScalarValueInitExpr>(E));
case Expr::CXXDefaultArgExprClass:
return EmitLValue(cast<CXXDefaultArgExpr>(E)->getExpr());
case Expr::CXXDefaultInitExprClass: {
@@ -931,7 +855,7 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
case Expr::BinaryConditionalOperatorClass:
return EmitConditionalOperatorLValue(cast<BinaryConditionalOperator>(E));
case Expr::ChooseExprClass:
- return EmitLValue(cast<ChooseExpr>(E)->getChosenSubExpr(getContext()));
+ return EmitLValue(cast<ChooseExpr>(E)->getChosenSubExpr());
case Expr::OpaqueValueExprClass:
return EmitOpaqueValueLValue(cast<OpaqueValueExpr>(E));
case Expr::SubstNonTypeTemplateParmExprClass:
@@ -1047,7 +971,7 @@ CodeGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) {
llvm::Constant *C = CGM.EmitConstantValue(result.Val, resultType, this);
// Make sure we emit a debug reference to the global variable.
- // This should probably fire even for
+ // This should probably fire even for
if (isa<VarDecl>(value)) {
if (!getContext().DeclMustBeEmitted(cast<VarDecl>(value)))
EmitDeclRefExprDbgValue(refExpr, C);
@@ -1063,10 +987,11 @@ CodeGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) {
return ConstantEmission::forValue(C);
}
-llvm::Value *CodeGenFunction::EmitLoadOfScalar(LValue lvalue) {
+llvm::Value *CodeGenFunction::EmitLoadOfScalar(LValue lvalue,
+ SourceLocation Loc) {
return EmitLoadOfScalar(lvalue.getAddress(), lvalue.isVolatile(),
lvalue.getAlignment().getQuantity(),
- lvalue.getType(), lvalue.getTBAAInfo(),
+ lvalue.getType(), Loc, lvalue.getTBAAInfo(),
lvalue.getTBAABaseType(), lvalue.getTBAAOffset());
}
@@ -1128,21 +1053,22 @@ llvm::MDNode *CodeGenFunction::getRangeForLoadFromType(QualType Ty) {
}
llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,
- unsigned Alignment, QualType Ty,
- llvm::MDNode *TBAAInfo,
- QualType TBAABaseType,
- uint64_t TBAAOffset) {
+ unsigned Alignment, QualType Ty,
+ SourceLocation Loc,
+ llvm::MDNode *TBAAInfo,
+ QualType TBAABaseType,
+ uint64_t TBAAOffset) {
// For better performance, handle vector loads differently.
if (Ty->isVectorType()) {
llvm::Value *V;
const llvm::Type *EltTy =
cast<llvm::PointerType>(Addr->getType())->getElementType();
-
+
const llvm::VectorType *VTy = cast<llvm::VectorType>(EltTy);
-
+
// Handle vectors of size 3, like size 4 for better performance.
if (VTy->getNumElements() == 3) {
-
+
// Bitcast to vec4 type.
llvm::VectorType *vec4Ty = llvm::VectorType::get(VTy->getElementType(),
4);
@@ -1175,9 +1101,9 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,
LValue lvalue = LValue::MakeAddr(Addr, Ty,
CharUnits::fromQuantity(Alignment),
getContext(), TBAAInfo);
- return EmitAtomicLoad(lvalue).getScalarVal();
+ return EmitAtomicLoad(lvalue, Loc).getScalarVal();
}
-
+
llvm::LoadInst *Load = Builder.CreateLoad(Addr);
if (Volatile)
Load->setVolatile(true);
@@ -1186,7 +1112,8 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,
if (TBAAInfo) {
llvm::MDNode *TBAAPath = CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo,
TBAAOffset);
- CGM.DecorateInstruction(Load, TBAAPath, false/*ConvertTypeToTag*/);
+ if (TBAAPath)
+ CGM.DecorateInstruction(Load, TBAAPath, false/*ConvertTypeToTag*/);
}
if ((SanOpts->Bool && hasBooleanRepresentation(Ty)) ||
@@ -1205,9 +1132,12 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,
Load, llvm::ConstantInt::get(getLLVMContext(), Min));
Check = Builder.CreateAnd(Upper, Lower);
}
- // FIXME: Provide a SourceLocation.
- EmitCheck(Check, "load_invalid_value", EmitCheckTypeDescriptor(Ty),
- EmitCheckValue(Load), CRK_Recoverable);
+ llvm::Constant *StaticArgs[] = {
+ EmitCheckSourceLocation(Loc),
+ EmitCheckTypeDescriptor(Ty)
+ };
+ EmitCheck(Check, "load_invalid_value", StaticArgs, EmitCheckValue(Load),
+ CRK_Recoverable);
}
} else if (CGM.getCodeGenOpts().OptimizationLevel > 0)
if (llvm::MDNode *RangeInfo = getRangeForLoadFromType(Ty))
@@ -1243,11 +1173,10 @@ llvm::Value *CodeGenFunction::EmitFromMemory(llvm::Value *Value, QualType Ty) {
void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr,
bool Volatile, unsigned Alignment,
- QualType Ty,
- llvm::MDNode *TBAAInfo,
+ QualType Ty, llvm::MDNode *TBAAInfo,
bool isInit, QualType TBAABaseType,
uint64_t TBAAOffset) {
-
+
// Handle vectors differently to get better performance.
if (Ty->isVectorType()) {
llvm::Type *SrcTy = Value->getType();
@@ -1255,20 +1184,17 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr,
// Handle vec3 special.
if (VecTy->getNumElements() == 3) {
llvm::LLVMContext &VMContext = getLLVMContext();
-
+
// Our source is a vec3, do a shuffle vector to make it a vec4.
SmallVector<llvm::Constant*, 4> Mask;
- Mask.push_back(llvm::ConstantInt::get(
- llvm::Type::getInt32Ty(VMContext),
+ Mask.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
0));
- Mask.push_back(llvm::ConstantInt::get(
- llvm::Type::getInt32Ty(VMContext),
+ Mask.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
1));
- Mask.push_back(llvm::ConstantInt::get(
- llvm::Type::getInt32Ty(VMContext),
+ Mask.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
2));
Mask.push_back(llvm::UndefValue::get(llvm::Type::getInt32Ty(VMContext)));
-
+
llvm::Value *MaskV = llvm::ConstantVector::get(Mask);
Value = Builder.CreateShuffleVector(Value,
llvm::UndefValue::get(VecTy),
@@ -1282,7 +1208,7 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr,
Addr = Builder.CreateBitCast(Addr, MemTy, "storetmp");
}
}
-
+
Value = EmitToMemory(Value, Ty);
if (Ty->isAtomicType()) {
@@ -1300,7 +1226,8 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr,
if (TBAAInfo) {
llvm::MDNode *TBAAPath = CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo,
TBAAOffset);
- CGM.DecorateInstruction(Store, TBAAPath, false/*ConvertTypeToTag*/);
+ if (TBAAPath)
+ CGM.DecorateInstruction(Store, TBAAPath, false/*ConvertTypeToTag*/);
}
}
@@ -1315,7 +1242,7 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *value, LValue lvalue,
/// EmitLoadOfLValue - Given an expression that represents a value lvalue, this
/// method emits the address of the lvalue, then loads the result as an rvalue,
/// returning the rvalue.
-RValue CodeGenFunction::EmitLoadOfLValue(LValue LV) {
+RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, SourceLocation Loc) {
if (LV.isObjCWeak()) {
// load of a __weak object.
llvm::Value *AddrWeakObj = LV.getAddress();
@@ -1332,7 +1259,7 @@ RValue CodeGenFunction::EmitLoadOfLValue(LValue LV) {
assert(!LV.getType()->isFunctionType());
// Everything needs a load.
- return RValue::get(EmitLoadOfScalar(LV));
+ return RValue::get(EmitLoadOfScalar(LV, Loc));
}
if (LV.isVectorElt()) {
@@ -1420,7 +1347,8 @@ RValue CodeGenFunction::EmitLoadOfExtVectorElementLValue(LValue LV) {
/// EmitStoreThroughLValue - Store the specified rvalue into the specified
/// lvalue, where both are guaranteed to the have the same type, and that type
/// is 'Ty'.
-void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit) {
+void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
+ bool isInit) {
if (!Dst.isSimple()) {
if (Dst.isVectorElt()) {
// Read/modify/write the vector, inserting the new element.
@@ -1489,7 +1417,7 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit
llvm::Value *RHS = EmitScalarExpr(Dst.getBaseIvarExp());
llvm::Value *dst = RHS;
RHS = Builder.CreatePtrToInt(RHS, ResultType, "sub.ptr.rhs.cast");
- llvm::Value *LHS =
+ llvm::Value *LHS =
Builder.CreatePtrToInt(LvalueDst, ResultType, "sub.ptr.lhs.cast");
llvm::Value *BytesBetween = Builder.CreateSub(LHS, RHS, "ivar.offset");
CGM.getObjCRuntime().EmitObjCIvarAssign(*this, src, dst,
@@ -1625,6 +1553,12 @@ void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src,
for (unsigned i = 0; i != NumDstElts; ++i)
Mask.push_back(Builder.getInt32(i));
+ // When the vector size is odd and .odd or .hi is used, the last element
+ // of the Elts constant array will be one past the size of the vector.
+ // Ignore the last element here, if it is greater than the mask size.
+ if (getAccessedFieldNo(NumSrcElts - 1, Elts) == Mask.size())
+ NumSrcElts--;
+
// modify when what gets shuffled in
for (unsigned i = 0; i != NumSrcElts; ++i)
Mask[getAccessedFieldNo(i, Elts)] = Builder.getInt32(i+NumDstElts);
@@ -1654,12 +1588,12 @@ static void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E,
bool IsMemberAccess=false) {
if (Ctx.getLangOpts().getGC() == LangOptions::NonGC)
return;
-
+
if (isa<ObjCIvarRefExpr>(E)) {
QualType ExpTy = E->getType();
if (IsMemberAccess && ExpTy->isPointerType()) {
// If ivar is a structure pointer, assigning to field of
- // this struct follows gcc's behavior and makes it a non-ivar
+ // this struct follows gcc's behavior and makes it a non-ivar
// writer-barrier conservatively.
ExpTy = ExpTy->getAs<PointerType>()->getPointeeType();
if (ExpTy->isRecordType()) {
@@ -1673,7 +1607,7 @@ static void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E,
LV.setObjCArray(E->getType()->isArrayType());
return;
}
-
+
if (const DeclRefExpr *Exp = dyn_cast<DeclRefExpr>(E)) {
if (const VarDecl *VD = dyn_cast<VarDecl>(Exp->getDecl())) {
if (VD->hasGlobalStorage()) {
@@ -1684,12 +1618,12 @@ static void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E,
LV.setObjCArray(E->getType()->isArrayType());
return;
}
-
+
if (const UnaryOperator *Exp = dyn_cast<UnaryOperator>(E)) {
setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV, IsMemberAccess);
return;
}
-
+
if (const ParenExpr *Exp = dyn_cast<ParenExpr>(E)) {
setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV, IsMemberAccess);
if (LV.isObjCIvar()) {
@@ -1699,7 +1633,7 @@ static void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E,
if (ExpTy->isPointerType())
ExpTy = ExpTy->getAs<PointerType>()->getPointeeType();
if (ExpTy->isRecordType())
- LV.setObjCIvar(false);
+ LV.setObjCIvar(false);
}
return;
}
@@ -1713,7 +1647,7 @@ static void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E,
setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV, IsMemberAccess);
return;
}
-
+
if (const CStyleCastExpr *Exp = dyn_cast<CStyleCastExpr>(E)) {
setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV, IsMemberAccess);
return;
@@ -1726,12 +1660,12 @@ static void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E,
if (const ArraySubscriptExpr *Exp = dyn_cast<ArraySubscriptExpr>(E)) {
setObjCGCLValueClass(Ctx, Exp->getBase(), LV);
- if (LV.isObjCIvar() && !LV.isObjCArray())
- // Using array syntax to assigning to what an ivar points to is not
+ if (LV.isObjCIvar() && !LV.isObjCArray())
+ // Using array syntax to assigning to what an ivar points to is not
// same as assigning to the ivar itself. {id *Names;} Names[i] = 0;
- LV.setObjCIvar(false);
+ LV.setObjCIvar(false);
else if (LV.isGlobalObjCRef() && !LV.isObjCArray())
- // Using array syntax to assigning to what global points to is not
+ // Using array syntax to assigning to what global points to is not
// same as assigning to the global itself. {id *G;} G[i] = 0;
LV.setGlobalObjCRef(false);
return;
@@ -1793,6 +1727,13 @@ static LValue EmitFunctionDeclLValue(CodeGenFunction &CGF,
return CGF.MakeAddrLValue(V, E->getType(), Alignment);
}
+static LValue EmitCapturedFieldLValue(CodeGenFunction &CGF, const FieldDecl *FD,
+ llvm::Value *ThisValue) {
+ QualType TagType = CGF.getContext().getTagDeclType(FD->getParent());
+ LValue LV = CGF.MakeNaturalAlignAddrLValue(ThisValue, TagType);
+ return CGF.EmitLValueForField(LV, FD);
+}
+
LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
const NamedDecl *ND = E->getDecl();
CharUnits Alignment = getContext().getDeclAlign(ND);
@@ -1838,16 +1779,17 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
bool isBlockVariable = VD->hasAttr<BlocksAttr>();
llvm::Value *V = LocalDeclMap.lookup(VD);
- if (!V && VD->isStaticLocal())
+ if (!V && VD->isStaticLocal())
V = CGM.getStaticLocalDeclAddress(VD);
// Use special handling for lambdas.
if (!V) {
if (FieldDecl *FD = LambdaCaptureFields.lookup(VD)) {
- QualType LambdaTagType = getContext().getTagDeclType(FD->getParent());
- LValue LambdaLV = MakeNaturalAlignAddrLValue(CXXABIThisValue,
- LambdaTagType);
- return EmitLValueForField(LambdaLV, FD);
+ return EmitCapturedFieldLValue(*this, FD, CXXABIThisValue);
+ } else if (CapturedStmtInfo) {
+ if (const FieldDecl *FD = CapturedStmtInfo->lookup(VD))
+ return EmitCapturedFieldLValue(*this, FD,
+ CapturedStmtInfo->getContextValue());
}
assert(isa<BlockDecl>(CurCodeDecl) && E->refersToEnclosingLocal());
@@ -1888,8 +1830,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
return LV;
}
- if (const FunctionDecl *fn = dyn_cast<FunctionDecl>(ND))
- return EmitFunctionDeclLValue(*this, E, fn);
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND))
+ return EmitFunctionDeclLValue(*this, E, FD);
llvm_unreachable("Unhandled DeclRefExpr");
}
@@ -1945,7 +1887,7 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
case UO_PreDec: {
LValue LV = EmitLValue(E->getSubExpr());
bool isInc = E->getOpcode() == UO_PreInc;
-
+
if (E->getType()->isAnyComplexType())
EmitComplexPrePostIncDec(E, LV, isInc, true/*isPre*/);
else
@@ -2008,8 +1950,9 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
case PredefinedExpr::Func:
case PredefinedExpr::Function:
case PredefinedExpr::LFunction:
+ case PredefinedExpr::FuncDName:
case PredefinedExpr::PrettyFunction: {
- unsigned IdentType = E->getIdentType();
+ PredefinedExpr::IdentType IdentType = E->getIdentType();
std::string GlobalVarName;
switch (IdentType) {
@@ -2020,6 +1963,9 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
case PredefinedExpr::Function:
GlobalVarName = "__FUNCTION__.";
break;
+ case PredefinedExpr::FuncDName:
+ GlobalVarName = "__FUNCDNAME__.";
+ break;
case PredefinedExpr::LFunction:
GlobalVarName = "L__FUNCTION__.";
break;
@@ -2033,17 +1979,28 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
FnName = FnName.substr(1);
GlobalVarName += FnName;
+ // If this is outside of a function use the top level decl.
const Decl *CurDecl = CurCodeDecl;
- if (CurDecl == 0)
+ if (CurDecl == 0 || isa<VarDecl>(CurDecl))
CurDecl = getContext().getTranslationUnitDecl();
- std::string FunctionName =
- (isa<BlockDecl>(CurDecl)
- ? FnName.str()
- : PredefinedExpr::ComputeName((PredefinedExpr::IdentType)IdentType,
- CurDecl));
+ const Type *ElemType = E->getType()->getArrayElementTypeNoTypeQual();
+ std::string FunctionName;
+ if (isa<BlockDecl>(CurDecl)) {
+ // Blocks use the mangled function name.
+ // FIXME: ComputeName should handle blocks.
+ FunctionName = FnName.str();
+ } else if (isa<CapturedDecl>(CurDecl)) {
+ // For a captured statement, the function name is its enclosing
+ // function name not the one compiler generated.
+ FunctionName = PredefinedExpr::ComputeName(IdentType, CurDecl);
+ } else {
+ FunctionName = PredefinedExpr::ComputeName(IdentType, CurDecl);
+ assert(cast<ConstantArrayType>(E->getType())->getSize() - 1 ==
+ FunctionName.size() &&
+ "Computed __func__ length differs from type!");
+ }
- const Type* ElemType = E->getType()->getArrayElementTypeNoTypeQual();
llvm::Constant *C;
if (ElemType->isWideCharType()) {
SmallString<32> RawChars;
@@ -2076,7 +2033,10 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
/// followed by an array of i8 containing the type name. TypeKind is 0 for an
/// integer, 1 for a floating point value, and -1 for anything else.
llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) {
- // FIXME: Only emit each type's descriptor once.
+ // Only emit each type's descriptor once.
+ if (llvm::Constant *C = CGM.getTypeDescriptor(T))
+ return C;
+
uint16_t TypeKind = -1;
uint16_t TypeInfo = 0;
@@ -2109,6 +2069,10 @@ llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) {
llvm::GlobalVariable::PrivateLinkage,
Descriptor);
GV->setUnnamedAddr(true);
+
+ // Remember the descriptor for this type.
+ CGM.setTypeDescriptor(T, GV);
+
return GV;
}
@@ -2151,12 +2115,10 @@ llvm::Constant *CodeGenFunction::EmitCheckSourceLocation(SourceLocation Loc) {
PresumedLoc PLoc = getContext().getSourceManager().getPresumedLoc(Loc);
llvm::Constant *Data[] = {
- // FIXME: Only emit each file name once.
- PLoc.isValid() ? cast<llvm::Constant>(
- Builder.CreateGlobalStringPtr(PLoc.getFilename()))
+ PLoc.isValid() ? CGM.GetAddrOfConstantCString(PLoc.getFilename(), ".src")
: llvm::Constant::getNullValue(Int8PtrTy),
- Builder.getInt32(PLoc.getLine()),
- Builder.getInt32(PLoc.getColumn())
+ Builder.getInt32(PLoc.isValid() ? PLoc.getLine() : 0),
+ Builder.getInt32(PLoc.isValid() ? PLoc.getColumn() : 0)
};
return llvm::ConstantStruct::getAnon(Data);
@@ -2271,12 +2233,12 @@ static const Expr *isSimpleArrayDecayOperand(const Expr *E) {
const CastExpr *CE = dyn_cast<CastExpr>(E);
if (CE == 0 || CE->getCastKind() != CK_ArrayToPointerDecay)
return 0;
-
+
// If this is a decay from variable width array, bail out.
const Expr *SubExpr = CE->getSubExpr();
if (SubExpr->getType()->isVariableArrayType())
return 0;
-
+
return SubExpr;
}
@@ -2287,7 +2249,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
QualType IdxTy = E->getIdx()->getType();
bool IdxSigned = IdxTy->isSignedIntegerOrEnumerationType();
- if (SanOpts->Bounds)
+ if (SanOpts->ArrayBounds)
EmitBoundsCheck(E, E->getBase(), Idx, IdxTy, Accessed);
// If the base is a vector type, then we are forming a vector element lvalue
@@ -2360,7 +2322,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
llvm::Value *ArrayPtr = ArrayLV.getAddress();
llvm::Value *Zero = llvm::ConstantInt::get(Int32Ty, 0);
llvm::Value *Args[] = { Zero, Idx };
-
+
// Propagate the alignment from the array itself to the result.
ArrayAlignment = ArrayLV.getAlignment();
@@ -2381,7 +2343,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
assert(!T.isNull() &&
"CodeGenFunction::EmitArraySubscriptExpr(): Illegal base type");
-
+
// Limit the alignment to that of the result type.
LValue LV;
if (!ArrayAlignment.isZero()) {
@@ -2404,7 +2366,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
static
llvm::Constant *GenerateConstantVector(CGBuilderTy &Builder,
- SmallVector<unsigned, 4> &Elts) {
+ SmallVectorImpl<unsigned> &Elts) {
SmallVector<llvm::Constant*, 4> CElts;
for (unsigned i = 0, e = Elts.size(); i != e; ++i)
CElts.push_back(Builder.getInt32(Elts[i]));
@@ -2435,7 +2397,7 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
assert(E->getBase()->getType()->isVectorType() &&
"Result must be a vector");
llvm::Value *Vec = EmitScalarExpr(E->getBase());
-
+
// Store the vector to memory (because LValue wants an address).
llvm::Value *VecMem = CreateMemTemp(E->getBase()->getType());
Builder.CreateStore(Vec, VecMem);
@@ -2444,7 +2406,7 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
QualType type =
E->getType().withCVRQualifiers(Base.getQuals().getCVRQualifiers());
-
+
// Encode the element access list into a vector of unsigned indices.
SmallVector<unsigned, 4> Indices;
E->getEncodedElementAccess(Indices);
@@ -2485,7 +2447,7 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
setObjCGCLValueClass(getContext(), E, LV);
return LV;
}
-
+
if (VarDecl *VD = dyn_cast<VarDecl>(ND))
return EmitGlobalVarDeclLValue(*this, E, VD);
@@ -2567,7 +2529,8 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
tbaa = CGM.getTBAAInfo(getContext().CharTy);
else
tbaa = CGM.getTBAAInfo(type);
- CGM.DecorateInstruction(load, tbaa);
+ if (tbaa)
+ CGM.DecorateInstruction(load, tbaa);
}
addr = load;
@@ -2580,7 +2543,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
cvr = 0; // qualifiers don't recursively apply to referencee
}
}
-
+
// Make sure that the address is pointing to the right type. This is critical
// for both unions and structs. A union needs a bitcast, a struct element
// will need a bitcast if the LLVM type laid out doesn't match the desired
@@ -2618,11 +2581,11 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
return LV;
}
-LValue
-CodeGenFunction::EmitLValueForFieldInitialization(LValue Base,
+LValue
+CodeGenFunction::EmitLValueForFieldInitialization(LValue Base,
const FieldDecl *Field) {
QualType FieldType = Field->getType();
-
+
if (!FieldType->isReferenceType())
return EmitLValueForField(Base, Field);
@@ -2657,7 +2620,7 @@ LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr *E){
if (E->getType()->isVariablyModifiedType())
// make sure to emit the VLA size.
EmitVariablyModifiedType(E->getType());
-
+
llvm::Value *DeclPtr = CreateMemTemp(E->getType(), ".compoundliteral");
const Expr *InitExpr = E->getInitializer();
LValue Result = MakeAddrLValue(DeclPtr, E->getType());
@@ -2705,19 +2668,19 @@ EmitConditionalOperatorLValue(const AbstractConditionalOperator *expr) {
ConditionalEvaluation eval(*this);
EmitBranchOnBoolExpr(condExpr, lhsBlock, rhsBlock);
-
+
// Any temporaries created here are conditional.
EmitBlock(lhsBlock);
eval.begin(*this);
LValue lhs = EmitLValue(expr->getTrueExpr());
eval.end(*this);
-
+
if (!lhs.isSimple())
return EmitUnsupportedLValue(expr, "conditional operator");
lhsBlock = Builder.GetInsertBlock();
Builder.CreateBr(contBlock);
-
+
// Any temporaries created here are conditional.
EmitBlock(rhsBlock);
eval.begin(*this);
@@ -2746,26 +2709,6 @@ EmitConditionalOperatorLValue(const AbstractConditionalOperator *expr) {
LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
switch (E->getCastKind()) {
case CK_ToVoid:
- return EmitUnsupportedLValue(E, "unexpected cast lvalue");
-
- case CK_Dependent:
- llvm_unreachable("dependent cast kind in IR gen!");
-
- case CK_BuiltinFnToFnPtr:
- llvm_unreachable("builtin functions are handled elsewhere");
-
- // These two casts are currently treated as no-ops, although they could
- // potentially be real operations depending on the target's ABI.
- case CK_NonAtomicToAtomic:
- case CK_AtomicToNonAtomic:
-
- case CK_NoOp:
- case CK_LValueToRValue:
- if (!E->getSubExpr()->Classify(getContext()).isPRValue()
- || E->getType()->isRecordType())
- return EmitLValue(E->getSubExpr());
- // Fall through to synthesize a temporary.
-
case CK_BitCast:
case CK_ArrayToPointerDecay:
case CK_FunctionToPointerDecay:
@@ -2799,16 +2742,20 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
case CK_ARCProduceObject:
case CK_ARCConsumeObject:
case CK_ARCReclaimReturnedObject:
- case CK_ARCExtendBlockObject:
- case CK_CopyAndAutoreleaseBlockObject: {
- // These casts only produce lvalues when we're binding a reference to a
- // temporary realized from a (converted) pure rvalue. Emit the expression
- // as a value, copy it into a temporary, and return an lvalue referring to
- // that temporary.
- llvm::Value *V = CreateMemTemp(E->getType(), "ref.temp");
- EmitAnyExprToMem(E, V, E->getType().getQualifiers(), false);
- return MakeAddrLValue(V, E->getType());
- }
+ case CK_ARCExtendBlockObject:
+ case CK_CopyAndAutoreleaseBlockObject:
+ return EmitUnsupportedLValue(E, "unexpected cast lvalue");
+
+ case CK_Dependent:
+ llvm_unreachable("dependent cast kind in IR gen!");
+
+ case CK_BuiltinFnToFnPtr:
+ llvm_unreachable("builtin functions are handled elsewhere");
+
+ // These are never l-values; just use the aggregate emission code.
+ case CK_NonAtomicToAtomic:
+ case CK_AtomicToNonAtomic:
+ return EmitAggExprToLValue(E);
case CK_Dynamic: {
LValue LV = EmitLValue(E->getSubExpr());
@@ -2821,53 +2768,55 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
case CK_UserDefinedConversion:
case CK_CPointerToObjCPointerCast:
case CK_BlockPointerToObjCPointerCast:
+ case CK_NoOp:
+ case CK_LValueToRValue:
return EmitLValue(E->getSubExpr());
-
+
case CK_UncheckedDerivedToBase:
case CK_DerivedToBase: {
- const RecordType *DerivedClassTy =
+ const RecordType *DerivedClassTy =
E->getSubExpr()->getType()->getAs<RecordType>();
- CXXRecordDecl *DerivedClassDecl =
+ CXXRecordDecl *DerivedClassDecl =
cast<CXXRecordDecl>(DerivedClassTy->getDecl());
-
+
LValue LV = EmitLValue(E->getSubExpr());
llvm::Value *This = LV.getAddress();
-
+
// Perform the derived-to-base conversion
- llvm::Value *Base =
- GetAddressOfBaseClass(This, DerivedClassDecl,
+ llvm::Value *Base =
+ GetAddressOfBaseClass(This, DerivedClassDecl,
E->path_begin(), E->path_end(),
/*NullCheckValue=*/false);
-
+
return MakeAddrLValue(Base, E->getType());
}
case CK_ToUnion:
return EmitAggExprToLValue(E);
case CK_BaseToDerived: {
const RecordType *DerivedClassTy = E->getType()->getAs<RecordType>();
- CXXRecordDecl *DerivedClassDecl =
+ CXXRecordDecl *DerivedClassDecl =
cast<CXXRecordDecl>(DerivedClassTy->getDecl());
-
+
LValue LV = EmitLValue(E->getSubExpr());
+ // Perform the base-to-derived conversion
+ llvm::Value *Derived =
+ GetAddressOfDerivedClass(LV.getAddress(), DerivedClassDecl,
+ E->path_begin(), E->path_end(),
+ /*NullCheckValue=*/false);
+
// C++11 [expr.static.cast]p2: Behavior is undefined if a downcast is
// performed and the object is not of the derived type.
if (SanitizePerformTypeCheck)
EmitTypeCheck(TCK_DowncastReference, E->getExprLoc(),
- LV.getAddress(), E->getType());
+ Derived, E->getType());
- // Perform the base-to-derived conversion
- llvm::Value *Derived =
- GetAddressOfDerivedClass(LV.getAddress(), DerivedClassDecl,
- E->path_begin(), E->path_end(),
- /*NullCheckValue=*/false);
-
return MakeAddrLValue(Derived, E->getType());
}
case CK_LValueBitCast: {
// This must be a reinterpret_cast (or c-style equivalent).
const ExplicitCastExpr *CE = cast<ExplicitCastExpr>(E);
-
+
LValue LV = EmitLValue(E->getSubExpr());
llvm::Value *V = Builder.CreateBitCast(LV.getAddress(),
ConvertType(CE->getTypeAsWritten()));
@@ -2876,23 +2825,15 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
case CK_ObjCObjectLValueCast: {
LValue LV = EmitLValue(E->getSubExpr());
QualType ToType = getContext().getLValueReferenceType(E->getType());
- llvm::Value *V = Builder.CreateBitCast(LV.getAddress(),
+ llvm::Value *V = Builder.CreateBitCast(LV.getAddress(),
ConvertType(ToType));
return MakeAddrLValue(V, E->getType());
}
case CK_ZeroToOCLEvent:
llvm_unreachable("NULL to OpenCL event lvalue cast is not valid");
}
-
- llvm_unreachable("Unhandled lvalue cast kind?");
-}
-LValue CodeGenFunction::EmitNullInitializationLValue(
- const CXXScalarValueInitExpr *E) {
- QualType Ty = E->getType();
- LValue LV = MakeAddrLValue(CreateMemTemp(Ty), Ty);
- EmitNullInitialization(LV.getAddress(), Ty);
- return LV;
+ llvm_unreachable("Unhandled lvalue cast kind?");
}
LValue CodeGenFunction::EmitOpaqueValueLValue(const OpaqueValueExpr *e) {
@@ -2900,23 +2841,18 @@ LValue CodeGenFunction::EmitOpaqueValueLValue(const OpaqueValueExpr *e) {
return getOpaqueLValueMapping(e);
}
-LValue CodeGenFunction::EmitMaterializeTemporaryExpr(
- const MaterializeTemporaryExpr *E) {
- RValue RV = EmitReferenceBindingToExpr(E, /*InitializedDecl=*/0);
- return MakeAddrLValue(RV.getScalarVal(), E->getType());
-}
-
RValue CodeGenFunction::EmitRValueForField(LValue LV,
- const FieldDecl *FD) {
+ const FieldDecl *FD,
+ SourceLocation Loc) {
QualType FT = FD->getType();
LValue FieldLV = EmitLValueForField(LV, FD);
switch (getEvaluationKind(FT)) {
case TEK_Complex:
- return RValue::getComplex(EmitLoadOfComplex(FieldLV));
+ return RValue::getComplex(EmitLoadOfComplex(FieldLV, Loc));
case TEK_Aggregate:
return FieldLV.asAggregateRValue();
case TEK_Scalar:
- return EmitLoadOfLValue(FieldLV);
+ return EmitLoadOfLValue(FieldLV, Loc);
}
llvm_unreachable("bad evaluation kind");
}
@@ -2925,7 +2861,7 @@ RValue CodeGenFunction::EmitRValueForField(LValue LV,
// Expression Emission
//===--------------------------------------------------------------------===//
-RValue CodeGenFunction::EmitCallExpr(const CallExpr *E,
+RValue CodeGenFunction::EmitCallExpr(const CallExpr *E,
ReturnValueSlot ReturnValue) {
if (CGDebugInfo *DI = getDebugInfo()) {
SourceLocation Loc = E->getLocStart();
@@ -2956,7 +2892,7 @@ RValue CodeGenFunction::EmitCallExpr(const CallExpr *E,
if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(TargetDecl))
return EmitCXXOperatorMemberCallExpr(CE, MD, ReturnValue);
- if (const CXXPseudoDestructorExpr *PseudoDtor
+ if (const CXXPseudoDestructorExpr *PseudoDtor
= dyn_cast<CXXPseudoDestructorExpr>(E->getCallee()->IgnoreParens())) {
QualType DestroyedType = PseudoDtor->getDestroyedType();
if (getLangOpts().ObjCAutoRefCount &&
@@ -2969,7 +2905,7 @@ RValue CodeGenFunction::EmitCallExpr(const CallExpr *E,
Expr *BaseExpr = PseudoDtor->getBase();
llvm::Value *BaseValue = NULL;
Qualifiers BaseQuals;
-
+
// If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar.
if (PseudoDtor->isArrow()) {
BaseValue = EmitScalarExpr(BaseExpr);
@@ -2981,15 +2917,15 @@ RValue CodeGenFunction::EmitCallExpr(const CallExpr *E,
QualType BaseTy = BaseExpr->getType();
BaseQuals = BaseTy.getQualifiers();
}
-
+
switch (PseudoDtor->getDestroyedType().getObjCLifetime()) {
case Qualifiers::OCL_None:
case Qualifiers::OCL_ExplicitNone:
case Qualifiers::OCL_Autoreleasing:
break;
-
+
case Qualifiers::OCL_Strong:
- EmitARCRelease(Builder.CreateLoad(BaseValue,
+ EmitARCRelease(Builder.CreateLoad(BaseValue,
PseudoDtor->getDestroyedType().isVolatileQualified()),
ARCPreciseLifetime);
break;
@@ -3003,16 +2939,16 @@ RValue CodeGenFunction::EmitCallExpr(const CallExpr *E,
// The result shall only be used as the operand for the function call
// operator (), and the result of such a call has type void. The only
// effect is the evaluation of the postfix-expression before the dot or
- // arrow.
+ // arrow.
EmitScalarExpr(E->getCallee());
}
-
+
return RValue::get(0);
}
llvm::Value *Callee = EmitScalarExpr(E->getCallee());
- return EmitCall(E->getCallee()->getType(), Callee, ReturnValue,
- E->arg_begin(), E->arg_end(), TargetDecl);
+ return EmitCall(E->getCallee()->getType(), Callee, E->getLocStart(),
+ ReturnValue, E->arg_begin(), E->arg_end(), TargetDecl);
}
LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) {
@@ -3068,7 +3004,7 @@ LValue CodeGenFunction::EmitCallExprLValue(const CallExpr *E) {
if (!RV.isScalar())
return MakeAddrLValue(RV.getAggregateAddr(), E->getType());
-
+
assert(E->getCallReturnType()->isReferenceType() &&
"Can't have a scalar return unless the return type is a "
"reference type!");
@@ -3095,7 +3031,8 @@ CodeGenFunction::EmitCXXTypeidLValue(const CXXTypeidExpr *E) {
}
llvm::Value *CodeGenFunction::EmitCXXUuidofExpr(const CXXUuidofExpr *E) {
- return CGM.GetAddrOfUuidDescriptor(E);
+ return Builder.CreateBitCast(CGM.GetAddrOfUuidDescriptor(E),
+ ConvertType(E->getType())->getPointerTo());
}
LValue CodeGenFunction::EmitCXXUuidofLValue(const CXXUuidofExpr *E) {
@@ -3120,19 +3057,19 @@ CodeGenFunction::EmitLambdaLValue(const LambdaExpr *E) {
LValue CodeGenFunction::EmitObjCMessageExprLValue(const ObjCMessageExpr *E) {
RValue RV = EmitObjCMessageExpr(E);
-
+
if (!RV.isScalar())
return MakeAddrLValue(RV.getAggregateAddr(), E->getType());
-
+
assert(E->getMethodDecl()->getResultType()->isReferenceType() &&
"Can't have a scalar return unless the return type is a "
"reference type!");
-
+
return MakeAddrLValue(RV.getScalarVal(), E->getType());
}
LValue CodeGenFunction::EmitObjCSelectorLValue(const ObjCSelectorExpr *E) {
- llvm::Value *V =
+ llvm::Value *V =
CGM.getObjCRuntime().GetSelector(*this, E->getSelector(), true);
return MakeAddrLValue(V, E->getType());
}
@@ -3168,7 +3105,7 @@ LValue CodeGenFunction::EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E) {
BaseQuals = ObjectTy.getQualifiers();
}
- LValue LV =
+ LValue LV =
EmitLValueForIvar(ObjectTy, BaseValue, E->getDecl(),
BaseQuals.getCVRQualifiers());
setObjCGCLValueClass(getContext(), E, LV);
@@ -3182,6 +3119,7 @@ LValue CodeGenFunction::EmitStmtExprLValue(const StmtExpr *E) {
}
RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
+ SourceLocation CallLoc,
ReturnValueSlot ReturnValue,
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd,
@@ -3196,8 +3134,60 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
const FunctionType *FnType
= cast<FunctionType>(cast<PointerType>(CalleeType)->getPointeeType());
+ // Force column info to differentiate multiple inlined call sites on
+ // the same line, analoguous to EmitCallExpr.
+ bool ForceColumnInfo = false;
+ if (const FunctionDecl* FD = dyn_cast_or_null<const FunctionDecl>(TargetDecl))
+ ForceColumnInfo = FD->isInlineSpecified();
+
+ if (getLangOpts().CPlusPlus && SanOpts->Function &&
+ (!TargetDecl || !isa<FunctionDecl>(TargetDecl))) {
+ if (llvm::Constant *PrefixSig =
+ CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM)) {
+ llvm::Constant *FTRTTIConst =
+ CGM.GetAddrOfRTTIDescriptor(QualType(FnType, 0), /*ForEH=*/true);
+ llvm::Type *PrefixStructTyElems[] = {
+ PrefixSig->getType(),
+ FTRTTIConst->getType()
+ };
+ llvm::StructType *PrefixStructTy = llvm::StructType::get(
+ CGM.getLLVMContext(), PrefixStructTyElems, /*isPacked=*/true);
+
+ llvm::Value *CalleePrefixStruct = Builder.CreateBitCast(
+ Callee, llvm::PointerType::getUnqual(PrefixStructTy));
+ llvm::Value *CalleeSigPtr =
+ Builder.CreateConstGEP2_32(CalleePrefixStruct, 0, 0);
+ llvm::Value *CalleeSig = Builder.CreateLoad(CalleeSigPtr);
+ llvm::Value *CalleeSigMatch = Builder.CreateICmpEQ(CalleeSig, PrefixSig);
+
+ llvm::BasicBlock *Cont = createBasicBlock("cont");
+ llvm::BasicBlock *TypeCheck = createBasicBlock("typecheck");
+ Builder.CreateCondBr(CalleeSigMatch, TypeCheck, Cont);
+
+ EmitBlock(TypeCheck);
+ llvm::Value *CalleeRTTIPtr =
+ Builder.CreateConstGEP2_32(CalleePrefixStruct, 0, 1);
+ llvm::Value *CalleeRTTI = Builder.CreateLoad(CalleeRTTIPtr);
+ llvm::Value *CalleeRTTIMatch =
+ Builder.CreateICmpEQ(CalleeRTTI, FTRTTIConst);
+ llvm::Constant *StaticData[] = {
+ EmitCheckSourceLocation(CallLoc),
+ EmitCheckTypeDescriptor(CalleeType)
+ };
+ EmitCheck(CalleeRTTIMatch,
+ "function_type_mismatch",
+ StaticData,
+ Callee,
+ CRK_Recoverable);
+
+ Builder.CreateBr(Cont);
+ EmitBlock(Cont);
+ }
+ }
+
CallArgList Args;
- EmitCallArgs(Args, dyn_cast<FunctionProtoType>(FnType), ArgBeg, ArgEnd);
+ EmitCallArgs(Args, dyn_cast<FunctionProtoType>(FnType), ArgBeg, ArgEnd,
+ ForceColumnInfo);
const CGFunctionInfo &FnInfo =
CGM.getTypes().arrangeFreeFunctionCall(Args, FnType);
@@ -3250,15 +3240,16 @@ EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E) {
/// Given the address of a temporary variable, produce an r-value of
/// its type.
RValue CodeGenFunction::convertTempToRValue(llvm::Value *addr,
- QualType type) {
+ QualType type,
+ SourceLocation loc) {
LValue lvalue = MakeNaturalAlignAddrLValue(addr, type);
switch (getEvaluationKind(type)) {
case TEK_Complex:
- return RValue::getComplex(EmitLoadOfComplex(lvalue));
+ return RValue::getComplex(EmitLoadOfComplex(lvalue, loc));
case TEK_Aggregate:
return lvalue.asAggregateRValue();
case TEK_Scalar:
- return RValue::get(EmitLoadOfScalar(lvalue));
+ return RValue::get(EmitLoadOfScalar(lvalue, loc));
}
llvm_unreachable("bad evaluation kind");
}
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index b974e1d..9d0f3a9 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -29,14 +29,6 @@ using namespace CodeGen;
// Aggregate Expression Emitter
//===----------------------------------------------------------------------===//
-llvm::Value *AggValueSlot::getPaddedAtomicAddr() const {
- assert(isValueOfAtomic());
- llvm::GEPOperator *op = cast<llvm::GEPOperator>(getAddr());
- assert(op->getNumIndices() == 2);
- assert(op->hasAllZeroIndices());
- return op->getPointerOperand();
-}
-
namespace {
class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
CodeGenFunction &CGF;
@@ -91,7 +83,6 @@ public:
void EmitMoveFromReturnSlot(const Expr *E, RValue Src);
- void EmitStdInitializerList(llvm::Value *DestPtr, InitListExpr *InitList);
void EmitArrayInit(llvm::Value *DestPtr, llvm::ArrayType *AType,
QualType elementType, InitListExpr *E);
@@ -177,6 +168,7 @@ public:
void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E);
void VisitCXXConstructExpr(const CXXConstructExpr *E);
void VisitLambdaExpr(LambdaExpr *E);
+ void VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E);
void VisitExprWithCleanups(ExprWithCleanups *E);
void VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E);
void VisitCXXTypeidExpr(CXXTypeidExpr *E) { EmitAggLoadOfLValue(E); }
@@ -202,38 +194,6 @@ public:
CGF.EmitAtomicExpr(E, EnsureSlot(E->getType()).getAddr());
}
};
-
-/// A helper class for emitting expressions into the value sub-object
-/// of a padded atomic type.
-class ValueDestForAtomic {
- AggValueSlot Dest;
-public:
- ValueDestForAtomic(CodeGenFunction &CGF, AggValueSlot dest, QualType type)
- : Dest(dest) {
- assert(!Dest.isValueOfAtomic());
- if (!Dest.isIgnored() && CGF.CGM.isPaddedAtomicType(type)) {
- llvm::Value *valueAddr = CGF.Builder.CreateStructGEP(Dest.getAddr(), 0);
- Dest = AggValueSlot::forAddr(valueAddr,
- Dest.getAlignment(),
- Dest.getQualifiers(),
- Dest.isExternallyDestructed(),
- Dest.requiresGCollection(),
- Dest.isPotentiallyAliased(),
- Dest.isZeroed(),
- AggValueSlot::IsValueOfAtomic);
- }
- }
-
- const AggValueSlot &getDest() const { return Dest; }
-
- ~ValueDestForAtomic() {
- // Kill the GEP if we made one and it didn't end up used.
- if (Dest.isValueOfAtomic()) {
- llvm::Instruction *addr = cast<llvm::GetElementPtrInst>(Dest.getAddr());
- if (addr->use_empty()) addr->eraseFromParent();
- }
- }
-};
} // end anonymous namespace.
//===----------------------------------------------------------------------===//
@@ -248,8 +208,7 @@ void AggExprEmitter::EmitAggLoadOfLValue(const Expr *E) {
// If the type of the l-value is atomic, then do an atomic load.
if (LV.getType()->isAtomicType()) {
- ValueDestForAtomic valueDest(CGF, Dest, LV.getType());
- CGF.EmitAtomicLoad(LV, valueDest.getDest());
+ CGF.EmitAtomicLoad(LV, E->getExprLoc(), Dest);
return;
}
@@ -345,89 +304,70 @@ void AggExprEmitter::EmitCopy(QualType type, const AggValueSlot &dest,
std::min(dest.getAlignment(), src.getAlignment()));
}
-static QualType GetStdInitializerListElementType(QualType T) {
- // Just assume that this is really std::initializer_list.
- ClassTemplateSpecializationDecl *specialization =
- cast<ClassTemplateSpecializationDecl>(T->castAs<RecordType>()->getDecl());
- return specialization->getTemplateArgs()[0].getAsType();
-}
-
-/// \brief Prepare cleanup for the temporary array.
-static void EmitStdInitializerListCleanup(CodeGenFunction &CGF,
- QualType arrayType,
- llvm::Value *addr,
- const InitListExpr *initList) {
- QualType::DestructionKind dtorKind = arrayType.isDestructedType();
- if (!dtorKind)
- return; // Type doesn't need destroying.
- if (dtorKind != QualType::DK_cxx_destructor) {
- CGF.ErrorUnsupported(initList, "ObjC ARC type in initializer_list");
- return;
- }
-
- CodeGenFunction::Destroyer *destroyer = CGF.getDestroyer(dtorKind);
- CGF.pushDestroy(NormalAndEHCleanup, addr, arrayType, destroyer,
- /*EHCleanup=*/true);
-}
-
/// \brief Emit the initializer for a std::initializer_list initialized with a
/// real initializer list.
-void AggExprEmitter::EmitStdInitializerList(llvm::Value *destPtr,
- InitListExpr *initList) {
- // We emit an array containing the elements, then have the init list point
- // at the array.
- ASTContext &ctx = CGF.getContext();
- unsigned numInits = initList->getNumInits();
- QualType element = GetStdInitializerListElementType(initList->getType());
- llvm::APInt size(ctx.getTypeSize(ctx.getSizeType()), numInits);
- QualType array = ctx.getConstantArrayType(element, size, ArrayType::Normal,0);
- llvm::Type *LTy = CGF.ConvertTypeForMem(array);
- llvm::AllocaInst *alloc = CGF.CreateTempAlloca(LTy);
- alloc->setAlignment(ctx.getTypeAlignInChars(array).getQuantity());
- alloc->setName(".initlist.");
-
- EmitArrayInit(alloc, cast<llvm::ArrayType>(LTy), element, initList);
-
- // FIXME: The diagnostics are somewhat out of place here.
- RecordDecl *record = initList->getType()->castAs<RecordType>()->getDecl();
- RecordDecl::field_iterator field = record->field_begin();
- if (field == record->field_end()) {
- CGF.ErrorUnsupported(initList, "weird std::initializer_list");
+void
+AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) {
+ // Emit an array containing the elements. The array is externally destructed
+ // if the std::initializer_list object is.
+ ASTContext &Ctx = CGF.getContext();
+ LValue Array = CGF.EmitLValue(E->getSubExpr());
+ assert(Array.isSimple() && "initializer_list array not a simple lvalue");
+ llvm::Value *ArrayPtr = Array.getAddress();
+
+ const ConstantArrayType *ArrayType =
+ Ctx.getAsConstantArrayType(E->getSubExpr()->getType());
+ assert(ArrayType && "std::initializer_list constructed from non-array");
+
+ // FIXME: Perform the checks on the field types in SemaInit.
+ RecordDecl *Record = E->getType()->castAs<RecordType>()->getDecl();
+ RecordDecl::field_iterator Field = Record->field_begin();
+ if (Field == Record->field_end()) {
+ CGF.ErrorUnsupported(E, "weird std::initializer_list");
return;
}
- QualType elementPtr = ctx.getPointerType(element.withConst());
-
// Start pointer.
- if (!ctx.hasSameType(field->getType(), elementPtr)) {
- CGF.ErrorUnsupported(initList, "weird std::initializer_list");
+ if (!Field->getType()->isPointerType() ||
+ !Ctx.hasSameType(Field->getType()->getPointeeType(),
+ ArrayType->getElementType())) {
+ CGF.ErrorUnsupported(E, "weird std::initializer_list");
return;
}
- LValue DestLV = CGF.MakeNaturalAlignAddrLValue(destPtr, initList->getType());
- LValue start = CGF.EmitLValueForFieldInitialization(DestLV, *field);
- llvm::Value *arrayStart = Builder.CreateStructGEP(alloc, 0, "arraystart");
- CGF.EmitStoreThroughLValue(RValue::get(arrayStart), start);
- ++field;
-
- if (field == record->field_end()) {
- CGF.ErrorUnsupported(initList, "weird std::initializer_list");
+
+ AggValueSlot Dest = EnsureSlot(E->getType());
+ LValue DestLV = CGF.MakeAddrLValue(Dest.getAddr(), E->getType(),
+ Dest.getAlignment());
+ LValue Start = CGF.EmitLValueForFieldInitialization(DestLV, *Field);
+ llvm::Value *Zero = llvm::ConstantInt::get(CGF.PtrDiffTy, 0);
+ llvm::Value *IdxStart[] = { Zero, Zero };
+ llvm::Value *ArrayStart =
+ Builder.CreateInBoundsGEP(ArrayPtr, IdxStart, "arraystart");
+ CGF.EmitStoreThroughLValue(RValue::get(ArrayStart), Start);
+ ++Field;
+
+ if (Field == Record->field_end()) {
+ CGF.ErrorUnsupported(E, "weird std::initializer_list");
return;
}
- LValue endOrLength = CGF.EmitLValueForFieldInitialization(DestLV, *field);
- if (ctx.hasSameType(field->getType(), elementPtr)) {
+
+ llvm::Value *Size = Builder.getInt(ArrayType->getSize());
+ LValue EndOrLength = CGF.EmitLValueForFieldInitialization(DestLV, *Field);
+ if (Field->getType()->isPointerType() &&
+ Ctx.hasSameType(Field->getType()->getPointeeType(),
+ ArrayType->getElementType())) {
// End pointer.
- llvm::Value *arrayEnd = Builder.CreateStructGEP(alloc,numInits, "arrayend");
- CGF.EmitStoreThroughLValue(RValue::get(arrayEnd), endOrLength);
- } else if(ctx.hasSameType(field->getType(), ctx.getSizeType())) {
+ llvm::Value *IdxEnd[] = { Zero, Size };
+ llvm::Value *ArrayEnd =
+ Builder.CreateInBoundsGEP(ArrayPtr, IdxEnd, "arrayend");
+ CGF.EmitStoreThroughLValue(RValue::get(ArrayEnd), EndOrLength);
+ } else if (Ctx.hasSameType(Field->getType(), Ctx.getSizeType())) {
// Length.
- CGF.EmitStoreThroughLValue(RValue::get(Builder.getInt(size)), endOrLength);
+ CGF.EmitStoreThroughLValue(RValue::get(Size), EndOrLength);
} else {
- CGF.ErrorUnsupported(initList, "weird std::initializer_list");
+ CGF.ErrorUnsupported(E, "weird std::initializer_list");
return;
}
-
- if (!Dest.isExternallyDestructed())
- EmitStdInitializerListCleanup(CGF, array, alloc, initList);
}
/// \brief Emit initialization of an array from an initializer list.
@@ -490,15 +430,8 @@ void AggExprEmitter::EmitArrayInit(llvm::Value *DestPtr, llvm::ArrayType *AType,
if (endOfInit) Builder.CreateStore(element, endOfInit);
}
- // If these are nested std::initializer_list inits, do them directly,
- // because they are conceptually the same "location".
- InitListExpr *initList = dyn_cast<InitListExpr>(E->getInit(i));
- if (initList && initList->initializesStdInitializerList()) {
- EmitStdInitializerList(element, initList);
- } else {
- LValue elementLV = CGF.MakeAddrLValue(element, elementType);
- EmitInitializationToLValue(E->getInit(i), elementLV);
- }
+ LValue elementLV = CGF.MakeAddrLValue(element, elementType);
+ EmitInitializationToLValue(E->getInit(i), elementLV);
}
// Check whether there's a non-trivial array-fill expression.
@@ -679,34 +612,33 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
}
// If we're converting an r-value of non-atomic type to an r-value
- // of atomic type, just make an atomic temporary, emit into that,
- // and then copy the value out. (FIXME: do we need to
- // zero-initialize it first?)
+ // of atomic type, just emit directly into the relevant sub-object.
if (isToAtomic) {
- ValueDestForAtomic valueDest(CGF, Dest, atomicType);
- CGF.EmitAggExpr(E->getSubExpr(), valueDest.getDest());
+ AggValueSlot valueDest = Dest;
+ if (!valueDest.isIgnored() && CGF.CGM.isPaddedAtomicType(atomicType)) {
+ // Zero-initialize. (Strictly speaking, we only need to intialize
+ // the padding at the end, but this is simpler.)
+ if (!Dest.isZeroed())
+ CGF.EmitNullInitialization(Dest.getAddr(), atomicType);
+
+ // Build a GEP to refer to the subobject.
+ llvm::Value *valueAddr =
+ CGF.Builder.CreateStructGEP(valueDest.getAddr(), 0);
+ valueDest = AggValueSlot::forAddr(valueAddr,
+ valueDest.getAlignment(),
+ valueDest.getQualifiers(),
+ valueDest.isExternallyDestructed(),
+ valueDest.requiresGCollection(),
+ valueDest.isPotentiallyAliased(),
+ AggValueSlot::IsZeroed);
+ }
+
+ CGF.EmitAggExpr(E->getSubExpr(), valueDest);
return;
}
// Otherwise, we're converting an atomic type to a non-atomic type.
-
- // If the dest is a value-of-atomic subobject, drill back out.
- if (Dest.isValueOfAtomic()) {
- AggValueSlot atomicSlot =
- AggValueSlot::forAddr(Dest.getPaddedAtomicAddr(),
- Dest.getAlignment(),
- Dest.getQualifiers(),
- Dest.isExternallyDestructed(),
- Dest.requiresGCollection(),
- Dest.isPotentiallyAliased(),
- Dest.isZeroed(),
- AggValueSlot::IsNotValueOfAtomic);
- CGF.EmitAggExpr(E->getSubExpr(), atomicSlot);
- return;
- }
-
- // Otherwise, make an atomic temporary, emit into that, and then
- // copy the value out.
+ // Make an atomic temporary, emit into that, and then copy the value out.
AggValueSlot atomicSlot =
CGF.CreateAggTemp(atomicType, "atomic-to-nonatomic.temp");
CGF.EmitAggExpr(E->getSubExpr(), atomicSlot);
@@ -988,7 +920,7 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
}
void AggExprEmitter::VisitChooseExpr(const ChooseExpr *CE) {
- Visit(CE->getChosenSubExpr(CGF.getContext()));
+ Visit(CE->getChosenSubExpr());
}
void AggExprEmitter::VisitVAArgExpr(VAArgExpr *VE) {
@@ -1078,7 +1010,7 @@ static bool isSimpleZero(const Expr *E, CodeGenFunction &CGF) {
void
-AggExprEmitter::EmitInitializationToLValue(Expr* E, LValue LV) {
+AggExprEmitter::EmitInitializationToLValue(Expr *E, LValue LV) {
QualType type = LV.getType();
// FIXME: Ignore result?
// FIXME: Are initializers affected by volatile?
@@ -1088,7 +1020,7 @@ AggExprEmitter::EmitInitializationToLValue(Expr* E, LValue LV) {
} else if (isa<ImplicitValueInitExpr>(E) || isa<CXXScalarValueInitExpr>(E)) {
return EmitNullInitializationToLValue(LV);
} else if (type->isReferenceType()) {
- RValue RV = CGF.EmitReferenceBindingToExpr(E, /*InitializedDecl=*/0);
+ RValue RV = CGF.EmitReferenceBindingToExpr(E);
return CGF.EmitStoreThroughLValue(RV, LV);
}
@@ -1159,12 +1091,8 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
if (E->hadArrayRangeDesignator())
CGF.ErrorUnsupported(E, "GNU array range designator extension");
- if (E->initializesStdInitializerList()) {
- EmitStdInitializerList(Dest.getAddr(), E);
- return;
- }
-
AggValueSlot Dest = EnsureSlot(E->getType());
+
LValue DestLV = CGF.MakeAddrLValue(Dest.getAddr(), E->getType(),
Dest.getAlignment());
@@ -1545,58 +1473,3 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr,
alignment.getQuantity(), isVolatile,
/*TBAATag=*/0, TBAAStructTag);
}
-
-void CodeGenFunction::MaybeEmitStdInitializerListCleanup(llvm::Value *loc,
- const Expr *init) {
- const ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(init);
- if (cleanups)
- init = cleanups->getSubExpr();
-
- if (isa<InitListExpr>(init) &&
- cast<InitListExpr>(init)->initializesStdInitializerList()) {
- // We initialized this std::initializer_list with an initializer list.
- // A backing array was created. Push a cleanup for it.
- EmitStdInitializerListCleanup(loc, cast<InitListExpr>(init));
- }
-}
-
-static void EmitRecursiveStdInitializerListCleanup(CodeGenFunction &CGF,
- llvm::Value *arrayStart,
- const InitListExpr *init) {
- // Check if there are any recursive cleanups to do, i.e. if we have
- // std::initializer_list<std::initializer_list<obj>> list = {{obj()}};
- // then we need to destroy the inner array as well.
- for (unsigned i = 0, e = init->getNumInits(); i != e; ++i) {
- const InitListExpr *subInit = dyn_cast<InitListExpr>(init->getInit(i));
- if (!subInit || !subInit->initializesStdInitializerList())
- continue;
-
- // This one needs to be destroyed. Get the address of the std::init_list.
- llvm::Value *offset = llvm::ConstantInt::get(CGF.SizeTy, i);
- llvm::Value *loc = CGF.Builder.CreateInBoundsGEP(arrayStart, offset,
- "std.initlist");
- CGF.EmitStdInitializerListCleanup(loc, subInit);
- }
-}
-
-void CodeGenFunction::EmitStdInitializerListCleanup(llvm::Value *loc,
- const InitListExpr *init) {
- ASTContext &ctx = getContext();
- QualType element = GetStdInitializerListElementType(init->getType());
- unsigned numInits = init->getNumInits();
- llvm::APInt size(ctx.getTypeSize(ctx.getSizeType()), numInits);
- QualType array =ctx.getConstantArrayType(element, size, ArrayType::Normal, 0);
- QualType arrayPtr = ctx.getPointerType(array);
- llvm::Type *arrayPtrType = ConvertType(arrayPtr);
-
- // lvalue is the location of a std::initializer_list, which as its first
- // element has a pointer to the array we want to destroy.
- llvm::Value *startPointer = Builder.CreateStructGEP(loc, 0, "startPointer");
- llvm::Value *startAddress = Builder.CreateLoad(startPointer, "startAddress");
-
- ::EmitRecursiveStdInitializerListCleanup(*this, startAddress, init);
-
- llvm::Value *arrayAddress =
- Builder.CreateBitCast(startAddress, arrayPtrType, "arrayAddress");
- ::EmitStdInitializerListCleanup(*this, array, arrayAddress, init);
-}
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp
index 83c8ace..cc7b24d 100644
--- a/lib/CodeGen/CGExprCXX.cpp
+++ b/lib/CodeGen/CGExprCXX.cpp
@@ -16,6 +16,7 @@
#include "CGCXXABI.h"
#include "CGDebugInfo.h"
#include "CGObjCRuntime.h"
+#include "clang/CodeGen/CGFunctionInfo.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/Support/CallSite.h"
@@ -62,99 +63,6 @@ RValue CodeGenFunction::EmitCXXMemberCall(const CXXMethodDecl *MD,
Callee, ReturnValue, Args, MD);
}
-// FIXME: Ideally Expr::IgnoreParenNoopCasts should do this, but it doesn't do
-// quite what we want.
-static const Expr *skipNoOpCastsAndParens(const Expr *E) {
- while (true) {
- if (const ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
- E = PE->getSubExpr();
- continue;
- }
-
- if (const CastExpr *CE = dyn_cast<CastExpr>(E)) {
- if (CE->getCastKind() == CK_NoOp) {
- E = CE->getSubExpr();
- continue;
- }
- }
- if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
- if (UO->getOpcode() == UO_Extension) {
- E = UO->getSubExpr();
- continue;
- }
- }
- return E;
- }
-}
-
-/// canDevirtualizeMemberFunctionCalls - Checks whether virtual calls on given
-/// expr can be devirtualized.
-static bool canDevirtualizeMemberFunctionCalls(ASTContext &Context,
- const Expr *Base,
- const CXXMethodDecl *MD) {
-
- // When building with -fapple-kext, all calls must go through the vtable since
- // the kernel linker can do runtime patching of vtables.
- if (Context.getLangOpts().AppleKext)
- return false;
-
- // If the most derived class is marked final, we know that no subclass can
- // override this member function and so we can devirtualize it. For example:
- //
- // struct A { virtual void f(); }
- // struct B final : A { };
- //
- // void f(B *b) {
- // b->f();
- // }
- //
- const CXXRecordDecl *MostDerivedClassDecl = Base->getBestDynamicClassType();
- if (MostDerivedClassDecl->hasAttr<FinalAttr>())
- return true;
-
- // If the member function is marked 'final', we know that it can't be
- // overridden and can therefore devirtualize it.
- if (MD->hasAttr<FinalAttr>())
- return true;
-
- // Similarly, if the class itself is marked 'final' it can't be overridden
- // and we can therefore devirtualize the member function call.
- if (MD->getParent()->hasAttr<FinalAttr>())
- return true;
-
- Base = skipNoOpCastsAndParens(Base);
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base)) {
- if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
- // This is a record decl. We know the type and can devirtualize it.
- return VD->getType()->isRecordType();
- }
-
- return false;
- }
-
- // We can devirtualize calls on an object accessed by a class member access
- // expression, since by C++11 [basic.life]p6 we know that it can't refer to
- // a derived class object constructed in the same location.
- if (const MemberExpr *ME = dyn_cast<MemberExpr>(Base))
- if (const ValueDecl *VD = dyn_cast<ValueDecl>(ME->getMemberDecl()))
- return VD->getType()->isRecordType();
-
- // We can always devirtualize calls on temporary object expressions.
- if (isa<CXXConstructExpr>(Base))
- return true;
-
- // And calls on bound temporaries.
- if (isa<CXXBindTemporaryExpr>(Base))
- return true;
-
- // Check if this is a call expr that returns a record type.
- if (const CallExpr *CE = dyn_cast<CallExpr>(Base))
- return CE->getCallReturnType()->isRecordType();
-
- // We can't devirtualize the call.
- return false;
-}
-
static CXXRecordDecl *getCXXRecord(const Expr *E) {
QualType T = E->getType();
if (const PointerType *PTy = T->getAs<PointerType>())
@@ -175,22 +83,12 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
const MemberExpr *ME = cast<MemberExpr>(callee);
const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl());
- CGDebugInfo *DI = getDebugInfo();
- if (DI &&
- CGM.getCodeGenOpts().getDebugInfo() == CodeGenOptions::LimitedDebugInfo &&
- !isa<CallExpr>(ME->getBase())) {
- QualType PQTy = ME->getBase()->IgnoreParenImpCasts()->getType();
- if (const PointerType * PTy = dyn_cast<PointerType>(PQTy)) {
- DI->getOrCreateRecordType(PTy->getPointeeType(),
- MD->getParent()->getLocation());
- }
- }
-
if (MD->isStatic()) {
// The method is static, emit it as we would a regular call.
llvm::Value *Callee = CGM.GetAddrOfFunction(MD);
return EmitCall(getContext().getPointerType(MD->getType()), Callee,
- ReturnValue, CE->arg_begin(), CE->arg_end());
+ CE->getLocStart(), ReturnValue, CE->arg_begin(),
+ CE->arg_end());
}
// Compute the object pointer.
@@ -198,8 +96,7 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
bool CanUseVirtualCall = MD->isVirtual() && !ME->hasQualifier();
const CXXMethodDecl *DevirtualizedMethod = NULL;
- if (CanUseVirtualCall &&
- canDevirtualizeMemberFunctionCalls(getContext(), Base, MD)) {
+ if (CanUseVirtualCall && CanDevirtualizeMemberFunctionCall(Base, MD)) {
const CXXRecordDecl *BestDynamicDecl = Base->getBestDynamicClassType();
DevirtualizedMethod = MD->getCorrespondingMethodInClass(BestDynamicDecl);
assert(DevirtualizedMethod);
@@ -271,7 +168,7 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
else
FInfo = &CGM.getTypes().arrangeCXXMethodDeclaration(CalleeDecl);
- llvm::Type *Ty = CGM.getTypes().GetFunctionType(*FInfo);
+ llvm::FunctionType *Ty = CGM.getTypes().GetFunctionType(*FInfo);
// C++ [class.virtual]p12:
// Explicit qualification with the scope operator (5.1) suppresses the
@@ -280,34 +177,37 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
// We also don't emit a virtual call if the base expression has a record type
// because then we know what the type is.
bool UseVirtualCall = CanUseVirtualCall && !DevirtualizedMethod;
-
llvm::Value *Callee;
+
if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD)) {
+ assert(CE->arg_begin() == CE->arg_end() &&
+ "Destructor shouldn't have explicit parameters");
+ assert(ReturnValue.isNull() && "Destructor shouldn't have return value");
if (UseVirtualCall) {
- assert(CE->arg_begin() == CE->arg_end() &&
- "Virtual destructor shouldn't have explicit parameters");
- return CGM.getCXXABI().EmitVirtualDestructorCall(*this, Dtor,
- Dtor_Complete,
- CE->getExprLoc(),
- ReturnValue, This);
+ CGM.getCXXABI().EmitVirtualDestructorCall(*this, Dtor, Dtor_Complete,
+ CE->getExprLoc(), This);
} else {
if (getLangOpts().AppleKext &&
MD->isVirtual() &&
ME->hasQualifier())
Callee = BuildAppleKextVirtualCall(MD, ME->getQualifier(), Ty);
else if (!DevirtualizedMethod)
- Callee = CGM.GetAddrOfFunction(GlobalDecl(Dtor, Dtor_Complete), Ty);
+ Callee = CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete, FInfo, Ty);
else {
const CXXDestructorDecl *DDtor =
cast<CXXDestructorDecl>(DevirtualizedMethod);
Callee = CGM.GetAddrOfFunction(GlobalDecl(DDtor, Dtor_Complete), Ty);
}
+ EmitCXXMemberCall(MD, CE->getExprLoc(), Callee, ReturnValue, This,
+ /*ImplicitParam=*/0, QualType(), 0, 0);
}
- } else if (const CXXConstructorDecl *Ctor =
- dyn_cast<CXXConstructorDecl>(MD)) {
+ return RValue::get(0);
+ }
+
+ if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(MD)) {
Callee = CGM.GetAddrOfFunction(GlobalDecl(Ctor, Ctor_Complete), Ty);
} else if (UseVirtualCall) {
- Callee = BuildVirtualCall(MD, This, Ty);
+ Callee = CGM.getCXXABI().getVirtualFunctionPointer(*this, MD, This, Ty);
} else {
if (getLangOpts().AppleKext &&
MD->isVirtual() &&
@@ -320,6 +220,9 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
}
}
+ if (MD->isVirtual())
+ This = CGM.getCXXABI().adjustThisArgumentForVirtualCall(*this, MD, This);
+
return EmitCXXMemberCall(MD, CE->getExprLoc(), Callee, ReturnValue, This,
/*ImplicitParam=*/0, QualType(),
CE->arg_begin(), CE->arg_end());
@@ -371,8 +274,8 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E,
// And the rest of the call args
EmitCallArgs(Args, FPT, E->arg_begin(), E->arg_end());
- return EmitCall(CGM.getTypes().arrangeCXXMethodCall(Args, FPT, required), Callee,
- ReturnValue, Args);
+ return EmitCall(CGM.getTypes().arrangeCXXMethodCall(Args, FPT, required),
+ Callee, ReturnValue, Args);
}
RValue
@@ -540,8 +443,7 @@ CodeGenFunction::EmitSynthesizedCXXCopyCtor(llvm::Value *Dest,
assert(!getContext().getAsConstantArrayType(E->getType())
&& "EmitSynthesizedCXXCopyCtor - Copied-in Array");
- EmitSynthesizedCXXCopyCtorCall(CD, Dest, Src,
- E->arg_begin(), E->arg_end());
+ EmitSynthesizedCXXCopyCtorCall(CD, Dest, Src, E->arg_begin(), E->arg_end());
}
static CharUnits CalculateCookiePadding(CodeGenFunction &CGF,
@@ -818,7 +720,7 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const Expr *Init,
QualType AllocType, llvm::Value *NewPtr) {
-
+ // FIXME: Refactor with EmitExprAsInit.
CharUnits Alignment = CGF.getContext().getTypeAlignInChars(AllocType);
switch (CGF.getEvaluationKind(AllocType)) {
case TEK_Scalar:
@@ -838,8 +740,6 @@ static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const Expr *Init,
AggValueSlot::DoesNotNeedGCBarriers,
AggValueSlot::IsNotAliased);
CGF.EmitAggExpr(Init, Slot);
-
- CGF.MaybeEmitStdInitializerListCleanup(NewPtr, Init);
return;
}
}
@@ -866,10 +766,22 @@ CodeGenFunction::EmitNewArrayInitializer(const CXXNewExpr *E,
QualType::DestructionKind dtorKind = elementType.isDestructedType();
EHScopeStack::stable_iterator cleanup;
llvm::Instruction *cleanupDominator = 0;
+
// If the initializer is an initializer list, first do the explicit elements.
if (const InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
initializerElements = ILE->getNumInits();
+ // If this is a multi-dimensional array new, we will initialize multiple
+ // elements with each init list element.
+ QualType AllocType = E->getAllocatedType();
+ if (const ConstantArrayType *CAT = dyn_cast_or_null<ConstantArrayType>(
+ AllocType->getAsArrayTypeUnsafe())) {
+ unsigned AS = explicitPtr->getType()->getPointerAddressSpace();
+ llvm::Type *AllocPtrTy = ConvertTypeForMem(AllocType)->getPointerTo(AS);
+ explicitPtr = Builder.CreateBitCast(explicitPtr, AllocPtrTy);
+ initializerElements *= getContext().getConstantArrayElementCount(CAT);
+ }
+
// Enter a partial-destruction cleanup if necessary.
if (needsEHCleanup(dtorKind)) {
// In principle we could tell the cleanup where we are more
@@ -888,12 +800,16 @@ CodeGenFunction::EmitNewArrayInitializer(const CXXNewExpr *E,
// element. TODO: some of these stores can be trivially
// observed to be unnecessary.
if (endOfInit) Builder.CreateStore(explicitPtr, endOfInit);
- StoreAnyExprIntoOneUnit(*this, ILE->getInit(i), elementType, explicitPtr);
- explicitPtr =Builder.CreateConstGEP1_32(explicitPtr, 1, "array.exp.next");
+ StoreAnyExprIntoOneUnit(*this, ILE->getInit(i),
+ ILE->getInit(i)->getType(), explicitPtr);
+ explicitPtr = Builder.CreateConstGEP1_32(explicitPtr, 1,
+ "array.exp.next");
}
// The remaining elements are filled with the array filler expression.
Init = ILE->getArrayFiller();
+
+ explicitPtr = Builder.CreateBitCast(explicitPtr, beginPtr->getType());
}
// Create the continuation block.
@@ -1012,6 +928,41 @@ static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E,
StoreAnyExprIntoOneUnit(CGF, Init, E->getAllocatedType(), NewPtr);
}
+/// Emit a call to an operator new or operator delete function, as implicitly
+/// created by new-expressions and delete-expressions.
+static RValue EmitNewDeleteCall(CodeGenFunction &CGF,
+ const FunctionDecl *Callee,
+ const FunctionProtoType *CalleeType,
+ const CallArgList &Args) {
+ llvm::Instruction *CallOrInvoke;
+ llvm::Value *CalleeAddr = CGF.CGM.GetAddrOfFunction(Callee);
+ RValue RV =
+ CGF.EmitCall(CGF.CGM.getTypes().arrangeFreeFunctionCall(Args, CalleeType),
+ CalleeAddr, ReturnValueSlot(), Args,
+ Callee, &CallOrInvoke);
+
+ /// C++1y [expr.new]p10:
+ /// [In a new-expression,] an implementation is allowed to omit a call
+ /// to a replaceable global allocation function.
+ ///
+ /// We model such elidable calls with the 'builtin' attribute.
+ llvm::Function *Fn = dyn_cast<llvm::Function>(CalleeAddr);
+ if (Callee->isReplaceableGlobalAllocationFunction() &&
+ Fn && Fn->hasFnAttribute(llvm::Attribute::NoBuiltin)) {
+ // FIXME: Add addAttribute to CallSite.
+ if (llvm::CallInst *CI = dyn_cast<llvm::CallInst>(CallOrInvoke))
+ CI->addAttribute(llvm::AttributeSet::FunctionIndex,
+ llvm::Attribute::Builtin);
+ else if (llvm::InvokeInst *II = dyn_cast<llvm::InvokeInst>(CallOrInvoke))
+ II->addAttribute(llvm::AttributeSet::FunctionIndex,
+ llvm::Attribute::Builtin);
+ else
+ llvm_unreachable("unexpected kind of call instruction");
+ }
+
+ return RV;
+}
+
namespace {
/// A cleanup to call the given 'operator delete' function upon
/// abnormal exit from a new expression.
@@ -1061,9 +1012,7 @@ namespace {
DeleteArgs.add(getPlacementArgs()[I], *AI++);
// Call 'operator delete'.
- CGF.EmitCall(CGF.CGM.getTypes().arrangeFreeFunctionCall(DeleteArgs, FPT),
- CGF.CGM.GetAddrOfFunction(OperatorDelete),
- ReturnValueSlot(), DeleteArgs, OperatorDelete);
+ EmitNewDeleteCall(CGF, OperatorDelete, FPT, DeleteArgs);
}
};
@@ -1122,9 +1071,7 @@ namespace {
}
// Call 'operator delete'.
- CGF.EmitCall(CGF.CGM.getTypes().arrangeFreeFunctionCall(DeleteArgs, FPT),
- CGF.CGM.GetAddrOfFunction(OperatorDelete),
- ReturnValueSlot(), DeleteArgs, OperatorDelete);
+ EmitNewDeleteCall(CGF, OperatorDelete, FPT, DeleteArgs);
}
};
}
@@ -1237,10 +1184,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
// TODO: kill any unnecessary computations done for the size
// argument.
} else {
- RV = EmitCall(CGM.getTypes().arrangeFreeFunctionCall(allocatorArgs,
- allocatorType),
- CGM.GetAddrOfFunction(allocator), ReturnValueSlot(),
- allocatorArgs, allocator);
+ RV = EmitNewDeleteCall(*this, allocator, allocatorType, allocatorArgs);
}
// Emit a null check on the allocation result if the allocation
@@ -1360,9 +1304,7 @@ void CodeGenFunction::EmitDeleteCall(const FunctionDecl *DeleteFD,
DeleteArgs.add(RValue::get(Size), SizeTy);
// Emit the call to delete.
- EmitCall(CGM.getTypes().arrangeFreeFunctionCall(DeleteArgs, DeleteFTy),
- CGM.GetAddrOfFunction(DeleteFD), ReturnValueSlot(),
- DeleteArgs, DeleteFD);
+ EmitNewDeleteCall(*this, DeleteFD, DeleteFTy, DeleteArgs);
}
namespace {
@@ -1415,8 +1357,7 @@ static void EmitObjectDelete(CodeGenFunction &CGF,
// FIXME: Provide a source location here.
CXXDtorType DtorType = UseGlobalDelete ? Dtor_Complete : Dtor_Deleting;
CGF.CGM.getCXXABI().EmitVirtualDestructorCall(CGF, Dtor, DtorType,
- SourceLocation(),
- ReturnValueSlot(), Ptr);
+ SourceLocation(), Ptr);
if (UseGlobalDelete) {
CGF.PopCleanupBlock();
@@ -1519,9 +1460,7 @@ namespace {
}
// Emit the call to delete.
- CGF.EmitCall(CGF.getTypes().arrangeFreeFunctionCall(Args, DeleteFTy),
- CGF.CGM.GetAddrOfFunction(OperatorDelete),
- ReturnValueSlot(), Args, OperatorDelete);
+ EmitNewDeleteCall(CGF, OperatorDelete, DeleteFTy, Args);
}
};
}
@@ -1667,8 +1606,8 @@ llvm::Value *CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) {
ConvertType(E->getType())->getPointerTo();
if (E->isTypeOperand()) {
- llvm::Constant *TypeInfo =
- CGM.GetAddrOfRTTIDescriptor(E->getTypeOperand());
+ llvm::Constant *TypeInfo =
+ CGM.GetAddrOfRTTIDescriptor(E->getTypeOperand(getContext()));
return Builder.CreateBitCast(TypeInfo, StdTypeInfoPtrTy);
}
diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp
index 36f974a..73d5bcb 100644
--- a/lib/CodeGen/CGExprComplex.cpp
+++ b/lib/CodeGen/CGExprComplex.cpp
@@ -18,6 +18,7 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
+#include <algorithm>
using namespace clang;
using namespace CodeGen;
@@ -69,10 +70,10 @@ public:
/// value l-value, this method emits the address of the l-value, then loads
/// and returns the result.
ComplexPairTy EmitLoadOfLValue(const Expr *E) {
- return EmitLoadOfLValue(CGF.EmitLValue(E));
+ return EmitLoadOfLValue(CGF.EmitLValue(E), E->getExprLoc());
}
- ComplexPairTy EmitLoadOfLValue(LValue LV);
+ ComplexPairTy EmitLoadOfLValue(LValue LV, SourceLocation Loc);
/// EmitStoreOfComplex - Store the specified real/imag parts into the
/// specified value pointer.
@@ -81,6 +82,9 @@ public:
/// EmitComplexToComplexCast - Emit a cast from complex value Val to DestType.
ComplexPairTy EmitComplexToComplexCast(ComplexPairTy Val, QualType SrcType,
QualType DestType);
+ /// EmitComplexToComplexCast - Emit a cast from scalar value Val to DestType.
+ ComplexPairTy EmitScalarToComplexCast(llvm::Value *Val, QualType SrcType,
+ QualType DestType);
//===--------------------------------------------------------------------===//
// Visitor Methods
@@ -109,11 +113,12 @@ public:
ComplexPairTy VisitDeclRefExpr(DeclRefExpr *E) {
if (CodeGenFunction::ConstantEmission result = CGF.tryEmitAsConstant(E)) {
if (result.isReference())
- return EmitLoadOfLValue(result.getReferenceLValue(CGF, E));
+ return EmitLoadOfLValue(result.getReferenceLValue(CGF, E),
+ E->getExprLoc());
- llvm::ConstantStruct *pair =
- cast<llvm::ConstantStruct>(result.getValue());
- return ComplexPairTy(pair->getOperand(0), pair->getOperand(1));
+ llvm::Constant *pair = result.getValue();
+ return ComplexPairTy(pair->getAggregateElement(0U),
+ pair->getAggregateElement(1U));
}
return EmitLoadOfLValue(E);
}
@@ -127,7 +132,7 @@ public:
ComplexPairTy VisitMemberExpr(const Expr *E) { return EmitLoadOfLValue(E); }
ComplexPairTy VisitOpaqueValueExpr(OpaqueValueExpr *E) {
if (E->isGLValue())
- return EmitLoadOfLValue(CGF.getOpaqueLValueMapping(E));
+ return EmitLoadOfLValue(CGF.getOpaqueLValueMapping(E), E->getExprLoc());
return CGF.getOpaqueRValueMapping(E).getComplexVal();
}
@@ -215,7 +220,7 @@ public:
LValue EmitCompoundAssignLValue(const CompoundAssignOperator *E,
ComplexPairTy (ComplexExprEmitter::*Func)
(const BinOpInfo &),
- ComplexPairTy &Val);
+ RValue &Val);
ComplexPairTy EmitCompoundAssign(const CompoundAssignOperator *E,
ComplexPairTy (ComplexExprEmitter::*Func)
(const BinOpInfo &));
@@ -287,26 +292,34 @@ public:
/// EmitLoadOfLValue - Given an RValue reference for a complex, emit code to
/// load the real and imaginary pieces, returning them as Real/Imag.
-ComplexPairTy ComplexExprEmitter::EmitLoadOfLValue(LValue lvalue) {
+ComplexPairTy ComplexExprEmitter::EmitLoadOfLValue(LValue lvalue,
+ SourceLocation loc) {
assert(lvalue.isSimple() && "non-simple complex l-value?");
if (lvalue.getType()->isAtomicType())
- return CGF.EmitAtomicLoad(lvalue).getComplexVal();
+ return CGF.EmitAtomicLoad(lvalue, loc).getComplexVal();
llvm::Value *SrcPtr = lvalue.getAddress();
bool isVolatile = lvalue.isVolatileQualified();
+ unsigned AlignR = lvalue.getAlignment().getQuantity();
+ ASTContext &C = CGF.getContext();
+ QualType ComplexTy = lvalue.getType();
+ unsigned ComplexAlign = C.getTypeAlignInChars(ComplexTy).getQuantity();
+ unsigned AlignI = std::min(AlignR, ComplexAlign);
llvm::Value *Real=0, *Imag=0;
if (!IgnoreReal || isVolatile) {
llvm::Value *RealP = Builder.CreateStructGEP(SrcPtr, 0,
SrcPtr->getName() + ".realp");
- Real = Builder.CreateLoad(RealP, isVolatile, SrcPtr->getName() + ".real");
+ Real = Builder.CreateAlignedLoad(RealP, AlignR, isVolatile,
+ SrcPtr->getName() + ".real");
}
if (!IgnoreImag || isVolatile) {
llvm::Value *ImagP = Builder.CreateStructGEP(SrcPtr, 1,
SrcPtr->getName() + ".imagp");
- Imag = Builder.CreateLoad(ImagP, isVolatile, SrcPtr->getName() + ".imag");
+ Imag = Builder.CreateAlignedLoad(ImagP, AlignI, isVolatile,
+ SrcPtr->getName() + ".imag");
}
return ComplexPairTy(Real, Imag);
}
@@ -322,10 +335,16 @@ void ComplexExprEmitter::EmitStoreOfComplex(ComplexPairTy Val,
llvm::Value *Ptr = lvalue.getAddress();
llvm::Value *RealPtr = Builder.CreateStructGEP(Ptr, 0, "real");
llvm::Value *ImagPtr = Builder.CreateStructGEP(Ptr, 1, "imag");
-
- // TODO: alignment
- Builder.CreateStore(Val.first, RealPtr, lvalue.isVolatileQualified());
- Builder.CreateStore(Val.second, ImagPtr, lvalue.isVolatileQualified());
+ unsigned AlignR = lvalue.getAlignment().getQuantity();
+ ASTContext &C = CGF.getContext();
+ QualType ComplexTy = lvalue.getType();
+ unsigned ComplexAlign = C.getTypeAlignInChars(ComplexTy).getQuantity();
+ unsigned AlignI = std::min(AlignR, ComplexAlign);
+
+ Builder.CreateAlignedStore(Val.first, RealPtr, AlignR,
+ lvalue.isVolatileQualified());
+ Builder.CreateAlignedStore(Val.second, ImagPtr, AlignI,
+ lvalue.isVolatileQualified());
}
@@ -358,7 +377,10 @@ ComplexPairTy ComplexExprEmitter::VisitCallExpr(const CallExpr *E) {
ComplexPairTy ComplexExprEmitter::VisitStmtExpr(const StmtExpr *E) {
CodeGenFunction::StmtExprEvaluation eval(CGF);
- return CGF.EmitCompoundStmt(*E->getSubStmt(), true).getComplexVal();
+ llvm::Value *RetAlloca = CGF.EmitCompoundStmt(*E->getSubStmt(), true);
+ assert(RetAlloca && "Expected complex return value");
+ return EmitLoadOfLValue(CGF.MakeAddrLValue(RetAlloca, E->getType()),
+ E->getExprLoc());
}
/// EmitComplexToComplexCast - Emit a cast from complex value Val to DestType.
@@ -377,6 +399,17 @@ ComplexPairTy ComplexExprEmitter::EmitComplexToComplexCast(ComplexPairTy Val,
return Val;
}
+ComplexPairTy ComplexExprEmitter::EmitScalarToComplexCast(llvm::Value *Val,
+ QualType SrcType,
+ QualType DestType) {
+ // Convert the input element to the element type of the complex.
+ DestType = DestType->castAs<ComplexType>()->getElementType();
+ Val = CGF.EmitScalarConversion(Val, SrcType, DestType);
+
+ // Return (realval, 0).
+ return ComplexPairTy(Val, llvm::Constant::getNullValue(Val->getType()));
+}
+
ComplexPairTy ComplexExprEmitter::EmitCast(CastExpr::CastKind CK, Expr *Op,
QualType DestTy) {
switch (CK) {
@@ -397,7 +430,8 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastExpr::CastKind CK, Expr *Op,
V = Builder.CreateBitCast(V,
CGF.ConvertType(CGF.getContext().getPointerType(DestTy)));
return EmitLoadOfLValue(CGF.MakeAddrLValue(V, DestTy,
- origLV.getAlignment()));
+ origLV.getAlignment()),
+ Op->getExprLoc());
}
case CK_BitCast:
@@ -444,16 +478,9 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastExpr::CastKind CK, Expr *Op,
llvm_unreachable("invalid cast kind for complex value");
case CK_FloatingRealToComplex:
- case CK_IntegralRealToComplex: {
- llvm::Value *Elt = CGF.EmitScalarExpr(Op);
-
- // Convert the input element to the element type of the complex.
- DestTy = DestTy->castAs<ComplexType>()->getElementType();
- Elt = CGF.EmitScalarConversion(Elt, Op->getType(), DestTy);
-
- // Return (realval, 0).
- return ComplexPairTy(Elt, llvm::Constant::getNullValue(Elt->getType()));
- }
+ case CK_IntegralRealToComplex:
+ return EmitScalarToComplexCast(CGF.EmitScalarExpr(Op),
+ Op->getType(), DestTy);
case CK_FloatingComplexCast:
case CK_FloatingComplexToIntegralComplex:
@@ -608,7 +635,7 @@ ComplexExprEmitter::EmitBinOps(const BinaryOperator *E) {
LValue ComplexExprEmitter::
EmitCompoundAssignLValue(const CompoundAssignOperator *E,
ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&),
- ComplexPairTy &Val) {
+ RValue &Val) {
TestAndClearIgnoreReal();
TestAndClearIgnoreImag();
QualType LHSTy = E->getLHS()->getType();
@@ -628,20 +655,29 @@ EmitCompoundAssignLValue(const CompoundAssignOperator *E,
LValue LHS = CGF.EmitLValue(E->getLHS());
- // Load from the l-value.
- ComplexPairTy LHSComplexPair = EmitLoadOfLValue(LHS);
-
- OpInfo.LHS = EmitComplexToComplexCast(LHSComplexPair, LHSTy, OpInfo.Ty);
+ // Load from the l-value and convert it.
+ if (LHSTy->isAnyComplexType()) {
+ ComplexPairTy LHSVal = EmitLoadOfLValue(LHS, E->getExprLoc());
+ OpInfo.LHS = EmitComplexToComplexCast(LHSVal, LHSTy, OpInfo.Ty);
+ } else {
+ llvm::Value *LHSVal = CGF.EmitLoadOfScalar(LHS, E->getExprLoc());
+ OpInfo.LHS = EmitScalarToComplexCast(LHSVal, LHSTy, OpInfo.Ty);
+ }
// Expand the binary operator.
ComplexPairTy Result = (this->*Func)(OpInfo);
- // Truncate the result back to the LHS type.
- Result = EmitComplexToComplexCast(Result, OpInfo.Ty, LHSTy);
- Val = Result;
-
- // Store the result value into the LHS lvalue.
- EmitStoreOfComplex(Result, LHS, /*isInit*/ false);
+ // Truncate the result and store it into the LHS lvalue.
+ if (LHSTy->isAnyComplexType()) {
+ ComplexPairTy ResVal = EmitComplexToComplexCast(Result, OpInfo.Ty, LHSTy);
+ EmitStoreOfComplex(ResVal, LHS, /*isInit*/ false);
+ Val = RValue::getComplex(ResVal);
+ } else {
+ llvm::Value *ResVal =
+ CGF.EmitComplexToScalarConversion(Result, OpInfo.Ty, LHSTy);
+ CGF.EmitStoreOfScalar(ResVal, LHS, /*isInit*/ false);
+ Val = RValue::get(ResVal);
+ }
return LHS;
}
@@ -650,18 +686,18 @@ EmitCompoundAssignLValue(const CompoundAssignOperator *E,
ComplexPairTy ComplexExprEmitter::
EmitCompoundAssign(const CompoundAssignOperator *E,
ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&)){
- ComplexPairTy Val;
+ RValue Val;
LValue LV = EmitCompoundAssignLValue(E, Func, Val);
// The result of an assignment in C is the assigned r-value.
if (!CGF.getLangOpts().CPlusPlus)
- return Val;
+ return Val.getComplexVal();
// If the lvalue is non-volatile, return the computed value of the assignment.
if (!LV.isVolatileQualified())
- return Val;
+ return Val.getComplexVal();
- return EmitLoadOfLValue(LV);
+ return EmitLoadOfLValue(LV, E->getExprLoc());
}
LValue ComplexExprEmitter::EmitBinAssignLValue(const BinaryOperator *E,
@@ -696,7 +732,7 @@ ComplexPairTy ComplexExprEmitter::VisitBinAssign(const BinaryOperator *E) {
if (!LV.isVolatileQualified())
return Val;
- return EmitLoadOfLValue(LV);
+ return EmitLoadOfLValue(LV, E->getExprLoc());
}
ComplexPairTy ComplexExprEmitter::VisitBinComma(const BinaryOperator *E) {
@@ -746,7 +782,7 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
}
ComplexPairTy ComplexExprEmitter::VisitChooseExpr(ChooseExpr *E) {
- return Visit(E->getChosenSubExpr(CGF.getContext()));
+ return Visit(E->getChosenSubExpr());
}
ComplexPairTy ComplexExprEmitter::VisitInitListExpr(InitListExpr *E) {
@@ -785,8 +821,8 @@ ComplexPairTy ComplexExprEmitter::VisitVAArgExpr(VAArgExpr *E) {
return ComplexPairTy(U, U);
}
- return EmitLoadOfLValue(
- CGF.MakeNaturalAlignAddrLValue(ArgPtr, E->getType()));
+ return EmitLoadOfLValue(CGF.MakeNaturalAlignAddrLValue(ArgPtr, E->getType()),
+ E->getExprLoc());
}
//===----------------------------------------------------------------------===//
@@ -820,8 +856,9 @@ void CodeGenFunction::EmitStoreOfComplex(ComplexPairTy V, LValue dest,
}
/// EmitLoadOfComplex - Load a complex number from the specified address.
-ComplexPairTy CodeGenFunction::EmitLoadOfComplex(LValue src) {
- return ComplexExprEmitter(*this).EmitLoadOfLValue(src);
+ComplexPairTy CodeGenFunction::EmitLoadOfComplex(LValue src,
+ SourceLocation loc) {
+ return ComplexExprEmitter(*this).EmitLoadOfLValue(src, loc);
}
LValue CodeGenFunction::EmitComplexAssignmentLValue(const BinaryOperator *E) {
@@ -830,19 +867,33 @@ LValue CodeGenFunction::EmitComplexAssignmentLValue(const BinaryOperator *E) {
return ComplexExprEmitter(*this).EmitBinAssignLValue(E, Val);
}
-LValue CodeGenFunction::
-EmitComplexCompoundAssignmentLValue(const CompoundAssignOperator *E) {
- ComplexPairTy(ComplexExprEmitter::*Op)(const ComplexExprEmitter::BinOpInfo &);
- switch (E->getOpcode()) {
- case BO_MulAssign: Op = &ComplexExprEmitter::EmitBinMul; break;
- case BO_DivAssign: Op = &ComplexExprEmitter::EmitBinDiv; break;
- case BO_SubAssign: Op = &ComplexExprEmitter::EmitBinSub; break;
- case BO_AddAssign: Op = &ComplexExprEmitter::EmitBinAdd; break;
+typedef ComplexPairTy (ComplexExprEmitter::*CompoundFunc)(
+ const ComplexExprEmitter::BinOpInfo &);
+static CompoundFunc getComplexOp(BinaryOperatorKind Op) {
+ switch (Op) {
+ case BO_MulAssign: return &ComplexExprEmitter::EmitBinMul;
+ case BO_DivAssign: return &ComplexExprEmitter::EmitBinDiv;
+ case BO_SubAssign: return &ComplexExprEmitter::EmitBinSub;
+ case BO_AddAssign: return &ComplexExprEmitter::EmitBinAdd;
default:
llvm_unreachable("unexpected complex compound assignment");
}
+}
- ComplexPairTy Val; // ignored
+LValue CodeGenFunction::
+EmitComplexCompoundAssignmentLValue(const CompoundAssignOperator *E) {
+ CompoundFunc Op = getComplexOp(E->getOpcode());
+ RValue Val;
return ComplexExprEmitter(*this).EmitCompoundAssignLValue(E, Op, Val);
}
+
+LValue CodeGenFunction::
+EmitScalarCompooundAssignWithComplex(const CompoundAssignOperator *E,
+ llvm::Value *&Result) {
+ CompoundFunc Op = getComplexOp(E->getOpcode());
+ RValue Val;
+ LValue Ret = ComplexExprEmitter(*this).EmitCompoundAssignLValue(E, Op, Val);
+ Result = Val.getScalarVal();
+ return Ret;
+}
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index f5c8187..f4d6861 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -53,9 +53,6 @@ private:
NextFieldOffsetInChars(CharUnits::Zero()),
LLVMStructAlignment(CharUnits::One()) { }
- void AppendVTablePointer(BaseSubobject Base, llvm::Constant *VTable,
- const CXXRecordDecl *VTableClass);
-
void AppendField(const FieldDecl *Field, uint64_t FieldOffset,
llvm::Constant *InitExpr);
@@ -72,8 +69,7 @@ private:
bool Build(InitListExpr *ILE);
void Build(const APValue &Val, const RecordDecl *RD, bool IsPrimaryBase,
- llvm::Constant *VTable, const CXXRecordDecl *VTableClass,
- CharUnits BaseOffset);
+ const CXXRecordDecl *VTableClass, CharUnits BaseOffset);
llvm::Constant *Finalize(QualType Ty);
CharUnits getAlignment(const llvm::Constant *C) const {
@@ -88,23 +84,6 @@ private:
}
};
-void ConstStructBuilder::AppendVTablePointer(BaseSubobject Base,
- llvm::Constant *VTable,
- const CXXRecordDecl *VTableClass) {
- // Find the appropriate vtable within the vtable group.
- uint64_t AddressPoint =
- CGM.getVTableContext().getVTableLayout(VTableClass).getAddressPoint(Base);
- llvm::Value *Indices[] = {
- llvm::ConstantInt::get(CGM.Int64Ty, 0),
- llvm::ConstantInt::get(CGM.Int64Ty, AddressPoint)
- };
- llvm::Constant *VTableAddressPoint =
- llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Indices);
-
- // Add the vtable at the start of the object.
- AppendBytes(Base.getBaseOffset(), VTableAddressPoint);
-}
-
void ConstStructBuilder::
AppendField(const FieldDecl *Field, uint64_t FieldOffset,
llvm::Constant *InitCst) {
@@ -368,40 +347,21 @@ void ConstStructBuilder::ConvertStructToPacked() {
}
bool ConstStructBuilder::Build(InitListExpr *ILE) {
- if (ILE->initializesStdInitializerList()) {
- //CGM.ErrorUnsupported(ILE, "global std::initializer_list");
- return false;
- }
-
RecordDecl *RD = ILE->getType()->getAs<RecordType>()->getDecl();
const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
unsigned FieldNo = 0;
unsigned ElementNo = 0;
- const FieldDecl *LastFD = 0;
- bool IsMsStruct = RD->isMsStruct(CGM.getContext());
for (RecordDecl::field_iterator Field = RD->field_begin(),
FieldEnd = RD->field_end(); Field != FieldEnd; ++Field, ++FieldNo) {
- if (IsMsStruct) {
- // Zero-length bitfields following non-bitfield members are
- // ignored:
- if (CGM.getContext().ZeroBitfieldFollowsNonBitfield(*Field, LastFD)) {
- --FieldNo;
- continue;
- }
- LastFD = *Field;
- }
-
// If this is a union, skip all the fields that aren't being initialized.
if (RD->isUnion() && ILE->getInitializedFieldInUnion() != *Field)
continue;
// Don't emit anonymous bitfields, they just affect layout.
- if (Field->isUnnamedBitfield()) {
- LastFD = *Field;
+ if (Field->isUnnamedBitfield())
continue;
- }
// Get the initializer. A struct can include fields without initializers,
// we just use explicit null values for them.
@@ -443,15 +403,19 @@ struct BaseInfo {
}
void ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,
- bool IsPrimaryBase, llvm::Constant *VTable,
+ bool IsPrimaryBase,
const CXXRecordDecl *VTableClass,
CharUnits Offset) {
const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
if (const CXXRecordDecl *CD = dyn_cast<CXXRecordDecl>(RD)) {
// Add a vtable pointer, if we need one and it hasn't already been added.
- if (CD->isDynamicClass() && !IsPrimaryBase)
- AppendVTablePointer(BaseSubobject(CD, Offset), VTable, VTableClass);
+ if (CD->isDynamicClass() && !IsPrimaryBase) {
+ llvm::Constant *VTableAddressPoint =
+ CGM.getCXXABI().getVTableAddressPointForConstExpr(
+ BaseSubobject(CD, Offset), VTableClass);
+ AppendBytes(Offset, VTableAddressPoint);
+ }
// Accumulate and sort bases, in order to visit them in address order, which
// may not be the same as declaration order.
@@ -472,36 +436,22 @@ void ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,
bool IsPrimaryBase = Layout.getPrimaryBase() == Base.Decl;
Build(Val.getStructBase(Base.Index), Base.Decl, IsPrimaryBase,
- VTable, VTableClass, Offset + Base.Offset);
+ VTableClass, Offset + Base.Offset);
}
}
unsigned FieldNo = 0;
- const FieldDecl *LastFD = 0;
- bool IsMsStruct = RD->isMsStruct(CGM.getContext());
uint64_t OffsetBits = CGM.getContext().toBits(Offset);
for (RecordDecl::field_iterator Field = RD->field_begin(),
FieldEnd = RD->field_end(); Field != FieldEnd; ++Field, ++FieldNo) {
- if (IsMsStruct) {
- // Zero-length bitfields following non-bitfield members are
- // ignored:
- if (CGM.getContext().ZeroBitfieldFollowsNonBitfield(*Field, LastFD)) {
- --FieldNo;
- continue;
- }
- LastFD = *Field;
- }
-
// If this is a union, skip all the fields that aren't being initialized.
if (RD->isUnion() && Val.getUnionField() != *Field)
continue;
// Don't emit anonymous bitfields, they just affect layout.
- if (Field->isUnnamedBitfield()) {
- LastFD = *Field;
+ if (Field->isUnnamedBitfield())
continue;
- }
// Emit the value of the initializer.
const APValue &FieldValue =
@@ -593,11 +543,7 @@ llvm::Constant *ConstStructBuilder::BuildStruct(CodeGenModule &CGM,
const RecordDecl *RD = ValTy->castAs<RecordType>()->getDecl();
const CXXRecordDecl *CD = dyn_cast<CXXRecordDecl>(RD);
- llvm::Constant *VTable = 0;
- if (CD && CD->isDynamicClass())
- VTable = CGM.getVTables().GetAddrOfVTable(CD);
-
- Builder.Build(Val, RD, false, VTable, CD, CharUnits::Zero());
+ Builder.Build(Val, RD, false, CD, CharUnits::Zero());
return Builder.Finalize(ValTy);
}
@@ -642,6 +588,10 @@ public:
return Visit(GE->getResultExpr());
}
+ llvm::Constant *VisitChooseExpr(ChooseExpr *CE) {
+ return Visit(CE->getChosenSubExpr());
+ }
+
llvm::Constant *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
return Visit(E->getInitializer());
}
@@ -687,6 +637,7 @@ public:
case CK_AtomicToNonAtomic:
case CK_NonAtomicToAtomic:
case CK_NoOp:
+ case CK_ConstructorConversion:
return C;
case CK_Dependent: llvm_unreachable("saw dependent cast!");
@@ -716,7 +667,6 @@ public:
case CK_LValueBitCast:
case CK_NullToMemberPointer:
case CK_UserDefinedConversion:
- case CK_ConstructorConversion:
case CK_CPointerToObjCPointerCast:
case CK_BlockPointerToObjCPointerCast:
case CK_AnyPointerToBlockPointerCast:
@@ -995,7 +945,7 @@ public:
CXXTypeidExpr *Typeid = cast<CXXTypeidExpr>(E);
QualType T;
if (Typeid->isTypeOperand())
- T = Typeid->getTypeOperand();
+ T = Typeid->getTypeOperand(CGM.getContext());
else
T = Typeid->getExprOperand()->getType();
return CGM.GetAddrOfRTTIDescriptor(T);
@@ -1003,6 +953,15 @@ public:
case Expr::CXXUuidofExprClass: {
return CGM.GetAddrOfUuidDescriptor(cast<CXXUuidofExpr>(E));
}
+ case Expr::MaterializeTemporaryExprClass: {
+ MaterializeTemporaryExpr *MTE = cast<MaterializeTemporaryExpr>(E);
+ assert(MTE->getStorageDuration() == SD_Static);
+ SmallVector<const Expr *, 2> CommaLHSs;
+ SmallVector<SubobjectAdjustment, 2> Adjustments;
+ const Expr *Inner = MTE->GetTemporaryExpr()
+ ->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments);
+ return CGM.GetAddrOfGlobalTemporary(MTE, Inner);
+ }
}
return 0;
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index c1c252d..f3a5387 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -87,15 +87,16 @@ public:
void EmitBinOpCheck(Value *Check, const BinOpInfo &Info);
- Value *EmitLoadOfLValue(LValue LV) {
- return CGF.EmitLoadOfLValue(LV).getScalarVal();
+ Value *EmitLoadOfLValue(LValue LV, SourceLocation Loc) {
+ return CGF.EmitLoadOfLValue(LV, Loc).getScalarVal();
}
/// EmitLoadOfLValue - Given an expression with complex type that represents a
/// value l-value, this method emits the address of the l-value, then loads
/// and returns the result.
Value *EmitLoadOfLValue(const Expr *E) {
- return EmitLoadOfLValue(EmitCheckedLValue(E, CodeGenFunction::TCK_Load));
+ return EmitLoadOfLValue(EmitCheckedLValue(E, CodeGenFunction::TCK_Load),
+ E->getExprLoc());
}
/// EmitConversionToBool - Convert the specified expression value to a
@@ -161,18 +162,18 @@ public:
Value *Visit(Expr *E) {
return StmtVisitor<ScalarExprEmitter, Value*>::Visit(E);
}
-
+
Value *VisitStmt(Stmt *S) {
S->dump(CGF.getContext().getSourceManager());
llvm_unreachable("Stmt can't have complex result type!");
}
Value *VisitExpr(Expr *S);
-
+
Value *VisitParenExpr(ParenExpr *PE) {
- return Visit(PE->getSubExpr());
+ return Visit(PE->getSubExpr());
}
Value *VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E) {
- return Visit(E->getReplacement());
+ return Visit(E->getReplacement());
}
Value *VisitGenericSelectionExpr(GenericSelectionExpr *GE) {
return Visit(GE->getResultExpr());
@@ -217,7 +218,7 @@ public:
Value *VisitOpaqueValueExpr(OpaqueValueExpr *E) {
if (E->isGLValue())
- return EmitLoadOfLValue(CGF.getOpaqueLValueMapping(E));
+ return EmitLoadOfLValue(CGF.getOpaqueLValueMapping(E), E->getExprLoc());
// Otherwise, assume the mapping is the scalar directly.
return CGF.getOpaqueRValueMapping(E).getScalarVal();
@@ -227,7 +228,8 @@ public:
Value *VisitDeclRefExpr(DeclRefExpr *E) {
if (CodeGenFunction::ConstantEmission result = CGF.tryEmitAsConstant(E)) {
if (result.isReference())
- return EmitLoadOfLValue(result.getReferenceLValue(CGF, E));
+ return EmitLoadOfLValue(result.getReferenceLValue(CGF, E),
+ E->getExprLoc());
return result.getValue();
}
return EmitLoadOfLValue(E);
@@ -243,7 +245,7 @@ public:
return EmitLoadOfLValue(E);
}
Value *VisitObjCMessageExpr(ObjCMessageExpr *E) {
- if (E->getMethodDecl() &&
+ if (E->getMethodDecl() &&
E->getMethodDecl()->getResultType()->isReferenceType())
return EmitLoadOfLValue(E);
return CGF.EmitObjCMessageExpr(E).getScalarVal();
@@ -251,12 +253,13 @@ public:
Value *VisitObjCIsaExpr(ObjCIsaExpr *E) {
LValue LV = CGF.EmitObjCIsaExpr(E);
- Value *V = CGF.EmitLoadOfLValue(LV).getScalarVal();
+ Value *V = CGF.EmitLoadOfLValue(LV, E->getExprLoc()).getScalarVal();
return V;
}
Value *VisitArraySubscriptExpr(ArraySubscriptExpr *E);
Value *VisitShuffleVectorExpr(ShuffleVectorExpr *E);
+ Value *VisitConvertVectorExpr(ConvertVectorExpr *E);
Value *VisitMemberExpr(MemberExpr *E);
Value *VisitExtVectorElementExpr(Expr *E) { return EmitLoadOfLValue(E); }
Value *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
@@ -310,7 +313,7 @@ public:
llvm::Value *EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
bool isInc, bool isPre);
-
+
Value *VisitUnaryAddrOf(const UnaryOperator *E) {
if (isa<MemberPointerType>(E->getType())) // never sugared
return CGF.CGM.getMemberPointerConstant(E);
@@ -335,12 +338,12 @@ public:
Value *VisitUnaryExtension(const UnaryOperator *E) {
return Visit(E->getSubExpr());
}
-
+
// C++
Value *VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E) {
return EmitLoadOfLValue(E);
}
-
+
Value *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
return Visit(DAE->getExpr());
}
@@ -430,7 +433,7 @@ public:
Value *EmitOverflowCheckedBinOp(const BinOpInfo &Ops);
// Check for undefined division and modulus behaviors.
- void EmitUndefinedBehaviorIntegerDivAndRemCheck(const BinOpInfo &Ops,
+ void EmitUndefinedBehaviorIntegerDivAndRemCheck(const BinOpInfo &Ops,
llvm::Value *Zero,bool isDiv);
// Common helper for getting how wide LHS of shift is.
static Value *GetWidthMinusOneValue(Value* LHS,Value* RHS);
@@ -893,51 +896,43 @@ Value *ScalarExprEmitter::VisitExpr(Expr *E) {
Value *ScalarExprEmitter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) {
// Vector Mask Case
- if (E->getNumSubExprs() == 2 ||
+ if (E->getNumSubExprs() == 2 ||
(E->getNumSubExprs() == 3 && E->getExpr(2)->getType()->isVectorType())) {
Value *LHS = CGF.EmitScalarExpr(E->getExpr(0));
Value *RHS = CGF.EmitScalarExpr(E->getExpr(1));
Value *Mask;
-
+
llvm::VectorType *LTy = cast<llvm::VectorType>(LHS->getType());
unsigned LHSElts = LTy->getNumElements();
if (E->getNumSubExprs() == 3) {
Mask = CGF.EmitScalarExpr(E->getExpr(2));
-
+
// Shuffle LHS & RHS into one input vector.
SmallVector<llvm::Constant*, 32> concat;
for (unsigned i = 0; i != LHSElts; ++i) {
concat.push_back(Builder.getInt32(2*i));
concat.push_back(Builder.getInt32(2*i+1));
}
-
+
Value* CV = llvm::ConstantVector::get(concat);
LHS = Builder.CreateShuffleVector(LHS, RHS, CV, "concat");
LHSElts *= 2;
} else {
Mask = RHS;
}
-
+
llvm::VectorType *MTy = cast<llvm::VectorType>(Mask->getType());
llvm::Constant* EltMask;
-
- // Treat vec3 like vec4.
- if ((LHSElts == 6) && (E->getNumSubExprs() == 3))
- EltMask = llvm::ConstantInt::get(MTy->getElementType(),
- (1 << llvm::Log2_32(LHSElts+2))-1);
- else if ((LHSElts == 3) && (E->getNumSubExprs() == 2))
- EltMask = llvm::ConstantInt::get(MTy->getElementType(),
- (1 << llvm::Log2_32(LHSElts+1))-1);
- else
- EltMask = llvm::ConstantInt::get(MTy->getElementType(),
- (1 << llvm::Log2_32(LHSElts))-1);
-
+
+ EltMask = llvm::ConstantInt::get(MTy->getElementType(),
+ llvm::NextPowerOf2(LHSElts-1)-1);
+
// Mask off the high bits of each shuffle index.
Value *MaskBits = llvm::ConstantVector::getSplat(MTy->getNumElements(),
EltMask);
Mask = Builder.CreateAnd(Mask, MaskBits, "mask");
-
+
// newv = undef
// mask = mask & maskbits
// for each elt
@@ -945,43 +940,110 @@ Value *ScalarExprEmitter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) {
// x = extract val n
// newv = insert newv, x, i
llvm::VectorType *RTy = llvm::VectorType::get(LTy->getElementType(),
- MTy->getNumElements());
+ MTy->getNumElements());
Value* NewV = llvm::UndefValue::get(RTy);
for (unsigned i = 0, e = MTy->getNumElements(); i != e; ++i) {
Value *IIndx = Builder.getInt32(i);
Value *Indx = Builder.CreateExtractElement(Mask, IIndx, "shuf_idx");
Indx = Builder.CreateZExt(Indx, CGF.Int32Ty, "idx_zext");
-
- // Handle vec3 special since the index will be off by one for the RHS.
- if ((LHSElts == 6) && (E->getNumSubExprs() == 3)) {
- Value *cmpIndx, *newIndx;
- cmpIndx = Builder.CreateICmpUGT(Indx, Builder.getInt32(3),
- "cmp_shuf_idx");
- newIndx = Builder.CreateSub(Indx, Builder.getInt32(1), "shuf_idx_adj");
- Indx = Builder.CreateSelect(cmpIndx, newIndx, Indx, "sel_shuf_idx");
- }
+
Value *VExt = Builder.CreateExtractElement(LHS, Indx, "shuf_elt");
NewV = Builder.CreateInsertElement(NewV, VExt, IIndx, "shuf_ins");
}
return NewV;
}
-
+
Value* V1 = CGF.EmitScalarExpr(E->getExpr(0));
Value* V2 = CGF.EmitScalarExpr(E->getExpr(1));
-
- // Handle vec3 special since the index will be off by one for the RHS.
- llvm::VectorType *VTy = cast<llvm::VectorType>(V1->getType());
+
SmallVector<llvm::Constant*, 32> indices;
- for (unsigned i = 2; i < E->getNumSubExprs(); i++) {
- unsigned Idx = E->getShuffleMaskIdx(CGF.getContext(), i-2);
- if (VTy->getNumElements() == 3 && Idx > 3)
- Idx -= 1;
- indices.push_back(Builder.getInt32(Idx));
+ for (unsigned i = 2; i < E->getNumSubExprs(); ++i) {
+ llvm::APSInt Idx = E->getShuffleMaskIdx(CGF.getContext(), i-2);
+ // Check for -1 and output it as undef in the IR.
+ if (Idx.isSigned() && Idx.isAllOnesValue())
+ indices.push_back(llvm::UndefValue::get(CGF.Int32Ty));
+ else
+ indices.push_back(Builder.getInt32(Idx.getZExtValue()));
}
Value *SV = llvm::ConstantVector::get(indices);
return Builder.CreateShuffleVector(V1, V2, SV, "shuffle");
}
+
+Value *ScalarExprEmitter::VisitConvertVectorExpr(ConvertVectorExpr *E) {
+ QualType SrcType = E->getSrcExpr()->getType(),
+ DstType = E->getType();
+
+ Value *Src = CGF.EmitScalarExpr(E->getSrcExpr());
+
+ SrcType = CGF.getContext().getCanonicalType(SrcType);
+ DstType = CGF.getContext().getCanonicalType(DstType);
+ if (SrcType == DstType) return Src;
+
+ assert(SrcType->isVectorType() &&
+ "ConvertVector source type must be a vector");
+ assert(DstType->isVectorType() &&
+ "ConvertVector destination type must be a vector");
+
+ llvm::Type *SrcTy = Src->getType();
+ llvm::Type *DstTy = ConvertType(DstType);
+
+ // Ignore conversions like int -> uint.
+ if (SrcTy == DstTy)
+ return Src;
+
+ QualType SrcEltType = SrcType->getAs<VectorType>()->getElementType(),
+ DstEltType = DstType->getAs<VectorType>()->getElementType();
+
+ assert(SrcTy->isVectorTy() &&
+ "ConvertVector source IR type must be a vector");
+ assert(DstTy->isVectorTy() &&
+ "ConvertVector destination IR type must be a vector");
+
+ llvm::Type *SrcEltTy = SrcTy->getVectorElementType(),
+ *DstEltTy = DstTy->getVectorElementType();
+
+ if (DstEltType->isBooleanType()) {
+ assert((SrcEltTy->isFloatingPointTy() ||
+ isa<llvm::IntegerType>(SrcEltTy)) && "Unknown boolean conversion");
+
+ llvm::Value *Zero = llvm::Constant::getNullValue(SrcTy);
+ if (SrcEltTy->isFloatingPointTy()) {
+ return Builder.CreateFCmpUNE(Src, Zero, "tobool");
+ } else {
+ return Builder.CreateICmpNE(Src, Zero, "tobool");
+ }
+ }
+
+ // We have the arithmetic types: real int/float.
+ Value *Res = NULL;
+
+ if (isa<llvm::IntegerType>(SrcEltTy)) {
+ bool InputSigned = SrcEltType->isSignedIntegerOrEnumerationType();
+ if (isa<llvm::IntegerType>(DstEltTy))
+ Res = Builder.CreateIntCast(Src, DstTy, InputSigned, "conv");
+ else if (InputSigned)
+ Res = Builder.CreateSIToFP(Src, DstTy, "conv");
+ else
+ Res = Builder.CreateUIToFP(Src, DstTy, "conv");
+ } else if (isa<llvm::IntegerType>(DstEltTy)) {
+ assert(SrcEltTy->isFloatingPointTy() && "Unknown real conversion");
+ if (DstEltType->isSignedIntegerOrEnumerationType())
+ Res = Builder.CreateFPToSI(Src, DstTy, "conv");
+ else
+ Res = Builder.CreateFPToUI(Src, DstTy, "conv");
+ } else {
+ assert(SrcEltTy->isFloatingPointTy() && DstEltTy->isFloatingPointTy() &&
+ "Unknown real conversion");
+ if (DstEltTy->getTypeID() < SrcEltTy->getTypeID())
+ Res = Builder.CreateFPTrunc(Src, DstTy, "conv");
+ else
+ Res = Builder.CreateFPExt(Src, DstTy, "conv");
+ }
+
+ return Res;
+}
+
Value *ScalarExprEmitter::VisitMemberExpr(MemberExpr *E) {
llvm::APSInt Value;
if (E->EvaluateAsInt(Value, CGF.getContext(), Expr::SE_AllowSideEffects)) {
@@ -992,18 +1054,6 @@ Value *ScalarExprEmitter::VisitMemberExpr(MemberExpr *E) {
return Builder.getInt(Value);
}
- // Emit debug info for aggregate now, if it was delayed to reduce
- // debug info size.
- CGDebugInfo *DI = CGF.getDebugInfo();
- if (DI &&
- CGF.CGM.getCodeGenOpts().getDebugInfo()
- == CodeGenOptions::LimitedDebugInfo) {
- QualType PQTy = E->getBase()->IgnoreParenImpCasts()->getType();
- if (const PointerType * PTy = dyn_cast<PointerType>(PQTy))
- if (FieldDecl *M = dyn_cast<FieldDecl>(E->getMemberDecl()))
- DI->getOrCreateRecordType(PTy->getPointeeType(),
- M->getParent()->getLocation());
- }
return EmitLoadOfLValue(E);
}
@@ -1023,7 +1073,7 @@ Value *ScalarExprEmitter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
Value *Idx = Visit(E->getIdx());
QualType IdxTy = E->getIdx()->getType();
- if (CGF.SanOpts->Bounds)
+ if (CGF.SanOpts->ArrayBounds)
CGF.EmitBoundsCheck(E, E->getBase(), Idx, IdxTy, /*Accessed*/true);
bool IdxSigned = IdxTy->isSignedIntegerOrEnumerationType();
@@ -1034,7 +1084,7 @@ Value *ScalarExprEmitter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
static llvm::Constant *getMaskElt(llvm::ShuffleVectorInst *SVI, unsigned Idx,
unsigned Off, llvm::Type *I32Ty) {
int MV = SVI->getMaskValue(Idx);
- if (MV == -1)
+ if (MV == -1)
return llvm::UndefValue::get(I32Ty);
return llvm::ConstantInt::get(I32Ty, Off+MV);
}
@@ -1044,13 +1094,13 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) {
(void)Ignore;
assert (Ignore == false && "init list ignored");
unsigned NumInitElements = E->getNumInits();
-
+
if (E->hadArrayRangeDesignator())
CGF.ErrorUnsupported(E, "GNU array range designator extension");
-
+
llvm::VectorType *VType =
dyn_cast<llvm::VectorType>(ConvertType(E->getType()));
-
+
if (!VType) {
if (NumInitElements == 0) {
// C++11 value-initialization for the scalar.
@@ -1059,10 +1109,10 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) {
// We have a scalar in braces. Just use the first element.
return Visit(E->getInit(0));
}
-
+
unsigned ResElts = VType->getNumElements();
-
- // Loop over initializers collecting the Value for each, and remembering
+
+ // Loop over initializers collecting the Value for each, and remembering
// whether the source was swizzle (ExtVectorElementExpr). This will allow
// us to fold the shuffle for the swizzle into the shuffle for the vector
// initializer, since LLVM optimizers generally do not want to touch
@@ -1074,11 +1124,11 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) {
Expr *IE = E->getInit(i);
Value *Init = Visit(IE);
SmallVector<llvm::Constant*, 16> Args;
-
+
llvm::VectorType *VVT = dyn_cast<llvm::VectorType>(Init->getType());
-
+
// Handle scalar elements. If the scalar initializer is actually one
- // element of a different vector of the same width, use shuffle instead of
+ // element of a different vector of the same width, use shuffle instead of
// extract+insert.
if (!VVT) {
if (isa<ExtVectorElementExpr>(IE)) {
@@ -1121,10 +1171,10 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) {
++CurIdx;
continue;
}
-
+
unsigned InitElts = VVT->getNumElements();
- // If the initializer is an ExtVecEltExpr (a swizzle), and the swizzle's
+ // If the initializer is an ExtVecEltExpr (a swizzle), and the swizzle's
// input is the same width as the vector being constructed, generate an
// optimized shuffle of the swizzle input into the result.
unsigned Offset = (CurIdx == 0) ? 0 : ResElts;
@@ -1132,7 +1182,7 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) {
llvm::ShuffleVectorInst *SVI = cast<llvm::ShuffleVectorInst>(Init);
Value *SVOp = SVI->getOperand(0);
llvm::VectorType *OpTy = cast<llvm::VectorType>(SVOp->getType());
-
+
if (OpTy->getNumElements() == ResElts) {
for (unsigned j = 0; j != CurIdx; ++j) {
// If the current vector initializer is a shuffle with undef, merge
@@ -1182,11 +1232,11 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) {
VIsUndefShuffle = isa<llvm::UndefValue>(Init);
CurIdx += InitElts;
}
-
+
// FIXME: evaluate codegen vs. shuffling against constant null vector.
// Emit remaining default initializers.
llvm::Type *EltTy = VType->getElementType();
-
+
// Emit remaining default initializers
for (/* Do not initialize i*/; CurIdx < ResElts; ++CurIdx) {
Value *Idx = Builder.getInt32(CurIdx);
@@ -1201,12 +1251,12 @@ static bool ShouldNullCheckClassCastValue(const CastExpr *CE) {
if (CE->getCastKind() == CK_UncheckedDerivedToBase)
return false;
-
+
if (isa<CXXThisExpr>(E)) {
// We always assume that 'this' is never null.
return false;
}
-
+
if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(CE)) {
// And that glvalue casts are never null.
if (ICE->getValueKind() != VK_RValue)
@@ -1223,7 +1273,7 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
Expr *E = CE->getSubExpr();
QualType DestTy = CE->getType();
CastKind Kind = CE->getCastKind();
-
+
if (!DestTy->isVoidType())
TestAndClearIgnoreResultAssign();
@@ -1235,12 +1285,13 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
case CK_BuiltinFnToFnPtr:
llvm_unreachable("builtin functions are handled elsewhere");
- case CK_LValueBitCast:
+ case CK_LValueBitCast:
case CK_ObjCObjectLValueCast: {
Value *V = EmitLValue(E).getAddress();
- V = Builder.CreateBitCast(V,
+ V = Builder.CreateBitCast(V,
ConvertType(CGF.getContext().getPointerType(DestTy)));
- return EmitLoadOfLValue(CGF.MakeNaturalAlignAddrLValue(V, DestTy));
+ return EmitLoadOfLValue(CGF.MakeNaturalAlignAddrLValue(V, DestTy),
+ CE->getExprLoc());
}
case CK_CPointerToObjCPointerCast:
@@ -1262,15 +1313,18 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
llvm::Value *V = Visit(E);
+ llvm::Value *Derived =
+ CGF.GetAddressOfDerivedClass(V, DerivedClassDecl,
+ CE->path_begin(), CE->path_end(),
+ ShouldNullCheckClassCastValue(CE));
+
// C++11 [expr.static.cast]p11: Behavior is undefined if a downcast is
// performed and the object is not of the derived type.
if (CGF.SanitizePerformTypeCheck)
CGF.EmitTypeCheck(CodeGenFunction::TCK_DowncastPointer, CE->getExprLoc(),
- V, DestTy->getPointeeType());
+ Derived, DestTy->getPointeeType());
- return CGF.GetAddressOfDerivedClass(V, DerivedClassDecl,
- CE->path_begin(), CE->path_end(),
- ShouldNullCheckClassCastValue(CE));
+ return Derived;
}
case CK_UncheckedDerivedToBase:
case CK_DerivedToBase: {
@@ -1278,7 +1332,7 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
E->getType()->getPointeeCXXRecordDecl();
assert(DerivedClassDecl && "DerivedToBase arg isn't a C++ object pointer!");
- return CGF.GetAddressOfBaseClass(Visit(E), DerivedClassDecl,
+ return CGF.GetAddressOfBaseClass(Visit(E), DerivedClassDecl,
CE->path_begin(), CE->path_end(),
ShouldNullCheckClassCastValue(CE));
}
@@ -1330,7 +1384,7 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
case CK_BaseToDerivedMemberPointer:
case CK_DerivedToBaseMemberPointer: {
Value *Src = Visit(E);
-
+
// Note that the AST doesn't distinguish between checked and
// unchecked member pointer conversions, so we always have to
// implement checked conversions here. This is inefficient when
@@ -1354,7 +1408,7 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
case CK_CopyAndAutoreleaseBlockObject:
return CGF.EmitBlockCopyAndAutorelease(Visit(E), E->getType());
-
+
case CK_FloatingRealToComplex:
case CK_FloatingComplexCast:
case CK_IntegralRealToComplex:
@@ -1442,8 +1496,12 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
Value *ScalarExprEmitter::VisitStmtExpr(const StmtExpr *E) {
CodeGenFunction::StmtExprEvaluation eval(CGF);
- return CGF.EmitCompoundStmt(*E->getSubStmt(), !E->getType()->isVoidType())
- .getScalarVal();
+ llvm::Value *RetAlloca = CGF.EmitCompoundStmt(*E->getSubStmt(),
+ !E->getType()->isVoidType());
+ if (!RetAlloca)
+ return 0;
+ return CGF.EmitLoadOfScalar(CGF.MakeAddrLValue(RetAlloca, E->getType()),
+ E->getExprLoc());
}
//===----------------------------------------------------------------------===//
@@ -1477,7 +1535,7 @@ EmitAddConsiderOverflowBehavior(const UnaryOperator *E,
llvm::Value *
ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
bool isInc, bool isPre) {
-
+
QualType type = E->getSubExpr()->getType();
llvm::PHINode *atomicPHI = 0;
llvm::Value *value;
@@ -1503,7 +1561,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
}
// Special case for atomic increment / decrement on integers, emit
// atomicrmw instructions. We skip this if we want to be doing overflow
- // checking, and fall into the slow path with the atomic cmpxchg loop.
+ // checking, and fall into the slow path with the atomic cmpxchg loop.
if (!type->isBooleanType() && type->isIntegerType() &&
!(type->isUnsignedIntegerType() &&
CGF.SanOpts->UnsignedIntegerOverflow) &&
@@ -1519,7 +1577,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
LV.getAddress(), amt, llvm::SequentiallyConsistent);
return isPre ? Builder.CreateBinOp(op, old, amt) : old;
}
- value = EmitLoadOfLValue(LV);
+ value = EmitLoadOfLValue(LV, E->getExprLoc());
input = value;
// For every other atomic operation, we need to emit a load-op-cmpxchg loop
llvm::BasicBlock *startBB = Builder.GetInsertBlock();
@@ -1531,7 +1589,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
atomicPHI->addIncoming(value, startBB);
value = atomicPHI;
} else {
- value = EmitLoadOfLValue(LV);
+ value = EmitLoadOfLValue(LV, E->getExprLoc());
input = value;
}
@@ -1569,7 +1627,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
value = EmitOverflowCheckedBinOp(BinOp);
} else
value = Builder.CreateAdd(value, amt, isInc ? "inc" : "dec");
-
+
// Next most common: pointer increment.
} else if (const PointerType *ptr = type->getAs<PointerType>()) {
QualType type = ptr->getPointeeType();
@@ -1583,7 +1641,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
value = Builder.CreateGEP(value, numElts, "vla.inc");
else
value = Builder.CreateInBoundsGEP(value, numElts, "vla.inc");
-
+
// Arithmetic on function pointers (!) is just +-1.
} else if (type->isFunctionType()) {
llvm::Value *amt = Builder.getInt32(amount);
@@ -1665,7 +1723,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
value = Builder.CreateInBoundsGEP(value, sizeValue, "incdec.objptr");
value = Builder.CreateBitCast(value, input->getType());
}
-
+
if (atomicPHI) {
llvm::BasicBlock *opBB = Builder.GetInsertBlock();
llvm::BasicBlock *contBB = CGF.createBasicBlock("atomic_cont", CGF.CurFn);
@@ -1696,10 +1754,10 @@ Value *ScalarExprEmitter::VisitUnaryMinus(const UnaryOperator *E) {
// Emit unary minus with EmitSub so we handle overflow cases etc.
BinOpInfo BinOp;
BinOp.RHS = Visit(E->getSubExpr());
-
+
if (BinOp.RHS->getType()->isFPOrFPVectorTy())
BinOp.LHS = llvm::ConstantFP::getZeroValueForNegation(BinOp.RHS->getType());
- else
+ else
BinOp.LHS = llvm::Constant::getNullValue(BinOp.RHS->getType());
BinOp.Ty = E->getType();
BinOp.Opcode = BO_Sub;
@@ -1726,7 +1784,7 @@ Value *ScalarExprEmitter::VisitUnaryLNot(const UnaryOperator *E) {
Result = Builder.CreateICmp(llvm::CmpInst::ICMP_EQ, Oper, Zero, "cmp");
return Builder.CreateSExt(Result, ConvertType(E->getType()), "sext");
}
-
+
// Compare operand to zero.
Value *BoolVal = CGF.EvaluateExprAsBool(E->getSubExpr());
@@ -1814,7 +1872,7 @@ Value *ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *E) {
// Save the element type.
CurrentType = ON.getBase()->getType();
-
+
// Compute the offset to the base.
const RecordType *BaseRT = CurrentType->getAs<RecordType>();
CXXRecordDecl *BaseRD = cast<CXXRecordDecl>(BaseRT->getDecl());
@@ -1873,7 +1931,8 @@ Value *ScalarExprEmitter::VisitUnaryReal(const UnaryOperator *E) {
// Note that we have to ask E because Op might be an l-value that
// this won't work for, e.g. an Obj-C property.
if (E->isGLValue())
- return CGF.EmitLoadOfLValue(CGF.EmitLValue(E)).getScalarVal();
+ return CGF.EmitLoadOfLValue(CGF.EmitLValue(E),
+ E->getExprLoc()).getScalarVal();
// Otherwise, calculate and project.
return CGF.EmitComplexExpr(Op, false, true).first;
@@ -1889,7 +1948,8 @@ Value *ScalarExprEmitter::VisitUnaryImag(const UnaryOperator *E) {
// Note that we have to ask E because Op might be an l-value that
// this won't work for, e.g. an Obj-C property.
if (Op->isGLValue())
- return CGF.EmitLoadOfLValue(CGF.EmitLValue(E)).getScalarVal();
+ return CGF.EmitLoadOfLValue(CGF.EmitLValue(E),
+ E->getExprLoc()).getScalarVal();
// Otherwise, calculate and project.
return CGF.EmitComplexExpr(Op, true, false).second;
@@ -1926,17 +1986,10 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue(
Value *&Result) {
QualType LHSTy = E->getLHS()->getType();
BinOpInfo OpInfo;
-
- if (E->getComputationResultType()->isAnyComplexType()) {
- // This needs to go through the complex expression emitter, but it's a tad
- // complicated to do that... I'm leaving it out for now. (Note that we do
- // actually need the imaginary part of the RHS for multiplication and
- // division.)
- CGF.ErrorUnsupported(E, "complex compound assignment");
- Result = llvm::UndefValue::get(CGF.ConvertType(E->getType()));
- return LValue();
- }
-
+
+ if (E->getComputationResultType()->isAnyComplexType())
+ return CGF.EmitScalarCompooundAssignWithComplex(E, Result);
+
// Emit the RHS first. __block variables need to have the rhs evaluated
// first, plus this should improve codegen a little.
OpInfo.RHS = Visit(E->getRHS());
@@ -1993,7 +2046,7 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue(
// floating point environment in the loop.
llvm::BasicBlock *startBB = Builder.GetInsertBlock();
llvm::BasicBlock *opBB = CGF.createBasicBlock("atomic_op", CGF.CurFn);
- OpInfo.LHS = EmitLoadOfLValue(LHSLV);
+ OpInfo.LHS = EmitLoadOfLValue(LHSLV, E->getExprLoc());
OpInfo.LHS = CGF.EmitToMemory(OpInfo.LHS, type);
Builder.CreateBr(opBB);
Builder.SetInsertPoint(opBB);
@@ -2002,14 +2055,14 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue(
OpInfo.LHS = atomicPHI;
}
else
- OpInfo.LHS = EmitLoadOfLValue(LHSLV);
+ OpInfo.LHS = EmitLoadOfLValue(LHSLV, E->getExprLoc());
OpInfo.LHS = EmitScalarConversion(OpInfo.LHS, LHSTy,
E->getComputationLHSType());
// Expand the binary operator.
Result = (this->*Func)(OpInfo);
-
+
// Convert the result back to the LHS type.
Result = EmitScalarConversion(Result, E->getComputationResultType(), LHSTy);
@@ -2024,7 +2077,7 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue(
Builder.SetInsertPoint(contBB);
return LHSLV;
}
-
+
// Store the result value into the LHS lvalue. Bit-fields are handled
// specially because the result is altered by the store, i.e., [C99 6.5.16p1]
// 'An assignment expression has the value of the left operand after the
@@ -2056,7 +2109,7 @@ Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E,
return RHS;
// Otherwise, reload the value.
- return EmitLoadOfLValue(LHS);
+ return EmitLoadOfLValue(LHS, E->getExprLoc());
}
void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
@@ -2236,7 +2289,7 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF,
// Must have binary (not unary) expr here. Unary pointer
// increment/decrement doesn't use this path.
const BinaryOperator *expr = cast<BinaryOperator>(op.E);
-
+
Value *pointer = op.LHS;
Expr *pointerOperand = expr->getLHS();
Value *index = op.RHS;
@@ -2261,7 +2314,7 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF,
if (isSubtraction)
index = CGF.Builder.CreateNeg(index, "idx.neg");
- if (CGF.SanOpts->Bounds)
+ if (CGF.SanOpts->ArrayBounds)
CGF.EmitBoundsCheck(op.E, pointerOperand, index, indexOperand->getType(),
/*Accessed*/ false);
@@ -2325,7 +2378,7 @@ static Value* buildFMulAdd(llvm::BinaryOperator *MulOp, Value *Addend,
const CodeGenFunction &CGF, CGBuilderTy &Builder,
bool negMul, bool negAdd) {
assert(!(negMul && negAdd) && "Only one of negMul and negAdd should be set.");
-
+
Value *MulOp0 = MulOp->getOperand(0);
Value *MulOp1 = MulOp->getOperand(1);
if (negMul) {
@@ -2355,7 +2408,7 @@ static Value* buildFMulAdd(llvm::BinaryOperator *MulOp, Value *Addend,
// Checks that (a) the operation is fusable, and (b) -ffp-contract=on.
// Does NOT check the type of the operation - it's assumed that this function
// will be called from contexts where it's known that the type is contractable.
-static Value* tryEmitFMulAdd(const BinOpInfo &op,
+static Value* tryEmitFMulAdd(const BinOpInfo &op,
const CodeGenFunction &CGF, CGBuilderTy &Builder,
bool isSub=false) {
@@ -2503,7 +2556,7 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &op) {
divisor = CGF.CGM.getSize(elementSize);
}
-
+
// Otherwise, do a full sdiv. This uses the "exact" form of sdiv, since
// pointer difference in C is only defined in the case where both operands
// are pointing to elements of an array.
@@ -2809,7 +2862,7 @@ Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) {
return RHS;
// Otherwise, reload the value.
- return EmitLoadOfLValue(LHS);
+ return EmitLoadOfLValue(LHS, E->getExprLoc());
}
Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
@@ -2828,9 +2881,9 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
Value *And = Builder.CreateAnd(LHS, RHS);
return Builder.CreateSExt(And, ConvertType(E->getType()), "sext");
}
-
+
llvm::Type *ResTy = ConvertType(E->getType());
-
+
// If we have 0 && RHS, see if we can elide RHS, if so, just return 0.
// If we have 1 && X, just emit X without inserting the control flow.
bool LHSCondVal;
@@ -2899,9 +2952,9 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
Value *Or = Builder.CreateOr(LHS, RHS);
return Builder.CreateSExt(Or, ConvertType(E->getType()), "sext");
}
-
+
llvm::Type *ResTy = ConvertType(E->getType());
-
+
// If we have 1 || RHS, see if we can elide RHS, if so, just return 1.
// If we have 0 || X, just emit X without inserting the control flow.
bool LHSCondVal;
@@ -2970,22 +3023,15 @@ Value *ScalarExprEmitter::VisitBinComma(const BinaryOperator *E) {
/// flow into selects in some cases.
static bool isCheapEnoughToEvaluateUnconditionally(const Expr *E,
CodeGenFunction &CGF) {
- E = E->IgnoreParens();
-
// Anything that is an integer or floating point constant is fine.
- if (E->isConstantInitializer(CGF.getContext(), false))
- return true;
-
- // Non-volatile automatic variables too, to get "cond ? X : Y" where
- // X and Y are local variables.
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
- if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl()))
- if (VD->hasLocalStorage() && !(CGF.getContext()
- .getCanonicalType(VD->getType())
- .isVolatileQualified()))
- return true;
-
- return false;
+ return E->IgnoreParens()->isEvaluatable(CGF.getContext());
+
+ // Even non-volatile automatic variables can't be evaluated unconditionally.
+ // Referencing a thread_local may cause non-trivial initialization work to
+ // occur. If we're inside a lambda and one of the variables is from the scope
+ // outside the lambda, that function may have returned already. Reading its
+ // locals is a bad idea. Also, these reads may introduce races there didn't
+ // exist in the source-level program.
}
@@ -3023,26 +3069,26 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
// OpenCL: If the condition is a vector, we can treat this condition like
// the select function.
- if (CGF.getLangOpts().OpenCL
+ if (CGF.getLangOpts().OpenCL
&& condExpr->getType()->isVectorType()) {
llvm::Value *CondV = CGF.EmitScalarExpr(condExpr);
llvm::Value *LHS = Visit(lhsExpr);
llvm::Value *RHS = Visit(rhsExpr);
-
+
llvm::Type *condType = ConvertType(condExpr->getType());
llvm::VectorType *vecTy = cast<llvm::VectorType>(condType);
-
- unsigned numElem = vecTy->getNumElements();
+
+ unsigned numElem = vecTy->getNumElements();
llvm::Type *elemType = vecTy->getElementType();
-
+
llvm::Value *zeroVec = llvm::Constant::getNullValue(vecTy);
llvm::Value *TestMSB = Builder.CreateICmpSLT(CondV, zeroVec);
- llvm::Value *tmp = Builder.CreateSExt(TestMSB,
+ llvm::Value *tmp = Builder.CreateSExt(TestMSB,
llvm::VectorType::get(elemType,
- numElem),
+ numElem),
"sext");
llvm::Value *tmp2 = Builder.CreateNot(tmp);
-
+
// Cast float to int to perform ANDs if necessary.
llvm::Value *RHSTmp = RHS;
llvm::Value *LHSTmp = LHS;
@@ -3053,7 +3099,7 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
LHSTmp = Builder.CreateBitCast(LHS, tmp->getType());
wasCast = true;
}
-
+
llvm::Value *tmp3 = Builder.CreateAnd(RHSTmp, tmp2);
llvm::Value *tmp4 = Builder.CreateAnd(LHSTmp, tmp);
llvm::Value *tmp5 = Builder.CreateOr(tmp3, tmp4, "cond");
@@ -3062,7 +3108,7 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
return tmp5;
}
-
+
// If this is a really simple expression (like x ? 4 : 5), emit this as a
// select instead of as control flow. We can only do this if it is cheap and
// safe to evaluate the LHS and RHS unconditionally.
@@ -3116,7 +3162,7 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
}
Value *ScalarExprEmitter::VisitChooseExpr(ChooseExpr *E) {
- return Visit(E->getChosenSubExpr(CGF.getContext()));
+ return Visit(E->getChosenSubExpr());
}
Value *ScalarExprEmitter::VisitVAArgExpr(VAArgExpr *VE) {
@@ -3138,49 +3184,49 @@ Value *ScalarExprEmitter::VisitBlockExpr(const BlockExpr *block) {
Value *ScalarExprEmitter::VisitAsTypeExpr(AsTypeExpr *E) {
Value *Src = CGF.EmitScalarExpr(E->getSrcExpr());
llvm::Type *DstTy = ConvertType(E->getType());
-
+
// Going from vec4->vec3 or vec3->vec4 is a special case and requires
// a shuffle vector instead of a bitcast.
llvm::Type *SrcTy = Src->getType();
if (isa<llvm::VectorType>(DstTy) && isa<llvm::VectorType>(SrcTy)) {
unsigned numElementsDst = cast<llvm::VectorType>(DstTy)->getNumElements();
unsigned numElementsSrc = cast<llvm::VectorType>(SrcTy)->getNumElements();
- if ((numElementsDst == 3 && numElementsSrc == 4)
+ if ((numElementsDst == 3 && numElementsSrc == 4)
|| (numElementsDst == 4 && numElementsSrc == 3)) {
-
-
+
+
// In the case of going from int4->float3, a bitcast is needed before
// doing a shuffle.
- llvm::Type *srcElemTy =
+ llvm::Type *srcElemTy =
cast<llvm::VectorType>(SrcTy)->getElementType();
- llvm::Type *dstElemTy =
+ llvm::Type *dstElemTy =
cast<llvm::VectorType>(DstTy)->getElementType();
-
+
if ((srcElemTy->isIntegerTy() && dstElemTy->isFloatTy())
|| (srcElemTy->isFloatTy() && dstElemTy->isIntegerTy())) {
// Create a float type of the same size as the source or destination.
llvm::VectorType *newSrcTy = llvm::VectorType::get(dstElemTy,
numElementsSrc);
-
+
Src = Builder.CreateBitCast(Src, newSrcTy, "astypeCast");
}
-
+
llvm::Value *UnV = llvm::UndefValue::get(Src->getType());
-
+
SmallVector<llvm::Constant*, 3> Args;
Args.push_back(Builder.getInt32(0));
Args.push_back(Builder.getInt32(1));
Args.push_back(Builder.getInt32(2));
-
+
if (numElementsDst == 4)
Args.push_back(llvm::UndefValue::get(CGF.Int32Ty));
-
+
llvm::Constant *Mask = llvm::ConstantVector::get(Args);
-
+
return Builder.CreateShuffleVector(Src, UnV, Mask, "astype");
}
}
-
+
return Builder.CreateBitCast(Src, DstTy, "astype");
}
@@ -3248,14 +3294,14 @@ LValue CodeGenFunction::EmitObjCIsaExpr(const ObjCIsaExpr *E) {
llvm::Value *Src = EmitScalarExpr(BaseExpr);
Builder.CreateStore(Src, V);
V = ScalarExprEmitter(*this).EmitLoadOfLValue(
- MakeNaturalAlignAddrLValue(V, E->getType()));
+ MakeNaturalAlignAddrLValue(V, E->getType()), E->getExprLoc());
} else {
if (E->isArrow())
V = ScalarExprEmitter(*this).EmitLoadOfLValue(BaseExpr);
else
V = EmitLValue(BaseExpr).getAddress();
}
-
+
// build Class* type
ClassPtrTy = ClassPtrTy->getPointerTo();
V = Builder.CreateBitCast(V, ClassPtrTy);
@@ -3283,7 +3329,7 @@ LValue CodeGenFunction::EmitCompoundAssignmentLValue(
COMPOUND_OP(Xor);
COMPOUND_OP(Or);
#undef COMPOUND_OP
-
+
case BO_PtrMemD:
case BO_PtrMemI:
case BO_Mul:
@@ -3308,6 +3354,6 @@ LValue CodeGenFunction::EmitCompoundAssignmentLValue(
case BO_Comma:
llvm_unreachable("Not valid compound assignment operators");
}
-
+
llvm_unreachable("Unhandled compound assignment operator");
}
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
index 713509b..0bda053 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -20,6 +20,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/StmtObjC.h"
#include "clang/Basic/Diagnostic.h"
+#include "clang/CodeGen/CGFunctionInfo.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/CallSite.h"
#include "llvm/IR/DataLayout.h"
@@ -468,8 +469,8 @@ void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD,
SourceLocation StartLoc) {
FunctionArgList args;
// Check if we should generate debug info for this method.
- if (!OMD->hasAttr<NoDebugAttr>())
- maybeInitializeDebugInfo();
+ if (OMD->hasAttr<NoDebugAttr>())
+ DebugInfo = NULL; // disable debug info indefinitely for this function
llvm::Function *Fn = CGM.getObjCRuntime().GenerateMethod(OMD, CD);
@@ -925,7 +926,7 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
QualType ivarType = ivar->getType();
switch (getEvaluationKind(ivarType)) {
case TEK_Complex: {
- ComplexPairTy pair = EmitLoadOfComplex(LV);
+ ComplexPairTy pair = EmitLoadOfComplex(LV, SourceLocation());
EmitStoreOfComplex(pair,
MakeNaturalAlignAddrLValue(ReturnValue, ivarType),
/*init*/ true);
@@ -949,7 +950,7 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
// Otherwise we want to do a simple load, suppressing the
// final autorelease.
} else {
- value = EmitLoadOfLValue(LV).getScalarVal();
+ value = EmitLoadOfLValue(LV, SourceLocation()).getScalarVal();
AutoreleaseResult = false;
}
@@ -1048,8 +1049,6 @@ static void emitCPPObjectAtomicSetterCall(CodeGenFunction &CGF,
FunctionType::ExtInfo(),
RequiredArgs::All),
copyCppAtomicObjectFn, ReturnValueSlot(), args);
-
-
}
@@ -1404,7 +1403,7 @@ llvm::Value *CodeGenFunction::LoadObjCSelf() {
VarDecl *Self = cast<ObjCMethodDecl>(CurFuncDecl)->getSelfDecl();
DeclRefExpr DRE(Self, /*is enclosing local*/ (CurFuncDecl != CurCodeDecl),
Self->getType(), VK_LValue, SourceLocation());
- return EmitLoadOfScalar(EmitDeclRefLValue(&DRE));
+ return EmitLoadOfScalar(EmitDeclRefLValue(&DRE), SourceLocation());
}
QualType CodeGenFunction::TypeOfSelfObject() {
@@ -2084,7 +2083,7 @@ llvm::Value *CodeGenFunction::EmitARCStoreStrong(LValue dst,
newValue = EmitARCRetain(type, newValue);
// Read the old value.
- llvm::Value *oldValue = EmitLoadOfScalar(dst);
+ llvm::Value *oldValue = EmitLoadOfScalar(dst, SourceLocation());
// Store. We do this before the release so that any deallocs won't
// see the old value.
@@ -2355,7 +2354,8 @@ static TryEmitResult tryEmitARCRetainLoadOfScalar(CodeGenFunction &CGF,
case Qualifiers::OCL_ExplicitNone:
case Qualifiers::OCL_Strong:
case Qualifiers::OCL_Autoreleasing:
- return TryEmitResult(CGF.EmitLoadOfLValue(lvalue).getScalarVal(),
+ return TryEmitResult(CGF.EmitLoadOfLValue(lvalue,
+ SourceLocation()).getScalarVal(),
false);
case Qualifiers::OCL_Weak:
@@ -2381,7 +2381,8 @@ static TryEmitResult tryEmitARCRetainLoadOfScalar(CodeGenFunction &CGF,
LValue lv = CGF.EmitLValue(e);
// Load the object pointer.
- llvm::Value *result = CGF.EmitLoadOfLValue(lv).getScalarVal();
+ llvm::Value *result = CGF.EmitLoadOfLValue(lv,
+ SourceLocation()).getScalarVal();
// Set the source pointer to NULL.
CGF.EmitStoreOfScalar(getNullForVariable(lv.getAddress()), lv);
@@ -2784,8 +2785,7 @@ CodeGenFunction::EmitARCStoreStrong(const BinaryOperator *e,
// If the RHS was emitted retained, expand this.
if (hasImmediateRetain) {
- llvm::Value *oldValue =
- EmitLoadOfScalar(lvalue);
+ llvm::Value *oldValue = EmitLoadOfScalar(lvalue, SourceLocation());
EmitStoreOfScalar(value, lvalue);
EmitARCRelease(oldValue, lvalue.isARCPreciseLifetime());
} else {
@@ -2905,9 +2905,6 @@ CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction(
"__assign_helper_atomic_property_",
&CGM.getModule());
- // Initialize debug info if needed.
- maybeInitializeDebugInfo();
-
StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation());
DeclRefExpr DstExpr(&dstDecl, false, DestTy,
@@ -2988,9 +2985,6 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
"__copy_helper_atomic_property_", &CGM.getModule());
- // Initialize debug info if needed.
- maybeInitializeDebugInfo();
-
StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation());
DeclRefExpr SrcExpr(&srcDecl, false, SrcTy,
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp
index fbf8a1a..a7ab850 100644
--- a/lib/CodeGen/CGObjCGNU.cpp
+++ b/lib/CodeGen/CGObjCGNU.cpp
@@ -454,13 +454,15 @@ protected:
virtual llvm::Value *LookupIMP(CodeGenFunction &CGF,
llvm::Value *&Receiver,
llvm::Value *cmd,
- llvm::MDNode *node) = 0;
+ llvm::MDNode *node,
+ MessageSendInfo &MSI) = 0;
/// Looks up the method for sending a message to a superclass. This
/// mechanism differs between the GCC and GNU runtimes, so this method must
/// be overridden in subclasses.
virtual llvm::Value *LookupIMPSuper(CodeGenFunction &CGF,
llvm::Value *ObjCSuper,
- llvm::Value *cmd) = 0;
+ llvm::Value *cmd,
+ MessageSendInfo &MSI) = 0;
/// Libobjc2 uses a bitfield representation where small(ish) bitfields are
/// stored in a 64-bit value with the low bit set to 1 and the remaining 63
/// bits set to their values, LSB first, while larger ones are stored in a
@@ -596,7 +598,8 @@ protected:
virtual llvm::Value *LookupIMP(CodeGenFunction &CGF,
llvm::Value *&Receiver,
llvm::Value *cmd,
- llvm::MDNode *node) {
+ llvm::MDNode *node,
+ MessageSendInfo &MSI) {
CGBuilderTy &Builder = CGF.Builder;
llvm::Value *args[] = {
EnforceType(Builder, Receiver, IdTy),
@@ -607,7 +610,8 @@ protected:
}
virtual llvm::Value *LookupIMPSuper(CodeGenFunction &CGF,
llvm::Value *ObjCSuper,
- llvm::Value *cmd) {
+ llvm::Value *cmd,
+ MessageSendInfo &MSI) {
CGBuilderTy &Builder = CGF.Builder;
llvm::Value *lookupArgs[] = {EnforceType(Builder, ObjCSuper,
PtrToObjCSuperTy), cmd};
@@ -655,7 +659,8 @@ class CGObjCGNUstep : public CGObjCGNU {
virtual llvm::Value *LookupIMP(CodeGenFunction &CGF,
llvm::Value *&Receiver,
llvm::Value *cmd,
- llvm::MDNode *node) {
+ llvm::MDNode *node,
+ MessageSendInfo &MSI) {
CGBuilderTy &Builder = CGF.Builder;
llvm::Function *LookupFn = SlotLookupFn;
@@ -693,7 +698,8 @@ class CGObjCGNUstep : public CGObjCGNU {
}
virtual llvm::Value *LookupIMPSuper(CodeGenFunction &CGF,
llvm::Value *ObjCSuper,
- llvm::Value *cmd) {
+ llvm::Value *cmd,
+ MessageSendInfo &MSI) {
CGBuilderTy &Builder = CGF.Builder;
llvm::Value *lookupArgs[] = {ObjCSuper, cmd};
@@ -790,38 +796,52 @@ class CGObjCGNUstep : public CGObjCGNU {
}
};
-/// Support for the ObjFW runtime. Support here is due to
-/// Jonathan Schleifer <js@webkeks.org>, the ObjFW maintainer.
+/// Support for the ObjFW runtime.
class CGObjCObjFW: public CGObjCGNU {
protected:
/// The GCC ABI message lookup function. Returns an IMP pointing to the
/// method implementation for this message.
LazyRuntimeFunction MsgLookupFn;
+ /// stret lookup function. While this does not seem to make sense at the
+ /// first look, this is required to call the correct forwarding function.
+ LazyRuntimeFunction MsgLookupFnSRet;
/// The GCC ABI superclass message lookup function. Takes a pointer to a
/// structure describing the receiver and the class, and a selector as
/// arguments. Returns the IMP for the corresponding method.
- LazyRuntimeFunction MsgLookupSuperFn;
+ LazyRuntimeFunction MsgLookupSuperFn, MsgLookupSuperFnSRet;
virtual llvm::Value *LookupIMP(CodeGenFunction &CGF,
llvm::Value *&Receiver,
llvm::Value *cmd,
- llvm::MDNode *node) {
+ llvm::MDNode *node,
+ MessageSendInfo &MSI) {
CGBuilderTy &Builder = CGF.Builder;
llvm::Value *args[] = {
EnforceType(Builder, Receiver, IdTy),
EnforceType(Builder, cmd, SelectorTy) };
- llvm::CallSite imp = CGF.EmitRuntimeCallOrInvoke(MsgLookupFn, args);
+
+ llvm::CallSite imp;
+ if (CGM.ReturnTypeUsesSRet(MSI.CallInfo))
+ imp = CGF.EmitRuntimeCallOrInvoke(MsgLookupFnSRet, args);
+ else
+ imp = CGF.EmitRuntimeCallOrInvoke(MsgLookupFn, args);
+
imp->setMetadata(msgSendMDKind, node);
return imp.getInstruction();
}
virtual llvm::Value *LookupIMPSuper(CodeGenFunction &CGF,
llvm::Value *ObjCSuper,
- llvm::Value *cmd) {
+ llvm::Value *cmd,
+ MessageSendInfo &MSI) {
CGBuilderTy &Builder = CGF.Builder;
llvm::Value *lookupArgs[] = {EnforceType(Builder, ObjCSuper,
PtrToObjCSuperTy), cmd};
- return CGF.EmitNounwindRuntimeCall(MsgLookupSuperFn, lookupArgs);
+
+ if (CGM.ReturnTypeUsesSRet(MSI.CallInfo))
+ return CGF.EmitNounwindRuntimeCall(MsgLookupSuperFnSRet, lookupArgs);
+ else
+ return CGF.EmitNounwindRuntimeCall(MsgLookupSuperFn, lookupArgs);
}
virtual llvm::Value *GetClassNamed(CodeGenFunction &CGF,
@@ -847,9 +867,13 @@ public:
CGObjCObjFW(CodeGenModule &Mod): CGObjCGNU(Mod, 9, 3) {
// IMP objc_msg_lookup(id, SEL);
MsgLookupFn.init(&CGM, "objc_msg_lookup", IMPTy, IdTy, SelectorTy, NULL);
+ MsgLookupFnSRet.init(&CGM, "objc_msg_lookup_stret", IMPTy, IdTy,
+ SelectorTy, NULL);
// IMP objc_msg_lookup_super(struct objc_super*, SEL);
MsgLookupSuperFn.init(&CGM, "objc_msg_lookup_super", IMPTy,
PtrToObjCSuperTy, SelectorTy, NULL);
+ MsgLookupSuperFnSRet.init(&CGM, "objc_msg_lookup_super_stret", IMPTy,
+ PtrToObjCSuperTy, SelectorTy, NULL);
}
};
} // end anonymous namespace
@@ -1041,7 +1065,7 @@ llvm::Value *CGObjCGNU::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF, Selector Sel,
const std::string &TypeEncoding, bool lval) {
- SmallVector<TypedSelector, 2> &Types = SelectorTable[Sel];
+ SmallVectorImpl<TypedSelector> &Types = SelectorTable[Sel];
llvm::GlobalAlias *SelValue = 0;
@@ -1291,7 +1315,7 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGenFunction &CGF,
ObjCSuper = EnforceType(Builder, ObjCSuper, PtrToObjCSuperTy);
// Get the IMP
- llvm::Value *imp = LookupIMPSuper(CGF, ObjCSuper, cmd);
+ llvm::Value *imp = LookupIMPSuper(CGF, ObjCSuper, cmd, MSI);
imp = EnforceType(Builder, imp, MSI.MessengerType);
llvm::Value *impMD[] = {
@@ -1390,7 +1414,7 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF,
// given platform), so we
switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
case CodeGenOptions::Legacy:
- imp = LookupIMP(CGF, Receiver, cmd, node);
+ imp = LookupIMP(CGF, Receiver, cmd, node, MSI);
break;
case CodeGenOptions::Mixed:
case CodeGenOptions::NonLegacy:
@@ -1414,8 +1438,7 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF,
imp = EnforceType(Builder, imp, MSI.MessengerType);
llvm::Instruction *call;
- RValue msgRet = CGF.EmitCall(MSI.CallInfo, imp, Return, ActualArgs,
- 0, &call);
+ RValue msgRet = CGF.EmitCall(MSI.CallInfo, imp, Return, ActualArgs, 0, &call);
call->setMetadata(msgSendMDKind, node);
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index e8498b0..2b2a5b8 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -23,6 +23,7 @@
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtObjC.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/CodeGen/CGFunctionInfo.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SetVector.h"
@@ -4348,7 +4349,7 @@ void CGObjCCommonMac::EmitImageInfo() {
// Indicate whether we're compiling this to run on a simulator.
const llvm::Triple &Triple = CGM.getTarget().getTriple();
- if (Triple.getOS() == llvm::Triple::IOS &&
+ if (Triple.isiOS() &&
(Triple.getArch() == llvm::Triple::x86 ||
Triple.getArch() == llvm::Triple::x86_64))
Mod.addModuleFlag(llvm::Module::Error, "Objective-C Is Simulated",
@@ -5757,6 +5758,9 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData(
};
if (!Values[1])
Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy);
+ if (!Values[3])
+ Values[3] = llvm::Constant::getNullValue(
+ llvm::PointerType::getUnqual(ObjCTypes.ImpnfABITy));
llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy,
Values);
llvm::GlobalVariable *GV = GetClassGlobal(ClassName);
@@ -5800,14 +5804,21 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
llvm::GlobalValue::ExternalLinkage,
0,
"_objc_empty_cache");
-
- ObjCEmptyVtableVar = new llvm::GlobalVariable(
- CGM.getModule(),
- ObjCTypes.ImpnfABITy,
- false,
- llvm::GlobalValue::ExternalLinkage,
- 0,
- "_objc_empty_vtable");
+
+ // Make this entry NULL for any iOS device target, any iOS simulator target,
+ // OS X with deployment target 10.9 or later.
+ const llvm::Triple &Triple = CGM.getTarget().getTriple();
+ if (Triple.isiOS() || (Triple.isMacOSX() && !Triple.isMacOSXVersionLT(10, 9)))
+ // This entry will be null.
+ ObjCEmptyVtableVar = 0;
+ else
+ ObjCEmptyVtableVar = new llvm::GlobalVariable(
+ CGM.getModule(),
+ ObjCTypes.ImpnfABITy,
+ false,
+ llvm::GlobalValue::ExternalLinkage,
+ 0,
+ "_objc_empty_vtable");
}
assert(ID->getClassInterface() &&
"CGObjCNonFragileABIMac::GenerateClass - class is 0");
diff --git a/lib/CodeGen/CGObjCRuntime.cpp b/lib/CodeGen/CGObjCRuntime.cpp
index 9c0d518..d097b6f 100644
--- a/lib/CodeGen/CGObjCRuntime.cpp
+++ b/lib/CodeGen/CGObjCRuntime.cpp
@@ -20,6 +20,7 @@
#include "CodeGenModule.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtObjC.h"
+#include "clang/CodeGen/CGFunctionInfo.h"
#include "llvm/Support/CallSite.h"
using namespace clang;
diff --git a/lib/CodeGen/CGRTTI.cpp b/lib/CodeGen/CGRTTI.cpp
index 40dc6bf..aa687b9 100644
--- a/lib/CodeGen/CGRTTI.cpp
+++ b/lib/CodeGen/CGRTTI.cpp
@@ -332,6 +332,7 @@ getTypeInfoLinkage(CodeGenModule &CGM, QualType Ty) {
switch (Ty->getLinkage()) {
case NoLinkage:
+ case VisibleNoLinkage:
case InternalLinkage:
case UniqueExternalLinkage:
return llvm::GlobalValue::InternalLinkage;
@@ -507,60 +508,6 @@ void RTTIBuilder::BuildVTablePointer(const Type *Ty) {
Fields.push_back(VTable);
}
-// maybeUpdateRTTILinkage - Will update the linkage of the RTTI data structures
-// from available_externally to the correct linkage if necessary. An example of
-// this is:
-//
-// struct A {
-// virtual void f();
-// };
-//
-// const std::type_info &g() {
-// return typeid(A);
-// }
-//
-// void A::f() { }
-//
-// When we're generating the typeid(A) expression, we do not yet know that
-// A's key function is defined in this translation unit, so we will give the
-// typeinfo and typename structures available_externally linkage. When A::f
-// forces the vtable to be generated, we need to change the linkage of the
-// typeinfo and typename structs, otherwise we'll end up with undefined
-// externals when linking.
-static void
-maybeUpdateRTTILinkage(CodeGenModule &CGM, llvm::GlobalVariable *GV,
- QualType Ty) {
- // We're only interested in globals with available_externally linkage.
- if (!GV->hasAvailableExternallyLinkage())
- return;
-
- // Get the real linkage for the type.
- llvm::GlobalVariable::LinkageTypes Linkage = getTypeInfoLinkage(CGM, Ty);
-
- // If variable is supposed to have available_externally linkage, we don't
- // need to do anything.
- if (Linkage == llvm::GlobalVariable::AvailableExternallyLinkage)
- return;
-
- // Update the typeinfo linkage.
- GV->setLinkage(Linkage);
-
- // Get the typename global.
- SmallString<256> OutName;
- llvm::raw_svector_ostream Out(OutName);
- CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(Ty, Out);
- Out.flush();
- StringRef Name = OutName.str();
-
- llvm::GlobalVariable *TypeNameGV = CGM.getModule().getNamedGlobal(Name);
-
- assert(TypeNameGV->hasAvailableExternallyLinkage() &&
- "Type name has different linkage from type info!");
-
- // And update its linkage.
- TypeNameGV->setLinkage(Linkage);
-}
-
llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) {
// We want to operate on the canonical type.
Ty = CGM.getContext().getCanonicalType(Ty);
@@ -574,7 +521,8 @@ llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) {
llvm::GlobalVariable *OldGV = CGM.getModule().getNamedGlobal(Name);
if (OldGV && !OldGV->isDeclaration()) {
- maybeUpdateRTTILinkage(CGM, OldGV, Ty);
+ assert(!OldGV->hasAvailableExternallyLinkage() &&
+ "available_externally typeinfos not yet implemented");
return llvm::ConstantExpr::getBitCast(OldGV, CGM.Int8PtrTy);
}
@@ -898,7 +846,7 @@ void RTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
CharUnits Offset;
if (Base->isVirtual())
Offset =
- CGM.getVTableContext().getVirtualBaseOffsetOffset(RD, BaseDecl);
+ CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(RD, BaseDecl);
else {
const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
Offset = Layout.getBaseClassOffset(BaseDecl);
@@ -1024,6 +972,6 @@ void CodeGenModule::EmitFundamentalRTTIDescriptors() {
Context.UnsignedLongLongTy, Context.FloatTy,
Context.DoubleTy, Context.LongDoubleTy,
Context.Char16Ty, Context.Char32Ty };
- for (unsigned i = 0; i < sizeof(FundamentalTypes)/sizeof(QualType); ++i)
+ for (unsigned i = 0; i < llvm::array_lengthof(FundamentalTypes); ++i)
EmitFundamentalRTTIDescriptor(FundamentalTypes[i]);
}
diff --git a/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp
index 30ab528..ab92563 100644
--- a/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -78,9 +78,6 @@ public:
/// Packed - Whether the resulting LLVM struct will be packed or not.
bool Packed;
-
- /// IsMsStruct - Whether ms_struct is in effect or not
- bool IsMsStruct;
private:
CodeGenTypes &Types;
@@ -117,7 +114,7 @@ private:
RecordDecl::field_iterator &FI,
RecordDecl::field_iterator FE);
- /// LayoutField - try to layout all fields in the record decl.
+ /// LayoutFields - try to layout all fields in the record decl.
/// Returns false if the operation failed because the struct is not packed.
bool LayoutFields(const RecordDecl *D);
@@ -195,8 +192,7 @@ public:
CGRecordLayoutBuilder(CodeGenTypes &Types)
: BaseSubobjectType(0),
IsZeroInitializable(true), IsZeroInitializableAsBase(true),
- Packed(false), IsMsStruct(false),
- Types(Types) { }
+ Packed(false), Types(Types) { }
/// Layout - Will layout a RecordDecl.
void Layout(const RecordDecl *D);
@@ -205,10 +201,9 @@ public:
}
void CGRecordLayoutBuilder::Layout(const RecordDecl *D) {
- Alignment = Types.getContext().getASTRecordLayout(D).getAlignment();
- Packed = D->hasAttr<PackedAttr>();
-
- IsMsStruct = D->isMsStruct(Types.getContext());
+ const ASTRecordLayout &Layout = Types.getContext().getASTRecordLayout(D);
+ Alignment = Layout.getAlignment();
+ Packed = D->hasAttr<PackedAttr>() || Layout.getSize() % Alignment != 0;
if (D->isUnion()) {
LayoutUnion(D);
@@ -702,7 +697,7 @@ CGRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD,
}
// Add a vb-table pointer if the layout insists.
- if (Layout.getVBPtrOffset() != CharUnits::fromQuantity(-1)) {
+ if (Layout.hasOwnVBPtr()) {
CharUnits VBPtrOffset = Layout.getVBPtrOffset();
llvm::Type *Vbptr = llvm::Type::getInt32PtrTy(Types.getLLVMContext());
AppendPadding(VBPtrOffset, getTypeAlignment(Vbptr));
@@ -764,20 +759,10 @@ bool CGRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
return false;
unsigned FieldNo = 0;
- const FieldDecl *LastFD = 0;
for (RecordDecl::field_iterator FI = D->field_begin(), FE = D->field_end();
FI != FE; ++FI, ++FieldNo) {
FieldDecl *FD = *FI;
- if (IsMsStruct) {
- // Zero-length bitfields following non-bitfield members are
- // ignored:
- if (Types.getContext().ZeroBitfieldFollowsNonBitfield(FD, LastFD)) {
- --FieldNo;
- continue;
- }
- LastFD = FD;
- }
// If this field is a bitfield, layout all of the consecutive
// non-zero-length bitfields and the last zero-length bitfield; these will
@@ -992,11 +977,11 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D,
// Dump the layout, if requested.
if (getContext().getLangOpts().DumpRecordLayouts) {
- llvm::errs() << "\n*** Dumping IRgen Record Layout\n";
- llvm::errs() << "Record: ";
- D->dump();
- llvm::errs() << "\nLayout: ";
- RL->dump();
+ llvm::outs() << "\n*** Dumping IRgen Record Layout\n";
+ llvm::outs() << "Record: ";
+ D->dump(llvm::outs());
+ llvm::outs() << "\nLayout: ";
+ RL->print(llvm::outs());
}
#ifndef NDEBUG
@@ -1028,8 +1013,6 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D,
const ASTRecordLayout &AST_RL = getContext().getASTRecordLayout(D);
RecordDecl::field_iterator it = D->field_begin();
- const FieldDecl *LastFD = 0;
- bool IsMsStruct = D->isMsStruct(getContext());
for (unsigned i = 0, e = AST_RL.getFieldCount(); i != e; ++i, ++it) {
const FieldDecl *FD = *it;
@@ -1039,25 +1022,12 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D,
unsigned FieldNo = RL->getLLVMFieldNo(FD);
assert(AST_RL.getFieldOffset(i) == SL->getElementOffsetInBits(FieldNo) &&
"Invalid field offset!");
- LastFD = FD;
continue;
}
-
- if (IsMsStruct) {
- // Zero-length bitfields following non-bitfield members are
- // ignored:
- if (getContext().ZeroBitfieldFollowsNonBitfield(FD, LastFD)) {
- --i;
- continue;
- }
- LastFD = FD;
- }
// Ignore unnamed bit-fields.
- if (!FD->getDeclName()) {
- LastFD = FD;
+ if (!FD->getDeclName())
continue;
- }
// Don't inspect zero-length bitfields.
if (FD->getBitWidthValue(getContext()) == 0)
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index 5e2ebe0..0bc51dd 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -16,12 +16,14 @@
#include "CodeGenModule.h"
#include "TargetInfo.h"
#include "clang/AST/StmtVisitor.h"
+#include "clang/Sema/SemaDiagnostic.h"
#include "clang/Basic/PrettyStackTrace.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/Intrinsics.h"
+#include "llvm/Support/CallSite.h"
using namespace clang;
using namespace CodeGen;
@@ -32,14 +34,10 @@ using namespace CodeGen;
void CodeGenFunction::EmitStopPoint(const Stmt *S) {
if (CGDebugInfo *DI = getDebugInfo()) {
SourceLocation Loc;
- if (isa<DeclStmt>(S))
- Loc = S->getLocEnd();
- else
- Loc = S->getLocStart();
+ Loc = S->getLocStart();
DI->EmitLocation(Builder, Loc);
- //if (++NumStopPoints == 1)
- LastStopPoint = Loc;
+ LastStopPoint = Loc;
}
}
@@ -77,6 +75,7 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
case Stmt::SEHExceptStmtClass:
case Stmt::SEHFinallyStmtClass:
case Stmt::MSDependentExistsStmtClass:
+ case Stmt::OMPParallelDirectiveClass:
llvm_unreachable("invalid statement class to emit generically");
case Stmt::NullStmtClass:
case Stmt::CompoundStmtClass:
@@ -137,8 +136,10 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
case Stmt::SwitchStmtClass: EmitSwitchStmt(cast<SwitchStmt>(*S)); break;
case Stmt::GCCAsmStmtClass: // Intentional fall-through.
case Stmt::MSAsmStmtClass: EmitAsmStmt(cast<AsmStmt>(*S)); break;
- case Stmt::CapturedStmtClass:
- EmitCapturedStmt(cast<CapturedStmt>(*S));
+ case Stmt::CapturedStmtClass: {
+ const CapturedStmt *CS = cast<CapturedStmt>(S);
+ EmitCapturedStmt(*CS, CS->getCapturedRegionKind());
+ }
break;
case Stmt::ObjCAtTryStmtClass:
EmitObjCAtTryStmt(cast<ObjCAtTryStmt>(*S));
@@ -167,8 +168,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
break;
case Stmt::CXXForRangeStmtClass:
EmitCXXForRangeStmt(cast<CXXForRangeStmt>(*S));
+ break;
case Stmt::SEHTryStmtClass:
- // FIXME Not yet implemented
+ EmitSEHTryStmt(cast<SEHTryStmt>(*S));
break;
}
}
@@ -195,8 +197,8 @@ bool CodeGenFunction::EmitSimpleStmt(const Stmt *S) {
/// EmitCompoundStmt - Emit a compound statement {..} node. If GetLast is true,
/// this captures the expression result of the last sub-statement and returns it
/// (for use by the statement expression extension).
-RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast,
- AggValueSlot AggSlot) {
+llvm::Value* CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast,
+ AggValueSlot AggSlot) {
PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),S.getLBracLoc(),
"LLVM IR generation of compound statement ('{}')");
@@ -206,17 +208,17 @@ RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast,
return EmitCompoundStmtWithoutScope(S, GetLast, AggSlot);
}
-RValue CodeGenFunction::EmitCompoundStmtWithoutScope(const CompoundStmt &S, bool GetLast,
- AggValueSlot AggSlot) {
+llvm::Value*
+CodeGenFunction::EmitCompoundStmtWithoutScope(const CompoundStmt &S,
+ bool GetLast,
+ AggValueSlot AggSlot) {
for (CompoundStmt::const_body_iterator I = S.body_begin(),
E = S.body_end()-GetLast; I != E; ++I)
EmitStmt(*I);
- RValue RV;
- if (!GetLast)
- RV = RValue::get(0);
- else {
+ llvm::Value *RetAlloca = 0;
+ if (GetLast) {
// We have to special case labels here. They are statements, but when put
// at the end of a statement expression, they yield the value of their
// subexpression. Handle this by walking through all labels we encounter,
@@ -229,10 +231,21 @@ RValue CodeGenFunction::EmitCompoundStmtWithoutScope(const CompoundStmt &S, bool
EnsureInsertPoint();
- RV = EmitAnyExpr(cast<Expr>(LastStmt), AggSlot);
+ QualType ExprTy = cast<Expr>(LastStmt)->getType();
+ if (hasAggregateEvaluationKind(ExprTy)) {
+ EmitAggExpr(cast<Expr>(LastStmt), AggSlot);
+ } else {
+ // We can't return an RValue here because there might be cleanups at
+ // the end of the StmtExpr. Because of that, we have to emit the result
+ // here into a temporary alloca.
+ RetAlloca = CreateMemTemp(ExprTy);
+ EmitAnyExprToMem(cast<Expr>(LastStmt), RetAlloca, Qualifiers(),
+ /*IsInit*/false);
+ }
+
}
- return RV;
+ return RetAlloca;
}
void CodeGenFunction::SimplifyForwardingBlocks(llvm::BasicBlock *BB) {
@@ -416,7 +429,7 @@ void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) {
void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
// C99 6.8.4.1: The first substatement is executed if the expression compares
// unequal to 0. The condition must be a scalar type.
- RunCleanupsScope ConditionScope(*this);
+ LexicalScope ConditionScope(*this, S.getSourceRange());
if (S.getConditionVariable())
EmitAutoVarDecl(*S.getConditionVariable());
@@ -626,15 +639,14 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S) {
// Create a cleanup scope for the condition variable cleanups.
RunCleanupsScope ConditionScope(*this);
- llvm::Value *BoolCondVal = 0;
if (S.getCond()) {
// If the for statement has a condition scope, emit the local variable
// declaration.
- llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
if (S.getConditionVariable()) {
EmitAutoVarDecl(*S.getConditionVariable());
}
+ llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
// If there are any cleanups between here and the loop-exit scope,
// create a block to stage a loop exit along.
if (ForScope.requiresCleanups())
@@ -645,8 +657,7 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S) {
// C99 6.8.5p2/p4: The first substatement is executed if the expression
// compares unequal to 0. The condition must be a scalar type.
- BoolCondVal = EvaluateExprAsBool(S.getCond());
- Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock);
+ EmitBranchOnBoolExpr(S.getCond(), ForBody, ExitBlock);
if (ExitBlock != LoopExit.getBlock()) {
EmitBlock(ExitBlock);
@@ -726,8 +737,7 @@ void CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S) {
// The body is executed if the expression, contextually converted
// to bool, is true.
- llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
- Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock);
+ EmitBranchOnBoolExpr(S.getCond(), ForBody, ExitBlock);
if (ExitBlock != LoopExit.getBlock()) {
EmitBlock(ExitBlock);
@@ -818,7 +828,7 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
} else if (FnRetTy->isReferenceType()) {
// If this function returns a reference, take the address of the expression
// rather than the value.
- RValue Result = EmitReferenceBindingToExpr(RV, /*InitializedDecl=*/0);
+ RValue Result = EmitReferenceBindingToExpr(RV);
Builder.CreateStore(Result.getScalarVal(), ReturnValue);
} else {
switch (getEvaluationKind(RV->getType())) {
@@ -842,9 +852,9 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
}
}
- NumReturnExprs += 1;
+ ++NumReturnExprs;
if (RV == 0 || RV->isEvaluatable(getContext()))
- NumSimpleReturnExprs += 1;
+ ++NumSimpleReturnExprs;
cleanupScope.ForceCleanup();
EmitBranchThroughCleanup(ReturnBlock);
@@ -1334,7 +1344,7 @@ SimplifyConstraint(const char *Constraint, const TargetInfo &Target,
break;
case '#': // Ignore the rest of the constraint alternative.
while (Constraint[1] && Constraint[1] != ',')
- Constraint++;
+ Constraint++;
break;
case ',':
Result += "|";
@@ -1398,11 +1408,12 @@ AddVariableConstraints(const std::string &Constraint, const Expr &AsmExpr,
llvm::Value*
CodeGenFunction::EmitAsmInputLValue(const TargetInfo::ConstraintInfo &Info,
LValue InputValue, QualType InputType,
- std::string &ConstraintStr) {
+ std::string &ConstraintStr,
+ SourceLocation Loc) {
llvm::Value *Arg;
if (Info.allowsRegister() || !Info.allowsMemory()) {
if (CodeGenFunction::hasScalarEvaluationKind(InputType)) {
- Arg = EmitLoadOfLValue(InputValue).getScalarVal();
+ Arg = EmitLoadOfLValue(InputValue, Loc).getScalarVal();
} else {
llvm::Type *Ty = ConvertType(InputType);
uint64_t Size = CGM.getDataLayout().getTypeSizeInBits(Ty);
@@ -1435,7 +1446,8 @@ llvm::Value* CodeGenFunction::EmitAsmInput(
InputExpr = InputExpr->IgnoreParenNoopCasts(getContext());
LValue Dest = EmitLValue(InputExpr);
- return EmitAsmInputLValue(Info, Dest, InputExpr->getType(), ConstraintStr);
+ return EmitAsmInputLValue(Info, Dest, InputExpr->getType(), ConstraintStr,
+ InputExpr->getExprLoc());
}
/// getAsmSrcLocInfo - Return the !srcloc metadata node to attach to an inline
@@ -1559,10 +1571,15 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
ResultRegTypes.back() = ConvertType(InputTy);
}
}
- if (llvm::Type* AdjTy =
+ if (llvm::Type* AdjTy =
getTargetHooks().adjustInlineAsmType(*this, OutputConstraint,
ResultRegTypes.back()))
ResultRegTypes.back() = AdjTy;
+ else {
+ CGM.getDiags().Report(S.getAsmLoc(),
+ diag::err_asm_invalid_type_in_input)
+ << OutExpr->getType() << OutputConstraint;
+ }
} else {
ArgTypes.push_back(Dest.getAddress()->getType());
Args.push_back(Dest.getAddress());
@@ -1575,11 +1592,12 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
const Expr *InputExpr = S.getOutputExpr(i);
llvm::Value *Arg = EmitAsmInputLValue(Info, Dest, InputExpr->getType(),
- InOutConstraints);
+ InOutConstraints,
+ InputExpr->getExprLoc());
if (llvm::Type* AdjTy =
- getTargetHooks().adjustInlineAsmType(*this, OutputConstraint,
- Arg->getType()))
+ getTargetHooks().adjustInlineAsmType(*this, OutputConstraint,
+ Arg->getType()))
Arg = Builder.CreateBitCast(Arg, AdjTy);
if (Info.allowsRegister())
@@ -1644,6 +1662,9 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
getTargetHooks().adjustInlineAsmType(*this, InputConstraint,
Arg->getType()))
Arg = Builder.CreateBitCast(Arg, AdjTy);
+ else
+ CGM.getDiags().Report(S.getAsmLoc(), diag::err_asm_invalid_type_in_input)
+ << InputExpr->getType() << InputConstraint;
ArgTypes.push_back(Arg->getType());
Args.push_back(Arg);
@@ -1751,6 +1772,91 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
}
}
-void CodeGenFunction::EmitCapturedStmt(const CapturedStmt &S) {
- llvm_unreachable("not implemented yet");
+static LValue InitCapturedStruct(CodeGenFunction &CGF, const CapturedStmt &S) {
+ const RecordDecl *RD = S.getCapturedRecordDecl();
+ QualType RecordTy = CGF.getContext().getRecordType(RD);
+
+ // Initialize the captured struct.
+ LValue SlotLV = CGF.MakeNaturalAlignAddrLValue(
+ CGF.CreateMemTemp(RecordTy, "agg.captured"), RecordTy);
+
+ RecordDecl::field_iterator CurField = RD->field_begin();
+ for (CapturedStmt::capture_init_iterator I = S.capture_init_begin(),
+ E = S.capture_init_end();
+ I != E; ++I, ++CurField) {
+ LValue LV = CGF.EmitLValueForFieldInitialization(SlotLV, *CurField);
+ CGF.EmitInitializerForField(*CurField, LV, *I, ArrayRef<VarDecl *>());
+ }
+
+ return SlotLV;
+}
+
+/// Generate an outlined function for the body of a CapturedStmt, store any
+/// captured variables into the captured struct, and call the outlined function.
+llvm::Function *
+CodeGenFunction::EmitCapturedStmt(const CapturedStmt &S, CapturedRegionKind K) {
+ const CapturedDecl *CD = S.getCapturedDecl();
+ const RecordDecl *RD = S.getCapturedRecordDecl();
+ assert(CD->hasBody() && "missing CapturedDecl body");
+
+ LValue CapStruct = InitCapturedStruct(*this, S);
+
+ // Emit the CapturedDecl
+ CodeGenFunction CGF(CGM, true);
+ CGF.CapturedStmtInfo = new CGCapturedStmtInfo(S, K);
+ llvm::Function *F = CGF.GenerateCapturedStmtFunction(CD, RD, S.getLocStart());
+ delete CGF.CapturedStmtInfo;
+
+ // Emit call to the helper function.
+ EmitCallOrInvoke(F, CapStruct.getAddress());
+
+ return F;
+}
+
+/// Creates the outlined function for a CapturedStmt.
+llvm::Function *
+CodeGenFunction::GenerateCapturedStmtFunction(const CapturedDecl *CD,
+ const RecordDecl *RD,
+ SourceLocation Loc) {
+ assert(CapturedStmtInfo &&
+ "CapturedStmtInfo should be set when generating the captured function");
+
+ // Build the argument list.
+ ASTContext &Ctx = CGM.getContext();
+ FunctionArgList Args;
+ Args.append(CD->param_begin(), CD->param_end());
+
+ // Create the function declaration.
+ FunctionType::ExtInfo ExtInfo;
+ const CGFunctionInfo &FuncInfo =
+ CGM.getTypes().arrangeFunctionDeclaration(Ctx.VoidTy, Args, ExtInfo,
+ /*IsVariadic=*/false);
+ llvm::FunctionType *FuncLLVMTy = CGM.getTypes().GetFunctionType(FuncInfo);
+
+ llvm::Function *F =
+ llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
+ CapturedStmtInfo->getHelperName(), &CGM.getModule());
+ CGM.SetInternalFunctionAttributes(CD, F, FuncInfo);
+
+ // Generate the function.
+ StartFunction(CD, Ctx.VoidTy, F, FuncInfo, Args, CD->getBody()->getLocStart());
+
+ // Set the context parameter in CapturedStmtInfo.
+ llvm::Value *DeclPtr = LocalDeclMap[CD->getContextParam()];
+ assert(DeclPtr && "missing context parameter for CapturedStmt");
+ CapturedStmtInfo->setContextValue(Builder.CreateLoad(DeclPtr));
+
+ // If 'this' is captured, load it into CXXThisValue.
+ if (CapturedStmtInfo->isCXXThisExprCaptured()) {
+ FieldDecl *FD = CapturedStmtInfo->getThisFieldDecl();
+ LValue LV = MakeNaturalAlignAddrLValue(CapturedStmtInfo->getContextValue(),
+ Ctx.getTagDeclType(RD));
+ LValue ThisLValue = EmitLValueForField(LV, FD);
+ CXXThisValue = EmitLoadOfLValue(ThisLValue, Loc).getScalarVal();
+ }
+
+ CapturedStmtInfo->EmitBody(*this, CD->getBody());
+ FinishFunction(CD->getBodyRBrace());
+
+ return F;
}
diff --git a/lib/CodeGen/CGVTT.cpp b/lib/CodeGen/CGVTT.cpp
index 98be872..bfff470 100644
--- a/lib/CodeGen/CGVTT.cpp
+++ b/lib/CodeGen/CGVTT.cpp
@@ -19,7 +19,8 @@ using namespace clang;
using namespace CodeGen;
static llvm::Constant *
-GetAddrOfVTTVTable(CodeGenVTables &CGVT, const CXXRecordDecl *MostDerivedClass,
+GetAddrOfVTTVTable(CodeGenVTables &CGVT, CodeGenModule &CGM,
+ const CXXRecordDecl *MostDerivedClass,
const VTTVTable &VTable,
llvm::GlobalVariable::LinkageTypes Linkage,
llvm::DenseMap<BaseSubobject, uint64_t> &AddressPoints) {
@@ -27,7 +28,7 @@ GetAddrOfVTTVTable(CodeGenVTables &CGVT, const CXXRecordDecl *MostDerivedClass,
assert(VTable.getBaseOffset().isZero() &&
"Most derived class vtable must have a zero offset!");
// This is a regular vtable.
- return CGVT.GetAddrOfVTable(MostDerivedClass);
+ return CGM.getCXXABI().getAddrOfVTable(MostDerivedClass, CharUnits());
}
return CGVT.GenerateConstructionVTable(MostDerivedClass,
@@ -52,7 +53,7 @@ CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT,
for (const VTTVTable *i = Builder.getVTTVTables().begin(),
*e = Builder.getVTTVTables().end(); i != e; ++i) {
VTableAddressPoints.push_back(VTableAddressPointsMapTy());
- VTables.push_back(GetAddrOfVTTVTable(*this, RD, *i, Linkage,
+ VTables.push_back(GetAddrOfVTTVTable(*this, CGM, RD, *i, Linkage,
VTableAddressPoints.back()));
}
@@ -64,8 +65,8 @@ CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT,
uint64_t AddressPoint;
if (VTTVT.getBase() == RD) {
// Just get the address point for the regular vtable.
- AddressPoint = VTContext.getVTableLayout(RD)
- .getAddressPoint(i->VTableBase);
+ AddressPoint =
+ ItaniumVTContext.getVTableLayout(RD).getAddressPoint(i->VTableBase);
assert(AddressPoint != 0 && "Did not find vtable address point!");
} else {
AddressPoint = VTableAddressPoints[i->VTableIndex].lookup(i->VTableBase);
@@ -101,12 +102,13 @@ llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTT(const CXXRecordDecl *RD) {
SmallString<256> OutName;
llvm::raw_svector_ostream Out(OutName);
- CGM.getCXXABI().getMangleContext().mangleCXXVTT(RD, Out);
+ cast<ItaniumMangleContext>(CGM.getCXXABI().getMangleContext())
+ .mangleCXXVTT(RD, Out);
Out.flush();
StringRef Name = OutName.str();
// This will also defer the definition of the VTT.
- (void) GetAddrOfVTable(RD);
+ (void) CGM.getCXXABI().getAddrOfVTable(RD, CharUnits());
VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false);
@@ -120,24 +122,6 @@ llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTT(const CXXRecordDecl *RD) {
return GV;
}
-bool CodeGenVTables::needsVTTParameter(GlobalDecl GD) {
- const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
-
- // We don't have any virtual bases, just return early.
- if (!MD->getParent()->getNumVBases())
- return false;
-
- // Check if we have a base constructor.
- if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base)
- return true;
-
- // Check if we have a base destructor.
- if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
- return true;
-
- return false;
-}
-
uint64_t CodeGenVTables::getSubVTTIndex(const CXXRecordDecl *RD,
BaseSubobject Base) {
BaseSubobjectPairTy ClassSubobjectPair(RD, Base);
diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp
index 069cd5f..f28d9b6 100644
--- a/lib/CodeGen/CGVTables.cpp
+++ b/lib/CodeGen/CGVTables.cpp
@@ -16,6 +16,7 @@
#include "CodeGenModule.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/RecordLayout.h"
+#include "clang/CodeGen/CGFunctionInfo.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SetVector.h"
@@ -29,7 +30,14 @@ using namespace clang;
using namespace CodeGen;
CodeGenVTables::CodeGenVTables(CodeGenModule &CGM)
- : CGM(CGM), VTContext(CGM.getContext()) { }
+ : CGM(CGM), ItaniumVTContext(CGM.getContext()) {
+ if (CGM.getTarget().getCXXABI().isMicrosoft()) {
+ // FIXME: Eventually, we should only have one of V*TContexts available.
+ // Today we use both in the Microsoft ABI as MicrosoftVFTableContext
+ // is not completely supported in CodeGen yet.
+ MicrosoftVTContext.reset(new MicrosoftVTableContext(CGM.getContext()));
+ }
+}
llvm::Constant *CodeGenModule::GetAddrOfThunk(GlobalDecl GD,
const ThunkInfo &Thunk) {
@@ -49,53 +57,6 @@ llvm::Constant *CodeGenModule::GetAddrOfThunk(GlobalDecl GD,
return GetOrCreateLLVMFunction(Name, Ty, GD, /*ForVTable=*/true);
}
-static llvm::Value *PerformTypeAdjustment(CodeGenFunction &CGF,
- llvm::Value *Ptr,
- int64_t NonVirtualAdjustment,
- int64_t VirtualAdjustment,
- bool IsReturnAdjustment) {
- if (!NonVirtualAdjustment && !VirtualAdjustment)
- return Ptr;
-
- llvm::Type *Int8PtrTy = CGF.Int8PtrTy;
- llvm::Value *V = CGF.Builder.CreateBitCast(Ptr, Int8PtrTy);
-
- if (NonVirtualAdjustment && !IsReturnAdjustment) {
- // Perform the non-virtual adjustment for a base-to-derived cast.
- V = CGF.Builder.CreateConstInBoundsGEP1_64(V, NonVirtualAdjustment);
- }
-
- if (VirtualAdjustment) {
- llvm::Type *PtrDiffTy =
- CGF.ConvertType(CGF.getContext().getPointerDiffType());
-
- // Perform the virtual adjustment.
- llvm::Value *VTablePtrPtr =
- CGF.Builder.CreateBitCast(V, Int8PtrTy->getPointerTo());
-
- llvm::Value *VTablePtr = CGF.Builder.CreateLoad(VTablePtrPtr);
-
- llvm::Value *OffsetPtr =
- CGF.Builder.CreateConstInBoundsGEP1_64(VTablePtr, VirtualAdjustment);
-
- OffsetPtr = CGF.Builder.CreateBitCast(OffsetPtr, PtrDiffTy->getPointerTo());
-
- // Load the adjustment offset from the vtable.
- llvm::Value *Offset = CGF.Builder.CreateLoad(OffsetPtr);
-
- // Adjust our pointer.
- V = CGF.Builder.CreateInBoundsGEP(V, Offset);
- }
-
- if (NonVirtualAdjustment && IsReturnAdjustment) {
- // Perform the non-virtual adjustment for a derived-to-base cast.
- V = CGF.Builder.CreateConstInBoundsGEP1_64(V, NonVirtualAdjustment);
- }
-
- // Cast back to the original type.
- return CGF.Builder.CreateBitCast(V, Ptr->getType());
-}
-
static void setThunkVisibility(CodeGenModule &CGM, const CXXMethodDecl *MD,
const ThunkInfo &Thunk, llvm::Function *Fn) {
CGM.setGlobalVisibility(Fn, MD);
@@ -174,12 +135,10 @@ static RValue PerformReturnAdjustment(CodeGenFunction &CGF,
CGF.Builder.CreateCondBr(IsNull, AdjustNull, AdjustNotNull);
CGF.EmitBlock(AdjustNotNull);
}
-
- ReturnValue = PerformTypeAdjustment(CGF, ReturnValue,
- Thunk.Return.NonVirtual,
- Thunk.Return.VBaseOffsetOffset,
- /*IsReturnAdjustment*/true);
-
+
+ ReturnValue = CGF.CGM.getCXXABI().performReturnAdjustment(CGF, ReturnValue,
+ Thunk.Return);
+
if (NullCheckValue) {
CGF.Builder.CreateBr(AdjustEnd);
CGF.EmitBlock(AdjustNull);
@@ -259,11 +218,8 @@ void CodeGenFunction::GenerateVarArgsThunk(
assert(ThisStore && "Store of this should be in entry block?");
// Adjust "this", if necessary.
Builder.SetInsertPoint(ThisStore);
- llvm::Value *AdjustedThisPtr =
- PerformTypeAdjustment(*this, ThisPtr,
- Thunk.This.NonVirtual,
- Thunk.This.VCallOffsetOffset,
- /*IsReturnAdjustment*/false);
+ llvm::Value *AdjustedThisPtr =
+ CGM.getCXXABI().performThisAdjustment(*this, ThisPtr, Thunk.This);
ThisStore->setOperand(0, AdjustedThisPtr);
if (!Thunk.Return.isEmpty()) {
@@ -282,94 +238,99 @@ void CodeGenFunction::GenerateVarArgsThunk(
}
}
-void CodeGenFunction::GenerateThunk(llvm::Function *Fn,
- const CGFunctionInfo &FnInfo,
- GlobalDecl GD, const ThunkInfo &Thunk) {
+void CodeGenFunction::StartThunk(llvm::Function *Fn, GlobalDecl GD,
+ const CGFunctionInfo &FnInfo) {
+ assert(!CurGD.getDecl() && "CurGD was already set!");
+ CurGD = GD;
+
+ // Build FunctionArgs.
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
- const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
- QualType ResultType = FPT->getResultType();
QualType ThisType = MD->getThisType(getContext());
-
+ const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
+ QualType ResultType =
+ CGM.getCXXABI().HasThisReturn(GD) ? ThisType : FPT->getResultType();
FunctionArgList FunctionArgs;
- // FIXME: It would be nice if more of this code could be shared with
- // CodeGenFunction::GenerateCode.
-
// Create the implicit 'this' parameter declaration.
- CurGD = GD;
CGM.getCXXABI().BuildInstanceFunctionParams(*this, ResultType, FunctionArgs);
// Add the rest of the parameters.
for (FunctionDecl::param_const_iterator I = MD->param_begin(),
- E = MD->param_end(); I != E; ++I) {
- ParmVarDecl *Param = *I;
-
- FunctionArgs.push_back(Param);
- }
-
- // Initialize debug info if needed.
- maybeInitializeDebugInfo();
+ E = MD->param_end();
+ I != E; ++I)
+ FunctionArgs.push_back(*I);
+ // Start defining the function.
StartFunction(GlobalDecl(), ResultType, Fn, FnInfo, FunctionArgs,
SourceLocation());
+ // Since we didn't pass a GlobalDecl to StartFunction, do this ourselves.
CGM.getCXXABI().EmitInstanceFunctionProlog(*this);
CXXThisValue = CXXABIThisValue;
+}
- // Adjust the 'this' pointer if necessary.
- llvm::Value *AdjustedThisPtr =
- PerformTypeAdjustment(*this, LoadCXXThis(),
- Thunk.This.NonVirtual,
- Thunk.This.VCallOffsetOffset,
- /*IsReturnAdjustment*/false);
-
+void CodeGenFunction::EmitCallAndReturnForThunk(GlobalDecl GD,
+ llvm::Value *Callee,
+ const ThunkInfo *Thunk) {
+ assert(isa<CXXMethodDecl>(CurGD.getDecl()) &&
+ "Please use a new CGF for this thunk");
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+
+ // Adjust the 'this' pointer if necessary
+ llvm::Value *AdjustedThisPtr = Thunk ? CGM.getCXXABI().performThisAdjustment(
+ *this, LoadCXXThis(), Thunk->This)
+ : LoadCXXThis();
+
+ // Start building CallArgs.
CallArgList CallArgs;
-
- // Add our adjusted 'this' pointer.
+ QualType ThisType = MD->getThisType(getContext());
CallArgs.add(RValue::get(AdjustedThisPtr), ThisType);
- // Add the rest of the parameters.
+ if (isa<CXXDestructorDecl>(MD))
+ CGM.getCXXABI().adjustCallArgsForDestructorThunk(*this, GD, CallArgs);
+
+ // Add the rest of the arguments.
for (FunctionDecl::param_const_iterator I = MD->param_begin(),
- E = MD->param_end(); I != E; ++I) {
- ParmVarDecl *param = *I;
- EmitDelegateCallArg(CallArgs, param);
- }
+ E = MD->param_end(); I != E; ++I)
+ EmitDelegateCallArg(CallArgs, *I, (*I)->getLocStart());
- // Get our callee.
- llvm::Type *Ty =
- CGM.getTypes().GetFunctionType(CGM.getTypes().arrangeGlobalDeclaration(GD));
- llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true);
+ const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
#ifndef NDEBUG
const CGFunctionInfo &CallFnInfo =
CGM.getTypes().arrangeCXXMethodCall(CallArgs, FPT,
RequiredArgs::forPrototypePlus(FPT, 1));
- assert(CallFnInfo.getRegParm() == FnInfo.getRegParm() &&
- CallFnInfo.isNoReturn() == FnInfo.isNoReturn() &&
- CallFnInfo.getCallingConvention() == FnInfo.getCallingConvention());
+ assert(CallFnInfo.getRegParm() == CurFnInfo->getRegParm() &&
+ CallFnInfo.isNoReturn() == CurFnInfo->isNoReturn() &&
+ CallFnInfo.getCallingConvention() == CurFnInfo->getCallingConvention());
assert(isa<CXXDestructorDecl>(MD) || // ignore dtor return types
similar(CallFnInfo.getReturnInfo(), CallFnInfo.getReturnType(),
- FnInfo.getReturnInfo(), FnInfo.getReturnType()));
- assert(CallFnInfo.arg_size() == FnInfo.arg_size());
- for (unsigned i = 0, e = FnInfo.arg_size(); i != e; ++i)
+ CurFnInfo->getReturnInfo(), CurFnInfo->getReturnType()));
+ assert(CallFnInfo.arg_size() == CurFnInfo->arg_size());
+ for (unsigned i = 0, e = CurFnInfo->arg_size(); i != e; ++i)
assert(similar(CallFnInfo.arg_begin()[i].info,
CallFnInfo.arg_begin()[i].type,
- FnInfo.arg_begin()[i].info, FnInfo.arg_begin()[i].type));
+ CurFnInfo->arg_begin()[i].info,
+ CurFnInfo->arg_begin()[i].type));
#endif
-
+
// Determine whether we have a return value slot to use.
+ QualType ResultType =
+ CGM.getCXXABI().HasThisReturn(GD) ? ThisType : FPT->getResultType();
ReturnValueSlot Slot;
if (!ResultType->isVoidType() &&
- FnInfo.getReturnInfo().getKind() == ABIArgInfo::Indirect &&
+ CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect &&
!hasScalarEvaluationKind(CurFnInfo->getReturnType()))
Slot = ReturnValueSlot(ReturnValue, ResultType.isVolatileQualified());
// Now emit our call.
- RValue RV = EmitCall(FnInfo, Callee, Slot, CallArgs, MD);
+ RValue RV = EmitCall(*CurFnInfo, Callee, Slot, CallArgs, MD);
- if (!Thunk.Return.isEmpty())
- RV = PerformReturnAdjustment(*this, ResultType, RV, Thunk);
+ // Consider return adjustment if we have ThunkInfo.
+ if (Thunk && !Thunk->Return.isEmpty())
+ RV = PerformReturnAdjustment(*this, ResultType, RV, *Thunk);
+ // Emit return.
if (!ResultType->isVoidType() && Slot.isNull())
CGM.getCXXABI().EmitReturnFromThunk(*this, RV, ResultType);
@@ -377,17 +338,31 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn,
AutoreleaseResult = false;
FinishFunction();
+}
+
+void CodeGenFunction::GenerateThunk(llvm::Function *Fn,
+ const CGFunctionInfo &FnInfo,
+ GlobalDecl GD, const ThunkInfo &Thunk) {
+ StartThunk(Fn, GD, FnInfo);
+
+ // Get our callee.
+ llvm::Type *Ty =
+ CGM.getTypes().GetFunctionType(CGM.getTypes().arrangeGlobalDeclaration(GD));
+ llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true);
+
+ // Make the call and return the result.
+ EmitCallAndReturnForThunk(GD, Callee, &Thunk);
// Set the right linkage.
- CGM.setFunctionLinkage(MD, Fn);
+ CGM.setFunctionLinkage(GD, Fn);
// Set the right visibility.
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
setThunkVisibility(CGM, MD, Thunk, Fn);
}
-void CodeGenVTables::EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk,
- bool UseAvailableExternallyLinkage)
-{
+void CodeGenVTables::emitThunk(GlobalDecl GD, const ThunkInfo &Thunk,
+ bool ForVTable) {
const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeGlobalDeclaration(GD);
// FIXME: re-use FnInfo in this computation.
@@ -425,19 +400,17 @@ void CodeGenVTables::EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk,
}
llvm::Function *ThunkFn = cast<llvm::Function>(Entry);
+ bool ABIHasKeyFunctions = CGM.getTarget().getCXXABI().hasKeyFunctions();
+ bool UseAvailableExternallyLinkage = ForVTable && ABIHasKeyFunctions;
if (!ThunkFn->isDeclaration()) {
- if (UseAvailableExternallyLinkage) {
+ if (!ABIHasKeyFunctions || UseAvailableExternallyLinkage) {
// There is already a thunk emitted for this function, do nothing.
return;
}
- // If a function has a body, it should have available_externally linkage.
- assert(ThunkFn->hasAvailableExternallyLinkage() &&
- "Function should have available_externally linkage!");
-
// Change the linkage.
- CGM.setFunctionLinkage(cast<CXXMethodDecl>(GD.getDecl()), ThunkFn);
+ CGM.setFunctionLinkage(GD, ThunkFn);
return;
}
@@ -449,30 +422,34 @@ void CodeGenVTables::EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk,
// expensive/sucky at the moment, so don't generate the thunk unless
// we have to.
// FIXME: Do something better here; GenerateVarArgsThunk is extremely ugly.
- if (!UseAvailableExternallyLinkage)
+ if (!UseAvailableExternallyLinkage) {
CodeGenFunction(CGM).GenerateVarArgsThunk(ThunkFn, FnInfo, GD, Thunk);
+ CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable);
+ }
} else {
// Normal thunk body generation.
CodeGenFunction(CGM).GenerateThunk(ThunkFn, FnInfo, GD, Thunk);
+ CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable);
}
-
- if (UseAvailableExternallyLinkage)
- ThunkFn->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
}
-void CodeGenVTables::MaybeEmitThunkAvailableExternally(GlobalDecl GD,
- const ThunkInfo &Thunk) {
- // We only want to do this when building with optimizations.
- if (!CGM.getCodeGenOpts().OptimizationLevel)
+void CodeGenVTables::maybeEmitThunkForVTable(GlobalDecl GD,
+ const ThunkInfo &Thunk) {
+ // If the ABI has key functions, only the TU with the key function should emit
+ // the thunk. However, we can allow inlining of thunks if we emit them with
+ // available_externally linkage together with vtables when optimizations are
+ // enabled.
+ if (CGM.getTarget().getCXXABI().hasKeyFunctions() &&
+ !CGM.getCodeGenOpts().OptimizationLevel)
return;
// We can't emit thunks for member functions with incomplete types.
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
if (!CGM.getTypes().isFuncTypeConvertible(
- cast<FunctionType>(MD->getType().getTypePtr())))
+ MD->getType()->castAs<FunctionType>()))
return;
- EmitThunk(GD, Thunk, /*UseAvailableExternallyLinkage=*/true);
+ emitThunk(GD, Thunk, /*ForVTable=*/true);
}
void CodeGenVTables::EmitThunks(GlobalDecl GD)
@@ -484,14 +461,18 @@ void CodeGenVTables::EmitThunks(GlobalDecl GD)
if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
return;
- const VTableContext::ThunkInfoVectorTy *ThunkInfoVector =
- VTContext.getThunkInfo(MD);
+ const VTableContextBase::ThunkInfoVectorTy *ThunkInfoVector;
+ if (MicrosoftVTContext.isValid()) {
+ ThunkInfoVector = MicrosoftVTContext->getThunkInfo(GD);
+ } else {
+ ThunkInfoVector = ItaniumVTContext.getThunkInfo(GD);
+ }
+
if (!ThunkInfoVector)
return;
for (unsigned I = 0, E = ThunkInfoVector->size(); I != E; ++I)
- EmitThunk(GD, (*ThunkInfoVector)[I],
- /*UseAvailableExternallyLinkage=*/false);
+ emitThunk(GD, (*ThunkInfoVector)[I], /*ForVTable=*/false);
}
llvm::Constant *
@@ -586,7 +567,7 @@ CodeGenVTables::CreateVTableInitializer(const CXXRecordDecl *RD,
VTableThunks[NextVTableThunkIndex].first == I) {
const ThunkInfo &Thunk = VTableThunks[NextVTableThunkIndex].second;
- MaybeEmitThunkAvailableExternally(GD, Thunk);
+ maybeEmitThunkForVTable(GD, Thunk);
Init = CGM.GetAddrOfThunk(GD, Thunk);
NextVTableThunkIndex++;
@@ -613,63 +594,18 @@ CodeGenVTables::CreateVTableInitializer(const CXXRecordDecl *RD,
return llvm::ConstantArray::get(ArrayType, Inits);
}
-llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTable(const CXXRecordDecl *RD) {
- llvm::GlobalVariable *&VTable = VTables[RD];
- if (VTable)
- return VTable;
-
- // Queue up this v-table for possible deferred emission.
- CGM.addDeferredVTable(RD);
-
- SmallString<256> OutName;
- llvm::raw_svector_ostream Out(OutName);
- CGM.getCXXABI().getMangleContext().mangleCXXVTable(RD, Out);
- Out.flush();
- StringRef Name = OutName.str();
-
- llvm::ArrayType *ArrayType =
- llvm::ArrayType::get(CGM.Int8PtrTy,
- VTContext.getVTableLayout(RD).getNumVTableComponents());
-
- VTable =
- CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType,
- llvm::GlobalValue::ExternalLinkage);
- VTable->setUnnamedAddr(true);
- return VTable;
-}
-
-void
-CodeGenVTables::EmitVTableDefinition(llvm::GlobalVariable *VTable,
- llvm::GlobalVariable::LinkageTypes Linkage,
- const CXXRecordDecl *RD) {
- const VTableLayout &VTLayout = VTContext.getVTableLayout(RD);
-
- // Create and set the initializer.
- llvm::Constant *Init =
- CreateVTableInitializer(RD,
- VTLayout.vtable_component_begin(),
- VTLayout.getNumVTableComponents(),
- VTLayout.vtable_thunk_begin(),
- VTLayout.getNumVTableThunks());
- VTable->setInitializer(Init);
-
- // Set the correct linkage.
- VTable->setLinkage(Linkage);
-
- // Set the right visibility.
- CGM.setTypeVisibility(VTable, RD, CodeGenModule::TVK_ForVTable);
-}
-
llvm::GlobalVariable *
CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
const BaseSubobject &Base,
bool BaseIsVirtual,
llvm::GlobalVariable::LinkageTypes Linkage,
VTableAddressPointsMapTy& AddressPoints) {
+ if (CGDebugInfo *DI = CGM.getModuleDebugInfo())
+ DI->completeClassData(Base.getBase());
+
OwningPtr<VTableLayout> VTLayout(
- VTContext.createConstructionVTableLayout(Base.getBase(),
- Base.getBaseOffset(),
- BaseIsVirtual, RD));
+ ItaniumVTContext.createConstructionVTableLayout(
+ Base.getBase(), Base.getBaseOffset(), BaseIsVirtual, RD));
// Add the address points.
AddressPoints = VTLayout->getAddressPoints();
@@ -677,9 +613,9 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
// Get the mangled construction vtable name.
SmallString<256> OutName;
llvm::raw_svector_ostream Out(OutName);
- CGM.getCXXABI().getMangleContext().
- mangleCXXCtorVTable(RD, Base.getBaseOffset().getQuantity(), Base.getBase(),
- Out);
+ cast<ItaniumMangleContext>(CGM.getCXXABI().getMangleContext())
+ .mangleCXXCtorVTable(RD, Base.getBaseOffset().getQuantity(),
+ Base.getBase(), Out);
Out.flush();
StringRef Name = OutName.str();
@@ -719,7 +655,7 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
/// Note that we only call this at the end of the translation unit.
llvm::GlobalVariable::LinkageTypes
CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
- if (RD->getLinkage() != ExternalLinkage)
+ if (!RD->isExternallyVisible())
return llvm::GlobalVariable::InternalLinkage;
// We're at the end of the translation unit, so the current key
@@ -734,12 +670,7 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
switch (keyFunction->getTemplateSpecializationKind()) {
case TSK_Undeclared:
case TSK_ExplicitSpecialization:
- // When compiling with optimizations turned on, we emit all vtables,
- // even if the key function is not defined in the current translation
- // unit. If this is the case, use available_externally linkage.
- if (!def && CodeGenOpts.OptimizationLevel)
- return llvm::GlobalVariable::AvailableExternallyLinkage;
-
+ assert(def && "Should not have been asked to emit this");
if (keyFunction->isInlined())
return !Context.getLangOpts().AppleKext ?
llvm::GlobalVariable::LinkOnceODRLinkage :
@@ -758,9 +689,7 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
llvm::Function::InternalLinkage;
case TSK_ExplicitInstantiationDeclaration:
- return !Context.getLangOpts().AppleKext ?
- llvm::GlobalVariable::AvailableExternallyLinkage :
- llvm::Function::InternalLinkage;
+ llvm_unreachable("Should not have been asked to emit this");
}
}
@@ -776,7 +705,7 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
return llvm::GlobalVariable::LinkOnceODRLinkage;
case TSK_ExplicitInstantiationDeclaration:
- return llvm::GlobalVariable::AvailableExternallyLinkage;
+ llvm_unreachable("Should not have been asked to emit this");
case TSK_ExplicitInstantiationDefinition:
return llvm::GlobalVariable::WeakODRLinkage;
@@ -803,35 +732,13 @@ void CodeGenModule::EmitVTable(CXXRecordDecl *theClass, bool isRequired) {
void
CodeGenVTables::GenerateClassData(const CXXRecordDecl *RD) {
- // First off, check whether we've already emitted the v-table and
- // associated stuff.
- llvm::GlobalVariable *VTable = GetAddrOfVTable(RD);
- if (VTable->hasInitializer())
- return;
-
- llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD);
- EmitVTableDefinition(VTable, Linkage, RD);
+ if (CGDebugInfo *DI = CGM.getModuleDebugInfo())
+ DI->completeClassData(RD);
- if (RD->getNumVBases()) {
- if (!CGM.getTarget().getCXXABI().isMicrosoft()) {
- llvm::GlobalVariable *VTT = GetAddrOfVTT(RD);
- EmitVTTDefinition(VTT, Linkage, RD);
- } else {
- // FIXME: Emit vbtables here.
- }
- }
+ if (RD->getNumVBases())
+ CGM.getCXXABI().emitVirtualInheritanceTables(RD);
- // If this is the magic class __cxxabiv1::__fundamental_type_info,
- // we will emit the typeinfo for the fundamental types. This is the
- // same behaviour as GCC.
- const DeclContext *DC = RD->getDeclContext();
- if (RD->getIdentifier() &&
- RD->getIdentifier()->isStr("__fundamental_type_info") &&
- isa<NamespaceDecl>(DC) &&
- cast<NamespaceDecl>(DC)->getIdentifier() &&
- cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__cxxabiv1") &&
- DC->getParent()->isTranslationUnit())
- CGM.EmitFundamentalRTTIDescriptors();
+ CGM.getCXXABI().emitVTableDefinitions(*this, RD);
}
/// At this point in the translation unit, does it appear that can we
@@ -875,16 +782,6 @@ bool CodeGenVTables::isVTableExternal(const CXXRecordDecl *RD) {
/// we define that v-table?
static bool shouldEmitVTableAtEndOfTranslationUnit(CodeGenModule &CGM,
const CXXRecordDecl *RD) {
- // If we're building with optimization, we always emit v-tables
- // since that allows for virtual function calls to be devirtualized.
- // If the v-table is defined strongly elsewhere, this definition
- // will be emitted available_externally.
- //
- // However, we don't want to do this in -fapple-kext mode, because
- // kext mode does not permit devirtualization.
- if (CGM.getCodeGenOpts().OptimizationLevel && !CGM.getLangOpts().AppleKext)
- return true;
-
return !CGM.getVTables().isVTableExternal(RD);
}
diff --git a/lib/CodeGen/CGVTables.h b/lib/CodeGen/CGVTables.h
index bd3bdb1..e8cd55e 100644
--- a/lib/CodeGen/CGVTables.h
+++ b/lib/CodeGen/CGVTables.h
@@ -31,10 +31,10 @@ namespace CodeGen {
class CodeGenVTables {
CodeGenModule &CGM;
- VTableContext VTContext;
-
- /// VTables - All the vtables which have been defined.
- llvm::DenseMap<const CXXRecordDecl *, llvm::GlobalVariable *> VTables;
+ // FIXME: Consider moving ItaniumVTContext and MicrosoftVTContext into
+ // respective CXXABI classes?
+ ItaniumVTableContext ItaniumVTContext;
+ OwningPtr<MicrosoftVTableContext> MicrosoftVTContext;
/// VTableAddressPointsMapTy - Address points for a single vtable.
typedef llvm::DenseMap<BaseSubobject, uint64_t> VTableAddressPointsMapTy;
@@ -52,16 +52,14 @@ class CodeGenVTables {
/// indices.
SecondaryVirtualPointerIndicesMapTy SecondaryVirtualPointerIndices;
- /// EmitThunk - Emit a single thunk.
- void EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk,
- bool UseAvailableExternallyLinkage);
+ /// emitThunk - Emit a single thunk.
+ void emitThunk(GlobalDecl GD, const ThunkInfo &Thunk, bool ForVTable);
- /// MaybeEmitThunkAvailableExternally - Try to emit the given thunk with
- /// available_externally linkage to allow for inlining of thunks.
- /// This will be done iff optimizations are enabled and the member function
- /// doesn't contain any incomplete types.
- void MaybeEmitThunkAvailableExternally(GlobalDecl GD, const ThunkInfo &Thunk);
+ /// maybeEmitThunkForVTable - Emit the given thunk for the vtable if needed by
+ /// the ABI.
+ void maybeEmitThunkForVTable(GlobalDecl GD, const ThunkInfo &Thunk);
+public:
/// CreateVTableInitializer - Create a vtable initializer for the given record
/// decl.
/// \param Components - The vtable components; this is really an array of
@@ -72,15 +70,13 @@ class CodeGenVTables {
const VTableLayout::VTableThunkTy *VTableThunks,
unsigned NumVTableThunks);
-public:
CodeGenVTables(CodeGenModule &CGM);
- VTableContext &getVTableContext() { return VTContext; }
+ ItaniumVTableContext &getItaniumVTableContext() { return ItaniumVTContext; }
- /// needsVTTParameter - Return whether the given global decl needs a VTT
- /// parameter, which it does if it's a base constructor or destructor with
- /// virtual bases.
- static bool needsVTTParameter(GlobalDecl GD);
+ MicrosoftVTableContext &getMicrosoftVTableContext() {
+ return *MicrosoftVTContext.get();
+ }
/// getSubVTTIndex - Return the index of the sub-VTT for the base class of the
/// given record decl.
@@ -95,14 +91,6 @@ public:
/// class decl.
uint64_t getAddressPoint(BaseSubobject Base, const CXXRecordDecl *RD);
- /// GetAddrOfVTable - Get the address of the vtable for the given record decl.
- llvm::GlobalVariable *GetAddrOfVTable(const CXXRecordDecl *RD);
-
- /// EmitVTableDefinition - Emit the definition of the given vtable.
- void EmitVTableDefinition(llvm::GlobalVariable *VTable,
- llvm::GlobalVariable::LinkageTypes Linkage,
- const CXXRecordDecl *RD);
-
/// GenerateConstructionVTable - Generate a construction vtable for the given
/// base subobject.
llvm::GlobalVariable *
diff --git a/lib/CodeGen/CGValue.h b/lib/CodeGen/CGValue.h
index b625b86..da2a034 100644
--- a/lib/CodeGen/CGValue.h
+++ b/lib/CodeGen/CGValue.h
@@ -381,23 +381,11 @@ class AggValueSlot {
/// evaluating an expression which constructs such an object.
bool AliasedFlag : 1;
- /// ValueOfAtomicFlag - This is set to true if the slot is the value
- /// subobject of an object the size of an _Atomic(T). The specific
- /// guarantees this makes are:
- /// - the address is guaranteed to be a getelementptr into the
- /// padding struct and
- /// - it is okay to store something the width of an _Atomic(T)
- /// into the address.
- /// Tracking this allows us to avoid some obviously unnecessary
- /// memcpys.
- bool ValueOfAtomicFlag : 1;
-
public:
enum IsAliased_t { IsNotAliased, IsAliased };
enum IsDestructed_t { IsNotDestructed, IsDestructed };
enum IsZeroed_t { IsNotZeroed, IsZeroed };
enum NeedsGCBarriers_t { DoesNotNeedGCBarriers, NeedsGCBarriers };
- enum IsValueOfAtomic_t { IsNotValueOfAtomic, IsValueOfAtomic };
/// ignored - Returns an aggregate value slot indicating that the
/// aggregate value is being ignored.
@@ -421,9 +409,7 @@ public:
IsDestructed_t isDestructed,
NeedsGCBarriers_t needsGC,
IsAliased_t isAliased,
- IsZeroed_t isZeroed = IsNotZeroed,
- IsValueOfAtomic_t isValueOfAtomic
- = IsNotValueOfAtomic) {
+ IsZeroed_t isZeroed = IsNotZeroed) {
AggValueSlot AV;
AV.Addr = addr;
AV.Alignment = align.getQuantity();
@@ -432,7 +418,6 @@ public:
AV.ObjCGCFlag = needsGC;
AV.ZeroedFlag = isZeroed;
AV.AliasedFlag = isAliased;
- AV.ValueOfAtomicFlag = isValueOfAtomic;
return AV;
}
@@ -440,12 +425,9 @@ public:
IsDestructed_t isDestructed,
NeedsGCBarriers_t needsGC,
IsAliased_t isAliased,
- IsZeroed_t isZeroed = IsNotZeroed,
- IsValueOfAtomic_t isValueOfAtomic
- = IsNotValueOfAtomic) {
+ IsZeroed_t isZeroed = IsNotZeroed) {
return forAddr(LV.getAddress(), LV.getAlignment(),
- LV.getQuals(), isDestructed, needsGC, isAliased, isZeroed,
- isValueOfAtomic);
+ LV.getQuals(), isDestructed, needsGC, isAliased, isZeroed);
}
IsDestructed_t isExternallyDestructed() const {
@@ -477,12 +459,6 @@ public:
return Addr;
}
- IsValueOfAtomic_t isValueOfAtomic() const {
- return IsValueOfAtomic_t(ValueOfAtomicFlag);
- }
-
- llvm::Value *getPaddedAtomicAddr() const;
-
bool isIgnored() const {
return Addr == 0;
}
diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt
index 9ca2295..83dbbf0 100644
--- a/lib/CodeGen/CMakeLists.txt
+++ b/lib/CodeGen/CMakeLists.txt
@@ -41,6 +41,7 @@ add_clang_library(clangCodeGen
CGStmt.cpp
CGVTables.cpp
CGVTT.cpp
+ CodeGenABITypes.cpp
CodeGenAction.cpp
CodeGenFunction.cpp
CodeGenModule.cpp
@@ -48,6 +49,7 @@ add_clang_library(clangCodeGen
CodeGenTypes.cpp
ItaniumCXXABI.cpp
MicrosoftCXXABI.cpp
+ MicrosoftVBTables.cpp
ModuleBuilder.cpp
TargetInfo.cpp
)
diff --git a/lib/CodeGen/CodeGenABITypes.cpp b/lib/CodeGen/CodeGenABITypes.cpp
new file mode 100644
index 0000000..18c836c
--- /dev/null
+++ b/lib/CodeGen/CodeGenABITypes.cpp
@@ -0,0 +1,69 @@
+//==--- CodeGenABITypes.cpp - Convert Clang types to LLVM types for ABI ----==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// CodeGenABITypes is a simple interface for getting LLVM types for
+// the parameters and the return value of a function given the Clang
+// types.
+//
+// The class is implemented as a public wrapper around the private
+// CodeGenTypes class in lib/CodeGen.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/CodeGen/CodeGenABITypes.h"
+
+#include "clang/CodeGen/CGFunctionInfo.h"
+#include "CodeGenModule.h"
+
+using namespace clang;
+using namespace CodeGen;
+
+CodeGenABITypes::CodeGenABITypes(ASTContext &C,
+ const CodeGenOptions &CodeGenOpts,
+ llvm::Module &M,
+ const llvm::DataLayout &TD,
+ DiagnosticsEngine &Diags)
+ : CGM(new CodeGen::CodeGenModule(C, CodeGenOpts, M, TD, Diags)) {
+}
+
+CodeGenABITypes::~CodeGenABITypes()
+{
+ delete CGM;
+}
+
+const CGFunctionInfo &
+CodeGenABITypes::arrangeObjCMessageSendSignature(const ObjCMethodDecl *MD,
+ QualType receiverType) {
+ return CGM->getTypes().arrangeObjCMessageSendSignature(MD, receiverType);
+}
+
+const CGFunctionInfo &
+CodeGenABITypes::arrangeFreeFunctionType(CanQual<FunctionProtoType> Ty) {
+ return CGM->getTypes().arrangeFreeFunctionType(Ty);
+}
+
+const CGFunctionInfo &
+CodeGenABITypes::arrangeFreeFunctionType(CanQual<FunctionNoProtoType> Ty) {
+ return CGM->getTypes().arrangeFreeFunctionType(Ty);
+}
+
+const CGFunctionInfo &
+CodeGenABITypes::arrangeCXXMethodType(const CXXRecordDecl *RD,
+ const FunctionProtoType *FTP) {
+ return CGM->getTypes().arrangeCXXMethodType(RD, FTP);
+}
+
+const CGFunctionInfo &
+CodeGenABITypes::arrangeLLVMFunctionInfo(CanQualType returnType,
+ llvm::ArrayRef<CanQualType> argTypes,
+ FunctionType::ExtInfo info,
+ RequiredArgs args) {
+ return CGM->getTypes().arrangeLLVMFunctionInfo(returnType, argTypes,
+ info, args);
+}
diff --git a/lib/CodeGen/CodeGenAction.cpp b/lib/CodeGen/CodeGenAction.cpp
index 679cfeb..3072204 100644
--- a/lib/CodeGen/CodeGenAction.cpp
+++ b/lib/CodeGen/CodeGenAction.cpp
@@ -171,6 +171,10 @@ namespace clang {
Gen->HandleTagDeclDefinition(D);
}
+ virtual void HandleTagDeclRequiredDefinition(const TagDecl *D) {
+ Gen->HandleTagDeclRequiredDefinition(D);
+ }
+
virtual void CompleteTentativeDefinition(VarDecl *D) {
Gen->CompleteTentativeDefinition(D);
}
@@ -179,6 +183,19 @@ namespace clang {
Gen->HandleVTable(RD, DefinitionRequired);
}
+ virtual void HandleLinkerOptionPragma(llvm::StringRef Opts) {
+ Gen->HandleLinkerOptionPragma(Opts);
+ }
+
+ virtual void HandleDetectMismatch(llvm::StringRef Name,
+ llvm::StringRef Value) {
+ Gen->HandleDetectMismatch(Name, Value);
+ }
+
+ virtual void HandleDependentLibrary(llvm::StringRef Opts) {
+ Gen->HandleDependentLibrary(Opts);
+ }
+
static void InlineAsmDiagHandler(const llvm::SMDiagnostic &SM,void *Context,
unsigned LocCookie) {
SourceLocation Loc = SourceLocation::getFromRawEncoding(LocCookie);
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 75c60ed..ce1b445 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -16,12 +16,14 @@
#include "CGCXXABI.h"
#include "CGDebugInfo.h"
#include "CodeGenModule.h"
+#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/StmtCXX.h"
#include "clang/Basic/OpenCL.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/CodeGen/CGFunctionInfo.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Intrinsics.h"
@@ -31,25 +33,23 @@ using namespace clang;
using namespace CodeGen;
CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
- : CodeGenTypeCache(cgm), CGM(cgm), Target(cgm.getTarget()),
- Builder(cgm.getModule().getContext()),
- SanitizePerformTypeCheck(CGM.getSanOpts().Null |
- CGM.getSanOpts().Alignment |
- CGM.getSanOpts().ObjectSize |
- CGM.getSanOpts().Vptr),
- SanOpts(&CGM.getSanOpts()),
- AutoreleaseResult(false), BlockInfo(0), BlockPointer(0),
- LambdaThisCaptureField(0), NormalCleanupDest(0), NextCleanupDestIndex(1),
- FirstBlockInfo(0), EHResumeBlock(0), ExceptionSlot(0), EHSelectorSlot(0),
- DebugInfo(0), DisableDebugInfo(false), CalleeWithThisReturn(0),
- DidCallStackSave(false),
- IndirectBranch(0), SwitchInsn(0), CaseRangeBlock(0), UnreachableBlock(0),
- NumReturnExprs(0), NumSimpleReturnExprs(0),
- CXXABIThisDecl(0), CXXABIThisValue(0), CXXThisValue(0),
- CXXDefaultInitExprThis(0),
- CXXStructorImplicitParamDecl(0), CXXStructorImplicitParamValue(0),
- OutermostConditional(0), CurLexicalScope(0), TerminateLandingPad(0),
- TerminateHandler(0), TrapBB(0) {
+ : CodeGenTypeCache(cgm), CGM(cgm), Target(cgm.getTarget()),
+ Builder(cgm.getModule().getContext()), CapturedStmtInfo(0),
+ SanitizePerformTypeCheck(CGM.getSanOpts().Null |
+ CGM.getSanOpts().Alignment |
+ CGM.getSanOpts().ObjectSize |
+ CGM.getSanOpts().Vptr),
+ SanOpts(&CGM.getSanOpts()), AutoreleaseResult(false), BlockInfo(0),
+ BlockPointer(0), LambdaThisCaptureField(0), NormalCleanupDest(0),
+ NextCleanupDestIndex(1), FirstBlockInfo(0), EHResumeBlock(0),
+ ExceptionSlot(0), EHSelectorSlot(0), DebugInfo(CGM.getModuleDebugInfo()),
+ DisableDebugInfo(false), DidCallStackSave(false), IndirectBranch(0),
+ SwitchInsn(0), CaseRangeBlock(0), UnreachableBlock(0), NumReturnExprs(0),
+ NumSimpleReturnExprs(0), CXXABIThisDecl(0), CXXABIThisValue(0),
+ CXXThisValue(0), CXXDefaultInitExprThis(0),
+ CXXStructorImplicitParamDecl(0), CXXStructorImplicitParamValue(0),
+ OutermostConditional(0), CurLexicalScope(0), TerminateLandingPad(0),
+ TerminateHandler(0), TrapBB(0) {
if (!suppressNewContext)
CGM.getCXXABI().getMangleContext().startNewFunction();
@@ -64,6 +64,8 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
}
CodeGenFunction::~CodeGenFunction() {
+ assert(LifetimeExtendedCleanupStack.empty() && "failed to emit a cleanup");
+
// If there are any unclaimed block infos, go ahead and destroy them
// now. This can happen if IR-gen gets clever and skips evaluating
// something.
@@ -189,15 +191,23 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
"mismatched push/pop in break/continue stack!");
bool OnlySimpleReturnStmts = NumSimpleReturnExprs > 0
- && NumSimpleReturnExprs == NumReturnExprs;
- // If the function contains only a simple return statement, the
- // cleanup code may become the first breakpoint in the function. To
- // be safe, set the debug location for it to the location of the
- // return statement. Otherwise point it to end of the function's
- // lexical scope.
+ && NumSimpleReturnExprs == NumReturnExprs
+ && ReturnBlock.getBlock()->use_empty();
+ // Usually the return expression is evaluated before the cleanup
+ // code. If the function contains only a simple return statement,
+ // such as a constant, the location before the cleanup code becomes
+ // the last useful breakpoint in the function, because the simple
+ // return expression will be evaluated after the cleanup code. To be
+ // safe, set the debug location for cleanup code to the location of
+ // the return statement. Otherwise the cleanup code should be at the
+ // end of the function's lexical scope.
+ //
+ // If there are multiple branches to the return block, the branch
+ // instructions will get the location of the return statements and
+ // all will be fine.
if (CGDebugInfo *DI = getDebugInfo()) {
if (OnlySimpleReturnStmts)
- DI->EmitLocation(Builder, LastStopPoint);
+ DI->EmitLocation(Builder, LastStopPoint);
else
DI->EmitLocation(Builder, EndLoc);
}
@@ -208,7 +218,7 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
// edges will be *really* confused.
bool EmitRetDbgLoc = true;
if (EHStack.stable_begin() != PrologueCleanupDepth) {
- PopCleanupBlocks(PrologueCleanupDepth, EndLoc);
+ PopCleanupBlocks(PrologueCleanupDepth);
// Make sure the line table doesn't jump back into the body for
// the ret after it's been at EndLoc.
@@ -230,7 +240,7 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
DI->EmitFunctionEnd(Builder);
}
- EmitFunctionEpilog(*CurFnInfo, EmitRetDbgLoc);
+ EmitFunctionEpilog(*CurFnInfo, EmitRetDbgLoc, EndLoc);
EmitEndEHSpec(CurCodeDecl);
assert(EHStack.empty() &&
@@ -511,6 +521,22 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
EmitOpenCLKernelMetadata(FD, Fn);
}
+ // If we are checking function types, emit a function type signature as
+ // prefix data.
+ if (getLangOpts().CPlusPlus && SanOpts->Function) {
+ if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
+ if (llvm::Constant *PrefixSig =
+ CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM)) {
+ llvm::Constant *FTRTTIConst =
+ CGM.GetAddrOfRTTIDescriptor(FD->getType(), /*ForEH=*/true);
+ llvm::Constant *PrefixStructElems[] = { PrefixSig, FTRTTIConst };
+ llvm::Constant *PrefixStructConst =
+ llvm::ConstantStruct::getAnon(PrefixStructElems, /*Packed=*/true);
+ Fn->setPrefixData(PrefixStructConst);
+ }
+ }
+ }
+
llvm::BasicBlock *EntryBB = createBasicBlock("entry", CurFn);
// Create a marker to make it easy to insert allocas into the entryblock
@@ -583,7 +609,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
if (LambdaThisCaptureField) {
// If this lambda captures this, load it.
LValue ThisLValue = EmitLValueForLambdaField(LambdaThisCaptureField);
- CXXThisValue = EmitLoadOfLValue(ThisLValue).getScalarVal();
+ CXXThisValue = EmitLoadOfLValue(ThisLValue,
+ SourceLocation()).getScalarVal();
}
} else {
// Not in a lambda; just use 'this' from the method.
@@ -616,13 +643,12 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
DI->EmitLocation(Builder, StartLoc);
}
-void CodeGenFunction::EmitFunctionBody(FunctionArgList &Args) {
- const FunctionDecl *FD = cast<FunctionDecl>(CurGD.getDecl());
- assert(FD->getBody());
- if (const CompoundStmt *S = dyn_cast<CompoundStmt>(FD->getBody()))
+void CodeGenFunction::EmitFunctionBody(FunctionArgList &Args,
+ const Stmt *Body) {
+ if (const CompoundStmt *S = dyn_cast<CompoundStmt>(Body))
EmitCompoundStmtWithoutScope(*S);
else
- EmitStmt(FD->getBody());
+ EmitStmt(Body);
}
/// Tries to mark the given function nounwind based on the
@@ -645,30 +671,42 @@ static void TryMarkNoThrow(llvm::Function *F) {
F->setDoesNotThrow();
}
+static void EmitSizedDeallocationFunction(CodeGenFunction &CGF,
+ const FunctionDecl *UnsizedDealloc) {
+ // This is a weak discardable definition of the sized deallocation function.
+ CGF.CurFn->setLinkage(llvm::Function::LinkOnceAnyLinkage);
+
+ // Call the unsized deallocation function and forward the first argument
+ // unchanged.
+ llvm::Constant *Unsized = CGF.CGM.GetAddrOfFunction(UnsizedDealloc);
+ CGF.Builder.CreateCall(Unsized, &*CGF.CurFn->arg_begin());
+}
+
void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
const CGFunctionInfo &FnInfo) {
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
// Check if we should generate debug info for this function.
- if (!FD->hasAttr<NoDebugAttr>())
- maybeInitializeDebugInfo();
+ if (FD->hasAttr<NoDebugAttr>())
+ DebugInfo = NULL; // disable debug info indefinitely for this function
FunctionArgList Args;
QualType ResTy = FD->getResultType();
CurGD = GD;
- if (isa<CXXMethodDecl>(FD) && cast<CXXMethodDecl>(FD)->isInstance())
+ const CXXMethodDecl *MD;
+ if ((MD = dyn_cast<CXXMethodDecl>(FD)) && MD->isInstance()) {
+ if (CGM.getCXXABI().HasThisReturn(GD))
+ ResTy = MD->getThisType(getContext());
CGM.getCXXABI().BuildInstanceFunctionParams(*this, ResTy, Args);
+ }
for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i)
Args.push_back(FD->getParamDecl(i));
SourceRange BodyRange;
if (Stmt *Body = FD->getBody()) BodyRange = Body->getSourceRange();
-
- // CalleeWithThisReturn keeps track of the last callee inside this function
- // that returns 'this'. Before starting the function, we set it to null.
- CalleeWithThisReturn = 0;
+ CurEHLocation = BodyRange.getEnd();
// Emit the standard function prologue.
StartFunction(GD, ResTy, Fn, FnInfo, Args, BodyRange.getBegin());
@@ -689,17 +727,24 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
EmitLambdaToBlockPointerBody(Args);
} else if (isa<CXXMethodDecl>(FD) &&
cast<CXXMethodDecl>(FD)->isLambdaStaticInvoker()) {
- // The lambda "__invoke" function is special, because it forwards or
+ // The lambda static invoker function is special, because it forwards or
// clones the body of the function call operator (but is actually static).
EmitLambdaStaticInvokeFunction(cast<CXXMethodDecl>(FD));
} else if (FD->isDefaulted() && isa<CXXMethodDecl>(FD) &&
- cast<CXXMethodDecl>(FD)->isCopyAssignmentOperator()) {
+ (cast<CXXMethodDecl>(FD)->isCopyAssignmentOperator() ||
+ cast<CXXMethodDecl>(FD)->isMoveAssignmentOperator())) {
// Implicit copy-assignment gets the same special treatment as implicit
// copy-constructors.
emitImplicitAssignmentOperatorBody(Args);
- }
- else
- EmitFunctionBody(Args);
+ } else if (Stmt *Body = FD->getBody()) {
+ EmitFunctionBody(Args, Body);
+ } else if (FunctionDecl *UnsizedDealloc =
+ FD->getCorrespondingUnsizedGlobalDeallocationFunction()) {
+ // Global sized deallocation functions get an implicit weak definition if
+ // they don't have an explicit definition.
+ EmitSizedDeallocationFunction(*this, UnsizedDealloc);
+ } else
+ llvm_unreachable("no definition for emitted function");
// C++11 [stmt.return]p2:
// Flowing off the end of a function [...] results in undefined behavior in
@@ -721,9 +766,6 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
// Emit the standard function epilogue.
FinishFunction(BodyRange.getEnd());
- // CalleeWithThisReturn keeps track of the last callee inside this function
- // that returns 'this'. After finishing the function, we set it to null.
- CalleeWithThisReturn = 0;
// If we haven't marked the function nothrow through other means, do
// a quick pass now to see if we can.
@@ -945,9 +987,8 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
/// ErrorUnsupported - Print out an error that codegen doesn't support the
/// specified stmt yet.
-void CodeGenFunction::ErrorUnsupported(const Stmt *S, const char *Type,
- bool OmitOnError) {
- CGM.ErrorUnsupported(S, Type, OmitOnError);
+void CodeGenFunction::ErrorUnsupported(const Stmt *S, const char *Type) {
+ CGM.ErrorUnsupported(S, Type);
}
/// emitNonZeroVLAInit - Emit the "zero" initialization of a
@@ -1267,6 +1308,10 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
case Type::ObjCObjectPointer:
llvm_unreachable("type class is never variably-modified!");
+ case Type::Decayed:
+ type = cast<DecayedType>(ty)->getPointeeType();
+ break;
+
case Type::Pointer:
type = cast<PointerType>(ty)->getPointeeType();
break;
@@ -1338,6 +1383,7 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
case Type::UnaryTransform:
case Type::Attributed:
case Type::SubstTemplateTypeParm:
+ case Type::PackExpansion:
// Keep walking after single level desugaring.
type = type.getSingleStepDesugaredType(getContext());
break;
@@ -1447,3 +1493,5 @@ llvm::Value *CodeGenFunction::EmitFieldAnnotations(const FieldDecl *D,
return V;
}
+
+CodeGenFunction::CGCapturedStmtInfo::~CGCapturedStmtInfo() { }
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index ff74c15..db291e3 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -17,12 +17,14 @@
#include "CGBuilder.h"
#include "CGDebugInfo.h"
#include "CGValue.h"
+#include "EHScopeStack.h"
#include "CodeGenModule.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/Type.h"
#include "clang/Basic/ABI.h"
+#include "clang/Basic/CapturedStmt.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/ArrayRef.h"
@@ -89,457 +91,6 @@ enum TypeEvaluationKind {
TEK_Aggregate
};
-/// A branch fixup. These are required when emitting a goto to a
-/// label which hasn't been emitted yet. The goto is optimistically
-/// emitted as a branch to the basic block for the label, and (if it
-/// occurs in a scope with non-trivial cleanups) a fixup is added to
-/// the innermost cleanup. When a (normal) cleanup is popped, any
-/// unresolved fixups in that scope are threaded through the cleanup.
-struct BranchFixup {
- /// The block containing the terminator which needs to be modified
- /// into a switch if this fixup is resolved into the current scope.
- /// If null, LatestBranch points directly to the destination.
- llvm::BasicBlock *OptimisticBranchBlock;
-
- /// The ultimate destination of the branch.
- ///
- /// This can be set to null to indicate that this fixup was
- /// successfully resolved.
- llvm::BasicBlock *Destination;
-
- /// The destination index value.
- unsigned DestinationIndex;
-
- /// The initial branch of the fixup.
- llvm::BranchInst *InitialBranch;
-};
-
-template <class T> struct InvariantValue {
- typedef T type;
- typedef T saved_type;
- static bool needsSaving(type value) { return false; }
- static saved_type save(CodeGenFunction &CGF, type value) { return value; }
- static type restore(CodeGenFunction &CGF, saved_type value) { return value; }
-};
-
-/// A metaprogramming class for ensuring that a value will dominate an
-/// arbitrary position in a function.
-template <class T> struct DominatingValue : InvariantValue<T> {};
-
-template <class T, bool mightBeInstruction =
- llvm::is_base_of<llvm::Value, T>::value &&
- !llvm::is_base_of<llvm::Constant, T>::value &&
- !llvm::is_base_of<llvm::BasicBlock, T>::value>
-struct DominatingPointer;
-template <class T> struct DominatingPointer<T,false> : InvariantValue<T*> {};
-// template <class T> struct DominatingPointer<T,true> at end of file
-
-template <class T> struct DominatingValue<T*> : DominatingPointer<T> {};
-
-enum CleanupKind {
- EHCleanup = 0x1,
- NormalCleanup = 0x2,
- NormalAndEHCleanup = EHCleanup | NormalCleanup,
-
- InactiveCleanup = 0x4,
- InactiveEHCleanup = EHCleanup | InactiveCleanup,
- InactiveNormalCleanup = NormalCleanup | InactiveCleanup,
- InactiveNormalAndEHCleanup = NormalAndEHCleanup | InactiveCleanup
-};
-
-/// A stack of scopes which respond to exceptions, including cleanups
-/// and catch blocks.
-class EHScopeStack {
-public:
- /// A saved depth on the scope stack. This is necessary because
- /// pushing scopes onto the stack invalidates iterators.
- class stable_iterator {
- friend class EHScopeStack;
-
- /// Offset from StartOfData to EndOfBuffer.
- ptrdiff_t Size;
-
- stable_iterator(ptrdiff_t Size) : Size(Size) {}
-
- public:
- static stable_iterator invalid() { return stable_iterator(-1); }
- stable_iterator() : Size(-1) {}
-
- bool isValid() const { return Size >= 0; }
-
- /// Returns true if this scope encloses I.
- /// Returns false if I is invalid.
- /// This scope must be valid.
- bool encloses(stable_iterator I) const { return Size <= I.Size; }
-
- /// Returns true if this scope strictly encloses I: that is,
- /// if it encloses I and is not I.
- /// Returns false is I is invalid.
- /// This scope must be valid.
- bool strictlyEncloses(stable_iterator I) const { return Size < I.Size; }
-
- friend bool operator==(stable_iterator A, stable_iterator B) {
- return A.Size == B.Size;
- }
- friend bool operator!=(stable_iterator A, stable_iterator B) {
- return A.Size != B.Size;
- }
- };
-
- /// Information for lazily generating a cleanup. Subclasses must be
- /// POD-like: cleanups will not be destructed, and they will be
- /// allocated on the cleanup stack and freely copied and moved
- /// around.
- ///
- /// Cleanup implementations should generally be declared in an
- /// anonymous namespace.
- class Cleanup {
- // Anchor the construction vtable.
- virtual void anchor();
- public:
- /// Generation flags.
- class Flags {
- enum {
- F_IsForEH = 0x1,
- F_IsNormalCleanupKind = 0x2,
- F_IsEHCleanupKind = 0x4
- };
- unsigned flags;
-
- public:
- Flags() : flags(0) {}
-
- /// isForEH - true if the current emission is for an EH cleanup.
- bool isForEHCleanup() const { return flags & F_IsForEH; }
- bool isForNormalCleanup() const { return !isForEHCleanup(); }
- void setIsForEHCleanup() { flags |= F_IsForEH; }
-
- bool isNormalCleanupKind() const { return flags & F_IsNormalCleanupKind; }
- void setIsNormalCleanupKind() { flags |= F_IsNormalCleanupKind; }
-
- /// isEHCleanupKind - true if the cleanup was pushed as an EH
- /// cleanup.
- bool isEHCleanupKind() const { return flags & F_IsEHCleanupKind; }
- void setIsEHCleanupKind() { flags |= F_IsEHCleanupKind; }
- };
-
- // Provide a virtual destructor to suppress a very common warning
- // that unfortunately cannot be suppressed without this. Cleanups
- // should not rely on this destructor ever being called.
- virtual ~Cleanup() {}
-
- /// Emit the cleanup. For normal cleanups, this is run in the
- /// same EH context as when the cleanup was pushed, i.e. the
- /// immediately-enclosing context of the cleanup scope. For
- /// EH cleanups, this is run in a terminate context.
- ///
- // \param flags cleanup kind.
- virtual void Emit(CodeGenFunction &CGF, Flags flags) = 0;
- };
-
- /// ConditionalCleanupN stores the saved form of its N parameters,
- /// then restores them and performs the cleanup.
- template <class T, class A0>
- class ConditionalCleanup1 : public Cleanup {
- typedef typename DominatingValue<A0>::saved_type A0_saved;
- A0_saved a0_saved;
-
- void Emit(CodeGenFunction &CGF, Flags flags) {
- A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
- T(a0).Emit(CGF, flags);
- }
-
- public:
- ConditionalCleanup1(A0_saved a0)
- : a0_saved(a0) {}
- };
-
- template <class T, class A0, class A1>
- class ConditionalCleanup2 : public Cleanup {
- typedef typename DominatingValue<A0>::saved_type A0_saved;
- typedef typename DominatingValue<A1>::saved_type A1_saved;
- A0_saved a0_saved;
- A1_saved a1_saved;
-
- void Emit(CodeGenFunction &CGF, Flags flags) {
- A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
- A1 a1 = DominatingValue<A1>::restore(CGF, a1_saved);
- T(a0, a1).Emit(CGF, flags);
- }
-
- public:
- ConditionalCleanup2(A0_saved a0, A1_saved a1)
- : a0_saved(a0), a1_saved(a1) {}
- };
-
- template <class T, class A0, class A1, class A2>
- class ConditionalCleanup3 : public Cleanup {
- typedef typename DominatingValue<A0>::saved_type A0_saved;
- typedef typename DominatingValue<A1>::saved_type A1_saved;
- typedef typename DominatingValue<A2>::saved_type A2_saved;
- A0_saved a0_saved;
- A1_saved a1_saved;
- A2_saved a2_saved;
-
- void Emit(CodeGenFunction &CGF, Flags flags) {
- A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
- A1 a1 = DominatingValue<A1>::restore(CGF, a1_saved);
- A2 a2 = DominatingValue<A2>::restore(CGF, a2_saved);
- T(a0, a1, a2).Emit(CGF, flags);
- }
-
- public:
- ConditionalCleanup3(A0_saved a0, A1_saved a1, A2_saved a2)
- : a0_saved(a0), a1_saved(a1), a2_saved(a2) {}
- };
-
- template <class T, class A0, class A1, class A2, class A3>
- class ConditionalCleanup4 : public Cleanup {
- typedef typename DominatingValue<A0>::saved_type A0_saved;
- typedef typename DominatingValue<A1>::saved_type A1_saved;
- typedef typename DominatingValue<A2>::saved_type A2_saved;
- typedef typename DominatingValue<A3>::saved_type A3_saved;
- A0_saved a0_saved;
- A1_saved a1_saved;
- A2_saved a2_saved;
- A3_saved a3_saved;
-
- void Emit(CodeGenFunction &CGF, Flags flags) {
- A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
- A1 a1 = DominatingValue<A1>::restore(CGF, a1_saved);
- A2 a2 = DominatingValue<A2>::restore(CGF, a2_saved);
- A3 a3 = DominatingValue<A3>::restore(CGF, a3_saved);
- T(a0, a1, a2, a3).Emit(CGF, flags);
- }
-
- public:
- ConditionalCleanup4(A0_saved a0, A1_saved a1, A2_saved a2, A3_saved a3)
- : a0_saved(a0), a1_saved(a1), a2_saved(a2), a3_saved(a3) {}
- };
-
-private:
- // The implementation for this class is in CGException.h and
- // CGException.cpp; the definition is here because it's used as a
- // member of CodeGenFunction.
-
- /// The start of the scope-stack buffer, i.e. the allocated pointer
- /// for the buffer. All of these pointers are either simultaneously
- /// null or simultaneously valid.
- char *StartOfBuffer;
-
- /// The end of the buffer.
- char *EndOfBuffer;
-
- /// The first valid entry in the buffer.
- char *StartOfData;
-
- /// The innermost normal cleanup on the stack.
- stable_iterator InnermostNormalCleanup;
-
- /// The innermost EH scope on the stack.
- stable_iterator InnermostEHScope;
-
- /// The current set of branch fixups. A branch fixup is a jump to
- /// an as-yet unemitted label, i.e. a label for which we don't yet
- /// know the EH stack depth. Whenever we pop a cleanup, we have
- /// to thread all the current branch fixups through it.
- ///
- /// Fixups are recorded as the Use of the respective branch or
- /// switch statement. The use points to the final destination.
- /// When popping out of a cleanup, these uses are threaded through
- /// the cleanup and adjusted to point to the new cleanup.
- ///
- /// Note that branches are allowed to jump into protected scopes
- /// in certain situations; e.g. the following code is legal:
- /// struct A { ~A(); }; // trivial ctor, non-trivial dtor
- /// goto foo;
- /// A a;
- /// foo:
- /// bar();
- SmallVector<BranchFixup, 8> BranchFixups;
-
- char *allocate(size_t Size);
-
- void *pushCleanup(CleanupKind K, size_t DataSize);
-
-public:
- EHScopeStack() : StartOfBuffer(0), EndOfBuffer(0), StartOfData(0),
- InnermostNormalCleanup(stable_end()),
- InnermostEHScope(stable_end()) {}
- ~EHScopeStack() { delete[] StartOfBuffer; }
-
- // Variadic templates would make this not terrible.
-
- /// Push a lazily-created cleanup on the stack.
- template <class T>
- void pushCleanup(CleanupKind Kind) {
- void *Buffer = pushCleanup(Kind, sizeof(T));
- Cleanup *Obj = new(Buffer) T();
- (void) Obj;
- }
-
- /// Push a lazily-created cleanup on the stack.
- template <class T, class A0>
- void pushCleanup(CleanupKind Kind, A0 a0) {
- void *Buffer = pushCleanup(Kind, sizeof(T));
- Cleanup *Obj = new(Buffer) T(a0);
- (void) Obj;
- }
-
- /// Push a lazily-created cleanup on the stack.
- template <class T, class A0, class A1>
- void pushCleanup(CleanupKind Kind, A0 a0, A1 a1) {
- void *Buffer = pushCleanup(Kind, sizeof(T));
- Cleanup *Obj = new(Buffer) T(a0, a1);
- (void) Obj;
- }
-
- /// Push a lazily-created cleanup on the stack.
- template <class T, class A0, class A1, class A2>
- void pushCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2) {
- void *Buffer = pushCleanup(Kind, sizeof(T));
- Cleanup *Obj = new(Buffer) T(a0, a1, a2);
- (void) Obj;
- }
-
- /// Push a lazily-created cleanup on the stack.
- template <class T, class A0, class A1, class A2, class A3>
- void pushCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2, A3 a3) {
- void *Buffer = pushCleanup(Kind, sizeof(T));
- Cleanup *Obj = new(Buffer) T(a0, a1, a2, a3);
- (void) Obj;
- }
-
- /// Push a lazily-created cleanup on the stack.
- template <class T, class A0, class A1, class A2, class A3, class A4>
- void pushCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
- void *Buffer = pushCleanup(Kind, sizeof(T));
- Cleanup *Obj = new(Buffer) T(a0, a1, a2, a3, a4);
- (void) Obj;
- }
-
- // Feel free to add more variants of the following:
-
- /// Push a cleanup with non-constant storage requirements on the
- /// stack. The cleanup type must provide an additional static method:
- /// static size_t getExtraSize(size_t);
- /// The argument to this method will be the value N, which will also
- /// be passed as the first argument to the constructor.
- ///
- /// The data stored in the extra storage must obey the same
- /// restrictions as normal cleanup member data.
- ///
- /// The pointer returned from this method is valid until the cleanup
- /// stack is modified.
- template <class T, class A0, class A1, class A2>
- T *pushCleanupWithExtra(CleanupKind Kind, size_t N, A0 a0, A1 a1, A2 a2) {
- void *Buffer = pushCleanup(Kind, sizeof(T) + T::getExtraSize(N));
- return new (Buffer) T(N, a0, a1, a2);
- }
-
- /// Pops a cleanup scope off the stack. This is private to CGCleanup.cpp.
- void popCleanup();
-
- /// Push a set of catch handlers on the stack. The catch is
- /// uninitialized and will need to have the given number of handlers
- /// set on it.
- class EHCatchScope *pushCatch(unsigned NumHandlers);
-
- /// Pops a catch scope off the stack. This is private to CGException.cpp.
- void popCatch();
-
- /// Push an exceptions filter on the stack.
- class EHFilterScope *pushFilter(unsigned NumFilters);
-
- /// Pops an exceptions filter off the stack.
- void popFilter();
-
- /// Push a terminate handler on the stack.
- void pushTerminate();
-
- /// Pops a terminate handler off the stack.
- void popTerminate();
-
- /// Determines whether the exception-scopes stack is empty.
- bool empty() const { return StartOfData == EndOfBuffer; }
-
- bool requiresLandingPad() const {
- return InnermostEHScope != stable_end();
- }
-
- /// Determines whether there are any normal cleanups on the stack.
- bool hasNormalCleanups() const {
- return InnermostNormalCleanup != stable_end();
- }
-
- /// Returns the innermost normal cleanup on the stack, or
- /// stable_end() if there are no normal cleanups.
- stable_iterator getInnermostNormalCleanup() const {
- return InnermostNormalCleanup;
- }
- stable_iterator getInnermostActiveNormalCleanup() const;
-
- stable_iterator getInnermostEHScope() const {
- return InnermostEHScope;
- }
-
- stable_iterator getInnermostActiveEHScope() const;
-
- /// An unstable reference to a scope-stack depth. Invalidated by
- /// pushes but not pops.
- class iterator;
-
- /// Returns an iterator pointing to the innermost EH scope.
- iterator begin() const;
-
- /// Returns an iterator pointing to the outermost EH scope.
- iterator end() const;
-
- /// Create a stable reference to the top of the EH stack. The
- /// returned reference is valid until that scope is popped off the
- /// stack.
- stable_iterator stable_begin() const {
- return stable_iterator(EndOfBuffer - StartOfData);
- }
-
- /// Create a stable reference to the bottom of the EH stack.
- static stable_iterator stable_end() {
- return stable_iterator(0);
- }
-
- /// Translates an iterator into a stable_iterator.
- stable_iterator stabilize(iterator it) const;
-
- /// Turn a stable reference to a scope depth into a unstable pointer
- /// to the EH stack.
- iterator find(stable_iterator save) const;
-
- /// Removes the cleanup pointed to by the given stable_iterator.
- void removeCleanup(stable_iterator save);
-
- /// Add a branch fixup to the current cleanup scope.
- BranchFixup &addBranchFixup() {
- assert(hasNormalCleanups() && "adding fixup in scope without cleanups");
- BranchFixups.push_back(BranchFixup());
- return BranchFixups.back();
- }
-
- unsigned getNumBranchFixups() const { return BranchFixups.size(); }
- BranchFixup &getBranchFixup(unsigned I) {
- assert(I < getNumBranchFixups());
- return BranchFixups[I];
- }
-
- /// Pops lazily-removed fixups from the end of the list. This
- /// should only be called by procedures which have just popped a
- /// cleanup or resolved one or more fixups.
- void popNullFixups();
-
- /// Clears the branch-fixups list. This should only be called by
- /// ResolveAllBranchFixups.
- void clearFixups() { BranchFixups.clear(); }
-};
-
/// CodeGenFunction - This class organizes the per-function state that is used
/// while generating LLVM code.
class CodeGenFunction : public CodeGenTypeCache {
@@ -606,6 +157,65 @@ public:
/// we prefer to insert allocas.
llvm::AssertingVH<llvm::Instruction> AllocaInsertPt;
+ /// \brief API for captured statement code generation.
+ class CGCapturedStmtInfo {
+ public:
+ explicit CGCapturedStmtInfo(const CapturedStmt &S,
+ CapturedRegionKind K = CR_Default)
+ : Kind(K), ThisValue(0), CXXThisFieldDecl(0) {
+
+ RecordDecl::field_iterator Field =
+ S.getCapturedRecordDecl()->field_begin();
+ for (CapturedStmt::const_capture_iterator I = S.capture_begin(),
+ E = S.capture_end();
+ I != E; ++I, ++Field) {
+ if (I->capturesThis())
+ CXXThisFieldDecl = *Field;
+ else
+ CaptureFields[I->getCapturedVar()] = *Field;
+ }
+ }
+
+ virtual ~CGCapturedStmtInfo();
+
+ CapturedRegionKind getKind() const { return Kind; }
+
+ void setContextValue(llvm::Value *V) { ThisValue = V; }
+ // \brief Retrieve the value of the context parameter.
+ llvm::Value *getContextValue() const { return ThisValue; }
+
+ /// \brief Lookup the captured field decl for a variable.
+ const FieldDecl *lookup(const VarDecl *VD) const {
+ return CaptureFields.lookup(VD);
+ }
+
+ bool isCXXThisExprCaptured() const { return CXXThisFieldDecl != 0; }
+ FieldDecl *getThisFieldDecl() const { return CXXThisFieldDecl; }
+
+ /// \brief Emit the captured statement body.
+ virtual void EmitBody(CodeGenFunction &CGF, Stmt *S) {
+ CGF.EmitStmt(S);
+ }
+
+ /// \brief Get the name of the capture helper.
+ virtual StringRef getHelperName() const { return "__captured_stmt"; }
+
+ private:
+ /// \brief The kind of captured statement being generated.
+ CapturedRegionKind Kind;
+
+ /// \brief Keep the map between VarDecl and FieldDecl.
+ llvm::SmallDenseMap<const VarDecl *, FieldDecl *> CaptureFields;
+
+ /// \brief The base address of the captured record, passed in as the first
+ /// argument of the parallel region function.
+ llvm::Value *ThisValue;
+
+ /// \brief Captured 'this' type.
+ FieldDecl *CXXThisFieldDecl;
+ };
+ CGCapturedStmtInfo *CapturedStmtInfo;
+
/// BoundsChecking - Emit run-time bounds checks. Higher values mean
/// potentially higher performance penalties.
unsigned char BoundsChecking;
@@ -631,6 +241,18 @@ public:
llvm::DenseMap<const VarDecl *, llvm::Value *> NRVOFlags;
EHScopeStack EHStack;
+ llvm::SmallVector<char, 256> LifetimeExtendedCleanupStack;
+
+ /// Header for data within LifetimeExtendedCleanupStack.
+ struct LifetimeExtendedCleanupHeader {
+ /// The size of the following cleanup object.
+ size_t Size : 29;
+ /// The kind of cleanup to push: a value from the CleanupKind enumeration.
+ unsigned Kind : 3;
+
+ size_t getSize() const { return Size; }
+ CleanupKind getKind() const { return static_cast<CleanupKind>(Kind); }
+ };
/// i32s containing the indexes of the cleanup destinations.
llvm::AllocaInst *NormalCleanupDest;
@@ -766,6 +388,23 @@ public:
initFullExprCleanup();
}
+ /// \brief Queue a cleanup to be pushed after finishing the current
+ /// full-expression.
+ template <class T, class A0, class A1, class A2, class A3>
+ void pushCleanupAfterFullExpr(CleanupKind Kind, A0 a0, A1 a1, A2 a2, A3 a3) {
+ assert(!isInConditionalBranch() && "can't defer conditional cleanup");
+
+ LifetimeExtendedCleanupHeader Header = { sizeof(T), Kind };
+
+ size_t OldSize = LifetimeExtendedCleanupStack.size();
+ LifetimeExtendedCleanupStack.resize(
+ LifetimeExtendedCleanupStack.size() + sizeof(Header) + Header.Size);
+
+ char *Buffer = &LifetimeExtendedCleanupStack[OldSize];
+ new (Buffer) LifetimeExtendedCleanupHeader(Header);
+ new (Buffer + sizeof(Header)) T(a0, a1, a2, a3);
+ }
+
/// Set up the last cleaup that was pushed as a conditional
/// full-expression cleanup.
void initFullExprCleanup();
@@ -784,9 +423,7 @@ public:
/// PopCleanupBlock - Will pop the cleanup entry on the stack and
/// process all branch fixups.
- /// \param EHLoc - Optional debug location for EH code.
- void PopCleanupBlock(bool FallThroughIsBranchThrough = false,
- SourceLocation EHLoc=SourceLocation());
+ void PopCleanupBlock(bool FallThroughIsBranchThrough = false);
/// DeactivateCleanupBlock - Deactivates the given cleanup block.
/// The block cannot be reactivated. Pops it if it's the top of the
@@ -813,6 +450,7 @@ public:
/// will be executed once the scope is exited.
class RunCleanupsScope {
EHScopeStack::stable_iterator CleanupStackDepth;
+ size_t LifetimeExtendedCleanupStackSize;
bool OldDidCallStackSave;
protected:
bool PerformCleanup;
@@ -830,6 +468,8 @@ public:
: PerformCleanup(true), CGF(CGF)
{
CleanupStackDepth = CGF.EHStack.stable_begin();
+ LifetimeExtendedCleanupStackSize =
+ CGF.LifetimeExtendedCleanupStack.size();
OldDidCallStackSave = CGF.DidCallStackSave;
CGF.DidCallStackSave = false;
}
@@ -839,7 +479,8 @@ public:
~RunCleanupsScope() {
if (PerformCleanup) {
CGF.DidCallStackSave = OldDidCallStackSave;
- CGF.PopCleanupBlocks(CleanupStackDepth);
+ CGF.PopCleanupBlocks(CleanupStackDepth,
+ LifetimeExtendedCleanupStackSize);
}
}
@@ -853,7 +494,8 @@ public:
void ForceCleanup() {
assert(PerformCleanup && "Already forced cleanup");
CGF.DidCallStackSave = OldDidCallStackSave;
- CGF.PopCleanupBlocks(CleanupStackDepth);
+ CGF.PopCleanupBlocks(CleanupStackDepth,
+ LifetimeExtendedCleanupStackSize);
PerformCleanup = false;
}
};
@@ -905,11 +547,15 @@ public:
};
- /// PopCleanupBlocks - Takes the old cleanup stack size and emits
- /// the cleanup blocks that have been added.
- /// \param EHLoc - Optional debug location for EH code.
+ /// \brief Takes the old cleanup stack size and emits the cleanup blocks
+ /// that have been added.
+ void PopCleanupBlocks(EHScopeStack::stable_iterator OldCleanupStackSize);
+
+ /// \brief Takes the old cleanup stack size and emits the cleanup blocks
+ /// that have been added, then adds all lifetime-extended cleanups from
+ /// the given position to the stack.
void PopCleanupBlocks(EHScopeStack::stable_iterator OldCleanupStackSize,
- SourceLocation EHLoc=SourceLocation());
+ size_t OldLifetimeExtendedStackSize);
void ResolveBranchFixups(llvm::BasicBlock *Target);
@@ -1152,10 +798,6 @@ private:
CGDebugInfo *DebugInfo;
bool DisableDebugInfo;
- /// If the current function returns 'this', use the field to keep track of
- /// the callee that returns 'this'.
- llvm::Value *CalleeWithThisReturn;
-
/// DidCallStackSave - Whether llvm.stacksave has been called. Used to avoid
/// calling llvm.stacksave for multiple VLAs in the same scope.
bool DidCallStackSave;
@@ -1279,6 +921,10 @@ private:
/// The current lexical scope.
LexicalScope *CurLexicalScope;
+ /// The current source location that should be used for exception
+ /// handling code.
+ SourceLocation CurEHLocation;
+
/// ByrefValueInfoMap - For each __block variable, contains a pair of the LLVM
/// type as well as the field number that contains the actual data.
llvm::DenseMap<const ValueDecl *, std::pair<llvm::Type *,
@@ -1307,14 +953,6 @@ public:
CodeGenTypes &getTypes() const { return CGM.getTypes(); }
ASTContext &getContext() const { return CGM.getContext(); }
- /// Returns true if DebugInfo is actually initialized.
- bool maybeInitializeDebugInfo() {
- if (CGM.getModuleDebugInfo()) {
- DebugInfo = CGM.getModuleDebugInfo();
- return true;
- }
- return false;
- }
CGDebugInfo *getDebugInfo() {
if (DisableDebugInfo)
return NULL;
@@ -1378,12 +1016,15 @@ public:
llvm::Value *addr, QualType type);
void pushDestroy(CleanupKind kind, llvm::Value *addr, QualType type,
Destroyer *destroyer, bool useEHCleanupForArray);
+ void pushLifetimeExtendedDestroy(CleanupKind kind, llvm::Value *addr,
+ QualType type, Destroyer *destroyer,
+ bool useEHCleanupForArray);
void emitDestroy(llvm::Value *addr, QualType type, Destroyer *destroyer,
bool useEHCleanupForArray);
- llvm::Function *generateDestroyHelper(llvm::Constant *addr,
- QualType type,
+ llvm::Function *generateDestroyHelper(llvm::Constant *addr, QualType type,
Destroyer *destroyer,
- bool useEHCleanupForArray);
+ bool useEHCleanupForArray,
+ const VarDecl *VD);
void emitArrayDestroy(llvm::Value *begin, llvm::Value *end,
QualType type, Destroyer *destroyer,
bool checkZeroLength, bool useEHCleanup);
@@ -1495,9 +1136,9 @@ public:
void EmitConstructorBody(FunctionArgList &Args);
void EmitDestructorBody(FunctionArgList &Args);
void emitImplicitAssignmentOperatorBody(FunctionArgList &Args);
- void EmitFunctionBody(FunctionArgList &Args);
+ void EmitFunctionBody(FunctionArgList &Args, const Stmt *Body);
- void EmitForwardingCallToLambda(const CXXRecordDecl *Lambda,
+ void EmitForwardingCallToLambda(const CXXMethodDecl *LambdaCallOperator,
CallArgList &CallArgs);
void EmitLambdaToBlockPointerBody(FunctionArgList &Args);
void EmitLambdaBlockInvokeBody();
@@ -1512,6 +1153,11 @@ public:
/// legal to call this function even if there is no current insertion point.
void FinishFunction(SourceLocation EndLoc=SourceLocation());
+ void StartThunk(llvm::Function *Fn, GlobalDecl GD, const CGFunctionInfo &FnInfo);
+
+ void EmitCallAndReturnForThunk(GlobalDecl GD, llvm::Value *Callee,
+ const ThunkInfo *Thunk);
+
/// GenerateThunk - Generate a thunk for the given method.
void GenerateThunk(llvm::Function *Fn, const CGFunctionInfo &FnInfo,
GlobalDecl GD, const ThunkInfo &Thunk);
@@ -1531,7 +1177,6 @@ public:
void InitializeVTablePointer(BaseSubobject Base,
const CXXRecordDecl *NearestVBase,
CharUnits OffsetFromNearestVBase,
- llvm::Constant *VTable,
const CXXRecordDecl *VTableClass);
typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
@@ -1539,7 +1184,6 @@ public:
const CXXRecordDecl *NearestVBase,
CharUnits OffsetFromNearestVBase,
bool BaseIsNonVirtualPrimaryBase,
- llvm::Constant *VTable,
const CXXRecordDecl *VTableClass,
VisitedVirtualBasesSetTy& VBases);
@@ -1549,6 +1193,12 @@ public:
/// to by This.
llvm::Value *GetVTablePtr(llvm::Value *This, llvm::Type *Ty);
+
+ /// CanDevirtualizeMemberFunctionCalls - Checks whether virtual calls on given
+ /// expr can be devirtualized.
+ bool CanDevirtualizeMemberFunctionCall(const Expr *Base,
+ const CXXMethodDecl *MD);
+
/// EnterDtorCleanups - Enter the cleanups necessary to complete the
/// given phase of destruction for a destructor. The end result
/// should call destructors on members and base classes in reverse
@@ -1576,7 +1226,8 @@ public:
/// EmitFunctionEpilog - Emit the target specific LLVM code to return the
/// given temporary.
- void EmitFunctionEpilog(const CGFunctionInfo &FI, bool EmitRetDbgLoc);
+ void EmitFunctionEpilog(const CGFunctionInfo &FI, bool EmitRetDbgLoc,
+ SourceLocation EndLoc);
/// EmitStartEHSpec - Emit the start of the exception spec.
void EmitStartEHSpec(const Decl *D);
@@ -1678,8 +1329,7 @@ public:
/// ErrorUnsupported - Print out an error that codegen doesn't support the
/// specified stmt yet.
- void ErrorUnsupported(const Stmt *S, const char *Type,
- bool OmitOnError=false);
+ void ErrorUnsupported(const Stmt *S, const char *Type);
//===--------------------------------------------------------------------===//
// Helpers
@@ -1915,10 +1565,6 @@ public:
CastExpr::path_const_iterator PathEnd,
bool NullCheckValue);
- llvm::Value *GetVirtualBaseClassOffset(llvm::Value *This,
- const CXXRecordDecl *ClassDecl,
- const CXXRecordDecl *BaseClassDecl);
-
/// GetVTTParameter - Return the VTT parameter that should be passed to a
/// base constructor/destructor with virtual bases.
/// FIXME: VTTs are Itanium ABI-specific, so the definition should move
@@ -1928,7 +1574,8 @@ public:
void EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,
CXXCtorType CtorType,
- const FunctionArgList &Args);
+ const FunctionArgList &Args,
+ SourceLocation Loc);
// It's important not to confuse this and the previous function. Delegating
// constructors are the C++0x feature. The constructor delegate optimization
// is used to reduce duplication in the base and complete consturctors where
@@ -1982,10 +1629,6 @@ public:
llvm::Value *EmitDynamicCast(llvm::Value *V, const CXXDynamicCastExpr *DCE);
llvm::Value* EmitCXXUuidofExpr(const CXXUuidofExpr *E);
- void MaybeEmitStdInitializerListCleanup(llvm::Value *loc, const Expr *init);
- void EmitStdInitializerListCleanup(llvm::Value *loc,
- const InitListExpr *init);
-
/// \brief Situations in which we might emit a check for the suitability of a
/// pointer or glvalue.
enum TypeCheckKind {
@@ -2161,11 +1804,12 @@ public:
/// \return True if the statement was handled.
bool EmitSimpleStmt(const Stmt *S);
- RValue EmitCompoundStmt(const CompoundStmt &S, bool GetLast = false,
- AggValueSlot AVS = AggValueSlot::ignored());
- RValue EmitCompoundStmtWithoutScope(const CompoundStmt &S,
- bool GetLast = false, AggValueSlot AVS =
- AggValueSlot::ignored());
+ llvm::Value *EmitCompoundStmt(const CompoundStmt &S, bool GetLast = false,
+ AggValueSlot AVS = AggValueSlot::ignored());
+ llvm::Value *EmitCompoundStmtWithoutScope(const CompoundStmt &S,
+ bool GetLast = false,
+ AggValueSlot AVS =
+ AggValueSlot::ignored());
/// EmitLabel - Emit the block for the given label. It is legal to call this
/// function even if there is no current insertion point.
@@ -2188,7 +1832,6 @@ public:
void EmitCaseStmt(const CaseStmt &S);
void EmitCaseStmtRange(const CaseStmt &S);
void EmitAsmStmt(const AsmStmt &S);
- void EmitCapturedStmt(const CapturedStmt &S);
void EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S);
void EmitObjCAtTryStmt(const ObjCAtTryStmt &S);
@@ -2202,8 +1845,14 @@ public:
void ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock = false);
void EmitCXXTryStmt(const CXXTryStmt &S);
+ void EmitSEHTryStmt(const SEHTryStmt &S);
void EmitCXXForRangeStmt(const CXXForRangeStmt &S);
+ llvm::Function *EmitCapturedStmt(const CapturedStmt &S, CapturedRegionKind K);
+ llvm::Function *GenerateCapturedStmtFunction(const CapturedDecl *CD,
+ const RecordDecl *RD,
+ SourceLocation Loc);
+
//===--------------------------------------------------------------------===//
// LValue Expression Emission
//===--------------------------------------------------------------------===//
@@ -2245,11 +1894,12 @@ public:
/// that the address will be used to access the object.
LValue EmitCheckedLValue(const Expr *E, TypeCheckKind TCK);
- RValue convertTempToRValue(llvm::Value *addr, QualType type);
+ RValue convertTempToRValue(llvm::Value *addr, QualType type,
+ SourceLocation Loc);
void EmitAtomicInit(Expr *E, LValue lvalue);
- RValue EmitAtomicLoad(LValue lvalue,
+ RValue EmitAtomicLoad(LValue lvalue, SourceLocation loc,
AggValueSlot slot = AggValueSlot::ignored());
void EmitAtomicStore(RValue rvalue, LValue lvalue, bool isInit);
@@ -2267,6 +1917,7 @@ public:
/// the LLVM value representation.
llvm::Value *EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,
unsigned Alignment, QualType Ty,
+ SourceLocation Loc,
llvm::MDNode *TBAAInfo = 0,
QualType TBAABaseTy = QualType(),
uint64_t TBAAOffset = 0);
@@ -2275,7 +1926,7 @@ public:
/// care to appropriately convert from the memory representation to
/// the LLVM value representation. The l-value must be a simple
/// l-value.
- llvm::Value *EmitLoadOfScalar(LValue lvalue);
+ llvm::Value *EmitLoadOfScalar(LValue lvalue, SourceLocation Loc);
/// EmitStoreOfScalar - Store a scalar value to an address, taking
/// care to appropriately convert from the memory representation to
@@ -2296,7 +1947,7 @@ public:
/// EmitLoadOfLValue - Given an expression that represents a value lvalue,
/// this method emits the address of the lvalue, then loads the result as an
/// rvalue, returning the rvalue.
- RValue EmitLoadOfLValue(LValue V);
+ RValue EmitLoadOfLValue(LValue V, SourceLocation Loc);
RValue EmitLoadOfExtVectorElementLValue(LValue V);
RValue EmitLoadOfBitfieldLValue(LValue LV);
@@ -2306,8 +1957,8 @@ public:
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false);
void EmitStoreThroughExtVectorComponentLValue(RValue Src, LValue Dst);
- /// EmitStoreThroughLValue - Store Src into Dst with same constraints as
- /// EmitStoreThroughLValue.
+ /// EmitStoreThroughBitfieldLValue - Store Src into Dst with same constraints
+ /// as EmitStoreThroughLValue.
///
/// \param Result [out] - If non-null, this will be set to a Value* for the
/// bit-field contents after the store, appropriate for use as the result of
@@ -2318,6 +1969,8 @@ public:
/// Emit an l-value for an assignment (simple or compound) of complex type.
LValue EmitComplexAssignmentLValue(const BinaryOperator *E);
LValue EmitComplexCompoundAssignmentLValue(const CompoundAssignOperator *E);
+ LValue EmitScalarCompooundAssignWithComplex(const CompoundAssignOperator *E,
+ llvm::Value *&Result);
// Note: only available for agg return types
LValue EmitBinaryOperatorLValue(const BinaryOperator *E);
@@ -2340,11 +1993,10 @@ public:
LValue EmitInitListLValue(const InitListExpr *E);
LValue EmitConditionalOperatorLValue(const AbstractConditionalOperator *E);
LValue EmitCastLValue(const CastExpr *E);
- LValue EmitNullInitializationLValue(const CXXScalarValueInitExpr *E);
LValue EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E);
LValue EmitOpaqueValueLValue(const OpaqueValueExpr *e);
- RValue EmitRValueForField(LValue LV, const FieldDecl *FD);
+ RValue EmitRValueForField(LValue LV, const FieldDecl *FD, SourceLocation Loc);
class ConstantEmission {
llvm::PointerIntPair<llvm::Constant*, 1, bool> ValueAndIsReference;
@@ -2359,7 +2011,7 @@ public:
return ConstantEmission(C, false);
}
- operator bool() const { return ValueAndIsReference.getOpaqueValue() != 0; }
+ LLVM_EXPLICIT operator bool() const { return ValueAndIsReference.getOpaqueValue() != 0; }
bool isReference() const { return ValueAndIsReference.getInt(); }
LValue getReferenceLValue(CodeGenFunction &CGF, Expr *refExpr) const {
@@ -2426,6 +2078,7 @@ public:
llvm::Instruction **callOrInvoke = 0);
RValue EmitCall(QualType FnType, llvm::Value *Callee,
+ SourceLocation CallLoc,
ReturnValueSlot ReturnValue,
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd,
@@ -2457,10 +2110,6 @@ public:
void EmitNoreturnRuntimeCallOrInvoke(llvm::Value *callee,
ArrayRef<llvm::Value*> args);
- llvm::Value *BuildVirtualCall(const CXXMethodDecl *MD, llvm::Value *This,
- llvm::Type *Ty);
- llvm::Value *BuildVirtualCall(const CXXDestructorDecl *DD, CXXDtorType Type,
- llvm::Value *This, llvm::Type *Ty);
llvm::Value *BuildAppleKextVirtualCall(const CXXMethodDecl *MD,
NestedNameSpecifier *Qual,
llvm::Type *Ty);
@@ -2503,6 +2152,11 @@ public:
/// is unhandled by the current target.
llvm::Value *EmitTargetBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
+ llvm::Value *EmitAArch64CompareBuiltinExpr(llvm::Value *Op, llvm::Type *Ty,
+ const llvm::CmpInst::Predicate Fp,
+ const llvm::CmpInst::Predicate Ip,
+ const llvm::Twine &Name = "");
+ llvm::Value *EmitAArch64CompareBuiltinExpr(llvm::Value *Op, llvm::Type *Ty);
llvm::Value *EmitAArch64BuiltinExpr(unsigned BuiltinID, const CallExpr *E);
llvm::Value *EmitARMBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
llvm::Value *EmitNeonCall(llvm::Function *F,
@@ -2512,6 +2166,8 @@ public:
llvm::Value *EmitNeonSplat(llvm::Value *V, llvm::Constant *Idx);
llvm::Value *EmitNeonShiftVector(llvm::Value *V, llvm::Type *Ty,
bool negateForRightShift);
+ llvm::Value *EmitNeonRShiftImm(llvm::Value *Vec, llvm::Value *Amt,
+ llvm::Type *Ty, bool usgn, const char *name);
llvm::Value *BuildVector(ArrayRef<llvm::Value*> Ops);
llvm::Value *EmitX86BuiltinExpr(unsigned BuiltinID, const CallExpr *E);
@@ -2587,10 +2243,8 @@ public:
void EmitObjCAutoreleasePoolCleanup(llvm::Value *Ptr);
void EmitObjCMRRAutoreleasePoolPop(llvm::Value *Ptr);
- /// EmitReferenceBindingToExpr - Emits a reference binding to the passed in
- /// expression. Will emit a temporary variable if E is not an LValue.
- RValue EmitReferenceBindingToExpr(const Expr* E,
- const NamedDecl *InitializedDecl);
+ /// \brief Emits a reference binding to the passed in expression.
+ RValue EmitReferenceBindingToExpr(const Expr *E);
//===--------------------------------------------------------------------===//
// Expression Emission
@@ -2646,7 +2300,7 @@ public:
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit);
/// EmitLoadOfComplex - Load a complex number from the specified l-value.
- ComplexPairTy EmitLoadOfComplex(LValue src);
+ ComplexPairTy EmitLoadOfComplex(LValue src, SourceLocation loc);
/// CreateStaticVarDecl - Create a zero-initialized LLVM global for
/// a static local variable.
@@ -2670,7 +2324,8 @@ public:
/// Call atexit() with a function that passes the given argument to
/// the given function.
- void registerGlobalDtorWithAtExit(llvm::Constant *fn, llvm::Constant *addr);
+ void registerGlobalDtorWithAtExit(const VarDecl &D, llvm::Constant *fn,
+ llvm::Constant *addr);
/// Emit code in this function to perform a guarded variable
/// initialization. Guarded initializations are used when it's not
@@ -2801,7 +2456,8 @@ public:
/// EmitDelegateCallArg - We are performing a delegate call; that
/// is, the current function is delegating to another one. Produce
/// a r-value suitable for passing the given parameter.
- void EmitDelegateCallArg(CallArgList &args, const VarDecl *param);
+ void EmitDelegateCallArg(CallArgList &args, const VarDecl *param,
+ SourceLocation loc);
/// SetFPAccuracy - Set the minimum required accuracy of the given floating
/// point operation, expressed as the maximum relative error in ulp.
@@ -2825,7 +2481,7 @@ private:
/// Ty, into individual arguments on the provided vector \arg Args. See
/// ABIArgInfo::Expand.
void ExpandTypeToArgs(QualType Ty, RValue Src,
- SmallVector<llvm::Value*, 16> &Args,
+ SmallVectorImpl<llvm::Value *> &Args,
llvm::FunctionType *IRFuncTy);
llvm::Value* EmitAsmInput(const TargetInfo::ConstraintInfo &Info,
@@ -2833,7 +2489,8 @@ private:
llvm::Value* EmitAsmInputLValue(const TargetInfo::ConstraintInfo &Info,
LValue InputValue, QualType InputType,
- std::string &ConstraintStr);
+ std::string &ConstraintStr,
+ SourceLocation Loc);
/// EmitCallArgs - Emit call arguments for a function.
/// The CallArgTypeInfo parameter is used for iterating over the known
@@ -2841,8 +2498,13 @@ private:
template<typename T>
void EmitCallArgs(CallArgList& Args, const T* CallArgTypeInfo,
CallExpr::const_arg_iterator ArgBeg,
- CallExpr::const_arg_iterator ArgEnd) {
- CallExpr::const_arg_iterator Arg = ArgBeg;
+ CallExpr::const_arg_iterator ArgEnd,
+ bool ForceColumnInfo = false) {
+ CGDebugInfo *DI = getDebugInfo();
+ SourceLocation CallLoc;
+ if (DI) CallLoc = DI->getLocation();
+
+ CallExpr::const_arg_iterator Arg = ArgBeg;
// First, use the argument types that the type info knows about
if (CallArgTypeInfo) {
@@ -2871,6 +2533,10 @@ private:
"type mismatch in call argument!");
#endif
EmitCallArg(Args, *Arg, ArgType);
+
+ // Each argument expression could modify the debug
+ // location. Restore it.
+ if (DI) DI->EmitLocation(Builder, CallLoc, ForceColumnInfo);
}
// Either we've emitted all the call args, or we have a call to a
@@ -2881,8 +2547,12 @@ private:
}
// If we still have any arguments, emit them using the type of the argument.
- for (; Arg != ArgEnd; ++Arg)
+ for (; Arg != ArgEnd; ++Arg) {
EmitCallArg(Args, *Arg, Arg->getType());
+
+ // Restore the debug location.
+ if (DI) DI->EmitLocation(Builder, CallLoc, ForceColumnInfo);
+ }
}
const TargetCodeGenInfo &getTargetHooks() const {
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 0b03a3c..792fbfc 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -35,7 +35,9 @@
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/Version.h"
#include "clang/Frontend/CodeGenOptions.h"
+#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/Triple.h"
#include "llvm/IR/CallingConv.h"
@@ -67,25 +69,23 @@ static CGCXXABI &createCXXABI(CodeGenModule &CGM) {
llvm_unreachable("invalid C++ ABI kind");
}
-
CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO,
llvm::Module &M, const llvm::DataLayout &TD,
DiagnosticsEngine &diags)
- : Context(C), LangOpts(C.getLangOpts()), CodeGenOpts(CGO), TheModule(M),
- Diags(diags), TheDataLayout(TD), Target(C.getTargetInfo()),
- ABI(createCXXABI(*this)), VMContext(M.getContext()), TBAA(0),
- TheTargetCodeGenInfo(0), Types(*this), VTables(*this),
- ObjCRuntime(0), OpenCLRuntime(0), CUDARuntime(0),
- DebugInfo(0), ARCData(0), NoObjCARCExceptionsMetadata(0),
- RRData(0), CFConstantStringClassRef(0),
- ConstantStringClassRef(0), NSConstantStringType(0),
- NSConcreteGlobalBlock(0), NSConcreteStackBlock(0),
- BlockObjectAssign(0), BlockObjectDispose(0),
- BlockDescriptorType(0), GenericBlockLiteralType(0),
- LifetimeStartFn(0), LifetimeEndFn(0),
- SanitizerBlacklist(CGO.SanitizerBlacklistFile),
- SanOpts(SanitizerBlacklist.isIn(M) ?
- SanitizerOptions::Disabled : LangOpts.Sanitize) {
+ : Context(C), LangOpts(C.getLangOpts()), CodeGenOpts(CGO), TheModule(M),
+ Diags(diags), TheDataLayout(TD), Target(C.getTargetInfo()),
+ ABI(createCXXABI(*this)), VMContext(M.getContext()), TBAA(0),
+ TheTargetCodeGenInfo(0), Types(*this), VTables(*this), ObjCRuntime(0),
+ OpenCLRuntime(0), CUDARuntime(0), DebugInfo(0), ARCData(0),
+ NoObjCARCExceptionsMetadata(0), RRData(0), CFConstantStringClassRef(0),
+ ConstantStringClassRef(0), NSConstantStringType(0),
+ NSConcreteGlobalBlock(0), NSConcreteStackBlock(0), BlockObjectAssign(0),
+ BlockObjectDispose(0), BlockDescriptorType(0), GenericBlockLiteralType(0),
+ LifetimeStartFn(0), LifetimeEndFn(0),
+ SanitizerBlacklist(
+ llvm::SpecialCaseList::createOrDie(CGO.SanitizerBlacklistFile)),
+ SanOpts(SanitizerBlacklist->isIn(M) ? SanitizerOptions::Disabled
+ : LangOpts.Sanitize) {
// Initialize the type cache.
llvm::LLVMContext &LLVMContext = M.getContext();
@@ -172,8 +172,71 @@ void CodeGenModule::createCUDARuntime() {
CUDARuntime = CreateNVCUDARuntime(*this);
}
+void CodeGenModule::applyReplacements() {
+ for (ReplacementsTy::iterator I = Replacements.begin(),
+ E = Replacements.end();
+ I != E; ++I) {
+ StringRef MangledName = I->first();
+ llvm::Constant *Replacement = I->second;
+ llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
+ if (!Entry)
+ continue;
+ llvm::Function *OldF = cast<llvm::Function>(Entry);
+ llvm::Function *NewF = dyn_cast<llvm::Function>(Replacement);
+ if (!NewF) {
+ llvm::ConstantExpr *CE = cast<llvm::ConstantExpr>(Replacement);
+ assert(CE->getOpcode() == llvm::Instruction::BitCast ||
+ CE->getOpcode() == llvm::Instruction::GetElementPtr);
+ NewF = dyn_cast<llvm::Function>(CE->getOperand(0));
+ }
+
+ // Replace old with new, but keep the old order.
+ OldF->replaceAllUsesWith(Replacement);
+ if (NewF) {
+ NewF->removeFromParent();
+ OldF->getParent()->getFunctionList().insertAfter(OldF, NewF);
+ }
+ OldF->eraseFromParent();
+ }
+}
+
+void CodeGenModule::checkAliases() {
+ bool Error = false;
+ for (std::vector<GlobalDecl>::iterator I = Aliases.begin(),
+ E = Aliases.end(); I != E; ++I) {
+ const GlobalDecl &GD = *I;
+ const ValueDecl *D = cast<ValueDecl>(GD.getDecl());
+ const AliasAttr *AA = D->getAttr<AliasAttr>();
+ StringRef MangledName = getMangledName(GD);
+ llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
+ llvm::GlobalAlias *Alias = cast<llvm::GlobalAlias>(Entry);
+ llvm::GlobalValue *GV = Alias->getAliasedGlobal();
+ if (GV->isDeclaration()) {
+ Error = true;
+ getDiags().Report(AA->getLocation(), diag::err_alias_to_undefined);
+ } else if (!Alias->resolveAliasedGlobal(/*stopOnWeak*/ false)) {
+ Error = true;
+ getDiags().Report(AA->getLocation(), diag::err_cyclic_alias);
+ }
+ }
+ if (!Error)
+ return;
+
+ for (std::vector<GlobalDecl>::iterator I = Aliases.begin(),
+ E = Aliases.end(); I != E; ++I) {
+ const GlobalDecl &GD = *I;
+ StringRef MangledName = getMangledName(GD);
+ llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
+ llvm::GlobalAlias *Alias = cast<llvm::GlobalAlias>(Entry);
+ Alias->replaceAllUsesWith(llvm::UndefValue::get(Alias->getType()));
+ Alias->eraseFromParent();
+ }
+}
+
void CodeGenModule::Release() {
EmitDeferred();
+ applyReplacements();
+ checkAliases();
EmitCXXGlobalInitFunc();
EmitCXXGlobalDtorFunc();
EmitCXXThreadLocalInitFunc();
@@ -186,9 +249,23 @@ void CodeGenModule::Release() {
EmitStaticExternCAliases();
EmitLLVMUsed();
- if (CodeGenOpts.Autolink && Context.getLangOpts().Modules) {
+ if (CodeGenOpts.Autolink &&
+ (Context.getLangOpts().Modules || !LinkerOptionsMetadata.empty())) {
EmitModuleLinkOptions();
}
+ if (CodeGenOpts.DwarfVersion)
+ // We actually want the latest version when there are conflicts.
+ // We can change from Warning to Latest if such mode is supported.
+ getModule().addModuleFlag(llvm::Module::Warning, "Dwarf Version",
+ CodeGenOpts.DwarfVersion);
+ if (DebugInfo)
+ // We support a single version in the linked module: error out when
+ // modules do not have the same version. We are going to implement dropping
+ // debug info when the version number is not up-to-date. Once that is
+ // done, the bitcode linker is not going to see modules with different
+ // version numbers.
+ getModule().addModuleFlag(llvm::Module::Error, "Debug Info Version",
+ llvm::DEBUG_METADATA_VERSION);
SimplifyPersonality();
@@ -200,6 +277,8 @@ void CodeGenModule::Release() {
if (DebugInfo)
DebugInfo->finalize();
+
+ EmitVersionIdentMetadata();
}
void CodeGenModule::UpdateCompletedType(const TagDecl *TD) {
@@ -239,14 +318,14 @@ llvm::MDNode *CodeGenModule::getTBAAStructTagInfo(QualType BaseTy,
return TBAA->getTBAAStructTagInfo(BaseTy, AccessN, O);
}
-/// Decorate the instruction with a TBAA tag. For scalar TBAA, the tag
-/// is the same as the type. For struct-path aware TBAA, the tag
-/// is different from the type: base type, access type and offset.
+/// Decorate the instruction with a TBAA tag. For both scalar TBAA
+/// and struct-path aware TBAA, the tag has the same format:
+/// base type, access type and offset.
/// When ConvertTypeToTag is true, we create a tag based on the scalar type.
void CodeGenModule::DecorateInstruction(llvm::Instruction *Inst,
llvm::MDNode *TBAAInfo,
bool ConvertTypeToTag) {
- if (ConvertTypeToTag && TBAA && CodeGenOpts.StructPathTBAA)
+ if (ConvertTypeToTag && TBAA)
Inst->setMetadata(llvm::LLVMContext::MD_tbaa,
TBAA->getTBAAScalarTagInfo(TBAAInfo));
else
@@ -260,10 +339,7 @@ void CodeGenModule::Error(SourceLocation loc, StringRef error) {
/// ErrorUnsupported - Print out an error that codegen doesn't support the
/// specified stmt yet.
-void CodeGenModule::ErrorUnsupported(const Stmt *S, const char *Type,
- bool OmitOnError) {
- if (OmitOnError && getDiags().hasErrorOccurred())
- return;
+void CodeGenModule::ErrorUnsupported(const Stmt *S, const char *Type) {
unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
"cannot compile this %0 yet");
std::string Msg = Type;
@@ -273,10 +349,7 @@ void CodeGenModule::ErrorUnsupported(const Stmt *S, const char *Type,
/// ErrorUnsupported - Print out an error that codegen doesn't support the
/// specified decl yet.
-void CodeGenModule::ErrorUnsupported(const Decl *D, const char *Type,
- bool OmitOnError) {
- if (OmitOnError && getDiags().hasErrorOccurred())
- return;
+void CodeGenModule::ErrorUnsupported(const Decl *D, const char *Type) {
unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
"cannot compile this %0 yet");
std::string Msg = Type;
@@ -428,9 +501,6 @@ StringRef CodeGenModule::getMangledName(GlobalDecl GD) {
getCXXABI().getMangleContext().mangleCXXCtor(D, GD.getCtorType(), Out);
else if (const CXXDestructorDecl *D = dyn_cast<CXXDestructorDecl>(ND))
getCXXABI().getMangleContext().mangleCXXDtor(D, GD.getDtorType(), Out);
- else if (const BlockDecl *BD = dyn_cast<BlockDecl>(ND))
- getCXXABI().getMangleContext().mangleBlock(BD, Out,
- dyn_cast_or_null<VarDecl>(initializedGlobalDecl.getDecl()));
else
getCXXABI().getMangleContext().mangleName(ND, Out);
@@ -508,7 +578,14 @@ void CodeGenModule::EmitCtorList(const CtorList &Fns, const char *GlobalName) {
}
llvm::GlobalValue::LinkageTypes
-CodeGenModule::getFunctionLinkage(const FunctionDecl *D) {
+CodeGenModule::getFunctionLinkage(GlobalDecl GD) {
+ const FunctionDecl *D = cast<FunctionDecl>(GD.getDecl());
+
+ if (isa<CXXDestructorDecl>(D) &&
+ getCXXABI().useThunkForDtorVariant(cast<CXXDestructorDecl>(D),
+ GD.getDtorType()))
+ return llvm::Function::LinkOnceODRLinkage;
+
GVALinkage Linkage = getContext().GetGVALinkageForFunction(D);
if (Linkage == GVA_Internal)
@@ -597,61 +674,66 @@ static bool hasUnwindExceptions(const LangOptions &LangOpts) {
void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
llvm::Function *F) {
+ llvm::AttrBuilder B;
+
if (CodeGenOpts.UnwindTables)
- F->setHasUWTable();
+ B.addAttribute(llvm::Attribute::UWTable);
if (!hasUnwindExceptions(LangOpts))
- F->addFnAttr(llvm::Attribute::NoUnwind);
+ B.addAttribute(llvm::Attribute::NoUnwind);
if (D->hasAttr<NakedAttr>()) {
// Naked implies noinline: we should not be inlining such functions.
- F->addFnAttr(llvm::Attribute::Naked);
- F->addFnAttr(llvm::Attribute::NoInline);
+ B.addAttribute(llvm::Attribute::Naked);
+ B.addAttribute(llvm::Attribute::NoInline);
+ } else if (D->hasAttr<NoInlineAttr>()) {
+ B.addAttribute(llvm::Attribute::NoInline);
+ } else if ((D->hasAttr<AlwaysInlineAttr>() ||
+ D->hasAttr<ForceInlineAttr>()) &&
+ !F->getAttributes().hasAttribute(llvm::AttributeSet::FunctionIndex,
+ llvm::Attribute::NoInline)) {
+ // (noinline wins over always_inline, and we can't specify both in IR)
+ B.addAttribute(llvm::Attribute::AlwaysInline);
}
- if (D->hasAttr<NoInlineAttr>())
- F->addFnAttr(llvm::Attribute::NoInline);
-
- // (noinline wins over always_inline, and we can't specify both in IR)
- if ((D->hasAttr<AlwaysInlineAttr>() || D->hasAttr<ForceInlineAttr>()) &&
- !F->getAttributes().hasAttribute(llvm::AttributeSet::FunctionIndex,
- llvm::Attribute::NoInline))
- F->addFnAttr(llvm::Attribute::AlwaysInline);
-
- // FIXME: Communicate hot and cold attributes to LLVM more directly.
- if (D->hasAttr<ColdAttr>())
- F->addFnAttr(llvm::Attribute::OptimizeForSize);
+ if (D->hasAttr<ColdAttr>()) {
+ B.addAttribute(llvm::Attribute::OptimizeForSize);
+ B.addAttribute(llvm::Attribute::Cold);
+ }
if (D->hasAttr<MinSizeAttr>())
- F->addFnAttr(llvm::Attribute::MinSize);
-
- if (isa<CXXConstructorDecl>(D) || isa<CXXDestructorDecl>(D))
- F->setUnnamedAddr(true);
-
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D))
- if (MD->isVirtual())
- F->setUnnamedAddr(true);
+ B.addAttribute(llvm::Attribute::MinSize);
if (LangOpts.getStackProtector() == LangOptions::SSPOn)
- F->addFnAttr(llvm::Attribute::StackProtect);
+ B.addAttribute(llvm::Attribute::StackProtect);
else if (LangOpts.getStackProtector() == LangOptions::SSPReq)
- F->addFnAttr(llvm::Attribute::StackProtectReq);
+ B.addAttribute(llvm::Attribute::StackProtectReq);
// Add sanitizer attributes if function is not blacklisted.
- if (!SanitizerBlacklist.isIn(*F)) {
+ if (!SanitizerBlacklist->isIn(*F)) {
// When AddressSanitizer is enabled, set SanitizeAddress attribute
// unless __attribute__((no_sanitize_address)) is used.
if (SanOpts.Address && !D->hasAttr<NoSanitizeAddressAttr>())
- F->addFnAttr(llvm::Attribute::SanitizeAddress);
+ B.addAttribute(llvm::Attribute::SanitizeAddress);
// Same for ThreadSanitizer and __attribute__((no_sanitize_thread))
if (SanOpts.Thread && !D->hasAttr<NoSanitizeThreadAttr>()) {
- F->addFnAttr(llvm::Attribute::SanitizeThread);
+ B.addAttribute(llvm::Attribute::SanitizeThread);
}
// Same for MemorySanitizer and __attribute__((no_sanitize_memory))
if (SanOpts.Memory && !D->hasAttr<NoSanitizeMemoryAttr>())
- F->addFnAttr(llvm::Attribute::SanitizeMemory);
+ B.addAttribute(llvm::Attribute::SanitizeMemory);
}
+ F->addAttributes(llvm::AttributeSet::FunctionIndex,
+ llvm::AttributeSet::get(
+ F->getContext(), llvm::AttributeSet::FunctionIndex, B));
+
+ if (isa<CXXConstructorDecl>(D) || isa<CXXDestructorDecl>(D))
+ F->setUnnamedAddr(true);
+ else if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D))
+ if (MD->isVirtual())
+ F->setUnnamedAddr(true);
+
unsigned alignment = D->getMaxAlignment() / Context.getCharWidth();
if (alignment)
F->setAlignment(alignment);
@@ -706,6 +788,14 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD,
if (!IsIncompleteFunction)
SetLLVMFunctionAttributes(FD, getTypes().arrangeGlobalDeclaration(GD), F);
+ if (getCXXABI().HasThisReturn(GD)) {
+ assert(!F->arg_empty() &&
+ F->arg_begin()->getType()
+ ->canLosslesslyBitCastTo(F->getReturnType()) &&
+ "unexpected this return");
+ F->addAttribute(1, llvm::Attribute::Returned);
+ }
+
// Only a few attributes are set on declarations; these may later be
// overridden by a definition.
@@ -727,6 +817,12 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD,
if (const SectionAttr *SA = FD->getAttr<SectionAttr>())
F->setSection(SA->getName());
+
+ // A replaceable global allocation function does not act like a builtin by
+ // default, only if it is invoked by a new-expression or delete-expression.
+ if (FD->isReplaceableGlobalAllocationFunction())
+ F->addAttribute(llvm::AttributeSet::FunctionIndex,
+ llvm::Attribute::NoBuiltin);
}
void CodeGenModule::AddUsedGlobal(llvm::GlobalValue *GV) {
@@ -762,31 +858,48 @@ void CodeGenModule::EmitLLVMUsed() {
GV->setSection("llvm.metadata");
}
+void CodeGenModule::AppendLinkerOptions(StringRef Opts) {
+ llvm::Value *MDOpts = llvm::MDString::get(getLLVMContext(), Opts);
+ LinkerOptionsMetadata.push_back(llvm::MDNode::get(getLLVMContext(), MDOpts));
+}
+
+void CodeGenModule::AddDetectMismatch(StringRef Name, StringRef Value) {
+ llvm::SmallString<32> Opt;
+ getTargetCodeGenInfo().getDetectMismatchOption(Name, Value, Opt);
+ llvm::Value *MDOpts = llvm::MDString::get(getLLVMContext(), Opt);
+ LinkerOptionsMetadata.push_back(llvm::MDNode::get(getLLVMContext(), MDOpts));
+}
+
+void CodeGenModule::AddDependentLib(StringRef Lib) {
+ llvm::SmallString<24> Opt;
+ getTargetCodeGenInfo().getDependentLibraryOption(Lib, Opt);
+ llvm::Value *MDOpts = llvm::MDString::get(getLLVMContext(), Opt);
+ LinkerOptionsMetadata.push_back(llvm::MDNode::get(getLLVMContext(), MDOpts));
+}
+
/// \brief Add link options implied by the given module, including modules
/// it depends on, using a postorder walk.
-static void addLinkOptionsPostorder(llvm::LLVMContext &Context,
+static void addLinkOptionsPostorder(CodeGenModule &CGM,
Module *Mod,
SmallVectorImpl<llvm::Value *> &Metadata,
llvm::SmallPtrSet<Module *, 16> &Visited) {
// Import this module's parent.
if (Mod->Parent && Visited.insert(Mod->Parent)) {
- addLinkOptionsPostorder(Context, Mod->Parent, Metadata, Visited);
+ addLinkOptionsPostorder(CGM, Mod->Parent, Metadata, Visited);
}
// Import this module's dependencies.
for (unsigned I = Mod->Imports.size(); I > 0; --I) {
if (Visited.insert(Mod->Imports[I-1]))
- addLinkOptionsPostorder(Context, Mod->Imports[I-1], Metadata, Visited);
+ addLinkOptionsPostorder(CGM, Mod->Imports[I-1], Metadata, Visited);
}
// Add linker options to link against the libraries/frameworks
// described by this module.
+ llvm::LLVMContext &Context = CGM.getLLVMContext();
for (unsigned I = Mod->LinkLibraries.size(); I > 0; --I) {
- // FIXME: -lfoo is Unix-centric and -framework Foo is Darwin-centric.
- // We need to know more about the linker to know how to encode these
- // options propertly.
-
- // Link against a framework.
+ // Link against a framework. Frameworks are currently Darwin only, so we
+ // don't to ask TargetCodeGenInfo for the spelling of the linker option.
if (Mod->LinkLibraries[I-1].IsFramework) {
llvm::Value *Args[2] = {
llvm::MDString::get(Context, "-framework"),
@@ -798,9 +911,10 @@ static void addLinkOptionsPostorder(llvm::LLVMContext &Context,
}
// Link against a library.
- llvm::Value *OptString
- = llvm::MDString::get(Context,
- "-l" + Mod->LinkLibraries[I-1].Library);
+ llvm::SmallString<24> Opt;
+ CGM.getTargetCodeGenInfo().getDependentLibraryOption(
+ Mod->LinkLibraries[I-1].Library, Opt);
+ llvm::Value *OptString = llvm::MDString::get(Context, Opt);
Metadata.push_back(llvm::MDNode::get(Context, OptString));
}
}
@@ -824,8 +938,7 @@ void CodeGenModule::EmitModuleLinkOptions() {
// Find all of the modules to import, making a little effort to prune
// non-leaf modules.
while (!Stack.empty()) {
- clang::Module *Mod = Stack.back();
- Stack.pop_back();
+ clang::Module *Mod = Stack.pop_back_val();
bool AnyChildren = false;
@@ -852,20 +965,23 @@ void CodeGenModule::EmitModuleLinkOptions() {
}
// Add link options for all of the imported modules in reverse topological
- // order.
+ // order. We don't do anything to try to order import link flags with respect
+ // to linker options inserted by things like #pragma comment().
SmallVector<llvm::Value *, 16> MetadataArgs;
Visited.clear();
for (llvm::SetVector<clang::Module *>::iterator M = LinkModules.begin(),
MEnd = LinkModules.end();
M != MEnd; ++M) {
if (Visited.insert(*M))
- addLinkOptionsPostorder(getLLVMContext(), *M, MetadataArgs, Visited);
+ addLinkOptionsPostorder(*this, *M, MetadataArgs, Visited);
}
std::reverse(MetadataArgs.begin(), MetadataArgs.end());
+ LinkerOptionsMetadata.append(MetadataArgs.begin(), MetadataArgs.end());
// Add the linker options metadata flag.
getModule().addModuleFlag(llvm::Module::AppendUnique, "Linker Options",
- llvm::MDNode::get(getLLVMContext(), MetadataArgs));
+ llvm::MDNode::get(getLLVMContext(),
+ LinkerOptionsMetadata));
}
void CodeGenModule::EmitDeferred() {
@@ -928,9 +1044,9 @@ void CodeGenModule::EmitGlobalAnnotations() {
}
llvm::Constant *CodeGenModule::EmitAnnotationString(StringRef Str) {
- llvm::StringMap<llvm::Constant*>::iterator i = AnnotationStrings.find(Str);
- if (i != AnnotationStrings.end())
- return i->second;
+ llvm::Constant *&AStr = AnnotationStrings[Str];
+ if (AStr)
+ return AStr;
// Not found yet, create a new global.
llvm::Constant *s = llvm::ConstantDataArray::getString(getLLVMContext(), Str);
@@ -938,7 +1054,7 @@ llvm::Constant *CodeGenModule::EmitAnnotationString(StringRef Str) {
true, llvm::GlobalValue::PrivateLinkage, s, ".str");
gv->setSection(AnnotationSection);
gv->setUnnamedAddr(true);
- AnnotationStrings[Str] = gv;
+ AStr = gv;
return gv;
}
@@ -998,18 +1114,9 @@ llvm::Constant *CodeGenModule::GetAddrOfUuidDescriptor(
const CXXUuidofExpr* E) {
// Sema has verified that IIDSource has a __declspec(uuid()), and that its
// well-formed.
- StringRef Uuid;
- if (E->isTypeOperand())
- Uuid = CXXUuidofExpr::GetUuidAttrOfType(E->getTypeOperand())->getGuid();
- else {
- // Special case: __uuidof(0) means an all-zero GUID.
- Expr *Op = E->getExprOperand();
- if (!Op->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull))
- Uuid = CXXUuidofExpr::GetUuidAttrOfType(Op->getType())->getGuid();
- else
- Uuid = "00000000-0000-0000-0000-000000000000";
- }
- std::string Name = "__uuid_" + Uuid.str();
+ StringRef Uuid = E->getUuidAsStringRef(Context);
+ std::string Name = "_GUID_" + Uuid.lower();
+ std::replace(Name.begin(), Name.end(), '-', '_');
// Look for an existing global.
if (llvm::GlobalVariable *GV = getModule().getNamedGlobal(Name))
@@ -1018,22 +1125,9 @@ llvm::Constant *CodeGenModule::GetAddrOfUuidDescriptor(
llvm::Constant *Init = EmitUuidofInitializer(Uuid, E->getType());
assert(Init && "failed to initialize as constant");
- // GUIDs are assumed to be 16 bytes, spread over 4-2-2-8 bytes. However, the
- // first field is declared as "long", which for many targets is 8 bytes.
- // Those architectures are not supported. (With the MS abi, long is always 4
- // bytes.)
- llvm::Type *GuidType = getTypes().ConvertType(E->getType());
- if (Init->getType() != GuidType) {
- DiagnosticsEngine &Diags = getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "__uuidof codegen is not supported on this architecture");
- Diags.Report(E->getExprLoc(), DiagID) << E->getSourceRange();
- Init = llvm::UndefValue::get(GuidType);
- }
-
- llvm::GlobalVariable *GV = new llvm::GlobalVariable(getModule(), GuidType,
- /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, Init, Name);
- GV->setUnnamedAddr(true);
+ llvm::GlobalVariable *GV = new llvm::GlobalVariable(
+ getModule(), Init->getType(),
+ /*isConstant=*/true, llvm::GlobalValue::LinkOnceODRLinkage, Init, Name);
return GV;
}
@@ -1203,9 +1297,10 @@ CodeGenModule::isTriviallyRecursive(const FunctionDecl *FD) {
}
bool
-CodeGenModule::shouldEmitFunction(const FunctionDecl *F) {
- if (getFunctionLinkage(F) != llvm::Function::AvailableExternallyLinkage)
+CodeGenModule::shouldEmitFunction(GlobalDecl GD) {
+ if (getFunctionLinkage(GD) != llvm::Function::AvailableExternallyLinkage)
return true;
+ const FunctionDecl *F = cast<FunctionDecl>(GD.getDecl());
if (CodeGenOpts.OptimizationLevel == 0 &&
!F->hasAttr<AlwaysInlineAttr>() && !F->hasAttr<ForceInlineAttr>())
return false;
@@ -1217,6 +1312,23 @@ CodeGenModule::shouldEmitFunction(const FunctionDecl *F) {
return !isTriviallyRecursive(F);
}
+/// If the type for the method's class was generated by
+/// CGDebugInfo::createContextChain(), the cache contains only a
+/// limited DIType without any declarations. Since EmitFunctionStart()
+/// needs to find the canonical declaration for each method, we need
+/// to construct the complete type prior to emitting the method.
+void CodeGenModule::CompleteDIClassType(const CXXMethodDecl* D) {
+ if (!D->isInstance())
+ return;
+
+ if (CGDebugInfo *DI = getModuleDebugInfo())
+ if (getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo) {
+ const PointerType *ThisPtr =
+ cast<PointerType>(D->getThisType(getContext()));
+ DI->getOrCreateRecordType(ThisPtr->getPointeeType(), D->getLocation());
+ }
+}
+
void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD) {
const ValueDecl *D = cast<ValueDecl>(GD.getDecl());
@@ -1224,13 +1336,14 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD) {
Context.getSourceManager(),
"Generating code for declaration");
- if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
+ if (isa<FunctionDecl>(D)) {
// At -O0, don't generate IR for functions with available_externally
// linkage.
- if (!shouldEmitFunction(Function))
+ if (!shouldEmitFunction(GD))
return;
if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
+ CompleteDIClassType(Method);
// Make sure to emit the definition(s) before we emit the thunks.
// This is necessary for the generation of certain thunks.
if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(Method))
@@ -1265,13 +1378,15 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD) {
llvm::Constant *
CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName,
llvm::Type *Ty,
- GlobalDecl D, bool ForVTable,
+ GlobalDecl GD, bool ForVTable,
llvm::AttributeSet ExtraAttrs) {
+ const Decl *D = GD.getDecl();
+
// Lookup the entry, lazily creating it if necessary.
llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
if (Entry) {
if (WeakRefReferences.erase(Entry)) {
- const FunctionDecl *FD = cast_or_null<FunctionDecl>(D.getDecl());
+ const FunctionDecl *FD = cast_or_null<FunctionDecl>(D);
if (FD && !FD->hasAttr<WeakAttr>())
Entry->setLinkage(llvm::Function::ExternalLinkage);
}
@@ -1283,6 +1398,14 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName,
return llvm::ConstantExpr::getBitCast(Entry, Ty->getPointerTo());
}
+ // All MSVC dtors other than the base dtor are linkonce_odr and delegate to
+ // each other bottoming out with the base dtor. Therefore we emit non-base
+ // dtors on usage, even if there is no dtor definition in the TU.
+ if (D && isa<CXXDestructorDecl>(D) &&
+ getCXXABI().useThunkForDtorVariant(cast<CXXDestructorDecl>(D),
+ GD.getDtorType()))
+ DeferredDeclsToEmit.push_back(GD);
+
// This function doesn't have a complete type (for example, the return
// type is an incomplete struct). Use a fake type instead, and make
// sure not to try to set attributes.
@@ -1300,8 +1423,8 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName,
llvm::Function::ExternalLinkage,
MangledName, &getModule());
assert(F->getName() == MangledName && "name was uniqued!");
- if (D.getDecl())
- SetFunctionAttributes(D, F, IsIncompleteFunction);
+ if (D)
+ SetFunctionAttributes(GD, F, IsIncompleteFunction);
if (ExtraAttrs.hasAttributes(llvm::AttributeSet::FunctionIndex)) {
llvm::AttrBuilder B(ExtraAttrs, llvm::AttributeSet::FunctionIndex);
F->addAttributes(llvm::AttributeSet::FunctionIndex,
@@ -1320,6 +1443,12 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName,
DeferredDeclsToEmit.push_back(DDI->second);
DeferredDecls.erase(DDI);
+ // Otherwise, if this is a sized deallocation function, emit a weak definition
+ // for it at the end of the translation unit.
+ } else if (D && cast<FunctionDecl>(D)
+ ->getCorrespondingUnsizedGlobalDeallocationFunction()) {
+ DeferredDeclsToEmit.push_back(GD);
+
// Otherwise, there are cases we have to worry about where we're
// using a declaration for which we must emit a definition but where
// we might not find a top-level definition:
@@ -1331,18 +1460,18 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName,
//
// We also don't emit a definition for a function if it's going to be an entry
// in a vtable, unless it's already marked as used.
- } else if (getLangOpts().CPlusPlus && D.getDecl()) {
+ } else if (getLangOpts().CPlusPlus && D) {
// Look for a declaration that's lexically in a record.
- const FunctionDecl *FD = cast<FunctionDecl>(D.getDecl());
+ const FunctionDecl *FD = cast<FunctionDecl>(D);
FD = FD->getMostRecentDecl();
do {
if (isa<CXXRecordDecl>(FD->getLexicalDeclContext())) {
if (FD->isImplicit() && !ForVTable) {
assert(FD->isUsed() && "Sema didn't mark implicit function as used!");
- DeferredDeclsToEmit.push_back(D.getWithDecl(FD));
+ DeferredDeclsToEmit.push_back(GD.getWithDecl(FD));
break;
} else if (FD->doesThisDeclarationHaveABody()) {
- DeferredDeclsToEmit.push_back(D.getWithDecl(FD));
+ DeferredDeclsToEmit.push_back(GD.getWithDecl(FD));
break;
}
}
@@ -1436,6 +1565,9 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
return Entry;
// Make sure the result is of the correct type.
+ if (Entry->getType()->getAddressSpace() != Ty->getAddressSpace())
+ return llvm::ConstantExpr::getAddrSpaceCast(Entry, Ty);
+
return llvm::ConstantExpr::getBitCast(Entry, Ty);
}
@@ -1483,12 +1615,19 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
CXXThreadLocals.push_back(std::make_pair(D, GV));
setTLSMode(GV, *D);
}
+
+ // If required by the ABI, treat declarations of static data members with
+ // inline initializers as definitions.
+ if (getCXXABI().isInlineInitializedStaticDataMemberLinkOnce() &&
+ D->isStaticDataMember() && D->hasInit() &&
+ !D->isThisDeclarationADefinition())
+ EmitGlobalVarDefinition(D);
}
if (AddrSpace != Ty->getAddressSpace())
- return llvm::ConstantExpr::getBitCast(GV, Ty);
- else
- return GV;
+ return llvm::ConstantExpr::getAddrSpaceCast(GV, Ty);
+
+ return GV;
}
@@ -1581,125 +1720,6 @@ CharUnits CodeGenModule::GetTargetTypeStoreSize(llvm::Type *Ty) const {
TheDataLayout.getTypeStoreSizeInBits(Ty));
}
-llvm::Constant *
-CodeGenModule::MaybeEmitGlobalStdInitializerListInitializer(const VarDecl *D,
- const Expr *rawInit) {
- ArrayRef<ExprWithCleanups::CleanupObject> cleanups;
- if (const ExprWithCleanups *withCleanups =
- dyn_cast<ExprWithCleanups>(rawInit)) {
- cleanups = withCleanups->getObjects();
- rawInit = withCleanups->getSubExpr();
- }
-
- const InitListExpr *init = dyn_cast<InitListExpr>(rawInit);
- if (!init || !init->initializesStdInitializerList() ||
- init->getNumInits() == 0)
- return 0;
-
- ASTContext &ctx = getContext();
- unsigned numInits = init->getNumInits();
- // FIXME: This check is here because we would otherwise silently miscompile
- // nested global std::initializer_lists. Better would be to have a real
- // implementation.
- for (unsigned i = 0; i < numInits; ++i) {
- const InitListExpr *inner = dyn_cast<InitListExpr>(init->getInit(i));
- if (inner && inner->initializesStdInitializerList()) {
- ErrorUnsupported(inner, "nested global std::initializer_list");
- return 0;
- }
- }
-
- // Synthesize a fake VarDecl for the array and initialize that.
- QualType elementType = init->getInit(0)->getType();
- llvm::APInt numElements(ctx.getTypeSize(ctx.getSizeType()), numInits);
- QualType arrayType = ctx.getConstantArrayType(elementType, numElements,
- ArrayType::Normal, 0);
-
- IdentifierInfo *name = &ctx.Idents.get(D->getNameAsString() + "__initlist");
- TypeSourceInfo *sourceInfo = ctx.getTrivialTypeSourceInfo(
- arrayType, D->getLocation());
- VarDecl *backingArray = VarDecl::Create(ctx, const_cast<DeclContext*>(
- D->getDeclContext()),
- D->getLocStart(), D->getLocation(),
- name, arrayType, sourceInfo,
- SC_Static);
- backingArray->setTSCSpec(D->getTSCSpec());
-
- // Now clone the InitListExpr to initialize the array instead.
- // Incredible hack: we want to use the existing InitListExpr here, so we need
- // to tell it that it no longer initializes a std::initializer_list.
- ArrayRef<Expr*> Inits(const_cast<InitListExpr*>(init)->getInits(),
- init->getNumInits());
- Expr *arrayInit = new (ctx) InitListExpr(ctx, init->getLBraceLoc(), Inits,
- init->getRBraceLoc());
- arrayInit->setType(arrayType);
-
- if (!cleanups.empty())
- arrayInit = ExprWithCleanups::Create(ctx, arrayInit, cleanups);
-
- backingArray->setInit(arrayInit);
-
- // Emit the definition of the array.
- EmitGlobalVarDefinition(backingArray);
-
- // Inspect the initializer list to validate it and determine its type.
- // FIXME: doing this every time is probably inefficient; caching would be nice
- RecordDecl *record = init->getType()->castAs<RecordType>()->getDecl();
- RecordDecl::field_iterator field = record->field_begin();
- if (field == record->field_end()) {
- ErrorUnsupported(D, "weird std::initializer_list");
- return 0;
- }
- QualType elementPtr = ctx.getPointerType(elementType.withConst());
- // Start pointer.
- if (!ctx.hasSameType(field->getType(), elementPtr)) {
- ErrorUnsupported(D, "weird std::initializer_list");
- return 0;
- }
- ++field;
- if (field == record->field_end()) {
- ErrorUnsupported(D, "weird std::initializer_list");
- return 0;
- }
- bool isStartEnd = false;
- if (ctx.hasSameType(field->getType(), elementPtr)) {
- // End pointer.
- isStartEnd = true;
- } else if(!ctx.hasSameType(field->getType(), ctx.getSizeType())) {
- ErrorUnsupported(D, "weird std::initializer_list");
- return 0;
- }
-
- // Now build an APValue representing the std::initializer_list.
- APValue initListValue(APValue::UninitStruct(), 0, 2);
- APValue &startField = initListValue.getStructField(0);
- APValue::LValuePathEntry startOffsetPathEntry;
- startOffsetPathEntry.ArrayIndex = 0;
- startField = APValue(APValue::LValueBase(backingArray),
- CharUnits::fromQuantity(0),
- llvm::makeArrayRef(startOffsetPathEntry),
- /*IsOnePastTheEnd=*/false, 0);
-
- if (isStartEnd) {
- APValue &endField = initListValue.getStructField(1);
- APValue::LValuePathEntry endOffsetPathEntry;
- endOffsetPathEntry.ArrayIndex = numInits;
- endField = APValue(APValue::LValueBase(backingArray),
- ctx.getTypeSizeInChars(elementType) * numInits,
- llvm::makeArrayRef(endOffsetPathEntry),
- /*IsOnePastTheEnd=*/true, 0);
- } else {
- APValue &sizeField = initListValue.getStructField(1);
- sizeField = APValue(llvm::APSInt(numElements));
- }
-
- // Emit the constant for the initializer_list.
- llvm::Constant *llvmInit =
- EmitConstantValueForMemory(initListValue, D->getType());
- assert(llvmInit && "failed to initialize as constant");
- return llvmInit;
-}
-
unsigned CodeGenModule::GetGlobalVarAddressSpace(const VarDecl *D,
unsigned AddrSpace) {
if (LangOpts.CUDA && CodeGenOpts.CUDAIsDevice) {
@@ -1726,12 +1746,12 @@ void CodeGenModule::MaybeHandleStaticInExternC(const SomeDecl *D,
return;
// Must have internal linkage and an ordinary name.
- if (!D->getIdentifier() || D->getLinkage() != InternalLinkage)
+ if (!D->getIdentifier() || D->getFormalLinkage() != InternalLinkage)
return;
// Must be in an extern "C" context. Entities declared directly within
// a record are not extern "C" even if the record is in such a context.
- const SomeDecl *First = D->getFirstDeclaration();
+ const SomeDecl *First = D->getFirstDecl();
if (First->getDeclContext()->isRecord() || !First->isInExternCContext())
return;
@@ -1770,18 +1790,10 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
assert(!ASTTy->isIncompleteType() && "Unexpected incomplete type");
Init = EmitNullConstant(D->getType());
} else {
- // If this is a std::initializer_list, emit the special initializer.
- Init = MaybeEmitGlobalStdInitializerListInitializer(D, InitExpr);
- // An empty init list will perform zero-initialization, which happens
- // to be exactly what we want.
- // FIXME: It does so in a global constructor, which is *not* what we
- // want.
+ initializedGlobalDecl = GlobalDecl(D);
+ Init = EmitConstantInit(*InitDecl);
if (!Init) {
- initializedGlobalDecl = GlobalDecl(D);
- Init = EmitConstantInit(*InitDecl);
- }
- if (!Init) {
QualType T = InitExpr->getType();
if (D->getType()->isReferenceType())
T = D->getType();
@@ -1808,7 +1820,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
// Strip off a bitcast if we got one back.
if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Entry)) {
assert(CE->getOpcode() == llvm::Instruction::BitCast ||
- // all zero index gep.
+ CE->getOpcode() == llvm::Instruction::AddrSpaceCast ||
+ // All zero index gep.
CE->getOpcode() == llvm::Instruction::GetElementPtr);
Entry = CE->getOperand(0);
}
@@ -1860,8 +1873,16 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
// Set the llvm linkage type as appropriate.
llvm::GlobalValue::LinkageTypes Linkage =
- GetLLVMLinkageVarDefinition(D, GV);
+ GetLLVMLinkageVarDefinition(D, GV->isConstant());
GV->setLinkage(Linkage);
+
+ // If required by the ABI, give definitions of static data members with inline
+ // initializers linkonce_odr linkage.
+ if (getCXXABI().isInlineInitializedStaticDataMemberLinkOnce() &&
+ D->isStaticDataMember() && InitExpr &&
+ !InitDecl->isThisDeclarationADefinition())
+ GV->setLinkage(llvm::GlobalVariable::LinkOnceODRLinkage);
+
if (Linkage == llvm::GlobalVariable::CommonLinkage)
// common vars aren't constant even if declared const.
GV->setConstant(false);
@@ -1891,8 +1912,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
}
llvm::GlobalValue::LinkageTypes
-CodeGenModule::GetLLVMLinkageVarDefinition(const VarDecl *D,
- llvm::GlobalVariable *GV) {
+CodeGenModule::GetLLVMLinkageVarDefinition(const VarDecl *D, bool isConstant) {
GVALinkage Linkage = getContext().GetGVALinkageForVariable(D);
if (Linkage == GVA_Internal)
return llvm::Function::InternalLinkage;
@@ -1900,8 +1920,14 @@ CodeGenModule::GetLLVMLinkageVarDefinition(const VarDecl *D,
return llvm::Function::DLLImportLinkage;
else if (D->hasAttr<DLLExportAttr>())
return llvm::Function::DLLExportLinkage;
- else if (D->hasAttr<WeakAttr>()) {
- if (GV->isConstant())
+ else if (D->hasAttr<SelectAnyAttr>()) {
+ // selectany symbols are externally visible, so use weak instead of
+ // linkonce. MSVC optimizes away references to const selectany globals, so
+ // all definitions should be the same and ODR linkage should be used.
+ // http://msdn.microsoft.com/en-us/library/5tkz6s71.aspx
+ return llvm::GlobalVariable::WeakODRLinkage;
+ } else if (D->hasAttr<WeakAttr>()) {
+ if (isConstant)
return llvm::GlobalVariable::WeakODRLinkage;
else
return llvm::GlobalVariable::WeakAnyLinkage;
@@ -2077,6 +2103,10 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) {
Entry = CE->getOperand(0);
}
+ if (!cast<llvm::GlobalValue>(Entry)->isDeclaration()) {
+ getDiags().Report(D->getLocation(), diag::err_duplicate_mangled_name);
+ return;
+ }
if (cast<llvm::GlobalValue>(Entry)->getType()->getElementType() != Ty) {
llvm::GlobalValue *OldFn = cast<llvm::GlobalValue>(Entry);
@@ -2126,7 +2156,7 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) {
// want to propagate this information down (e.g. to local static
// declarations).
llvm::Function *Fn = cast<llvm::Function>(Entry);
- setFunctionLinkage(D, Fn);
+ setFunctionLinkage(GD, Fn);
// FIXME: this is redundant with part of SetFunctionDefinitionAttributes
setGlobalVisibility(Fn, D);
@@ -2159,6 +2189,8 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
if (Entry && !Entry->isDeclaration())
return;
+ Aliases.push_back(GD);
+
llvm::Type *DeclTy = getTypes().ConvertTypeForMem(D->getType());
// Create a reference to the named value. This ensures that it is emitted
@@ -2624,11 +2656,16 @@ static llvm::GlobalVariable *GenerateStringLiteral(StringRef str,
llvm::Constant *C =
llvm::ConstantDataArray::getString(CGM.getLLVMContext(), str, false);
+ // OpenCL v1.1 s6.5.3: a string literal is in the constant address space.
+ unsigned AddrSpace = 0;
+ if (CGM.getLangOpts().OpenCL)
+ AddrSpace = CGM.getContext().getTargetAddressSpace(LangAS::opencl_constant);
+
// Create a global variable for this string
- llvm::GlobalVariable *GV =
- new llvm::GlobalVariable(CGM.getModule(), C->getType(), constant,
- llvm::GlobalValue::PrivateLinkage,
- C, GlobalName);
+ llvm::GlobalVariable *GV = new llvm::GlobalVariable(
+ CGM.getModule(), C->getType(), constant,
+ llvm::GlobalValue::PrivateLinkage, C, GlobalName, 0,
+ llvm::GlobalVariable::NotThreadLocal, AddrSpace);
GV->setAlignment(Alignment);
GV->setUnnamedAddr(true);
return GV;
@@ -2684,6 +2721,74 @@ llvm::Constant *CodeGenModule::GetAddrOfConstantCString(const std::string &Str,
return GetAddrOfConstantString(StrWithNull, GlobalName, Alignment);
}
+llvm::Constant *CodeGenModule::GetAddrOfGlobalTemporary(
+ const MaterializeTemporaryExpr *E, const Expr *Init) {
+ assert((E->getStorageDuration() == SD_Static ||
+ E->getStorageDuration() == SD_Thread) && "not a global temporary");
+ const VarDecl *VD = cast<VarDecl>(E->getExtendingDecl());
+
+ // If we're not materializing a subobject of the temporary, keep the
+ // cv-qualifiers from the type of the MaterializeTemporaryExpr.
+ QualType MaterializedType = Init->getType();
+ if (Init == E->GetTemporaryExpr())
+ MaterializedType = E->getType();
+
+ llvm::Constant *&Slot = MaterializedGlobalTemporaryMap[E];
+ if (Slot)
+ return Slot;
+
+ // FIXME: If an externally-visible declaration extends multiple temporaries,
+ // we need to give each temporary the same name in every translation unit (and
+ // we also need to make the temporaries externally-visible).
+ SmallString<256> Name;
+ llvm::raw_svector_ostream Out(Name);
+ getCXXABI().getMangleContext().mangleReferenceTemporary(VD, Out);
+ Out.flush();
+
+ APValue *Value = 0;
+ if (E->getStorageDuration() == SD_Static) {
+ // We might have a cached constant initializer for this temporary. Note
+ // that this might have a different value from the value computed by
+ // evaluating the initializer if the surrounding constant expression
+ // modifies the temporary.
+ Value = getContext().getMaterializedTemporaryValue(E, false);
+ if (Value && Value->isUninit())
+ Value = 0;
+ }
+
+ // Try evaluating it now, it might have a constant initializer.
+ Expr::EvalResult EvalResult;
+ if (!Value && Init->EvaluateAsRValue(EvalResult, getContext()) &&
+ !EvalResult.hasSideEffects())
+ Value = &EvalResult.Val;
+
+ llvm::Constant *InitialValue = 0;
+ bool Constant = false;
+ llvm::Type *Type;
+ if (Value) {
+ // The temporary has a constant initializer, use it.
+ InitialValue = EmitConstantValue(*Value, MaterializedType, 0);
+ Constant = isTypeConstant(MaterializedType, /*ExcludeCtor*/Value);
+ Type = InitialValue->getType();
+ } else {
+ // No initializer, the initialization will be provided when we
+ // initialize the declaration which performed lifetime extension.
+ Type = getTypes().ConvertTypeForMem(MaterializedType);
+ }
+
+ // Create a global variable for this lifetime-extended temporary.
+ llvm::GlobalVariable *GV =
+ new llvm::GlobalVariable(getModule(), Type, Constant,
+ llvm::GlobalValue::PrivateLinkage,
+ InitialValue, Name.c_str());
+ GV->setAlignment(
+ getContext().getTypeAlignInChars(MaterializedType).getQuantity());
+ if (VD->getTLSKind())
+ setTLSMode(GV, *VD);
+ Slot = GV;
+ return GV;
+}
+
/// EmitObjCPropertyImplementations - Emit information for synthesized
/// properties for an implementation.
void CodeGenModule::EmitObjCPropertyImplementations(const
@@ -2767,8 +2872,13 @@ void CodeGenModule::EmitObjCIvarInitializations(ObjCImplementationDecl *D) {
/// EmitNamespace - Emit all declarations in a namespace.
void CodeGenModule::EmitNamespace(const NamespaceDecl *ND) {
for (RecordDecl::decl_iterator I = ND->decls_begin(), E = ND->decls_end();
- I != E; ++I)
+ I != E; ++I) {
+ if (const VarDecl *VD = dyn_cast<VarDecl>(*I))
+ if (VD->getTemplateSpecializationKind() != TSK_ExplicitSpecialization &&
+ VD->getTemplateSpecializationKind() != TSK_Undeclared)
+ continue;
EmitTopLevelDecl(*I);
+ }
}
// EmitLinkageSpec - Emit all declarations in a linkage spec.
@@ -2795,12 +2905,6 @@ void CodeGenModule::EmitLinkageSpec(const LinkageSpecDecl *LSD) {
/// EmitTopLevelDecl - Emit code for a single top level declaration.
void CodeGenModule::EmitTopLevelDecl(Decl *D) {
- // If an error has occurred, stop code generation, but continue
- // parsing and semantic analysis (to ensure all warnings and errors
- // are emitted).
- if (Diags.hasErrorOccurred())
- return;
-
// Ignore dependent declarations.
if (D->getDeclContext() && D->getDeclContext()->isDependentContext())
return;
@@ -2816,8 +2920,12 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
EmitGlobal(cast<FunctionDecl>(D));
break;
-
+
case Decl::Var:
+ // Skip variable templates
+ if (cast<VarDecl>(D)->getDescribedVarTemplate())
+ return;
+ case Decl::VarTemplateSpecialization:
EmitGlobal(cast<VarDecl>(D));
break;
@@ -2834,12 +2942,17 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
case Decl::UsingShadow:
case Decl::Using:
case Decl::ClassTemplate:
+ case Decl::VarTemplate:
+ case Decl::VarTemplatePartialSpecialization:
case Decl::FunctionTemplate:
case Decl::TypeAliasTemplate:
- case Decl::NamespaceAlias:
case Decl::Block:
case Decl::Empty:
break;
+ case Decl::NamespaceAlias:
+ if (CGDebugInfo *DI = getModuleDebugInfo())
+ DI->EmitNamespaceAlias(cast<NamespaceAliasDecl>(*D));
+ return;
case Decl::UsingDirective: // using namespace X; [C++]
if (CGDebugInfo *DI = getModuleDebugInfo())
DI->EmitUsingDirective(cast<UsingDirectiveDecl>(*D));
@@ -2850,12 +2963,12 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
cast<FunctionDecl>(D)->isLateTemplateParsed())
return;
- EmitCXXConstructors(cast<CXXConstructorDecl>(D));
+ getCXXABI().EmitCXXConstructors(cast<CXXConstructorDecl>(D));
break;
case Decl::CXXDestructor:
if (cast<FunctionDecl>(D)->isLateTemplateParsed())
return;
- EmitCXXDestructors(cast<CXXDestructorDecl>(D));
+ getCXXABI().EmitCXXDestructors(cast<CXXDestructorDecl>(D));
break;
case Decl::StaticAssert:
@@ -3032,6 +3145,18 @@ void CodeGenFunction::EmitDeclMetadata() {
}
}
+void CodeGenModule::EmitVersionIdentMetadata() {
+ llvm::NamedMDNode *IdentMetadata =
+ TheModule.getOrInsertNamedMetadata("llvm.ident");
+ std::string Version = getClangFullVersion();
+ llvm::LLVMContext &Ctx = TheModule.getContext();
+
+ llvm::Value *IdentNode[] = {
+ llvm::MDString::get(Ctx, Version)
+ };
+ IdentMetadata->addOperand(llvm::MDNode::get(Ctx, IdentNode));
+}
+
void CodeGenModule::EmitCoverageFile() {
if (!getCodeGenOpts().CoverageFile.empty()) {
if (llvm::NamedMDNode *CUNode = TheModule.getNamedMetadata("llvm.dbg.cu")) {
@@ -3054,26 +3179,24 @@ llvm::Constant *CodeGenModule::EmitUuidofInitializer(StringRef Uuid,
// Sema has checked that all uuid strings are of the form
// "12345678-1234-1234-1234-1234567890ab".
assert(Uuid.size() == 36);
- const char *Uuidstr = Uuid.data();
- for (int i = 0; i < 36; ++i) {
- if (i == 8 || i == 13 || i == 18 || i == 23) assert(Uuidstr[i] == '-');
- else assert(isHexDigit(Uuidstr[i]));
+ for (unsigned i = 0; i < 36; ++i) {
+ if (i == 8 || i == 13 || i == 18 || i == 23) assert(Uuid[i] == '-');
+ else assert(isHexDigit(Uuid[i]));
}
-
- llvm::APInt Field0(32, StringRef(Uuidstr , 8), 16);
- llvm::APInt Field1(16, StringRef(Uuidstr + 9, 4), 16);
- llvm::APInt Field2(16, StringRef(Uuidstr + 14, 4), 16);
- static const int Field3ValueOffsets[] = { 19, 21, 24, 26, 28, 30, 32, 34 };
-
- APValue InitStruct(APValue::UninitStruct(), /*NumBases=*/0, /*NumFields=*/4);
- InitStruct.getStructField(0) = APValue(llvm::APSInt(Field0));
- InitStruct.getStructField(1) = APValue(llvm::APSInt(Field1));
- InitStruct.getStructField(2) = APValue(llvm::APSInt(Field2));
- APValue& Arr = InitStruct.getStructField(3);
- Arr = APValue(APValue::UninitArray(), 8, 8);
- for (int t = 0; t < 8; ++t)
- Arr.getArrayInitializedElt(t) = APValue(llvm::APSInt(
- llvm::APInt(8, StringRef(Uuidstr + Field3ValueOffsets[t], 2), 16)));
-
- return EmitConstantValue(InitStruct, GuidType);
+
+ const unsigned Field3ValueOffsets[8] = { 19, 21, 24, 26, 28, 30, 32, 34 };
+
+ llvm::Constant *Field3[8];
+ for (unsigned Idx = 0; Idx < 8; ++Idx)
+ Field3[Idx] = llvm::ConstantInt::get(
+ Int8Ty, Uuid.substr(Field3ValueOffsets[Idx], 2), 16);
+
+ llvm::Constant *Fields[4] = {
+ llvm::ConstantInt::get(Int32Ty, Uuid.substr(0, 8), 16),
+ llvm::ConstantInt::get(Int16Ty, Uuid.substr(9, 4), 16),
+ llvm::ConstantInt::get(Int16Ty, Uuid.substr(14, 4), 16),
+ llvm::ConstantArray::get(llvm::ArrayType::get(Int8Ty, 8), Field3)
+ };
+
+ return llvm::ConstantStruct::getAnon(Fields);
}
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 91138c6..c161224 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -31,7 +31,7 @@
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/ValueHandle.h"
-#include "llvm/Transforms/Utils/BlackList.h"
+#include "llvm/Transforms/Utils/SpecialCaseList.h"
namespace llvm {
class Module;
@@ -250,7 +250,6 @@ class CodeGenModule : public CodeGenTypeCache {
/// VTables - Holds information about C++ vtables.
CodeGenVTables VTables;
- friend class CodeGenVTables;
CGObjCRuntime* ObjCRuntime;
CGOpenCLRuntime* OpenCLRuntime;
@@ -276,6 +275,13 @@ class CodeGenModule : public CodeGenTypeCache {
/// is done.
std::vector<GlobalDecl> DeferredDeclsToEmit;
+ /// List of alias we have emitted. Used to make sure that what they point to
+ /// is defined once we get to the end of the of the translation unit.
+ std::vector<GlobalDecl> Aliases;
+
+ typedef llvm::StringMap<llvm::TrackingVH<llvm::Constant> > ReplacementsTy;
+ ReplacementsTy Replacements;
+
/// DeferredVTables - A queue of (optional) vtables to consider emitting.
std::vector<const CXXRecordDecl*> DeferredVTables;
@@ -307,10 +313,14 @@ class CodeGenModule : public CodeGenTypeCache {
llvm::StringMap<llvm::GlobalVariable*> ConstantStringMap;
llvm::DenseMap<const Decl*, llvm::Constant *> StaticLocalDeclMap;
llvm::DenseMap<const Decl*, llvm::GlobalVariable*> StaticLocalDeclGuardMap;
-
+ llvm::DenseMap<const Expr*, llvm::Constant *> MaterializedGlobalTemporaryMap;
+
llvm::DenseMap<QualType, llvm::Constant *> AtomicSetterHelperFnMap;
llvm::DenseMap<QualType, llvm::Constant *> AtomicGetterHelperFnMap;
+ /// Map used to get unique type descriptor constants for sanitizers.
+ llvm::DenseMap<QualType, llvm::Constant *> TypeDescriptorMap;
+
/// Map used to track internal linkage functions declared within
/// extern "C" regions.
typedef llvm::MapVector<IdentifierInfo *,
@@ -355,6 +365,9 @@ class CodeGenModule : public CodeGenTypeCache {
/// \brief The complete set of modules that has been imported.
llvm::SetVector<clang::Module *> ImportedModules;
+ /// \brief A vector of metadata strings.
+ SmallVector<llvm::Value *, 16> LinkerOptionsMetadata;
+
/// @name Cache for Objective-C runtime types
/// @{
@@ -382,7 +395,7 @@ class CodeGenModule : public CodeGenTypeCache {
void createCUDARuntime();
bool isTriviallyRecursive(const FunctionDecl *F);
- bool shouldEmitFunction(const FunctionDecl *F);
+ bool shouldEmitFunction(GlobalDecl GD);
/// @name Cache for Blocks Runtime Globals
/// @{
@@ -408,7 +421,7 @@ class CodeGenModule : public CodeGenTypeCache {
GlobalDecl initializedGlobalDecl;
- llvm::BlackList SanitizerBlacklist;
+ llvm::OwningPtr<llvm::SpecialCaseList> SanitizerBlacklist;
const SanitizerOptions &SanOpts;
@@ -488,6 +501,13 @@ public:
AtomicGetterHelperFnMap[Ty] = Fn;
}
+ llvm::Constant *getTypeDescriptor(QualType Ty) {
+ return TypeDescriptorMap[Ty];
+ }
+ void setTypeDescriptor(QualType Ty, llvm::Constant *C) {
+ TypeDescriptorMap[Ty] = C;
+ }
+
CGDebugInfo *getModuleDebugInfo() { return DebugInfo; }
llvm::MDNode *getNoObjCARCExceptionsMetadata() {
@@ -515,7 +535,14 @@ public:
CodeGenTypes &getTypes() { return Types; }
CodeGenVTables &getVTables() { return VTables; }
- VTableContext &getVTableContext() { return VTables.getVTableContext(); }
+
+ ItaniumVTableContext &getItaniumVTableContext() {
+ return VTables.getItaniumVTableContext();
+ }
+
+ MicrosoftVTableContext &getMicrosoftVTableContext() {
+ return VTables.getMicrosoftVTableContext();
+ }
llvm::MDNode *getTBAAInfo(QualType QTy);
llvm::MDNode *getTBAAInfoForVTablePtr();
@@ -728,7 +755,12 @@ public:
/// GetAddrOfConstantCompoundLiteral - Returns a pointer to a constant global
/// variable for the given file-scope compound literal expression.
llvm::Constant *GetAddrOfConstantCompoundLiteral(const CompoundLiteralExpr*E);
-
+
+ /// \brief Returns a pointer to a global variable representing a temporary
+ /// with static or thread storage duration.
+ llvm::Constant *GetAddrOfGlobalTemporary(const MaterializeTemporaryExpr *E,
+ const Expr *Inner);
+
/// \brief Retrieve the record type that describes the state of an
/// Objective-C fast enumeration loop (for..in).
QualType getObjCFastEnumerationStateType();
@@ -743,7 +775,8 @@ public:
/// given type.
llvm::GlobalValue *GetAddrOfCXXDestructor(const CXXDestructorDecl *dtor,
CXXDtorType dtorType,
- const CGFunctionInfo *fnInfo = 0);
+ const CGFunctionInfo *fnInfo = 0,
+ llvm::FunctionType *fnType = 0);
/// getBuiltinLibFunction - Given a builtin id for a function like
/// "__builtin_fabsf", return a Function* for "fabsf".
@@ -842,17 +875,11 @@ public:
/// ErrorUnsupported - Print out an error that codegen doesn't support the
/// specified stmt yet.
- /// \param OmitOnError - If true, then this error should only be emitted if no
- /// other errors have been reported.
- void ErrorUnsupported(const Stmt *S, const char *Type,
- bool OmitOnError=false);
+ void ErrorUnsupported(const Stmt *S, const char *Type);
/// ErrorUnsupported - Print out an error that codegen doesn't support the
/// specified decl yet.
- /// \param OmitOnError - If true, then this error should only be emitted if no
- /// other errors have been reported.
- void ErrorUnsupported(const Decl *D, const char *Type,
- bool OmitOnError=false);
+ void ErrorUnsupported(const Decl *D, const char *Type);
/// SetInternalFunctionAttributes - Set the attributes on the LLVM
/// function for the given decl and function info. This applies
@@ -906,11 +933,23 @@ public:
void EmitVTable(CXXRecordDecl *Class, bool DefinitionRequired);
- llvm::GlobalVariable::LinkageTypes
- getFunctionLinkage(const FunctionDecl *FD);
+ /// EmitFundamentalRTTIDescriptors - Emit the RTTI descriptors for the
+ /// builtin types.
+ void EmitFundamentalRTTIDescriptors();
+
+ /// \brief Appends Opts to the "Linker Options" metadata value.
+ void AppendLinkerOptions(StringRef Opts);
- void setFunctionLinkage(const FunctionDecl *FD, llvm::GlobalValue *V) {
- V->setLinkage(getFunctionLinkage(FD));
+ /// \brief Appends a detect mismatch command to the linker options.
+ void AddDetectMismatch(StringRef Name, StringRef Value);
+
+ /// \brief Appends a dependent lib to the "Linker Options" metadata value.
+ void AddDependentLib(StringRef Lib);
+
+ llvm::GlobalVariable::LinkageTypes getFunctionLinkage(GlobalDecl GD);
+
+ void setFunctionLinkage(GlobalDecl GD, llvm::GlobalValue *V) {
+ V->setLinkage(getFunctionLinkage(GD));
}
/// getVTableLinkage - Return the appropriate linkage for the vtable, VTT,
@@ -924,8 +963,7 @@ public:
/// GetLLVMLinkageVarDefinition - Returns LLVM linkage for a global
/// variable.
llvm::GlobalValue::LinkageTypes
- GetLLVMLinkageVarDefinition(const VarDecl *D,
- llvm::GlobalVariable *GV);
+ GetLLVMLinkageVarDefinition(const VarDecl *D, bool isConstant);
/// Emit all the global annotations.
void EmitGlobalAnnotations();
@@ -954,8 +992,8 @@ public:
/// annotations are emitted during finalization of the LLVM code.
void AddGlobalAnnotations(const ValueDecl *D, llvm::GlobalValue *GV);
- const llvm::BlackList &getSanitizerBlacklist() const {
- return SanitizerBlacklist;
+ const llvm::SpecialCaseList &getSanitizerBlacklist() const {
+ return *SanitizerBlacklist;
}
const SanitizerOptions &getSanOpts() const { return SanOpts; }
@@ -964,6 +1002,10 @@ public:
DeferredVTables.push_back(RD);
}
+ /// EmitGlobal - Emit code for a singal global function or var decl. Forward
+ /// declarations are emitted lazily.
+ void EmitGlobal(GlobalDecl D);
+
private:
llvm::GlobalValue *GetGlobalValue(StringRef Ref);
@@ -995,40 +1037,28 @@ private:
llvm::Function *F,
bool IsIncompleteFunction);
- /// EmitGlobal - Emit code for a singal global function or var decl. Forward
- /// declarations are emitted lazily.
- void EmitGlobal(GlobalDecl D);
-
void EmitGlobalDefinition(GlobalDecl D);
void EmitGlobalFunctionDefinition(GlobalDecl GD);
void EmitGlobalVarDefinition(const VarDecl *D);
- llvm::Constant *MaybeEmitGlobalStdInitializerListInitializer(const VarDecl *D,
- const Expr *init);
void EmitAliasDefinition(GlobalDecl GD);
void EmitObjCPropertyImplementations(const ObjCImplementationDecl *D);
void EmitObjCIvarInitializations(ObjCImplementationDecl *D);
// C++ related functions.
- bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target);
+ bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target,
+ bool InEveryTU);
bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D);
void EmitNamespace(const NamespaceDecl *D);
void EmitLinkageSpec(const LinkageSpecDecl *D);
-
- /// EmitCXXConstructors - Emit constructors (base, complete) from a
- /// C++ constructor Decl.
- void EmitCXXConstructors(const CXXConstructorDecl *D);
+ void CompleteDIClassType(const CXXMethodDecl* D);
/// EmitCXXConstructor - Emit a single constructor with the given type from
/// a C++ constructor Decl.
void EmitCXXConstructor(const CXXConstructorDecl *D, CXXCtorType Type);
- /// EmitCXXDestructors - Emit destructors (base, complete) from a
- /// C++ destructor Decl.
- void EmitCXXDestructors(const CXXDestructorDecl *D);
-
/// EmitCXXDestructor - Emit a single destructor with the given type from
/// a C++ destructor Decl.
void EmitCXXDestructor(const CXXDestructorDecl *D, CXXDtorType Type);
@@ -1061,14 +1091,15 @@ private:
/// given type.
void EmitFundamentalRTTIDescriptor(QualType Type);
- /// EmitFundamentalRTTIDescriptors - Emit the RTTI descriptors for the
- /// builtin types.
- void EmitFundamentalRTTIDescriptors();
-
/// EmitDeferred - Emit any needed decls for which code generation
/// was deferred.
void EmitDeferred();
+ /// Call replaceAllUsesWith on all pairs in Replacements.
+ void applyReplacements();
+
+ void checkAliases();
+
/// EmitDeferredVTables - Emit any vtables which we deferred and
/// still have a use for.
void EmitDeferredVTables();
@@ -1086,6 +1117,9 @@ private:
void EmitDeclMetadata();
+ /// \brief Emit the Clang version as llvm.ident metadata.
+ void EmitVersionIdentMetadata();
+
/// EmitCoverageFile - Emit the llvm.gcov metadata used to tell LLVM where
/// to emit the .gcno and .gcda files in a way that persists in .bc files.
void EmitCoverageFile();
diff --git a/lib/CodeGen/CodeGenTBAA.cpp b/lib/CodeGen/CodeGenTBAA.cpp
index 5ff1560..699cc2e 100644
--- a/lib/CodeGen/CodeGenTBAA.cpp
+++ b/lib/CodeGen/CodeGenTBAA.cpp
@@ -50,16 +50,11 @@ llvm::MDNode *CodeGenTBAA::getRoot() {
return Root;
}
-// For struct-path aware TBAA, the scalar type has the same format as
-// the struct type: name, offset, pointer to another node in the type DAG.
-// For scalar TBAA, the scalar type is the same as the scalar tag:
-// name and a parent pointer.
+// For both scalar TBAA and struct-path aware TBAA, the scalar type has the
+// same format: name, parent node, and offset.
llvm::MDNode *CodeGenTBAA::createTBAAScalarType(StringRef Name,
llvm::MDNode *Parent) {
- if (CodeGenOpts.StructPathTBAA)
- return MDHelper.createTBAAScalarTypeNode(Name, Parent);
- else
- return MDHelper.createTBAANode(Name, Parent);
+ return MDHelper.createTBAAScalarTypeNode(Name, Parent);
}
llvm::MDNode *CodeGenTBAA::getChar() {
@@ -91,7 +86,7 @@ static bool TypeHasMayAlias(QualType QTy) {
llvm::MDNode *
CodeGenTBAA::getTBAAInfo(QualType QTy) {
- // At -O0 TBAA is not emitted for regular types.
+ // At -O0 or relaxed aliasing, TBAA is not emitted for regular types.
if (CodeGenOpts.OptimizationLevel == 0 || CodeGenOpts.RelaxedAliasing)
return NULL;
@@ -150,27 +145,16 @@ CodeGenTBAA::getTBAAInfo(QualType QTy) {
// Enum types are distinct types. In C++ they have "underlying types",
// however they aren't related for TBAA.
if (const EnumType *ETy = dyn_cast<EnumType>(Ty)) {
- // In C mode, two anonymous enums are compatible iff their members
- // are the same -- see C99 6.2.7p1. For now, be conservative. We could
- // theoretically implement this by combining information about all the
- // members into a single identifying MDNode.
- if (!Features.CPlusPlus &&
- ETy->getDecl()->getTypedefNameForAnonDecl())
- return MetadataCache[Ty] = getChar();
-
// In C++ mode, types have linkage, so we can rely on the ODR and
// on their mangled names, if they're external.
// TODO: Is there a way to get a program-wide unique name for a
// decl with local linkage or no linkage?
- if (Features.CPlusPlus &&
- ETy->getDecl()->getLinkage() != ExternalLinkage)
+ if (!Features.CPlusPlus || !ETy->getDecl()->isExternallyVisible())
return MetadataCache[Ty] = getChar();
- // TODO: This is using the RTTI name. Is there a better way to get
- // a unique string for a type?
SmallString<256> OutName;
llvm::raw_svector_ostream Out(OutName);
- MContext.mangleCXXRTTIName(QualType(ETy, 0), Out);
+ MContext.mangleTypeName(QualType(ETy, 0), Out);
Out.flush();
return MetadataCache[Ty] = createTBAAScalarType(OutName, getChar());
}
@@ -204,18 +188,8 @@ CodeGenTBAA::CollectFields(uint64_t BaseOffset,
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
unsigned idx = 0;
- const FieldDecl *LastFD = 0;
- bool IsMsStruct = RD->isMsStruct(Context);
for (RecordDecl::field_iterator i = RD->field_begin(),
e = RD->field_end(); i != e; ++i, ++idx) {
- if (IsMsStruct) {
- // Zero-length bitfields following non-bitfield members are ignored.
- if (Context.ZeroBitfieldFollowsNonBitfield(*i, LastFD)) {
- --idx;
- continue;
- }
- LastFD = *i;
- }
uint64_t Offset = BaseOffset +
Layout.getFieldOffset(idx) / Context.getCharWidth();
QualType FieldQTy = i->getType();
@@ -230,8 +204,7 @@ CodeGenTBAA::CollectFields(uint64_t BaseOffset,
uint64_t Offset = BaseOffset;
uint64_t Size = Context.getTypeSizeInChars(QTy).getQuantity();
llvm::MDNode *TBAAInfo = MayAlias ? getChar() : getTBAAInfo(QTy);
- llvm::MDNode *TBAATag = CodeGenOpts.StructPathTBAA ?
- getTBAAScalarTagInfo(TBAAInfo) : TBAAInfo;
+ llvm::MDNode *TBAATag = getTBAAScalarTagInfo(TBAAInfo);
Fields.push_back(llvm::MDBuilder::TBAAStructField(Offset, Size, TBAATag));
return true;
}
@@ -279,19 +252,8 @@ CodeGenTBAA::getTBAAStructTypeInfo(QualType QTy) {
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
SmallVector <std::pair<llvm::MDNode*, uint64_t>, 4> Fields;
unsigned idx = 0;
- const FieldDecl *LastFD = 0;
- bool IsMsStruct = RD->isMsStruct(Context);
for (RecordDecl::field_iterator i = RD->field_begin(),
e = RD->field_end(); i != e; ++i, ++idx) {
- if (IsMsStruct) {
- // Zero-length bitfields following non-bitfield members are ignored.
- if (Context.ZeroBitfieldFollowsNonBitfield(*i, LastFD)) {
- --idx;
- continue;
- }
- LastFD = *i;
- }
-
QualType FieldQTy = i->getType();
llvm::MDNode *FieldNode;
if (isTBAAPathStruct(FieldQTy))
@@ -304,12 +266,15 @@ CodeGenTBAA::getTBAAStructTypeInfo(QualType QTy) {
FieldNode, Layout.getFieldOffset(idx) / Context.getCharWidth()));
}
- // TODO: This is using the RTTI name. Is there a better way to get
- // a unique string for a type?
SmallString<256> OutName;
- llvm::raw_svector_ostream Out(OutName);
- MContext.mangleCXXRTTIName(QualType(Ty, 0), Out);
- Out.flush();
+ if (Features.CPlusPlus) {
+ // Don't use the mangler for C code.
+ llvm::raw_svector_ostream Out(OutName);
+ MContext.mangleTypeName(QualType(Ty, 0), Out);
+ Out.flush();
+ } else {
+ OutName = RD->getName();
+ }
// Create the struct type node with a vector of pairs (offset, type).
return StructTypeMetadataCache[Ty] =
MDHelper.createTBAAStructTypeNode(OutName, Fields);
@@ -318,11 +283,15 @@ CodeGenTBAA::getTBAAStructTypeInfo(QualType QTy) {
return StructMetadataCache[Ty] = NULL;
}
+/// Return a TBAA tag node for both scalar TBAA and struct-path aware TBAA.
llvm::MDNode *
CodeGenTBAA::getTBAAStructTagInfo(QualType BaseQTy, llvm::MDNode *AccessNode,
uint64_t Offset) {
+ if (!AccessNode)
+ return NULL;
+
if (!CodeGenOpts.StructPathTBAA)
- return AccessNode;
+ return getTBAAScalarTagInfo(AccessNode);
const Type *BTy = Context.getCanonicalType(BaseQTy).getTypePtr();
TBAAPathTag PathTag = TBAAPathTag(BTy, AccessNode, Offset);
@@ -342,6 +311,8 @@ CodeGenTBAA::getTBAAStructTagInfo(QualType BaseQTy, llvm::MDNode *AccessNode,
llvm::MDNode *
CodeGenTBAA::getTBAAScalarTagInfo(llvm::MDNode *AccessNode) {
+ if (!AccessNode)
+ return NULL;
if (llvm::MDNode *N = ScalarTagMetadataCache[AccessNode])
return N;
diff --git a/lib/CodeGen/CodeGenTBAA.h b/lib/CodeGen/CodeGenTBAA.h
index f0c9e06..0ad4be2 100644
--- a/lib/CodeGen/CodeGenTBAA.h
+++ b/lib/CodeGen/CodeGenTBAA.h
@@ -117,7 +117,7 @@ public:
llvm::MDNode *getTBAAStructTagInfo(QualType BaseQType,
llvm::MDNode *AccessNode, uint64_t Offset);
- /// Get the sclar tag MDNode for a given scalar type.
+ /// Get the scalar tag MDNode for a given scalar type.
llvm::MDNode *getTBAAScalarTagInfo(llvm::MDNode *AccessNode);
};
diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp
index 4240216..5f3c59c 100644
--- a/lib/CodeGen/CodeGenTypes.cpp
+++ b/lib/CodeGen/CodeGenTypes.cpp
@@ -22,6 +22,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/RecordLayout.h"
+#include "clang/CodeGen/CGFunctionInfo.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Module.h"
@@ -32,7 +33,6 @@ CodeGenTypes::CodeGenTypes(CodeGenModule &cgm)
: CGM(cgm), Context(cgm.getContext()), TheModule(cgm.getModule()),
TheDataLayout(cgm.getDataLayout()),
Target(cgm.getTarget()), TheCXXABI(cgm.getCXXABI()),
- CodeGenOpts(cgm.getCodeGenOpts()),
TheABIInfo(cgm.getTargetCodeGenInfo().getABIInfo()) {
SkippedLayout = false;
}
@@ -260,6 +260,11 @@ void CodeGenTypes::UpdateCompletedType(const TagDecl *TD) {
// yet, we'll just do it lazily.
if (RecordDeclTypes.count(Context.getTagDeclType(RD).getTypePtr()))
ConvertRecordDeclType(RD);
+
+ // If necessary, provide the full definition of a type only used with a
+ // declaration so far.
+ if (CGDebugInfo *DI = CGM.getModuleDebugInfo())
+ DI->completeType(RD);
}
static llvm::Type *getTypeForFormat(llvm::LLVMContext &VMContext,
diff --git a/lib/CodeGen/CodeGenTypes.h b/lib/CodeGen/CodeGenTypes.h
index 452375f..94ca9e2 100644
--- a/lib/CodeGen/CodeGenTypes.h
+++ b/lib/CodeGen/CodeGenTypes.h
@@ -16,6 +16,7 @@
#include "CGCall.h"
#include "clang/AST/GlobalDecl.h"
+#include "clang/CodeGen/CGFunctionInfo.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/Module.h"
#include <vector>
@@ -58,21 +59,18 @@ namespace CodeGen {
/// CodeGenTypes - This class organizes the cross-module state that is used
/// while lowering AST types to LLVM types.
class CodeGenTypes {
-public:
- // Some of this stuff should probably be left on the CGM.
CodeGenModule &CGM;
+ // Some of this stuff should probably be left on the CGM.
ASTContext &Context;
llvm::Module &TheModule;
const llvm::DataLayout &TheDataLayout;
const TargetInfo &Target;
CGCXXABI &TheCXXABI;
- const CodeGenOptions &CodeGenOpts;
// This should not be moved earlier, since its initialization depends on some
// of the previous reference members being already initialized
const ABIInfo &TheABIInfo;
-private:
/// The opaque type map for Objective-C interfaces. All direct
/// manipulation is done by the runtime interfaces, which are
/// responsible for coercing to the appropriate type; these opaque
@@ -116,7 +114,6 @@ public:
const llvm::DataLayout &getDataLayout() const { return TheDataLayout; }
ASTContext &getContext() const { return Context; }
const ABIInfo &getABIInfo() const { return TheABIInfo; }
- const CodeGenOptions &getCodeGenOpts() const { return CodeGenOpts; }
const TargetInfo &getTarget() const { return Target; }
CGCXXABI &getCXXABI() const { return TheCXXABI; }
llvm::LLVMContext &getLLVMContext() { return TheModule.getContext(); }
diff --git a/lib/CodeGen/EHScopeStack.h b/lib/CodeGen/EHScopeStack.h
new file mode 100644
index 0000000..e9d9a33
--- /dev/null
+++ b/lib/CodeGen/EHScopeStack.h
@@ -0,0 +1,489 @@
+//===-- EHScopeStack.h - Stack for cleanup IR generation --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These classes should be the minimum interface required for other parts of
+// CodeGen to emit cleanups. The implementation is in CGCleanup.cpp and other
+// implemenentation details that are not widely needed are in CGCleanup.h.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CODEGEN_EHSCOPESTACK_H
+#define CLANG_CODEGEN_EHSCOPESTACK_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Value.h"
+#include "llvm/IR/Instructions.h"
+
+namespace clang {
+namespace CodeGen {
+
+class CodeGenFunction;
+
+/// A branch fixup. These are required when emitting a goto to a
+/// label which hasn't been emitted yet. The goto is optimistically
+/// emitted as a branch to the basic block for the label, and (if it
+/// occurs in a scope with non-trivial cleanups) a fixup is added to
+/// the innermost cleanup. When a (normal) cleanup is popped, any
+/// unresolved fixups in that scope are threaded through the cleanup.
+struct BranchFixup {
+ /// The block containing the terminator which needs to be modified
+ /// into a switch if this fixup is resolved into the current scope.
+ /// If null, LatestBranch points directly to the destination.
+ llvm::BasicBlock *OptimisticBranchBlock;
+
+ /// The ultimate destination of the branch.
+ ///
+ /// This can be set to null to indicate that this fixup was
+ /// successfully resolved.
+ llvm::BasicBlock *Destination;
+
+ /// The destination index value.
+ unsigned DestinationIndex;
+
+ /// The initial branch of the fixup.
+ llvm::BranchInst *InitialBranch;
+};
+
+template <class T> struct InvariantValue {
+ typedef T type;
+ typedef T saved_type;
+ static bool needsSaving(type value) { return false; }
+ static saved_type save(CodeGenFunction &CGF, type value) { return value; }
+ static type restore(CodeGenFunction &CGF, saved_type value) { return value; }
+};
+
+/// A metaprogramming class for ensuring that a value will dominate an
+/// arbitrary position in a function.
+template <class T> struct DominatingValue : InvariantValue<T> {};
+
+template <class T, bool mightBeInstruction =
+ llvm::is_base_of<llvm::Value, T>::value &&
+ !llvm::is_base_of<llvm::Constant, T>::value &&
+ !llvm::is_base_of<llvm::BasicBlock, T>::value>
+struct DominatingPointer;
+template <class T> struct DominatingPointer<T,false> : InvariantValue<T*> {};
+// template <class T> struct DominatingPointer<T,true> at end of file
+
+template <class T> struct DominatingValue<T*> : DominatingPointer<T> {};
+
+enum CleanupKind {
+ EHCleanup = 0x1,
+ NormalCleanup = 0x2,
+ NormalAndEHCleanup = EHCleanup | NormalCleanup,
+
+ InactiveCleanup = 0x4,
+ InactiveEHCleanup = EHCleanup | InactiveCleanup,
+ InactiveNormalCleanup = NormalCleanup | InactiveCleanup,
+ InactiveNormalAndEHCleanup = NormalAndEHCleanup | InactiveCleanup
+};
+
+/// A stack of scopes which respond to exceptions, including cleanups
+/// and catch blocks.
+class EHScopeStack {
+public:
+ /// A saved depth on the scope stack. This is necessary because
+ /// pushing scopes onto the stack invalidates iterators.
+ class stable_iterator {
+ friend class EHScopeStack;
+
+ /// Offset from StartOfData to EndOfBuffer.
+ ptrdiff_t Size;
+
+ stable_iterator(ptrdiff_t Size) : Size(Size) {}
+
+ public:
+ static stable_iterator invalid() { return stable_iterator(-1); }
+ stable_iterator() : Size(-1) {}
+
+ bool isValid() const { return Size >= 0; }
+
+ /// Returns true if this scope encloses I.
+ /// Returns false if I is invalid.
+ /// This scope must be valid.
+ bool encloses(stable_iterator I) const { return Size <= I.Size; }
+
+ /// Returns true if this scope strictly encloses I: that is,
+ /// if it encloses I and is not I.
+ /// Returns false is I is invalid.
+ /// This scope must be valid.
+ bool strictlyEncloses(stable_iterator I) const { return Size < I.Size; }
+
+ friend bool operator==(stable_iterator A, stable_iterator B) {
+ return A.Size == B.Size;
+ }
+ friend bool operator!=(stable_iterator A, stable_iterator B) {
+ return A.Size != B.Size;
+ }
+ };
+
+ /// Information for lazily generating a cleanup. Subclasses must be
+ /// POD-like: cleanups will not be destructed, and they will be
+ /// allocated on the cleanup stack and freely copied and moved
+ /// around.
+ ///
+ /// Cleanup implementations should generally be declared in an
+ /// anonymous namespace.
+ class Cleanup {
+ // Anchor the construction vtable.
+ virtual void anchor();
+ public:
+ /// Generation flags.
+ class Flags {
+ enum {
+ F_IsForEH = 0x1,
+ F_IsNormalCleanupKind = 0x2,
+ F_IsEHCleanupKind = 0x4
+ };
+ unsigned flags;
+
+ public:
+ Flags() : flags(0) {}
+
+ /// isForEH - true if the current emission is for an EH cleanup.
+ bool isForEHCleanup() const { return flags & F_IsForEH; }
+ bool isForNormalCleanup() const { return !isForEHCleanup(); }
+ void setIsForEHCleanup() { flags |= F_IsForEH; }
+
+ bool isNormalCleanupKind() const { return flags & F_IsNormalCleanupKind; }
+ void setIsNormalCleanupKind() { flags |= F_IsNormalCleanupKind; }
+
+ /// isEHCleanupKind - true if the cleanup was pushed as an EH
+ /// cleanup.
+ bool isEHCleanupKind() const { return flags & F_IsEHCleanupKind; }
+ void setIsEHCleanupKind() { flags |= F_IsEHCleanupKind; }
+ };
+
+ // Provide a virtual destructor to suppress a very common warning
+ // that unfortunately cannot be suppressed without this. Cleanups
+ // should not rely on this destructor ever being called.
+ virtual ~Cleanup() {}
+
+ /// Emit the cleanup. For normal cleanups, this is run in the
+ /// same EH context as when the cleanup was pushed, i.e. the
+ /// immediately-enclosing context of the cleanup scope. For
+ /// EH cleanups, this is run in a terminate context.
+ ///
+ // \param flags cleanup kind.
+ virtual void Emit(CodeGenFunction &CGF, Flags flags) = 0;
+ };
+
+ /// ConditionalCleanupN stores the saved form of its N parameters,
+ /// then restores them and performs the cleanup.
+ template <class T, class A0>
+ class ConditionalCleanup1 : public Cleanup {
+ typedef typename DominatingValue<A0>::saved_type A0_saved;
+ A0_saved a0_saved;
+
+ void Emit(CodeGenFunction &CGF, Flags flags) {
+ A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
+ T(a0).Emit(CGF, flags);
+ }
+
+ public:
+ ConditionalCleanup1(A0_saved a0)
+ : a0_saved(a0) {}
+ };
+
+ template <class T, class A0, class A1>
+ class ConditionalCleanup2 : public Cleanup {
+ typedef typename DominatingValue<A0>::saved_type A0_saved;
+ typedef typename DominatingValue<A1>::saved_type A1_saved;
+ A0_saved a0_saved;
+ A1_saved a1_saved;
+
+ void Emit(CodeGenFunction &CGF, Flags flags) {
+ A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
+ A1 a1 = DominatingValue<A1>::restore(CGF, a1_saved);
+ T(a0, a1).Emit(CGF, flags);
+ }
+
+ public:
+ ConditionalCleanup2(A0_saved a0, A1_saved a1)
+ : a0_saved(a0), a1_saved(a1) {}
+ };
+
+ template <class T, class A0, class A1, class A2>
+ class ConditionalCleanup3 : public Cleanup {
+ typedef typename DominatingValue<A0>::saved_type A0_saved;
+ typedef typename DominatingValue<A1>::saved_type A1_saved;
+ typedef typename DominatingValue<A2>::saved_type A2_saved;
+ A0_saved a0_saved;
+ A1_saved a1_saved;
+ A2_saved a2_saved;
+
+ void Emit(CodeGenFunction &CGF, Flags flags) {
+ A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
+ A1 a1 = DominatingValue<A1>::restore(CGF, a1_saved);
+ A2 a2 = DominatingValue<A2>::restore(CGF, a2_saved);
+ T(a0, a1, a2).Emit(CGF, flags);
+ }
+
+ public:
+ ConditionalCleanup3(A0_saved a0, A1_saved a1, A2_saved a2)
+ : a0_saved(a0), a1_saved(a1), a2_saved(a2) {}
+ };
+
+ template <class T, class A0, class A1, class A2, class A3>
+ class ConditionalCleanup4 : public Cleanup {
+ typedef typename DominatingValue<A0>::saved_type A0_saved;
+ typedef typename DominatingValue<A1>::saved_type A1_saved;
+ typedef typename DominatingValue<A2>::saved_type A2_saved;
+ typedef typename DominatingValue<A3>::saved_type A3_saved;
+ A0_saved a0_saved;
+ A1_saved a1_saved;
+ A2_saved a2_saved;
+ A3_saved a3_saved;
+
+ void Emit(CodeGenFunction &CGF, Flags flags) {
+ A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
+ A1 a1 = DominatingValue<A1>::restore(CGF, a1_saved);
+ A2 a2 = DominatingValue<A2>::restore(CGF, a2_saved);
+ A3 a3 = DominatingValue<A3>::restore(CGF, a3_saved);
+ T(a0, a1, a2, a3).Emit(CGF, flags);
+ }
+
+ public:
+ ConditionalCleanup4(A0_saved a0, A1_saved a1, A2_saved a2, A3_saved a3)
+ : a0_saved(a0), a1_saved(a1), a2_saved(a2), a3_saved(a3) {}
+ };
+
+private:
+ // The implementation for this class is in CGException.h and
+ // CGException.cpp; the definition is here because it's used as a
+ // member of CodeGenFunction.
+
+ /// The start of the scope-stack buffer, i.e. the allocated pointer
+ /// for the buffer. All of these pointers are either simultaneously
+ /// null or simultaneously valid.
+ char *StartOfBuffer;
+
+ /// The end of the buffer.
+ char *EndOfBuffer;
+
+ /// The first valid entry in the buffer.
+ char *StartOfData;
+
+ /// The innermost normal cleanup on the stack.
+ stable_iterator InnermostNormalCleanup;
+
+ /// The innermost EH scope on the stack.
+ stable_iterator InnermostEHScope;
+
+ /// The current set of branch fixups. A branch fixup is a jump to
+ /// an as-yet unemitted label, i.e. a label for which we don't yet
+ /// know the EH stack depth. Whenever we pop a cleanup, we have
+ /// to thread all the current branch fixups through it.
+ ///
+ /// Fixups are recorded as the Use of the respective branch or
+ /// switch statement. The use points to the final destination.
+ /// When popping out of a cleanup, these uses are threaded through
+ /// the cleanup and adjusted to point to the new cleanup.
+ ///
+ /// Note that branches are allowed to jump into protected scopes
+ /// in certain situations; e.g. the following code is legal:
+ /// struct A { ~A(); }; // trivial ctor, non-trivial dtor
+ /// goto foo;
+ /// A a;
+ /// foo:
+ /// bar();
+ SmallVector<BranchFixup, 8> BranchFixups;
+
+ char *allocate(size_t Size);
+
+ void *pushCleanup(CleanupKind K, size_t DataSize);
+
+public:
+ EHScopeStack() : StartOfBuffer(0), EndOfBuffer(0), StartOfData(0),
+ InnermostNormalCleanup(stable_end()),
+ InnermostEHScope(stable_end()) {}
+ ~EHScopeStack() { delete[] StartOfBuffer; }
+
+ // Variadic templates would make this not terrible.
+
+ /// Push a lazily-created cleanup on the stack.
+ template <class T>
+ void pushCleanup(CleanupKind Kind) {
+ void *Buffer = pushCleanup(Kind, sizeof(T));
+ Cleanup *Obj = new(Buffer) T();
+ (void) Obj;
+ }
+
+ /// Push a lazily-created cleanup on the stack.
+ template <class T, class A0>
+ void pushCleanup(CleanupKind Kind, A0 a0) {
+ void *Buffer = pushCleanup(Kind, sizeof(T));
+ Cleanup *Obj = new(Buffer) T(a0);
+ (void) Obj;
+ }
+
+ /// Push a lazily-created cleanup on the stack.
+ template <class T, class A0, class A1>
+ void pushCleanup(CleanupKind Kind, A0 a0, A1 a1) {
+ void *Buffer = pushCleanup(Kind, sizeof(T));
+ Cleanup *Obj = new(Buffer) T(a0, a1);
+ (void) Obj;
+ }
+
+ /// Push a lazily-created cleanup on the stack.
+ template <class T, class A0, class A1, class A2>
+ void pushCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2) {
+ void *Buffer = pushCleanup(Kind, sizeof(T));
+ Cleanup *Obj = new(Buffer) T(a0, a1, a2);
+ (void) Obj;
+ }
+
+ /// Push a lazily-created cleanup on the stack.
+ template <class T, class A0, class A1, class A2, class A3>
+ void pushCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2, A3 a3) {
+ void *Buffer = pushCleanup(Kind, sizeof(T));
+ Cleanup *Obj = new(Buffer) T(a0, a1, a2, a3);
+ (void) Obj;
+ }
+
+ /// Push a lazily-created cleanup on the stack.
+ template <class T, class A0, class A1, class A2, class A3, class A4>
+ void pushCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
+ void *Buffer = pushCleanup(Kind, sizeof(T));
+ Cleanup *Obj = new(Buffer) T(a0, a1, a2, a3, a4);
+ (void) Obj;
+ }
+
+ // Feel free to add more variants of the following:
+
+ /// Push a cleanup with non-constant storage requirements on the
+ /// stack. The cleanup type must provide an additional static method:
+ /// static size_t getExtraSize(size_t);
+ /// The argument to this method will be the value N, which will also
+ /// be passed as the first argument to the constructor.
+ ///
+ /// The data stored in the extra storage must obey the same
+ /// restrictions as normal cleanup member data.
+ ///
+ /// The pointer returned from this method is valid until the cleanup
+ /// stack is modified.
+ template <class T, class A0, class A1, class A2>
+ T *pushCleanupWithExtra(CleanupKind Kind, size_t N, A0 a0, A1 a1, A2 a2) {
+ void *Buffer = pushCleanup(Kind, sizeof(T) + T::getExtraSize(N));
+ return new (Buffer) T(N, a0, a1, a2);
+ }
+
+ void pushCopyOfCleanup(CleanupKind Kind, const void *Cleanup, size_t Size) {
+ void *Buffer = pushCleanup(Kind, Size);
+ std::memcpy(Buffer, Cleanup, Size);
+ }
+
+ /// Pops a cleanup scope off the stack. This is private to CGCleanup.cpp.
+ void popCleanup();
+
+ /// Push a set of catch handlers on the stack. The catch is
+ /// uninitialized and will need to have the given number of handlers
+ /// set on it.
+ class EHCatchScope *pushCatch(unsigned NumHandlers);
+
+ /// Pops a catch scope off the stack. This is private to CGException.cpp.
+ void popCatch();
+
+ /// Push an exceptions filter on the stack.
+ class EHFilterScope *pushFilter(unsigned NumFilters);
+
+ /// Pops an exceptions filter off the stack.
+ void popFilter();
+
+ /// Push a terminate handler on the stack.
+ void pushTerminate();
+
+ /// Pops a terminate handler off the stack.
+ void popTerminate();
+
+ /// Determines whether the exception-scopes stack is empty.
+ bool empty() const { return StartOfData == EndOfBuffer; }
+
+ bool requiresLandingPad() const {
+ return InnermostEHScope != stable_end();
+ }
+
+ /// Determines whether there are any normal cleanups on the stack.
+ bool hasNormalCleanups() const {
+ return InnermostNormalCleanup != stable_end();
+ }
+
+ /// Returns the innermost normal cleanup on the stack, or
+ /// stable_end() if there are no normal cleanups.
+ stable_iterator getInnermostNormalCleanup() const {
+ return InnermostNormalCleanup;
+ }
+ stable_iterator getInnermostActiveNormalCleanup() const;
+
+ stable_iterator getInnermostEHScope() const {
+ return InnermostEHScope;
+ }
+
+ stable_iterator getInnermostActiveEHScope() const;
+
+ /// An unstable reference to a scope-stack depth. Invalidated by
+ /// pushes but not pops.
+ class iterator;
+
+ /// Returns an iterator pointing to the innermost EH scope.
+ iterator begin() const;
+
+ /// Returns an iterator pointing to the outermost EH scope.
+ iterator end() const;
+
+ /// Create a stable reference to the top of the EH stack. The
+ /// returned reference is valid until that scope is popped off the
+ /// stack.
+ stable_iterator stable_begin() const {
+ return stable_iterator(EndOfBuffer - StartOfData);
+ }
+
+ /// Create a stable reference to the bottom of the EH stack.
+ static stable_iterator stable_end() {
+ return stable_iterator(0);
+ }
+
+ /// Translates an iterator into a stable_iterator.
+ stable_iterator stabilize(iterator it) const;
+
+ /// Turn a stable reference to a scope depth into a unstable pointer
+ /// to the EH stack.
+ iterator find(stable_iterator save) const;
+
+ /// Removes the cleanup pointed to by the given stable_iterator.
+ void removeCleanup(stable_iterator save);
+
+ /// Add a branch fixup to the current cleanup scope.
+ BranchFixup &addBranchFixup() {
+ assert(hasNormalCleanups() && "adding fixup in scope without cleanups");
+ BranchFixups.push_back(BranchFixup());
+ return BranchFixups.back();
+ }
+
+ unsigned getNumBranchFixups() const { return BranchFixups.size(); }
+ BranchFixup &getBranchFixup(unsigned I) {
+ assert(I < getNumBranchFixups());
+ return BranchFixups[I];
+ }
+
+ /// Pops lazily-removed fixups from the end of the list. This
+ /// should only be called by procedures which have just popped a
+ /// cleanup or resolved one or more fixups.
+ void popNullFixups();
+
+ /// Clears the branch-fixups list. This should only be called by
+ /// ResolveAllBranchFixups.
+ void clearFixups() { BranchFixups.clear(); }
+};
+
+} // namespace CodeGen
+} // namespace clang
+
+#endif
diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp
index e117e28..0e8f31a 100644
--- a/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/lib/CodeGen/ItaniumCXXABI.cpp
@@ -34,12 +34,23 @@ using namespace CodeGen;
namespace {
class ItaniumCXXABI : public CodeGen::CGCXXABI {
+ /// VTables - All the vtables which have been defined.
+ llvm::DenseMap<const CXXRecordDecl *, llvm::GlobalVariable *> VTables;
+
protected:
- bool IsARM;
+ bool UseARMMethodPtrABI;
+ bool UseARMGuardVarABI;
+
+ ItaniumMangleContext &getMangleContext() {
+ return cast<ItaniumMangleContext>(CodeGen::CGCXXABI::getMangleContext());
+ }
public:
- ItaniumCXXABI(CodeGen::CodeGenModule &CGM, bool IsARM = false) :
- CGCXXABI(CGM), IsARM(IsARM) { }
+ ItaniumCXXABI(CodeGen::CodeGenModule &CGM,
+ bool UseARMMethodPtrABI = false,
+ bool UseARMGuardVarABI = false) :
+ CGCXXABI(CGM), UseARMMethodPtrABI(UseARMMethodPtrABI),
+ UseARMGuardVarABI(UseARMGuardVarABI) { }
bool isReturnTypeIndirect(const CXXRecordDecl *RD) const {
// Structures with either a non-trivial destructor or a non-trivial
@@ -98,36 +109,82 @@ public:
llvm::Value *ptr,
QualType type);
+ llvm::Value *GetVirtualBaseClassOffset(CodeGenFunction &CGF,
+ llvm::Value *This,
+ const CXXRecordDecl *ClassDecl,
+ const CXXRecordDecl *BaseClassDecl);
+
void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
CXXCtorType T,
CanQualType &ResTy,
SmallVectorImpl<CanQualType> &ArgTys);
+ void EmitCXXConstructors(const CXXConstructorDecl *D);
+
void BuildDestructorSignature(const CXXDestructorDecl *Dtor,
CXXDtorType T,
CanQualType &ResTy,
SmallVectorImpl<CanQualType> &ArgTys);
+ bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor,
+ CXXDtorType DT) const {
+ // Itanium does not emit any destructor variant as an inline thunk.
+ // Delegating may occur as an optimization, but all variants are either
+ // emitted with external linkage or as linkonce if they are inline and used.
+ return false;
+ }
+
+ void EmitCXXDestructors(const CXXDestructorDecl *D);
+
void BuildInstanceFunctionParams(CodeGenFunction &CGF,
QualType &ResTy,
FunctionArgList &Params);
void EmitInstanceFunctionProlog(CodeGenFunction &CGF);
- llvm::Value *EmitConstructorCall(CodeGenFunction &CGF,
- const CXXConstructorDecl *D,
- CXXCtorType Type, bool ForVirtualBase,
- bool Delegating,
+ void EmitConstructorCall(CodeGenFunction &CGF,
+ const CXXConstructorDecl *D, CXXCtorType Type,
+ bool ForVirtualBase, bool Delegating,
llvm::Value *This,
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd);
- RValue EmitVirtualDestructorCall(CodeGenFunction &CGF,
- const CXXDestructorDecl *Dtor,
- CXXDtorType DtorType,
- SourceLocation CallLoc,
- ReturnValueSlot ReturnValue,
- llvm::Value *This);
+ void emitVTableDefinitions(CodeGenVTables &CGVT, const CXXRecordDecl *RD);
+
+ llvm::Value *getVTableAddressPointInStructor(
+ CodeGenFunction &CGF, const CXXRecordDecl *VTableClass,
+ BaseSubobject Base, const CXXRecordDecl *NearestVBase,
+ bool &NeedsVirtualOffset);
+
+ llvm::Constant *
+ getVTableAddressPointForConstExpr(BaseSubobject Base,
+ const CXXRecordDecl *VTableClass);
+
+ llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD,
+ CharUnits VPtrOffset);
+
+ llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD,
+ llvm::Value *This, llvm::Type *Ty);
+
+ void EmitVirtualDestructorCall(CodeGenFunction &CGF,
+ const CXXDestructorDecl *Dtor,
+ CXXDtorType DtorType, SourceLocation CallLoc,
+ llvm::Value *This);
+
+ void emitVirtualInheritanceTables(const CXXRecordDecl *RD);
+
+ void setThunkLinkage(llvm::Function *Thunk, bool ForVTable) {
+ // Allow inlining of thunks by emitting them with available_externally
+ // linkage together with vtables when needed.
+ if (ForVTable)
+ Thunk->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
+ }
+
+ llvm::Value *performThisAdjustment(CodeGenFunction &CGF, llvm::Value *This,
+ const ThisAdjustment &TA);
+
+ llvm::Value *performReturnAdjustment(CodeGenFunction &CGF, llvm::Value *Ret,
+ const ReturnAdjustment &RA);
StringRef GetPureVirtualCallName() { return "__cxa_pure_virtual"; }
StringRef GetDeletedVirtualCallName() { return "__cxa_deleted_virtual"; }
@@ -154,27 +211,21 @@ public:
llvm::Function *InitFunc);
LValue EmitThreadLocalDeclRefExpr(CodeGenFunction &CGF,
const DeclRefExpr *DRE);
+
+ bool NeedsVTTParameter(GlobalDecl GD);
};
class ARMCXXABI : public ItaniumCXXABI {
public:
- ARMCXXABI(CodeGen::CodeGenModule &CGM) : ItaniumCXXABI(CGM, /*ARM*/ true) {}
+ ARMCXXABI(CodeGen::CodeGenModule &CGM) :
+ ItaniumCXXABI(CGM, /* UseARMMethodPtrABI = */ true,
+ /* UseARMGuardVarABI = */ true) {}
- void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
- CXXCtorType T,
- CanQualType &ResTy,
- SmallVectorImpl<CanQualType> &ArgTys);
-
- void BuildDestructorSignature(const CXXDestructorDecl *Dtor,
- CXXDtorType T,
- CanQualType &ResTy,
- SmallVectorImpl<CanQualType> &ArgTys);
-
- void BuildInstanceFunctionParams(CodeGenFunction &CGF,
- QualType &ResTy,
- FunctionArgList &Params);
-
- void EmitInstanceFunctionProlog(CodeGenFunction &CGF);
+ bool HasThisReturn(GlobalDecl GD) const {
+ return (isa<CXXConstructorDecl>(GD.getDecl()) || (
+ isa<CXXDestructorDecl>(GD.getDecl()) &&
+ GD.getDtorType() != Dtor_Deleting));
+ }
void EmitReturnFromThunk(CodeGenFunction &CGF, RValue RV, QualType ResTy);
@@ -186,15 +237,6 @@ public:
QualType ElementType);
llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF, llvm::Value *allocPtr,
CharUnits cookieSize);
-
- /// \brief Returns true if the given instance method is one of the
- /// kinds that the ARM ABI says returns 'this'.
- bool HasThisReturn(GlobalDecl GD) const {
- const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(GD.getDecl());
- if (!MD) return false;
- return ((isa<CXXDestructorDecl>(MD) && GD.getDtorType() != Dtor_Deleting) ||
- (isa<CXXConstructorDecl>(MD)));
- }
};
}
@@ -210,9 +252,18 @@ CodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) {
// include the other 32-bit ARM oddities: constructor/destructor return values
// and array cookies.
case TargetCXXABI::GenericAArch64:
- return new ItaniumCXXABI(CGM, /*IsARM = */ true);
+ return new ItaniumCXXABI(CGM, /* UseARMMethodPtrABI = */ true,
+ /* UseARMGuardVarABI = */ true);
case TargetCXXABI::GenericItanium:
+ if (CGM.getContext().getTargetInfo().getTriple().getArch()
+ == llvm::Triple::le32) {
+ // For PNaCl, use ARM-style method pointers so that PNaCl code
+ // does not assume anything about the alignment of function
+ // pointers.
+ return new ItaniumCXXABI(CGM, /* UseARMMethodPtrABI = */ true,
+ /* UseARMGuardVarABI = */ false);
+ }
return new ItaniumCXXABI(CGM);
case TargetCXXABI::Microsoft:
@@ -275,7 +326,7 @@ ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
// Compute the true adjustment.
llvm::Value *Adj = RawAdj;
- if (IsARM)
+ if (UseARMMethodPtrABI)
Adj = Builder.CreateAShr(Adj, ptrdiff_1, "memptr.adj.shifted");
// Apply the adjustment and cast back to the original struct type
@@ -290,7 +341,7 @@ ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
// If the LSB in the function pointer is 1, the function pointer points to
// a virtual function.
llvm::Value *IsVirtual;
- if (IsARM)
+ if (UseARMMethodPtrABI)
IsVirtual = Builder.CreateAnd(RawAdj, ptrdiff_1);
else
IsVirtual = Builder.CreateAnd(FnAsInt, ptrdiff_1);
@@ -309,7 +360,8 @@ ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
// Apply the offset.
llvm::Value *VTableOffset = FnAsInt;
- if (!IsARM) VTableOffset = Builder.CreateSub(VTableOffset, ptrdiff_1);
+ if (!UseARMMethodPtrABI)
+ VTableOffset = Builder.CreateSub(VTableOffset, ptrdiff_1);
VTable = Builder.CreateGEP(VTable, VTableOffset);
// Load the virtual function to call.
@@ -419,7 +471,7 @@ ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
}
// The this-adjustment is left-shifted by 1 on ARM.
- if (IsARM) {
+ if (UseARMMethodPtrABI) {
uint64_t offset = cast<llvm::ConstantInt>(adj)->getZExtValue();
offset <<= 1;
adj = llvm::ConstantInt::get(adj->getType(), offset);
@@ -467,7 +519,7 @@ ItaniumCXXABI::EmitMemberPointerConversion(const CastExpr *E,
}
// The this-adjustment is left-shifted by 1 on ARM.
- if (IsARM) {
+ if (UseARMMethodPtrABI) {
uint64_t offset = cast<llvm::ConstantInt>(adj)->getZExtValue();
offset <<= 1;
adj = llvm::ConstantInt::get(adj->getType(), offset);
@@ -518,14 +570,14 @@ llvm::Constant *ItaniumCXXABI::BuildMemberPointer(const CXXMethodDecl *MD,
// Get the function pointer (or index if this is a virtual function).
llvm::Constant *MemPtr[2];
if (MD->isVirtual()) {
- uint64_t Index = CGM.getVTableContext().getMethodVTableIndex(MD);
+ uint64_t Index = CGM.getItaniumVTableContext().getMethodVTableIndex(MD);
const ASTContext &Context = getContext();
CharUnits PointerWidth =
Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
uint64_t VTableOffset = (Index * PointerWidth.getQuantity());
- if (IsARM) {
+ if (UseARMMethodPtrABI) {
// ARM C++ ABI 3.2.1:
// This ABI specifies that adj contains twice the this
// adjustment, plus 1 if the member function is virtual. The
@@ -559,7 +611,8 @@ llvm::Constant *ItaniumCXXABI::BuildMemberPointer(const CXXMethodDecl *MD,
llvm::Constant *addr = CGM.GetAddrOfFunction(MD, Ty);
MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, CGM.PtrDiffTy);
- MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy, (IsARM ? 2 : 1) *
+ MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy,
+ (UseARMMethodPtrABI ? 2 : 1) *
ThisAdjustment.getQuantity());
}
@@ -573,22 +626,7 @@ llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const APValue &MP,
if (!MPD)
return EmitNullMemberPointer(MPT);
- // Compute the this-adjustment.
- CharUnits ThisAdjustment = CharUnits::Zero();
- ArrayRef<const CXXRecordDecl*> Path = MP.getMemberPointerPath();
- bool DerivedMember = MP.isMemberPointerToDerivedMember();
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(MPD->getDeclContext());
- for (unsigned I = 0, N = Path.size(); I != N; ++I) {
- const CXXRecordDecl *Base = RD;
- const CXXRecordDecl *Derived = Path[I];
- if (DerivedMember)
- std::swap(Base, Derived);
- ThisAdjustment +=
- getContext().getASTRecordLayout(Derived).getBaseClassOffset(Base);
- RD = Path[I];
- }
- if (DerivedMember)
- ThisAdjustment = -ThisAdjustment;
+ CharUnits ThisAdjustment = getMemberPointerPathAdjustment(MP);
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD))
return BuildMemberPointer(MD, ThisAdjustment);
@@ -658,7 +696,7 @@ ItaniumCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
// Null member function pointers on ARM clear the low bit of Adj,
// so the zero condition has to check that neither low bit is set.
- if (IsARM) {
+ if (UseARMMethodPtrABI) {
llvm::Value *One = llvm::ConstantInt::get(LPtr->getType(), 1);
// Compute (l.adj | r.adj) & 1 and test it against zero.
@@ -698,7 +736,7 @@ ItaniumCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
// On ARM, a member function pointer is also non-null if the low bit of 'adj'
// (the virtual bit) is set.
- if (IsARM) {
+ if (UseARMMethodPtrABI) {
llvm::Constant *One = llvm::ConstantInt::get(Ptr->getType(), 1);
llvm::Value *Adj = Builder.CreateExtractValue(MemPtr, 1, "memptr.adj");
llvm::Value *VirtualBit = Builder.CreateAnd(Adj, One, "memptr.virtualbit");
@@ -735,6 +773,28 @@ llvm::Value *ItaniumCXXABI::adjustToCompleteObject(CodeGenFunction &CGF,
return CGF.Builder.CreateInBoundsGEP(ptr, offset);
}
+llvm::Value *
+ItaniumCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF,
+ llvm::Value *This,
+ const CXXRecordDecl *ClassDecl,
+ const CXXRecordDecl *BaseClassDecl) {
+ llvm::Value *VTablePtr = CGF.GetVTablePtr(This, CGM.Int8PtrTy);
+ CharUnits VBaseOffsetOffset =
+ CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(ClassDecl,
+ BaseClassDecl);
+
+ llvm::Value *VBaseOffsetPtr =
+ CGF.Builder.CreateConstGEP1_64(VTablePtr, VBaseOffsetOffset.getQuantity(),
+ "vbase.offset.ptr");
+ VBaseOffsetPtr = CGF.Builder.CreateBitCast(VBaseOffsetPtr,
+ CGM.PtrDiffTy->getPointerTo());
+
+ llvm::Value *VBaseOffset =
+ CGF.Builder.CreateLoad(VBaseOffsetPtr, "vbase.offset");
+
+ return VBaseOffset;
+}
+
/// The generic ABI passes 'this', plus a VTT if it's initializing a
/// base subobject.
void ItaniumCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,
@@ -743,20 +803,28 @@ void ItaniumCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,
SmallVectorImpl<CanQualType> &ArgTys) {
ASTContext &Context = getContext();
- // 'this' is already there.
+ // 'this' parameter is already there, as well as 'this' return if
+ // HasThisReturn(GlobalDecl(Ctor, Type)) is true
// Check if we need to add a VTT parameter (which has type void **).
if (Type == Ctor_Base && Ctor->getParent()->getNumVBases() != 0)
ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy));
}
-/// The ARM ABI does the same as the Itanium ABI, but returns 'this'.
-void ARMCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,
- CXXCtorType Type,
- CanQualType &ResTy,
- SmallVectorImpl<CanQualType> &ArgTys) {
- ItaniumCXXABI::BuildConstructorSignature(Ctor, Type, ResTy, ArgTys);
- ResTy = ArgTys[0];
+void ItaniumCXXABI::EmitCXXConstructors(const CXXConstructorDecl *D) {
+ // Just make sure we're in sync with TargetCXXABI.
+ assert(CGM.getTarget().getCXXABI().hasConstructorVariants());
+
+ // The constructor used for constructing this as a complete class;
+ // constucts the virtual bases, then calls the base constructor.
+ if (!D->getParent()->isAbstract()) {
+ // We don't need to emit the complete ctor if the class is abstract.
+ CGM.EmitGlobal(GlobalDecl(D, Ctor_Complete));
+ }
+
+ // The constructor used for constructing this as a base class;
+ // ignores virtual bases.
+ CGM.EmitGlobal(GlobalDecl(D, Ctor_Base));
}
/// The generic ABI passes 'this', plus a VTT if it's destroying a
@@ -767,23 +835,28 @@ void ItaniumCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor,
SmallVectorImpl<CanQualType> &ArgTys) {
ASTContext &Context = getContext();
- // 'this' is already there.
+ // 'this' parameter is already there, as well as 'this' return if
+ // HasThisReturn(GlobalDecl(Dtor, Type)) is true
// Check if we need to add a VTT parameter (which has type void **).
if (Type == Dtor_Base && Dtor->getParent()->getNumVBases() != 0)
ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy));
}
-/// The ARM ABI does the same as the Itanium ABI, but returns 'this'
-/// for non-deleting destructors.
-void ARMCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor,
- CXXDtorType Type,
- CanQualType &ResTy,
- SmallVectorImpl<CanQualType> &ArgTys) {
- ItaniumCXXABI::BuildDestructorSignature(Dtor, Type, ResTy, ArgTys);
+void ItaniumCXXABI::EmitCXXDestructors(const CXXDestructorDecl *D) {
+ // The destructor in a virtual table is always a 'deleting'
+ // destructor, which calls the complete destructor and then uses the
+ // appropriate operator delete.
+ if (D->isVirtual())
+ CGM.EmitGlobal(GlobalDecl(D, Dtor_Deleting));
+
+ // The destructor used for destructing this as a most-derived class;
+ // call the base destructor and then destructs any virtual bases.
+ CGM.EmitGlobal(GlobalDecl(D, Dtor_Complete));
- if (Type != Dtor_Deleting)
- ResTy = ArgTys[0];
+ // The destructor used for destructing this as a base class; ignores
+ // virtual bases.
+ CGM.EmitGlobal(GlobalDecl(D, Dtor_Base));
}
void ItaniumCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,
@@ -796,7 +869,7 @@ void ItaniumCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,
assert(MD->isInstance());
// Check if we need a VTT parameter as well.
- if (CodeGenVTables::needsVTTParameter(CGF.CurGD)) {
+ if (NeedsVTTParameter(CGF.CurGD)) {
ASTContext &Context = getContext();
// FIXME: avoid the fake decl
@@ -809,16 +882,6 @@ void ItaniumCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,
}
}
-void ARMCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,
- QualType &ResTy,
- FunctionArgList &Params) {
- ItaniumCXXABI::BuildInstanceFunctionParams(CGF, ResTy, Params);
-
- // Return 'this' from certain constructors and destructors.
- if (HasThisReturn(CGF.CurGD))
- ResTy = Params[0]->getType();
-}
-
void ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
/// Initialize the 'this' slot.
EmitThisParam(CGF);
@@ -829,21 +892,23 @@ void ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
= CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getVTTDecl(CGF)),
"vtt");
}
-}
-void ARMCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
- ItaniumCXXABI::EmitInstanceFunctionProlog(CGF);
-
- /// Initialize the return slot to 'this' at the start of the
- /// function.
+ /// If this is a function that the ABI specifies returns 'this', initialize
+ /// the return slot to 'this' at the start of the function.
+ ///
+ /// Unlike the setting of return types, this is done within the ABI
+ /// implementation instead of by clients of CGCXXABI because:
+ /// 1) getThisValue is currently protected
+ /// 2) in theory, an ABI could implement 'this' returns some other way;
+ /// HasThisReturn only specifies a contract, not the implementation
if (HasThisReturn(CGF.CurGD))
CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue);
}
-llvm::Value *ItaniumCXXABI::EmitConstructorCall(CodeGenFunction &CGF,
+void ItaniumCXXABI::EmitConstructorCall(CodeGenFunction &CGF,
const CXXConstructorDecl *D,
- CXXCtorType Type, bool ForVirtualBase,
- bool Delegating,
+ CXXCtorType Type,
+ bool ForVirtualBase, bool Delegating,
llvm::Value *This,
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd) {
@@ -853,26 +918,217 @@ llvm::Value *ItaniumCXXABI::EmitConstructorCall(CodeGenFunction &CGF,
llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Type);
// FIXME: Provide a source location here.
- CGF.EmitCXXMemberCall(D, SourceLocation(), Callee, ReturnValueSlot(), This,
- VTT, VTTTy, ArgBeg, ArgEnd);
- return Callee;
+ CGF.EmitCXXMemberCall(D, SourceLocation(), Callee, ReturnValueSlot(),
+ This, VTT, VTTTy, ArgBeg, ArgEnd);
+}
+
+void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
+ const CXXRecordDecl *RD) {
+ llvm::GlobalVariable *VTable = getAddrOfVTable(RD, CharUnits());
+ if (VTable->hasInitializer())
+ return;
+
+ ItaniumVTableContext &VTContext = CGM.getItaniumVTableContext();
+ const VTableLayout &VTLayout = VTContext.getVTableLayout(RD);
+ llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD);
+
+ // Create and set the initializer.
+ llvm::Constant *Init = CGVT.CreateVTableInitializer(
+ RD, VTLayout.vtable_component_begin(), VTLayout.getNumVTableComponents(),
+ VTLayout.vtable_thunk_begin(), VTLayout.getNumVTableThunks());
+ VTable->setInitializer(Init);
+
+ // Set the correct linkage.
+ VTable->setLinkage(Linkage);
+
+ // Set the right visibility.
+ CGM.setTypeVisibility(VTable, RD, CodeGenModule::TVK_ForVTable);
+
+ // If this is the magic class __cxxabiv1::__fundamental_type_info,
+ // we will emit the typeinfo for the fundamental types. This is the
+ // same behaviour as GCC.
+ const DeclContext *DC = RD->getDeclContext();
+ if (RD->getIdentifier() &&
+ RD->getIdentifier()->isStr("__fundamental_type_info") &&
+ isa<NamespaceDecl>(DC) && cast<NamespaceDecl>(DC)->getIdentifier() &&
+ cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__cxxabiv1") &&
+ DC->getParent()->isTranslationUnit())
+ CGM.EmitFundamentalRTTIDescriptors();
+}
+
+llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructor(
+ CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base,
+ const CXXRecordDecl *NearestVBase, bool &NeedsVirtualOffset) {
+ bool NeedsVTTParam = CGM.getCXXABI().NeedsVTTParameter(CGF.CurGD);
+ NeedsVirtualOffset = (NeedsVTTParam && NearestVBase);
+
+ llvm::Value *VTableAddressPoint;
+ if (NeedsVTTParam && (Base.getBase()->getNumVBases() || NearestVBase)) {
+ // Get the secondary vpointer index.
+ uint64_t VirtualPointerIndex =
+ CGM.getVTables().getSecondaryVirtualPointerIndex(VTableClass, Base);
+
+ /// Load the VTT.
+ llvm::Value *VTT = CGF.LoadCXXVTT();
+ if (VirtualPointerIndex)
+ VTT = CGF.Builder.CreateConstInBoundsGEP1_64(VTT, VirtualPointerIndex);
+
+ // And load the address point from the VTT.
+ VTableAddressPoint = CGF.Builder.CreateLoad(VTT);
+ } else {
+ llvm::Constant *VTable =
+ CGM.getCXXABI().getAddrOfVTable(VTableClass, CharUnits());
+ uint64_t AddressPoint = CGM.getItaniumVTableContext()
+ .getVTableLayout(VTableClass)
+ .getAddressPoint(Base);
+ VTableAddressPoint =
+ CGF.Builder.CreateConstInBoundsGEP2_64(VTable, 0, AddressPoint);
+ }
+
+ return VTableAddressPoint;
}
-RValue ItaniumCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,
- const CXXDestructorDecl *Dtor,
- CXXDtorType DtorType,
- SourceLocation CallLoc,
- ReturnValueSlot ReturnValue,
- llvm::Value *This) {
+llvm::Constant *ItaniumCXXABI::getVTableAddressPointForConstExpr(
+ BaseSubobject Base, const CXXRecordDecl *VTableClass) {
+ llvm::Constant *VTable = getAddrOfVTable(VTableClass, CharUnits());
+
+ // Find the appropriate vtable within the vtable group.
+ uint64_t AddressPoint = CGM.getItaniumVTableContext()
+ .getVTableLayout(VTableClass)
+ .getAddressPoint(Base);
+ llvm::Value *Indices[] = {
+ llvm::ConstantInt::get(CGM.Int64Ty, 0),
+ llvm::ConstantInt::get(CGM.Int64Ty, AddressPoint)
+ };
+
+ return llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Indices);
+}
+
+llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
+ CharUnits VPtrOffset) {
+ assert(VPtrOffset.isZero() && "Itanium ABI only supports zero vptr offsets");
+
+ llvm::GlobalVariable *&VTable = VTables[RD];
+ if (VTable)
+ return VTable;
+
+ // Queue up this v-table for possible deferred emission.
+ CGM.addDeferredVTable(RD);
+
+ SmallString<256> OutName;
+ llvm::raw_svector_ostream Out(OutName);
+ getMangleContext().mangleCXXVTable(RD, Out);
+ Out.flush();
+ StringRef Name = OutName.str();
+
+ ItaniumVTableContext &VTContext = CGM.getItaniumVTableContext();
+ llvm::ArrayType *ArrayType = llvm::ArrayType::get(
+ CGM.Int8PtrTy, VTContext.getVTableLayout(RD).getNumVTableComponents());
+
+ VTable = CGM.CreateOrReplaceCXXRuntimeVariable(
+ Name, ArrayType, llvm::GlobalValue::ExternalLinkage);
+ VTable->setUnnamedAddr(true);
+ return VTable;
+}
+
+llvm::Value *ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
+ GlobalDecl GD,
+ llvm::Value *This,
+ llvm::Type *Ty) {
+ GD = GD.getCanonicalDecl();
+ Ty = Ty->getPointerTo()->getPointerTo();
+ llvm::Value *VTable = CGF.GetVTablePtr(This, Ty);
+
+ uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD);
+ llvm::Value *VFuncPtr =
+ CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfn");
+ return CGF.Builder.CreateLoad(VFuncPtr);
+}
+
+void ItaniumCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,
+ const CXXDestructorDecl *Dtor,
+ CXXDtorType DtorType,
+ SourceLocation CallLoc,
+ llvm::Value *This) {
assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete);
const CGFunctionInfo *FInfo
= &CGM.getTypes().arrangeCXXDestructor(Dtor, DtorType);
llvm::Type *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);
- llvm::Value *Callee = CGF.BuildVirtualCall(Dtor, DtorType, This, Ty);
+ llvm::Value *Callee =
+ getVirtualFunctionPointer(CGF, GlobalDecl(Dtor, DtorType), This, Ty);
- return CGF.EmitCXXMemberCall(Dtor, CallLoc, Callee, ReturnValue, This,
- /*ImplicitParam=*/0, QualType(), 0, 0);
+ CGF.EmitCXXMemberCall(Dtor, CallLoc, Callee, ReturnValueSlot(), This,
+ /*ImplicitParam=*/0, QualType(), 0, 0);
+}
+
+void ItaniumCXXABI::emitVirtualInheritanceTables(const CXXRecordDecl *RD) {
+ CodeGenVTables &VTables = CGM.getVTables();
+ llvm::GlobalVariable *VTT = VTables.GetAddrOfVTT(RD);
+ VTables.EmitVTTDefinition(VTT, CGM.getVTableLinkage(RD), RD);
+}
+
+static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF,
+ llvm::Value *Ptr,
+ int64_t NonVirtualAdjustment,
+ int64_t VirtualAdjustment,
+ bool IsReturnAdjustment) {
+ if (!NonVirtualAdjustment && !VirtualAdjustment)
+ return Ptr;
+
+ llvm::Type *Int8PtrTy = CGF.Int8PtrTy;
+ llvm::Value *V = CGF.Builder.CreateBitCast(Ptr, Int8PtrTy);
+
+ if (NonVirtualAdjustment && !IsReturnAdjustment) {
+ // Perform the non-virtual adjustment for a base-to-derived cast.
+ V = CGF.Builder.CreateConstInBoundsGEP1_64(V, NonVirtualAdjustment);
+ }
+
+ if (VirtualAdjustment) {
+ llvm::Type *PtrDiffTy =
+ CGF.ConvertType(CGF.getContext().getPointerDiffType());
+
+ // Perform the virtual adjustment.
+ llvm::Value *VTablePtrPtr =
+ CGF.Builder.CreateBitCast(V, Int8PtrTy->getPointerTo());
+
+ llvm::Value *VTablePtr = CGF.Builder.CreateLoad(VTablePtrPtr);
+
+ llvm::Value *OffsetPtr =
+ CGF.Builder.CreateConstInBoundsGEP1_64(VTablePtr, VirtualAdjustment);
+
+ OffsetPtr = CGF.Builder.CreateBitCast(OffsetPtr, PtrDiffTy->getPointerTo());
+
+ // Load the adjustment offset from the vtable.
+ llvm::Value *Offset = CGF.Builder.CreateLoad(OffsetPtr);
+
+ // Adjust our pointer.
+ V = CGF.Builder.CreateInBoundsGEP(V, Offset);
+ }
+
+ if (NonVirtualAdjustment && IsReturnAdjustment) {
+ // Perform the non-virtual adjustment for a derived-to-base cast.
+ V = CGF.Builder.CreateConstInBoundsGEP1_64(V, NonVirtualAdjustment);
+ }
+
+ // Cast back to the original type.
+ return CGF.Builder.CreateBitCast(V, Ptr->getType());
+}
+
+llvm::Value *ItaniumCXXABI::performThisAdjustment(CodeGenFunction &CGF,
+ llvm::Value *This,
+ const ThisAdjustment &TA) {
+ return performTypeAdjustment(CGF, This, TA.NonVirtual,
+ TA.Virtual.Itanium.VCallOffsetOffset,
+ /*IsReturnAdjustment=*/false);
+}
+
+llvm::Value *
+ItaniumCXXABI::performReturnAdjustment(CodeGenFunction &CGF, llvm::Value *Ret,
+ const ReturnAdjustment &RA) {
+ return performTypeAdjustment(CGF, Ret, RA.NonVirtual,
+ RA.Virtual.Itanium.VBaseOffsetOffset,
+ /*IsReturnAdjustment=*/true);
}
void ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,
@@ -1079,7 +1335,7 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
} else {
// Guard variables are 64 bits in the generic ABI and size width on ARM
// (i.e. 32-bit on AArch32, 64-bit on AArch64).
- guardTy = (IsARM ? CGF.SizeTy : CGF.Int64Ty);
+ guardTy = (UseARMGuardVarABI ? CGF.SizeTy : CGF.Int64Ty);
}
llvm::PointerType *guardPtrTy = guardTy->getPointerTo();
@@ -1091,7 +1347,7 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
SmallString<256> guardName;
{
llvm::raw_svector_ostream out(guardName);
- getMangleContext().mangleItaniumGuardVariable(&D, out);
+ getMangleContext().mangleStaticGuardVariable(&D, out);
out.flush();
}
@@ -1122,7 +1378,7 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
// if (__cxa_guard_acquire(&obj_guard))
// ...
// }
- if (IsARM && !useInt8GuardVariable) {
+ if (UseARMGuardVarABI && !useInt8GuardVariable) {
llvm::Value *V = Builder.CreateLoad(guard);
llvm::Value *Test1 = llvm::ConstantInt::get(guardTy, 1);
V = Builder.CreateAnd(V, Test1);
@@ -1259,7 +1515,7 @@ void ItaniumCXXABI::registerGlobalDtor(CodeGenFunction &CGF,
return CGM.AddCXXDtorEntry(dtor, addr);
}
- CGF.registerGlobalDtorWithAtExit(dtor, addr);
+ CGF.registerGlobalDtorWithAtExit(D, dtor, addr);
}
/// Get the appropriate linkage for the wrapper function. This is essentially
@@ -1396,3 +1652,23 @@ LValue ItaniumCXXABI::EmitThreadLocalDeclRefExpr(CodeGenFunction &CGF,
// FIXME: need setObjCGCLValueClass?
return LV;
}
+
+/// Return whether the given global decl needs a VTT parameter, which it does
+/// if it's a base constructor or destructor with virtual bases.
+bool ItaniumCXXABI::NeedsVTTParameter(GlobalDecl GD) {
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+
+ // We don't have any virtual bases, just return early.
+ if (!MD->getParent()->getNumVBases())
+ return false;
+
+ // Check if we have a base constructor.
+ if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base)
+ return true;
+
+ // Check if we have a base destructor.
+ if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
+ return true;
+
+ return false;
+}
diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp
index f5242ea..7318fe7 100644
--- a/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -16,8 +16,12 @@
#include "CGCXXABI.h"
#include "CodeGenModule.h"
+#include "CGVTables.h"
+#include "MicrosoftVBTables.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/VTableBuilder.h"
+#include "llvm/ADT/StringSet.h"
using namespace clang;
using namespace CodeGen;
@@ -28,13 +32,15 @@ class MicrosoftCXXABI : public CGCXXABI {
public:
MicrosoftCXXABI(CodeGenModule &CGM) : CGCXXABI(CGM) {}
+ bool HasThisReturn(GlobalDecl GD) const;
+
bool isReturnTypeIndirect(const CXXRecordDecl *RD) const {
// Structures that are not C++03 PODs are always indirect.
return !RD->isPOD();
}
RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const {
- if (RD->hasNonTrivialCopyConstructor())
+ if (RD->hasNonTrivialCopyConstructor() || RD->hasNonTrivialDestructor())
return RAA_DirectInMemory;
return RAA_Default;
}
@@ -44,42 +50,153 @@ public:
// arbitrary.
StringRef GetDeletedVirtualCallName() { return "_purecall"; }
+ bool isInlineInitializedStaticDataMemberLinkOnce() { return true; }
+
llvm::Value *adjustToCompleteObject(CodeGenFunction &CGF,
llvm::Value *ptr,
QualType type);
+ llvm::Value *GetVirtualBaseClassOffset(CodeGenFunction &CGF,
+ llvm::Value *This,
+ const CXXRecordDecl *ClassDecl,
+ const CXXRecordDecl *BaseClassDecl);
+
void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
CXXCtorType Type,
CanQualType &ResTy,
SmallVectorImpl<CanQualType> &ArgTys);
- llvm::BasicBlock *EmitCtorCompleteObjectHandler(CodeGenFunction &CGF);
+ llvm::BasicBlock *EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
+ const CXXRecordDecl *RD);
+
+ void initializeHiddenVirtualInheritanceMembers(CodeGenFunction &CGF,
+ const CXXRecordDecl *RD);
+
+ void EmitCXXConstructors(const CXXConstructorDecl *D);
+
+ // Background on MSVC destructors
+ // ==============================
+ //
+ // Both Itanium and MSVC ABIs have destructor variants. The variant names
+ // roughly correspond in the following way:
+ // Itanium Microsoft
+ // Base -> no name, just ~Class
+ // Complete -> vbase destructor
+ // Deleting -> scalar deleting destructor
+ // vector deleting destructor
+ //
+ // The base and complete destructors are the same as in Itanium, although the
+ // complete destructor does not accept a VTT parameter when there are virtual
+ // bases. A separate mechanism involving vtordisps is used to ensure that
+ // virtual methods of destroyed subobjects are not called.
+ //
+ // The deleting destructors accept an i32 bitfield as a second parameter. Bit
+ // 1 indicates if the memory should be deleted. Bit 2 indicates if the this
+ // pointer points to an array. The scalar deleting destructor assumes that
+ // bit 2 is zero, and therefore does not contain a loop.
+ //
+ // For virtual destructors, only one entry is reserved in the vftable, and it
+ // always points to the vector deleting destructor. The vector deleting
+ // destructor is the most general, so it can be used to destroy objects in
+ // place, delete single heap objects, or delete arrays.
+ //
+ // A TU defining a non-inline destructor is only guaranteed to emit a base
+ // destructor, and all of the other variants are emitted on an as-needed basis
+ // in COMDATs. Because a non-base destructor can be emitted in a TU that
+ // lacks a definition for the destructor, non-base destructors must always
+ // delegate to or alias the base destructor.
- void BuildDestructorSignature(const CXXDestructorDecl *Ctor,
+ void BuildDestructorSignature(const CXXDestructorDecl *Dtor,
CXXDtorType Type,
CanQualType &ResTy,
SmallVectorImpl<CanQualType> &ArgTys);
+ /// Non-base dtors should be emitted as delegating thunks in this ABI.
+ bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor,
+ CXXDtorType DT) const {
+ return DT != Dtor_Base;
+ }
+
+ void EmitCXXDestructors(const CXXDestructorDecl *D);
+
+ const CXXRecordDecl *getThisArgumentTypeForMethod(const CXXMethodDecl *MD) {
+ MD = MD->getCanonicalDecl();
+ if (MD->isVirtual() && !isa<CXXDestructorDecl>(MD)) {
+ MicrosoftVTableContext::MethodVFTableLocation ML =
+ CGM.getMicrosoftVTableContext().getMethodVFTableLocation(MD);
+ // The vbases might be ordered differently in the final overrider object
+ // and the complete object, so the "this" argument may sometimes point to
+ // memory that has no particular type (e.g. past the complete object).
+ // In this case, we just use a generic pointer type.
+ // FIXME: might want to have a more precise type in the non-virtual
+ // multiple inheritance case.
+ if (ML.VBase || !ML.VFPtrOffset.isZero())
+ return 0;
+ }
+ return MD->getParent();
+ }
+
+ llvm::Value *adjustThisArgumentForVirtualCall(CodeGenFunction &CGF,
+ GlobalDecl GD,
+ llvm::Value *This);
+
void BuildInstanceFunctionParams(CodeGenFunction &CGF,
QualType &ResTy,
FunctionArgList &Params);
+ llvm::Value *adjustThisParameterInVirtualFunctionPrologue(
+ CodeGenFunction &CGF, GlobalDecl GD, llvm::Value *This);
+
void EmitInstanceFunctionProlog(CodeGenFunction &CGF);
- llvm::Value *EmitConstructorCall(CodeGenFunction &CGF,
- const CXXConstructorDecl *D,
- CXXCtorType Type, bool ForVirtualBase,
- bool Delegating,
+ void EmitConstructorCall(CodeGenFunction &CGF,
+ const CXXConstructorDecl *D, CXXCtorType Type,
+ bool ForVirtualBase, bool Delegating,
llvm::Value *This,
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd);
- RValue EmitVirtualDestructorCall(CodeGenFunction &CGF,
- const CXXDestructorDecl *Dtor,
- CXXDtorType DtorType,
- SourceLocation CallLoc,
- ReturnValueSlot ReturnValue,
- llvm::Value *This);
+ void emitVTableDefinitions(CodeGenVTables &CGVT, const CXXRecordDecl *RD);
+
+ llvm::Value *getVTableAddressPointInStructor(
+ CodeGenFunction &CGF, const CXXRecordDecl *VTableClass,
+ BaseSubobject Base, const CXXRecordDecl *NearestVBase,
+ bool &NeedsVirtualOffset);
+
+ llvm::Constant *
+ getVTableAddressPointForConstExpr(BaseSubobject Base,
+ const CXXRecordDecl *VTableClass);
+
+ llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD,
+ CharUnits VPtrOffset);
+
+ llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD,
+ llvm::Value *This, llvm::Type *Ty);
+
+ void EmitVirtualDestructorCall(CodeGenFunction &CGF,
+ const CXXDestructorDecl *Dtor,
+ CXXDtorType DtorType, SourceLocation CallLoc,
+ llvm::Value *This);
+
+ void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF, GlobalDecl GD,
+ CallArgList &CallArgs) {
+ assert(GD.getDtorType() == Dtor_Deleting &&
+ "Only deleting destructor thunks are available in this ABI");
+ CallArgs.add(RValue::get(getStructorImplicitParamValue(CGF)),
+ CGM.getContext().IntTy);
+ }
+
+ void emitVirtualInheritanceTables(const CXXRecordDecl *RD);
+
+ void setThunkLinkage(llvm::Function *Thunk, bool ForVTable) {
+ Thunk->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
+ }
+
+ llvm::Value *performThisAdjustment(CodeGenFunction &CGF, llvm::Value *This,
+ const ThisAdjustment &TA);
+
+ llvm::Value *performReturnAdjustment(CodeGenFunction &CGF, llvm::Value *Ret,
+ const ReturnAdjustment &RA);
void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
llvm::GlobalVariable *DeclPtr,
@@ -119,9 +236,12 @@ public:
llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF,
llvm::Value *allocPtr,
CharUnits cookieSize);
- static bool needThisReturn(GlobalDecl GD);
private:
+ MicrosoftMangleContext &getMangleContext() {
+ return cast<MicrosoftMangleContext>(CodeGen::CGCXXABI::getMangleContext());
+ }
+
llvm::Constant *getZeroInt() {
return llvm::ConstantInt::get(CGM.IntTy, 0);
}
@@ -130,10 +250,44 @@ private:
return llvm::Constant::getAllOnesValue(CGM.IntTy);
}
+ llvm::Constant *getConstantOrZeroInt(llvm::Constant *C) {
+ return C ? C : getZeroInt();
+ }
+
+ llvm::Value *getValueOrZeroInt(llvm::Value *C) {
+ return C ? C : getZeroInt();
+ }
+
void
GetNullMemberPointerFields(const MemberPointerType *MPT,
llvm::SmallVectorImpl<llvm::Constant *> &fields);
+ /// \brief Finds the offset from the base of RD to the vbptr it uses, even if
+ /// it is reusing a vbptr from a non-virtual base. RD must have morally
+ /// virtual bases.
+ CharUnits GetVBPtrOffsetFromBases(const CXXRecordDecl *RD);
+
+ /// \brief Shared code for virtual base adjustment. Returns the offset from
+ /// the vbptr to the virtual base. Optionally returns the address of the
+ /// vbptr itself.
+ llvm::Value *GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF,
+ llvm::Value *Base,
+ llvm::Value *VBPtrOffset,
+ llvm::Value *VBTableOffset,
+ llvm::Value **VBPtr = 0);
+
+ llvm::Value *GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF,
+ llvm::Value *Base,
+ int32_t VBPtrOffset,
+ int32_t VBTableOffset,
+ llvm::Value **VBPtr = 0) {
+ llvm::Value *VBPOffset = llvm::ConstantInt::get(CGM.IntTy, VBPtrOffset),
+ *VBTOffset = llvm::ConstantInt::get(CGM.IntTy, VBTableOffset);
+ return GetVBaseOffsetFromVBPtr(CGF, Base, VBPOffset, VBTOffset, VBPtr);
+ }
+
+ /// \brief Performs a full virtual base adjustment. Used to dereference
+ /// pointers to members of virtual bases.
llvm::Value *AdjustVirtualBase(CodeGenFunction &CGF, const CXXRecordDecl *RD,
llvm::Value *Base,
llvm::Value *VirtualBaseAdjustmentOffset,
@@ -143,7 +297,25 @@ private:
/// function member pointers.
llvm::Constant *EmitFullMemberPointer(llvm::Constant *FirstField,
bool IsMemberFunction,
- const CXXRecordDecl *RD);
+ const CXXRecordDecl *RD,
+ CharUnits NonVirtualBaseAdjustment);
+
+ llvm::Constant *BuildMemberPointer(const CXXRecordDecl *RD,
+ const CXXMethodDecl *MD,
+ CharUnits NonVirtualBaseAdjustment);
+
+ bool MemberPointerConstantIsNull(const MemberPointerType *MPT,
+ llvm::Constant *MP);
+
+ /// \brief - Initialize all vbptrs of 'this' with RD as the complete type.
+ void EmitVBPtrStores(CodeGenFunction &CGF, const CXXRecordDecl *RD);
+
+ /// \brief Caching wrapper around VBTableBuilder::enumerateVBTables().
+ const VBTableVector &EnumerateVBTables(const CXXRecordDecl *RD);
+
+ /// \brief Generate a thunk for calling a virtual member function MD.
+ llvm::Function *EmitVirtualMemPtrThunk(const CXXMethodDecl *MD,
+ StringRef ThunkName);
public:
virtual llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT);
@@ -172,12 +344,43 @@ public:
llvm::Value *MemPtr,
const MemberPointerType *MPT);
+ virtual llvm::Value *EmitMemberPointerConversion(CodeGenFunction &CGF,
+ const CastExpr *E,
+ llvm::Value *Src);
+
+ virtual llvm::Constant *EmitMemberPointerConversion(const CastExpr *E,
+ llvm::Constant *Src);
+
virtual llvm::Value *
EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
llvm::Value *&This,
llvm::Value *MemPtr,
const MemberPointerType *MPT);
+private:
+ typedef std::pair<const CXXRecordDecl *, CharUnits> VFTableIdTy;
+ typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalVariable *> VFTablesMapTy;
+ /// \brief All the vftables that have been referenced.
+ VFTablesMapTy VFTablesMap;
+
+ /// \brief This set holds the record decls we've deferred vtable emission for.
+ llvm::SmallPtrSet<const CXXRecordDecl *, 4> DeferredVFTables;
+
+
+ /// \brief All the vbtables which have been referenced.
+ llvm::DenseMap<const CXXRecordDecl *, VBTableVector> VBTablesMap;
+
+ /// Info on the global variable used to guard initialization of static locals.
+ /// The BitIndex field is only used for externally invisible declarations.
+ struct GuardInfo {
+ GuardInfo() : Guard(0), BitIndex(0) {}
+ llvm::GlobalVariable *Guard;
+ unsigned BitIndex;
+ };
+
+ /// Map from DeclContext to the current guard variable. We assume that the
+ /// AST is visited in source code order.
+ llvm::DenseMap<const DeclContext *, GuardInfo> GuardVariableMap;
};
}
@@ -189,19 +392,65 @@ llvm::Value *MicrosoftCXXABI::adjustToCompleteObject(CodeGenFunction &CGF,
return ptr;
}
-bool MicrosoftCXXABI::needThisReturn(GlobalDecl GD) {
- const CXXMethodDecl* MD = cast<CXXMethodDecl>(GD.getDecl());
- return isa<CXXConstructorDecl>(MD);
+/// \brief Finds the first non-virtual base of RD that has virtual bases. If RD
+/// doesn't have a vbptr, it will reuse the vbptr of the returned class.
+static const CXXRecordDecl *FindFirstNVBaseWithVBases(const CXXRecordDecl *RD) {
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ const CXXRecordDecl *Base = I->getType()->getAsCXXRecordDecl();
+ if (!I->isVirtual() && Base->getNumVBases() > 0)
+ return Base;
+ }
+ llvm_unreachable("RD must have an nv base with vbases");
+}
+
+CharUnits MicrosoftCXXABI::GetVBPtrOffsetFromBases(const CXXRecordDecl *RD) {
+ assert(RD->getNumVBases());
+ CharUnits Total = CharUnits::Zero();
+ while (RD) {
+ const ASTRecordLayout &RDLayout = getContext().getASTRecordLayout(RD);
+ CharUnits VBPtrOffset = RDLayout.getVBPtrOffset();
+ // -1 is the sentinel for no vbptr.
+ if (VBPtrOffset != CharUnits::fromQuantity(-1)) {
+ Total += VBPtrOffset;
+ break;
+ }
+ RD = FindFirstNVBaseWithVBases(RD);
+ Total += RDLayout.getBaseClassOffset(RD);
+ }
+ return Total;
+}
+
+llvm::Value *
+MicrosoftCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF,
+ llvm::Value *This,
+ const CXXRecordDecl *ClassDecl,
+ const CXXRecordDecl *BaseClassDecl) {
+ int64_t VBPtrChars = GetVBPtrOffsetFromBases(ClassDecl).getQuantity();
+ llvm::Value *VBPtrOffset = llvm::ConstantInt::get(CGM.PtrDiffTy, VBPtrChars);
+ CharUnits IntSize = getContext().getTypeSizeInChars(getContext().IntTy);
+ CharUnits VBTableChars =
+ IntSize *
+ CGM.getMicrosoftVTableContext().getVBTableIndex(ClassDecl, BaseClassDecl);
+ llvm::Value *VBTableOffset =
+ llvm::ConstantInt::get(CGM.IntTy, VBTableChars.getQuantity());
+
+ llvm::Value *VBPtrToNewBase =
+ GetVBaseOffsetFromVBPtr(CGF, This, VBPtrOffset, VBTableOffset);
+ VBPtrToNewBase =
+ CGF.Builder.CreateSExtOrBitCast(VBPtrToNewBase, CGM.PtrDiffTy);
+ return CGF.Builder.CreateNSWAdd(VBPtrOffset, VBPtrToNewBase);
+}
+
+bool MicrosoftCXXABI::HasThisReturn(GlobalDecl GD) const {
+ return isa<CXXConstructorDecl>(GD.getDecl());
}
void MicrosoftCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,
CXXCtorType Type,
CanQualType &ResTy,
SmallVectorImpl<CanQualType> &ArgTys) {
- // 'this' is already in place
-
- // Ctor returns this ptr
- ResTy = ArgTys[0];
+ // 'this' parameter and 'this' return are already in place
const CXXRecordDecl *Class = Ctor->getParent();
if (Class->getNumVBases()) {
@@ -210,13 +459,14 @@ void MicrosoftCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,
}
}
-llvm::BasicBlock *MicrosoftCXXABI::EmitCtorCompleteObjectHandler(
- CodeGenFunction &CGF) {
+llvm::BasicBlock *
+MicrosoftCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
+ const CXXRecordDecl *RD) {
llvm::Value *IsMostDerivedClass = getStructorImplicitParamValue(CGF);
assert(IsMostDerivedClass &&
"ctor for a class with virtual bases must have an implicit parameter");
- llvm::Value *IsCompleteObject
- = CGF.Builder.CreateIsNotNull(IsMostDerivedClass, "is_complete_object");
+ llvm::Value *IsCompleteObject =
+ CGF.Builder.CreateIsNotNull(IsMostDerivedClass, "is_complete_object");
llvm::BasicBlock *CallVbaseCtorsBB = CGF.createBasicBlock("ctor.init_vbases");
llvm::BasicBlock *SkipVbaseCtorsBB = CGF.createBasicBlock("ctor.skip_vbases");
@@ -224,24 +474,200 @@ llvm::BasicBlock *MicrosoftCXXABI::EmitCtorCompleteObjectHandler(
CallVbaseCtorsBB, SkipVbaseCtorsBB);
CGF.EmitBlock(CallVbaseCtorsBB);
- // FIXME: emit vbtables somewhere around here.
+
+ // Fill in the vbtable pointers here.
+ EmitVBPtrStores(CGF, RD);
// CGF will put the base ctor calls in this basic block for us later.
return SkipVbaseCtorsBB;
}
+void MicrosoftCXXABI::initializeHiddenVirtualInheritanceMembers(
+ CodeGenFunction &CGF, const CXXRecordDecl *RD) {
+ // In most cases, an override for a vbase virtual method can adjust
+ // the "this" parameter by applying a constant offset.
+ // However, this is not enough while a constructor or a destructor of some
+ // class X is being executed if all the following conditions are met:
+ // - X has virtual bases, (1)
+ // - X overrides a virtual method M of a vbase Y, (2)
+ // - X itself is a vbase of the most derived class.
+ //
+ // If (1) and (2) are true, the vtorDisp for vbase Y is a hidden member of X
+ // which holds the extra amount of "this" adjustment we must do when we use
+ // the X vftables (i.e. during X ctor or dtor).
+ // Outside the ctors and dtors, the values of vtorDisps are zero.
+
+ const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
+ typedef ASTRecordLayout::VBaseOffsetsMapTy VBOffsets;
+ const VBOffsets &VBaseMap = Layout.getVBaseOffsetsMap();
+ CGBuilderTy &Builder = CGF.Builder;
+
+ unsigned AS =
+ cast<llvm::PointerType>(getThisValue(CGF)->getType())->getAddressSpace();
+ llvm::Value *Int8This = 0; // Initialize lazily.
+
+ for (VBOffsets::const_iterator I = VBaseMap.begin(), E = VBaseMap.end();
+ I != E; ++I) {
+ if (!I->second.hasVtorDisp())
+ continue;
+
+ llvm::Value *VBaseOffset =
+ GetVirtualBaseClassOffset(CGF, getThisValue(CGF), RD, I->first);
+ // FIXME: it doesn't look right that we SExt in GetVirtualBaseClassOffset()
+ // just to Trunc back immediately.
+ VBaseOffset = Builder.CreateTruncOrBitCast(VBaseOffset, CGF.Int32Ty);
+ uint64_t ConstantVBaseOffset =
+ Layout.getVBaseClassOffset(I->first).getQuantity();
+
+ // vtorDisp_for_vbase = vbptr[vbase_idx] - offsetof(RD, vbase).
+ llvm::Value *VtorDispValue = Builder.CreateSub(
+ VBaseOffset, llvm::ConstantInt::get(CGM.Int32Ty, ConstantVBaseOffset),
+ "vtordisp.value");
+
+ if (!Int8This)
+ Int8This = Builder.CreateBitCast(getThisValue(CGF),
+ CGF.Int8Ty->getPointerTo(AS));
+ llvm::Value *VtorDispPtr = Builder.CreateInBoundsGEP(Int8This, VBaseOffset);
+ // vtorDisp is always the 32-bits before the vbase in the class layout.
+ VtorDispPtr = Builder.CreateConstGEP1_32(VtorDispPtr, -4);
+ VtorDispPtr = Builder.CreateBitCast(
+ VtorDispPtr, CGF.Int32Ty->getPointerTo(AS), "vtordisp.ptr");
+
+ Builder.CreateStore(VtorDispValue, VtorDispPtr);
+ }
+}
+
+void MicrosoftCXXABI::EmitCXXConstructors(const CXXConstructorDecl *D) {
+ // There's only one constructor type in this ABI.
+ CGM.EmitGlobal(GlobalDecl(D, Ctor_Complete));
+}
+
+void MicrosoftCXXABI::EmitVBPtrStores(CodeGenFunction &CGF,
+ const CXXRecordDecl *RD) {
+ llvm::Value *ThisInt8Ptr =
+ CGF.Builder.CreateBitCast(getThisValue(CGF), CGM.Int8PtrTy, "this.int8");
+
+ const VBTableVector &VBTables = EnumerateVBTables(RD);
+ for (VBTableVector::const_iterator I = VBTables.begin(), E = VBTables.end();
+ I != E; ++I) {
+ const ASTRecordLayout &SubobjectLayout =
+ CGM.getContext().getASTRecordLayout(I->VBPtrSubobject.getBase());
+ uint64_t Offs = (I->VBPtrSubobject.getBaseOffset() +
+ SubobjectLayout.getVBPtrOffset()).getQuantity();
+ llvm::Value *VBPtr =
+ CGF.Builder.CreateConstInBoundsGEP1_64(ThisInt8Ptr, Offs);
+ VBPtr = CGF.Builder.CreateBitCast(VBPtr, I->GV->getType()->getPointerTo(0),
+ "vbptr." + I->ReusingBase->getName());
+ CGF.Builder.CreateStore(I->GV, VBPtr);
+ }
+}
+
void MicrosoftCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor,
CXXDtorType Type,
CanQualType &ResTy,
SmallVectorImpl<CanQualType> &ArgTys) {
// 'this' is already in place
+
// TODO: 'for base' flag
if (Type == Dtor_Deleting) {
- // The scalar deleting destructor takes an implicit bool parameter.
- ArgTys.push_back(CGM.getContext().BoolTy);
+ // The scalar deleting destructor takes an implicit int parameter.
+ ArgTys.push_back(CGM.getContext().IntTy);
+ }
+}
+
+void MicrosoftCXXABI::EmitCXXDestructors(const CXXDestructorDecl *D) {
+ // The TU defining a dtor is only guaranteed to emit a base destructor. All
+ // other destructor variants are delegating thunks.
+ CGM.EmitGlobal(GlobalDecl(D, Dtor_Base));
+}
+
+llvm::Value *MicrosoftCXXABI::adjustThisArgumentForVirtualCall(
+ CodeGenFunction &CGF, GlobalDecl GD, llvm::Value *This) {
+ GD = GD.getCanonicalDecl();
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+ // FIXME: consider splitting the vdtor vs regular method code into two
+ // functions.
+
+ GlobalDecl LookupGD = GD;
+ if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
+ // Complete dtors take a pointer to the complete object,
+ // thus don't need adjustment.
+ if (GD.getDtorType() == Dtor_Complete)
+ return This;
+
+ // There's only Dtor_Deleting in vftable but it shares the this adjustment
+ // with the base one, so look up the deleting one instead.
+ LookupGD = GlobalDecl(DD, Dtor_Deleting);
+ }
+ MicrosoftVTableContext::MethodVFTableLocation ML =
+ CGM.getMicrosoftVTableContext().getMethodVFTableLocation(LookupGD);
+
+ unsigned AS = cast<llvm::PointerType>(This->getType())->getAddressSpace();
+ llvm::Type *charPtrTy = CGF.Int8Ty->getPointerTo(AS);
+ CharUnits StaticOffset = ML.VFPtrOffset;
+ if (ML.VBase) {
+ bool AvoidVirtualOffset = false;
+ if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base) {
+ // A base destructor can only be called from a complete destructor of the
+ // same record type or another destructor of a more derived type;
+ // or a constructor of the same record type if an exception is thrown.
+ assert(isa<CXXDestructorDecl>(CGF.CurGD.getDecl()) ||
+ isa<CXXConstructorDecl>(CGF.CurGD.getDecl()));
+ const CXXRecordDecl *CurRD =
+ cast<CXXMethodDecl>(CGF.CurGD.getDecl())->getParent();
+
+ if (MD->getParent() == CurRD) {
+ if (isa<CXXDestructorDecl>(CGF.CurGD.getDecl()))
+ assert(CGF.CurGD.getDtorType() == Dtor_Complete);
+ if (isa<CXXConstructorDecl>(CGF.CurGD.getDecl()))
+ assert(CGF.CurGD.getCtorType() == Ctor_Complete);
+ // We're calling the main base dtor from a complete structor,
+ // so we know the "this" offset statically.
+ AvoidVirtualOffset = true;
+ } else {
+ // Let's see if we try to call a destructor of a non-virtual base.
+ for (CXXRecordDecl::base_class_const_iterator I = CurRD->bases_begin(),
+ E = CurRD->bases_end(); I != E; ++I) {
+ if (I->getType()->getAsCXXRecordDecl() != MD->getParent())
+ continue;
+ // If we call a base destructor for a non-virtual base, we statically
+ // know where it expects the vfptr and "this" to be.
+ // The total offset should reflect the adjustment done by
+ // adjustThisParameterInVirtualFunctionPrologue().
+ AvoidVirtualOffset = true;
+ break;
+ }
+ }
+ }
+
+ if (AvoidVirtualOffset) {
+ const ASTRecordLayout &Layout =
+ CGF.getContext().getASTRecordLayout(MD->getParent());
+ StaticOffset += Layout.getVBaseClassOffset(ML.VBase);
+ } else {
+ This = CGF.Builder.CreateBitCast(This, charPtrTy);
+ llvm::Value *VBaseOffset =
+ GetVirtualBaseClassOffset(CGF, This, MD->getParent(), ML.VBase);
+ This = CGF.Builder.CreateInBoundsGEP(This, VBaseOffset);
+ }
+ }
+ if (!StaticOffset.isZero()) {
+ assert(StaticOffset.isPositive());
+ This = CGF.Builder.CreateBitCast(This, charPtrTy);
+ if (ML.VBase) {
+ // Non-virtual adjustment might result in a pointer outside the allocated
+ // object, e.g. if the final overrider class is laid out after the virtual
+ // base that declares a method in the most derived class.
+ // FIXME: Update the code that emits this adjustment in thunks prologues.
+ This = CGF.Builder.CreateConstGEP1_32(This, StaticOffset.getQuantity());
+ } else {
+ This = CGF.Builder.CreateConstInBoundsGEP1_32(This,
+ StaticOffset.getQuantity());
+ }
}
+ return This;
}
static bool IsDeletingDtor(GlobalDecl GD) {
@@ -256,9 +682,6 @@ void MicrosoftCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,
QualType &ResTy,
FunctionArgList &Params) {
BuildThisParam(CGF, Params);
- if (needThisReturn(CGF.CurGD)) {
- ResTy = Params[0]->getType();
- }
ASTContext &Context = getContext();
const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
@@ -275,17 +698,71 @@ void MicrosoftCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,
= ImplicitParamDecl::Create(Context, 0,
CGF.CurGD.getDecl()->getLocation(),
&Context.Idents.get("should_call_delete"),
- Context.BoolTy);
+ Context.IntTy);
Params.push_back(ShouldDelete);
getStructorImplicitParamDecl(CGF) = ShouldDelete;
}
}
+llvm::Value *MicrosoftCXXABI::adjustThisParameterInVirtualFunctionPrologue(
+ CodeGenFunction &CGF, GlobalDecl GD, llvm::Value *This) {
+ GD = GD.getCanonicalDecl();
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+
+ GlobalDecl LookupGD = GD;
+ if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
+ // Complete destructors take a pointer to the complete object as a
+ // parameter, thus don't need this adjustment.
+ if (GD.getDtorType() == Dtor_Complete)
+ return This;
+
+ // There's no Dtor_Base in vftable but it shares the this adjustment with
+ // the deleting one, so look it up instead.
+ LookupGD = GlobalDecl(DD, Dtor_Deleting);
+ }
+
+ // In this ABI, every virtual function takes a pointer to one of the
+ // subobjects that first defines it as the 'this' parameter, rather than a
+ // pointer to ther final overrider subobject. Thus, we need to adjust it back
+ // to the final overrider subobject before use.
+ // See comments in the MicrosoftVFTableContext implementation for the details.
+
+ MicrosoftVTableContext::MethodVFTableLocation ML =
+ CGM.getMicrosoftVTableContext().getMethodVFTableLocation(LookupGD);
+ CharUnits Adjustment = ML.VFPtrOffset;
+ if (ML.VBase) {
+ const ASTRecordLayout &DerivedLayout =
+ CGF.getContext().getASTRecordLayout(MD->getParent());
+ Adjustment += DerivedLayout.getVBaseClassOffset(ML.VBase);
+ }
+
+ if (Adjustment.isZero())
+ return This;
+
+ unsigned AS = cast<llvm::PointerType>(This->getType())->getAddressSpace();
+ llvm::Type *charPtrTy = CGF.Int8Ty->getPointerTo(AS),
+ *thisTy = This->getType();
+
+ This = CGF.Builder.CreateBitCast(This, charPtrTy);
+ assert(Adjustment.isPositive());
+ This =
+ CGF.Builder.CreateConstInBoundsGEP1_32(This, -Adjustment.getQuantity());
+ return CGF.Builder.CreateBitCast(This, thisTy);
+}
+
void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
EmitThisParam(CGF);
- if (needThisReturn(CGF.CurGD)) {
+
+ /// If this is a function that the ABI specifies returns 'this', initialize
+ /// the return slot to 'this' at the start of the function.
+ ///
+ /// Unlike the setting of return types, this is done within the ABI
+ /// implementation instead of by clients of CGCXXABI because:
+ /// 1) getThisValue is currently protected
+ /// 2) in theory, an ABI could implement 'this' returns some other way;
+ /// HasThisReturn only specifies a contract, not the implementation
+ if (HasThisReturn(CGF.CurGD))
CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue);
- }
const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
if (isa<CXXConstructorDecl>(MD) && MD->getParent()->getNumVBases()) {
@@ -307,9 +784,10 @@ void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
}
}
-llvm::Value *MicrosoftCXXABI::EmitConstructorCall(CodeGenFunction &CGF,
+void MicrosoftCXXABI::EmitConstructorCall(CodeGenFunction &CGF,
const CXXConstructorDecl *D,
- CXXCtorType Type, bool ForVirtualBase,
+ CXXCtorType Type,
+ bool ForVirtualBase,
bool Delegating,
llvm::Value *This,
CallExpr::const_arg_iterator ArgBeg,
@@ -326,33 +804,291 @@ llvm::Value *MicrosoftCXXABI::EmitConstructorCall(CodeGenFunction &CGF,
// FIXME: Provide a source location here.
CGF.EmitCXXMemberCall(D, SourceLocation(), Callee, ReturnValueSlot(), This,
- ImplicitParam, ImplicitParamTy,
- ArgBeg, ArgEnd);
- return Callee;
+ ImplicitParam, ImplicitParamTy, ArgBeg, ArgEnd);
+}
+
+void MicrosoftCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
+ const CXXRecordDecl *RD) {
+ MicrosoftVTableContext &VFTContext = CGM.getMicrosoftVTableContext();
+ MicrosoftVTableContext::VFPtrListTy VFPtrs = VFTContext.getVFPtrOffsets(RD);
+ llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD);
+
+ for (MicrosoftVTableContext::VFPtrListTy::iterator I = VFPtrs.begin(),
+ E = VFPtrs.end(); I != E; ++I) {
+ llvm::GlobalVariable *VTable = getAddrOfVTable(RD, I->VFPtrFullOffset);
+ if (VTable->hasInitializer())
+ continue;
+
+ const VTableLayout &VTLayout =
+ VFTContext.getVFTableLayout(RD, I->VFPtrFullOffset);
+ llvm::Constant *Init = CGVT.CreateVTableInitializer(
+ RD, VTLayout.vtable_component_begin(),
+ VTLayout.getNumVTableComponents(), VTLayout.vtable_thunk_begin(),
+ VTLayout.getNumVTableThunks());
+ VTable->setInitializer(Init);
+
+ VTable->setLinkage(Linkage);
+ CGM.setTypeVisibility(VTable, RD, CodeGenModule::TVK_ForVTable);
+ }
+}
+
+llvm::Value *MicrosoftCXXABI::getVTableAddressPointInStructor(
+ CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base,
+ const CXXRecordDecl *NearestVBase, bool &NeedsVirtualOffset) {
+ NeedsVirtualOffset = (NearestVBase != 0);
+
+ llvm::Value *VTableAddressPoint =
+ getAddrOfVTable(VTableClass, Base.getBaseOffset());
+ if (!VTableAddressPoint) {
+ assert(Base.getBase()->getNumVBases() &&
+ !CGM.getContext().getASTRecordLayout(Base.getBase()).hasOwnVFPtr());
+ }
+ return VTableAddressPoint;
+}
+
+static void mangleVFTableName(MicrosoftMangleContext &MangleContext,
+ const CXXRecordDecl *RD, const VFPtrInfo &VFPtr,
+ SmallString<256> &Name) {
+ llvm::raw_svector_ostream Out(Name);
+ MangleContext.mangleCXXVFTable(RD, VFPtr.PathToMangle, Out);
+}
+
+llvm::Constant *MicrosoftCXXABI::getVTableAddressPointForConstExpr(
+ BaseSubobject Base, const CXXRecordDecl *VTableClass) {
+ llvm::Constant *VTable = getAddrOfVTable(VTableClass, Base.getBaseOffset());
+ assert(VTable && "Couldn't find a vftable for the given base?");
+ return VTable;
+}
+
+llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
+ CharUnits VPtrOffset) {
+ // getAddrOfVTable may return 0 if asked to get an address of a vtable which
+ // shouldn't be used in the given record type. We want to cache this result in
+ // VFTablesMap, thus a simple zero check is not sufficient.
+ VFTableIdTy ID(RD, VPtrOffset);
+ VFTablesMapTy::iterator I;
+ bool Inserted;
+ llvm::tie(I, Inserted) = VFTablesMap.insert(
+ std::make_pair(ID, static_cast<llvm::GlobalVariable *>(0)));
+ if (!Inserted)
+ return I->second;
+
+ llvm::GlobalVariable *&VTable = I->second;
+
+ MicrosoftVTableContext &VTContext = CGM.getMicrosoftVTableContext();
+ const MicrosoftVTableContext::VFPtrListTy &VFPtrs =
+ VTContext.getVFPtrOffsets(RD);
+
+ if (DeferredVFTables.insert(RD)) {
+ // We haven't processed this record type before.
+ // Queue up this v-table for possible deferred emission.
+ CGM.addDeferredVTable(RD);
+
+#ifndef NDEBUG
+ // Create all the vftables at once in order to make sure each vftable has
+ // a unique mangled name.
+ llvm::StringSet<> ObservedMangledNames;
+ for (size_t J = 0, F = VFPtrs.size(); J != F; ++J) {
+ SmallString<256> Name;
+ mangleVFTableName(getMangleContext(), RD, VFPtrs[J], Name);
+ if (!ObservedMangledNames.insert(Name.str()))
+ llvm_unreachable("Already saw this mangling before?");
+ }
+#endif
+ }
+
+ for (size_t J = 0, F = VFPtrs.size(); J != F; ++J) {
+ if (VFPtrs[J].VFPtrFullOffset != VPtrOffset)
+ continue;
+
+ llvm::ArrayType *ArrayType = llvm::ArrayType::get(
+ CGM.Int8PtrTy,
+ VTContext.getVFTableLayout(RD, VFPtrs[J].VFPtrFullOffset)
+ .getNumVTableComponents());
+
+ SmallString<256> Name;
+ mangleVFTableName(getMangleContext(), RD, VFPtrs[J], Name);
+ VTable = CGM.CreateOrReplaceCXXRuntimeVariable(
+ Name.str(), ArrayType, llvm::GlobalValue::ExternalLinkage);
+ VTable->setUnnamedAddr(true);
+ break;
+ }
+
+ return VTable;
}
-RValue MicrosoftCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,
- const CXXDestructorDecl *Dtor,
- CXXDtorType DtorType,
- SourceLocation CallLoc,
- ReturnValueSlot ReturnValue,
- llvm::Value *This) {
+llvm::Value *MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
+ GlobalDecl GD,
+ llvm::Value *This,
+ llvm::Type *Ty) {
+ GD = GD.getCanonicalDecl();
+ CGBuilderTy &Builder = CGF.Builder;
+
+ Ty = Ty->getPointerTo()->getPointerTo();
+ llvm::Value *VPtr = adjustThisArgumentForVirtualCall(CGF, GD, This);
+ llvm::Value *VTable = CGF.GetVTablePtr(VPtr, Ty);
+
+ MicrosoftVTableContext::MethodVFTableLocation ML =
+ CGM.getMicrosoftVTableContext().getMethodVFTableLocation(GD);
+ llvm::Value *VFuncPtr =
+ Builder.CreateConstInBoundsGEP1_64(VTable, ML.Index, "vfn");
+ return Builder.CreateLoad(VFuncPtr);
+}
+
+void MicrosoftCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,
+ const CXXDestructorDecl *Dtor,
+ CXXDtorType DtorType,
+ SourceLocation CallLoc,
+ llvm::Value *This) {
assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete);
// We have only one destructor in the vftable but can get both behaviors
- // by passing an implicit bool parameter.
- const CGFunctionInfo *FInfo
- = &CGM.getTypes().arrangeCXXDestructor(Dtor, Dtor_Deleting);
+ // by passing an implicit int parameter.
+ GlobalDecl GD(Dtor, Dtor_Deleting);
+ const CGFunctionInfo *FInfo =
+ &CGM.getTypes().arrangeCXXDestructor(Dtor, Dtor_Deleting);
llvm::Type *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);
- llvm::Value *Callee = CGF.BuildVirtualCall(Dtor, Dtor_Deleting, This, Ty);
+ llvm::Value *Callee = getVirtualFunctionPointer(CGF, GD, This, Ty);
ASTContext &Context = CGF.getContext();
- llvm::Value *ImplicitParam
- = llvm::ConstantInt::get(llvm::IntegerType::getInt1Ty(CGF.getLLVMContext()),
+ llvm::Value *ImplicitParam =
+ llvm::ConstantInt::get(llvm::IntegerType::getInt32Ty(CGF.getLLVMContext()),
DtorType == Dtor_Deleting);
- return CGF.EmitCXXMemberCall(Dtor, CallLoc, Callee, ReturnValue, This,
- ImplicitParam, Context.BoolTy, 0, 0);
+ This = adjustThisArgumentForVirtualCall(CGF, GD, This);
+ CGF.EmitCXXMemberCall(Dtor, CallLoc, Callee, ReturnValueSlot(), This,
+ ImplicitParam, Context.IntTy, 0, 0);
+}
+
+const VBTableVector &
+MicrosoftCXXABI::EnumerateVBTables(const CXXRecordDecl *RD) {
+ // At this layer, we can key the cache off of a single class, which is much
+ // easier than caching at the GlobalVariable layer.
+ llvm::DenseMap<const CXXRecordDecl*, VBTableVector>::iterator I;
+ bool added;
+ llvm::tie(I, added) = VBTablesMap.insert(std::make_pair(RD, VBTableVector()));
+ VBTableVector &VBTables = I->second;
+ if (!added)
+ return VBTables;
+
+ VBTableBuilder(CGM, RD).enumerateVBTables(VBTables);
+
+ return VBTables;
+}
+
+llvm::Function *
+MicrosoftCXXABI::EmitVirtualMemPtrThunk(const CXXMethodDecl *MD,
+ StringRef ThunkName) {
+ // If the thunk has been generated previously, just return it.
+ if (llvm::GlobalValue *GV = CGM.getModule().getNamedValue(ThunkName))
+ return cast<llvm::Function>(GV);
+
+ // Create the llvm::Function.
+ const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeGlobalDeclaration(MD);
+ llvm::FunctionType *ThunkTy = CGM.getTypes().GetFunctionType(FnInfo);
+ llvm::Function *ThunkFn =
+ llvm::Function::Create(ThunkTy, llvm::Function::ExternalLinkage,
+ ThunkName.str(), &CGM.getModule());
+ assert(ThunkFn->getName() == ThunkName && "name was uniqued!");
+
+ ThunkFn->setLinkage(MD->isExternallyVisible()
+ ? llvm::GlobalValue::LinkOnceODRLinkage
+ : llvm::GlobalValue::InternalLinkage);
+
+ CGM.SetLLVMFunctionAttributes(MD, FnInfo, ThunkFn);
+ CGM.SetLLVMFunctionAttributesForDefinition(MD, ThunkFn);
+
+ // Start codegen.
+ CodeGenFunction CGF(CGM);
+ CGF.StartThunk(ThunkFn, MD, FnInfo);
+
+ // Get to the Callee.
+ llvm::Value *This = CGF.LoadCXXThis();
+ llvm::Value *Callee = getVirtualFunctionPointer(CGF, MD, This, ThunkTy);
+
+ // Make the call and return the result.
+ CGF.EmitCallAndReturnForThunk(MD, Callee, 0);
+
+ return ThunkFn;
+}
+
+void MicrosoftCXXABI::emitVirtualInheritanceTables(const CXXRecordDecl *RD) {
+ const VBTableVector &VBTables = EnumerateVBTables(RD);
+ llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD);
+
+ for (VBTableVector::const_iterator I = VBTables.begin(), E = VBTables.end();
+ I != E; ++I) {
+ I->EmitVBTableDefinition(CGM, RD, Linkage);
+ }
+}
+
+llvm::Value *MicrosoftCXXABI::performThisAdjustment(CodeGenFunction &CGF,
+ llvm::Value *This,
+ const ThisAdjustment &TA) {
+ if (TA.isEmpty())
+ return This;
+
+ llvm::Value *V = CGF.Builder.CreateBitCast(This, CGF.Int8PtrTy);
+
+ if (!TA.Virtual.isEmpty()) {
+ assert(TA.Virtual.Microsoft.VtordispOffset < 0);
+ // Adjust the this argument based on the vtordisp value.
+ llvm::Value *VtorDispPtr =
+ CGF.Builder.CreateConstGEP1_32(V, TA.Virtual.Microsoft.VtordispOffset);
+ VtorDispPtr =
+ CGF.Builder.CreateBitCast(VtorDispPtr, CGF.Int32Ty->getPointerTo());
+ llvm::Value *VtorDisp = CGF.Builder.CreateLoad(VtorDispPtr, "vtordisp");
+ V = CGF.Builder.CreateGEP(V, CGF.Builder.CreateNeg(VtorDisp));
+
+ if (TA.Virtual.Microsoft.VBPtrOffset) {
+ // If the final overrider is defined in a virtual base other than the one
+ // that holds the vfptr, we have to use a vtordispex thunk which looks up
+ // the vbtable of the derived class.
+ assert(TA.Virtual.Microsoft.VBPtrOffset > 0);
+ assert(TA.Virtual.Microsoft.VBOffsetOffset >= 0);
+ llvm::Value *VBPtr;
+ llvm::Value *VBaseOffset =
+ GetVBaseOffsetFromVBPtr(CGF, V, -TA.Virtual.Microsoft.VBPtrOffset,
+ TA.Virtual.Microsoft.VBOffsetOffset, &VBPtr);
+ V = CGF.Builder.CreateInBoundsGEP(VBPtr, VBaseOffset);
+ }
+ }
+
+ if (TA.NonVirtual) {
+ // Non-virtual adjustment might result in a pointer outside the allocated
+ // object, e.g. if the final overrider class is laid out after the virtual
+ // base that declares a method in the most derived class.
+ V = CGF.Builder.CreateConstGEP1_32(V, TA.NonVirtual);
+ }
+
+ // Don't need to bitcast back, the call CodeGen will handle this.
+ return V;
+}
+
+llvm::Value *
+MicrosoftCXXABI::performReturnAdjustment(CodeGenFunction &CGF, llvm::Value *Ret,
+ const ReturnAdjustment &RA) {
+ if (RA.isEmpty())
+ return Ret;
+
+ llvm::Value *V = CGF.Builder.CreateBitCast(Ret, CGF.Int8PtrTy);
+
+ if (RA.Virtual.Microsoft.VBIndex) {
+ assert(RA.Virtual.Microsoft.VBIndex > 0);
+ int32_t IntSize =
+ getContext().getTypeSizeInChars(getContext().IntTy).getQuantity();
+ llvm::Value *VBPtr;
+ llvm::Value *VBaseOffset =
+ GetVBaseOffsetFromVBPtr(CGF, V, RA.Virtual.Microsoft.VBPtrOffset,
+ IntSize * RA.Virtual.Microsoft.VBIndex, &VBPtr);
+ V = CGF.Builder.CreateInBoundsGEP(VBPtr, VBaseOffset);
+ }
+
+ if (RA.NonVirtual)
+ V = CGF.Builder.CreateConstInBoundsGEP1_32(V, RA.NonVirtual);
+
+ // Cast back to the original type.
+ return CGF.Builder.CreateBitCast(V, Ret->getType());
}
bool MicrosoftCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr,
@@ -411,17 +1147,86 @@ llvm::Value* MicrosoftCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
}
void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
- llvm::GlobalVariable *DeclPtr,
+ llvm::GlobalVariable *GV,
bool PerformInit) {
- // FIXME: this code was only tested for global initialization.
- // Not sure whether we want thread-safe static local variables as VS
- // doesn't make them thread-safe.
+ // MSVC always uses an i32 bitfield to guard initialization, which is *not*
+ // threadsafe. Since the user may be linking in inline functions compiled by
+ // cl.exe, there's no reason to provide a false sense of security by using
+ // critical sections here.
if (D.getTLSKind())
CGM.ErrorUnsupported(&D, "dynamic TLS initialization");
- // Emit the initializer and add a global destructor if appropriate.
- CGF.EmitCXXGlobalVarDeclInit(D, DeclPtr, PerformInit);
+ CGBuilderTy &Builder = CGF.Builder;
+ llvm::IntegerType *GuardTy = CGF.Int32Ty;
+ llvm::ConstantInt *Zero = llvm::ConstantInt::get(GuardTy, 0);
+
+ // Get the guard variable for this function if we have one already.
+ GuardInfo &GI = GuardVariableMap[D.getDeclContext()];
+
+ unsigned BitIndex;
+ if (D.isExternallyVisible()) {
+ // Externally visible variables have to be numbered in Sema to properly
+ // handle unreachable VarDecls.
+ BitIndex = getContext().getManglingNumber(&D);
+ assert(BitIndex > 0);
+ BitIndex--;
+ } else {
+ // Non-externally visible variables are numbered here in CodeGen.
+ BitIndex = GI.BitIndex++;
+ }
+
+ if (BitIndex >= 32) {
+ if (D.isExternallyVisible())
+ ErrorUnsupportedABI(CGF, "more than 32 guarded initializations");
+ BitIndex %= 32;
+ GI.Guard = 0;
+ }
+
+ // Lazily create the i32 bitfield for this function.
+ if (!GI.Guard) {
+ // Mangle the name for the guard.
+ SmallString<256> GuardName;
+ {
+ llvm::raw_svector_ostream Out(GuardName);
+ getMangleContext().mangleStaticGuardVariable(&D, Out);
+ Out.flush();
+ }
+
+ // Create the guard variable with a zero-initializer. Just absorb linkage
+ // and visibility from the guarded variable.
+ GI.Guard = new llvm::GlobalVariable(CGM.getModule(), GuardTy, false,
+ GV->getLinkage(), Zero, GuardName.str());
+ GI.Guard->setVisibility(GV->getVisibility());
+ } else {
+ assert(GI.Guard->getLinkage() == GV->getLinkage() &&
+ "static local from the same function had different linkage");
+ }
+
+ // Pseudo code for the test:
+ // if (!(GuardVar & MyGuardBit)) {
+ // GuardVar |= MyGuardBit;
+ // ... initialize the object ...;
+ // }
+
+ // Test our bit from the guard variable.
+ llvm::ConstantInt *Bit = llvm::ConstantInt::get(GuardTy, 1U << BitIndex);
+ llvm::LoadInst *LI = Builder.CreateLoad(GI.Guard);
+ llvm::Value *IsInitialized =
+ Builder.CreateICmpNE(Builder.CreateAnd(LI, Bit), Zero);
+ llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init");
+ llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end");
+ Builder.CreateCondBr(IsInitialized, EndBlock, InitBlock);
+
+ // Set our bit in the guard variable and emit the initializer and add a global
+ // destructor if appropriate.
+ CGF.EmitBlock(InitBlock);
+ Builder.CreateStore(Builder.CreateOr(LI, Bit), GI.Guard);
+ CGF.EmitCXXGlobalVarDeclInit(D, GV, PerformInit);
+ Builder.CreateBr(EndBlock);
+
+ // Continue.
+ CGF.EmitBlock(EndBlock);
}
// Member pointer helpers.
@@ -429,8 +1234,10 @@ static bool hasVBPtrOffsetField(MSInheritanceModel Inheritance) {
return Inheritance == MSIM_Unspecified;
}
-static bool hasOnlyOneField(MSInheritanceModel Inheritance) {
- return Inheritance <= MSIM_SinglePolymorphic;
+static bool hasOnlyOneField(bool IsMemberFunction,
+ MSInheritanceModel Inheritance) {
+ return Inheritance <= MSIM_SinglePolymorphic ||
+ (!IsMemberFunction && Inheritance <= MSIM_MultiplePolymorphic);
}
// Only member pointers to functions need a this adjustment, since it can be
@@ -531,27 +1338,28 @@ MicrosoftCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {
llvm::Constant *
MicrosoftCXXABI::EmitFullMemberPointer(llvm::Constant *FirstField,
bool IsMemberFunction,
- const CXXRecordDecl *RD)
+ const CXXRecordDecl *RD,
+ CharUnits NonVirtualBaseAdjustment)
{
MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
// Single inheritance class member pointer are represented as scalars instead
// of aggregates.
- if (hasOnlyOneField(Inheritance))
+ if (hasOnlyOneField(IsMemberFunction, Inheritance))
return FirstField;
llvm::SmallVector<llvm::Constant *, 4> fields;
fields.push_back(FirstField);
if (hasNonVirtualBaseAdjustmentField(IsMemberFunction, Inheritance))
- fields.push_back(getZeroInt());
+ fields.push_back(llvm::ConstantInt::get(
+ CGM.IntTy, NonVirtualBaseAdjustment.getQuantity()));
if (hasVBPtrOffsetField(Inheritance)) {
- int64_t VBPtrOffset =
- getContext().getASTRecordLayout(RD).getVBPtrOffset().getQuantity();
- if (VBPtrOffset == -1)
- VBPtrOffset = 0;
- fields.push_back(llvm::ConstantInt::get(CGM.IntTy, VBPtrOffset));
+ CharUnits Offs = CharUnits::Zero();
+ if (RD->getNumVBases())
+ Offs = GetVBPtrOffsetFromBases(RD);
+ fields.push_back(llvm::ConstantInt::get(CGM.IntTy, Offs.getQuantity()));
}
// The rest of the fields are adjusted by conversions to a more derived class.
@@ -567,22 +1375,44 @@ MicrosoftCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
llvm::Constant *FirstField =
llvm::ConstantInt::get(CGM.IntTy, offset.getQuantity());
- return EmitFullMemberPointer(FirstField, /*IsMemberFunction=*/false, RD);
+ return EmitFullMemberPointer(FirstField, /*IsMemberFunction=*/false, RD,
+ CharUnits::Zero());
+}
+
+llvm::Constant *MicrosoftCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
+ return BuildMemberPointer(MD->getParent(), MD, CharUnits::Zero());
+}
+
+llvm::Constant *MicrosoftCXXABI::EmitMemberPointer(const APValue &MP,
+ QualType MPType) {
+ const MemberPointerType *MPT = MPType->castAs<MemberPointerType>();
+ const ValueDecl *MPD = MP.getMemberPointerDecl();
+ if (!MPD)
+ return EmitNullMemberPointer(MPT);
+
+ CharUnits ThisAdjustment = getMemberPointerPathAdjustment(MP);
+
+ // FIXME PR15713: Support virtual inheritance paths.
+
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD))
+ return BuildMemberPointer(MPT->getClass()->getAsCXXRecordDecl(),
+ MD, ThisAdjustment);
+
+ CharUnits FieldOffset =
+ getContext().toCharUnitsFromBits(getContext().getFieldOffset(MPD));
+ return EmitMemberDataPointer(MPT, ThisAdjustment + FieldOffset);
}
llvm::Constant *
-MicrosoftCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
+MicrosoftCXXABI::BuildMemberPointer(const CXXRecordDecl *RD,
+ const CXXMethodDecl *MD,
+ CharUnits NonVirtualBaseAdjustment) {
assert(MD->isInstance() && "Member function must not be static!");
MD = MD->getCanonicalDecl();
- const CXXRecordDecl *RD = MD->getParent();
CodeGenTypes &Types = CGM.getTypes();
llvm::Constant *FirstField;
- if (MD->isVirtual()) {
- // FIXME: We have to instantiate a thunk that loads the vftable and jumps to
- // the right offset.
- FirstField = llvm::Constant::getNullValue(CGM.VoidPtrTy);
- } else {
+ if (!MD->isVirtual()) {
const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
llvm::Type *Ty;
// Check whether the function has a computable LLVM signature.
@@ -596,18 +1426,38 @@ MicrosoftCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
}
FirstField = CGM.GetAddrOfFunction(MD, Ty);
FirstField = llvm::ConstantExpr::getBitCast(FirstField, CGM.VoidPtrTy);
+ } else {
+ MicrosoftVTableContext::MethodVFTableLocation ML =
+ CGM.getMicrosoftVTableContext().getMethodVFTableLocation(MD);
+ if (MD->isVariadic()) {
+ CGM.ErrorUnsupported(MD, "pointer to variadic virtual member function");
+ FirstField = llvm::Constant::getNullValue(CGM.VoidPtrTy);
+ } else if (!CGM.getTypes().isFuncTypeConvertible(
+ MD->getType()->castAs<FunctionType>())) {
+ CGM.ErrorUnsupported(MD, "pointer to virtual member function with "
+ "incomplete return or parameter type");
+ FirstField = llvm::Constant::getNullValue(CGM.VoidPtrTy);
+ } else if (ML.VBase) {
+ CGM.ErrorUnsupported(MD, "pointer to virtual member function overriding "
+ "member function in virtual base class");
+ FirstField = llvm::Constant::getNullValue(CGM.VoidPtrTy);
+ } else {
+ SmallString<256> ThunkName;
+ CharUnits PointerWidth = getContext().toCharUnitsFromBits(
+ getContext().getTargetInfo().getPointerWidth(0));
+ uint64_t OffsetInVFTable = ML.Index * PointerWidth.getQuantity();
+ llvm::raw_svector_ostream Out(ThunkName);
+ getMangleContext().mangleVirtualMemPtrThunk(MD, OffsetInVFTable, Out);
+ Out.flush();
+
+ llvm::Function *Thunk = EmitVirtualMemPtrThunk(MD, ThunkName.str());
+ FirstField = llvm::ConstantExpr::getBitCast(Thunk, CGM.VoidPtrTy);
+ }
}
// The rest of the fields are common with data member pointers.
- return EmitFullMemberPointer(FirstField, /*IsMemberFunction=*/true, RD);
-}
-
-llvm::Constant *
-MicrosoftCXXABI::EmitMemberPointer(const APValue &MP, QualType MPT) {
- // FIXME PR15875: Implement member pointer conversions for Constants.
- const CXXRecordDecl *RD = MPT->castAs<MemberPointerType>()->getClass()->getAsCXXRecordDecl();
- return EmitFullMemberPointer(llvm::Constant::getNullValue(CGM.VoidPtrTy),
- /*IsMemberFunction=*/true, RD);
+ return EmitFullMemberPointer(FirstField, /*IsMemberFunction=*/true, RD,
+ NonVirtualBaseAdjustment);
}
/// Member pointers are the same if they're either bitwise identical *or* both
@@ -638,7 +1488,7 @@ MicrosoftCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
// single icmp.
const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
- if (hasOnlyOneField(Inheritance))
+ if (hasOnlyOneField(MPT->isMemberFunctionPointer(), Inheritance))
return Builder.CreateICmp(Eq, L, R);
// Compare the first field.
@@ -703,12 +1553,64 @@ MicrosoftCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
return Res;
}
+bool MicrosoftCXXABI::MemberPointerConstantIsNull(const MemberPointerType *MPT,
+ llvm::Constant *Val) {
+ // Function pointers are null if the pointer in the first field is null.
+ if (MPT->isMemberFunctionPointer()) {
+ llvm::Constant *FirstField = Val->getType()->isStructTy() ?
+ Val->getAggregateElement(0U) : Val;
+ return FirstField->isNullValue();
+ }
+
+ // If it's not a function pointer and it's zero initializable, we can easily
+ // check zero.
+ if (isZeroInitializable(MPT) && Val->isNullValue())
+ return true;
+
+ // Otherwise, break down all the fields for comparison. Hopefully these
+ // little Constants are reused, while a big null struct might not be.
+ llvm::SmallVector<llvm::Constant *, 4> Fields;
+ GetNullMemberPointerFields(MPT, Fields);
+ if (Fields.size() == 1) {
+ assert(Val->getType()->isIntegerTy());
+ return Val == Fields[0];
+ }
+
+ unsigned I, E;
+ for (I = 0, E = Fields.size(); I != E; ++I) {
+ if (Val->getAggregateElement(I) != Fields[I])
+ break;
+ }
+ return I == E;
+}
+
+llvm::Value *
+MicrosoftCXXABI::GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF,
+ llvm::Value *This,
+ llvm::Value *VBPtrOffset,
+ llvm::Value *VBTableOffset,
+ llvm::Value **VBPtrOut) {
+ CGBuilderTy &Builder = CGF.Builder;
+ // Load the vbtable pointer from the vbptr in the instance.
+ This = Builder.CreateBitCast(This, CGM.Int8PtrTy);
+ llvm::Value *VBPtr =
+ Builder.CreateInBoundsGEP(This, VBPtrOffset, "vbptr");
+ if (VBPtrOut) *VBPtrOut = VBPtr;
+ VBPtr = Builder.CreateBitCast(VBPtr, CGM.Int8PtrTy->getPointerTo(0));
+ llvm::Value *VBTable = Builder.CreateLoad(VBPtr, "vbtable");
+
+ // Load an i32 offset from the vb-table.
+ llvm::Value *VBaseOffs = Builder.CreateInBoundsGEP(VBTable, VBTableOffset);
+ VBaseOffs = Builder.CreateBitCast(VBaseOffs, CGM.Int32Ty->getPointerTo(0));
+ return Builder.CreateLoad(VBaseOffs, "vbase_offs");
+}
+
// Returns an adjusted base cast to i8*, since we do more address arithmetic on
// it.
llvm::Value *
MicrosoftCXXABI::AdjustVirtualBase(CodeGenFunction &CGF,
const CXXRecordDecl *RD, llvm::Value *Base,
- llvm::Value *VirtualBaseAdjustmentOffset,
+ llvm::Value *VBTableOffset,
llvm::Value *VBPtrOffset) {
CGBuilderTy &Builder = CGF.Builder;
Base = Builder.CreateBitCast(Base, CGM.Int8PtrTy);
@@ -725,7 +1627,7 @@ MicrosoftCXXABI::AdjustVirtualBase(CodeGenFunction &CGF,
VBaseAdjustBB = CGF.createBasicBlock("memptr.vadjust");
SkipAdjustBB = CGF.createBasicBlock("memptr.skip_vadjust");
llvm::Value *IsVirtual =
- Builder.CreateICmpNE(VirtualBaseAdjustmentOffset, getZeroInt(),
+ Builder.CreateICmpNE(VBTableOffset, getZeroInt(),
"memptr.is_vbase");
Builder.CreateCondBr(IsVirtual, VBaseAdjustBB, SkipAdjustBB);
CGF.EmitBlock(VBaseAdjustBB);
@@ -734,21 +1636,15 @@ MicrosoftCXXABI::AdjustVirtualBase(CodeGenFunction &CGF,
// If we weren't given a dynamic vbptr offset, RD should be complete and we'll
// know the vbptr offset.
if (!VBPtrOffset) {
- CharUnits offs = getContext().getASTRecordLayout(RD).getVBPtrOffset();
+ CharUnits offs = CharUnits::Zero();
+ if (RD->getNumVBases()) {
+ offs = GetVBPtrOffsetFromBases(RD);
+ }
VBPtrOffset = llvm::ConstantInt::get(CGM.IntTy, offs.getQuantity());
}
- // Load the vbtable pointer from the vbtable offset in the instance.
- llvm::Value *VBPtr =
- Builder.CreateInBoundsGEP(Base, VBPtrOffset, "memptr.vbptr");
- llvm::Value *VBTable =
- Builder.CreateBitCast(VBPtr, CGM.Int8PtrTy->getPointerTo(0));
- VBTable = Builder.CreateLoad(VBTable, "memptr.vbtable");
- // Load an i32 offset from the vb-table.
+ llvm::Value *VBPtr = 0;
llvm::Value *VBaseOffs =
- Builder.CreateInBoundsGEP(VBTable, VirtualBaseAdjustmentOffset);
- VBaseOffs = Builder.CreateBitCast(VBaseOffs, CGM.Int32Ty->getPointerTo(0));
- VBaseOffs = Builder.CreateLoad(VBaseOffs, "memptr.vbase_offs");
- // Add it to VBPtr. GEP will sign extend the i32 value for us.
+ GetVBaseOffsetFromVBPtr(CGF, Base, VBPtrOffset, VBTableOffset, &VBPtr);
llvm::Value *AdjustedBase = Builder.CreateInBoundsGEP(VBPtr, VBaseOffs);
// Merge control flow with the case where we didn't have to adjust.
@@ -803,6 +1699,194 @@ MicrosoftCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF,
return Builder.CreateBitCast(Addr, PType);
}
+static MSInheritanceModel
+getInheritanceFromMemptr(const MemberPointerType *MPT) {
+ return MPT->getClass()->getAsCXXRecordDecl()->getMSInheritanceModel();
+}
+
+llvm::Value *
+MicrosoftCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
+ const CastExpr *E,
+ llvm::Value *Src) {
+ assert(E->getCastKind() == CK_DerivedToBaseMemberPointer ||
+ E->getCastKind() == CK_BaseToDerivedMemberPointer ||
+ E->getCastKind() == CK_ReinterpretMemberPointer);
+
+ // Use constant emission if we can.
+ if (isa<llvm::Constant>(Src))
+ return EmitMemberPointerConversion(E, cast<llvm::Constant>(Src));
+
+ // We may be adding or dropping fields from the member pointer, so we need
+ // both types and the inheritance models of both records.
+ const MemberPointerType *SrcTy =
+ E->getSubExpr()->getType()->castAs<MemberPointerType>();
+ const MemberPointerType *DstTy = E->getType()->castAs<MemberPointerType>();
+ MSInheritanceModel SrcInheritance = getInheritanceFromMemptr(SrcTy);
+ MSInheritanceModel DstInheritance = getInheritanceFromMemptr(DstTy);
+ bool IsFunc = SrcTy->isMemberFunctionPointer();
+
+ // If the classes use the same null representation, reinterpret_cast is a nop.
+ bool IsReinterpret = E->getCastKind() == CK_ReinterpretMemberPointer;
+ if (IsReinterpret && (IsFunc ||
+ nullFieldOffsetIsZero(SrcInheritance) ==
+ nullFieldOffsetIsZero(DstInheritance)))
+ return Src;
+
+ CGBuilderTy &Builder = CGF.Builder;
+
+ // Branch past the conversion if Src is null.
+ llvm::Value *IsNotNull = EmitMemberPointerIsNotNull(CGF, Src, SrcTy);
+ llvm::Constant *DstNull = EmitNullMemberPointer(DstTy);
+
+ // C++ 5.2.10p9: The null member pointer value is converted to the null member
+ // pointer value of the destination type.
+ if (IsReinterpret) {
+ // For reinterpret casts, sema ensures that src and dst are both functions
+ // or data and have the same size, which means the LLVM types should match.
+ assert(Src->getType() == DstNull->getType());
+ return Builder.CreateSelect(IsNotNull, Src, DstNull);
+ }
+
+ llvm::BasicBlock *OriginalBB = Builder.GetInsertBlock();
+ llvm::BasicBlock *ConvertBB = CGF.createBasicBlock("memptr.convert");
+ llvm::BasicBlock *ContinueBB = CGF.createBasicBlock("memptr.converted");
+ Builder.CreateCondBr(IsNotNull, ConvertBB, ContinueBB);
+ CGF.EmitBlock(ConvertBB);
+
+ // Decompose src.
+ llvm::Value *FirstField = Src;
+ llvm::Value *NonVirtualBaseAdjustment = 0;
+ llvm::Value *VirtualBaseAdjustmentOffset = 0;
+ llvm::Value *VBPtrOffset = 0;
+ if (!hasOnlyOneField(IsFunc, SrcInheritance)) {
+ // We need to extract values.
+ unsigned I = 0;
+ FirstField = Builder.CreateExtractValue(Src, I++);
+ if (hasNonVirtualBaseAdjustmentField(IsFunc, SrcInheritance))
+ NonVirtualBaseAdjustment = Builder.CreateExtractValue(Src, I++);
+ if (hasVBPtrOffsetField(SrcInheritance))
+ VBPtrOffset = Builder.CreateExtractValue(Src, I++);
+ if (hasVirtualBaseAdjustmentField(SrcInheritance))
+ VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(Src, I++);
+ }
+
+ // For data pointers, we adjust the field offset directly. For functions, we
+ // have a separate field.
+ llvm::Constant *Adj = getMemberPointerAdjustment(E);
+ if (Adj) {
+ Adj = llvm::ConstantExpr::getTruncOrBitCast(Adj, CGM.IntTy);
+ llvm::Value *&NVAdjustField = IsFunc ? NonVirtualBaseAdjustment : FirstField;
+ bool isDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer);
+ if (!NVAdjustField) // If this field didn't exist in src, it's zero.
+ NVAdjustField = getZeroInt();
+ if (isDerivedToBase)
+ NVAdjustField = Builder.CreateNSWSub(NVAdjustField, Adj, "adj");
+ else
+ NVAdjustField = Builder.CreateNSWAdd(NVAdjustField, Adj, "adj");
+ }
+
+ // FIXME PR15713: Support conversions through virtually derived classes.
+
+ // Recompose dst from the null struct and the adjusted fields from src.
+ llvm::Value *Dst;
+ if (hasOnlyOneField(IsFunc, DstInheritance)) {
+ Dst = FirstField;
+ } else {
+ Dst = llvm::UndefValue::get(DstNull->getType());
+ unsigned Idx = 0;
+ Dst = Builder.CreateInsertValue(Dst, FirstField, Idx++);
+ if (hasNonVirtualBaseAdjustmentField(IsFunc, DstInheritance))
+ Dst = Builder.CreateInsertValue(
+ Dst, getValueOrZeroInt(NonVirtualBaseAdjustment), Idx++);
+ if (hasVBPtrOffsetField(DstInheritance))
+ Dst = Builder.CreateInsertValue(
+ Dst, getValueOrZeroInt(VBPtrOffset), Idx++);
+ if (hasVirtualBaseAdjustmentField(DstInheritance))
+ Dst = Builder.CreateInsertValue(
+ Dst, getValueOrZeroInt(VirtualBaseAdjustmentOffset), Idx++);
+ }
+ Builder.CreateBr(ContinueBB);
+
+ // In the continuation, choose between DstNull and Dst.
+ CGF.EmitBlock(ContinueBB);
+ llvm::PHINode *Phi = Builder.CreatePHI(DstNull->getType(), 2, "memptr.converted");
+ Phi->addIncoming(DstNull, OriginalBB);
+ Phi->addIncoming(Dst, ConvertBB);
+ return Phi;
+}
+
+llvm::Constant *
+MicrosoftCXXABI::EmitMemberPointerConversion(const CastExpr *E,
+ llvm::Constant *Src) {
+ const MemberPointerType *SrcTy =
+ E->getSubExpr()->getType()->castAs<MemberPointerType>();
+ const MemberPointerType *DstTy = E->getType()->castAs<MemberPointerType>();
+
+ // If src is null, emit a new null for dst. We can't return src because dst
+ // might have a new representation.
+ if (MemberPointerConstantIsNull(SrcTy, Src))
+ return EmitNullMemberPointer(DstTy);
+
+ // We don't need to do anything for reinterpret_casts of non-null member
+ // pointers. We should only get here when the two type representations have
+ // the same size.
+ if (E->getCastKind() == CK_ReinterpretMemberPointer)
+ return Src;
+
+ MSInheritanceModel SrcInheritance = getInheritanceFromMemptr(SrcTy);
+ MSInheritanceModel DstInheritance = getInheritanceFromMemptr(DstTy);
+
+ // Decompose src.
+ llvm::Constant *FirstField = Src;
+ llvm::Constant *NonVirtualBaseAdjustment = 0;
+ llvm::Constant *VirtualBaseAdjustmentOffset = 0;
+ llvm::Constant *VBPtrOffset = 0;
+ bool IsFunc = SrcTy->isMemberFunctionPointer();
+ if (!hasOnlyOneField(IsFunc, SrcInheritance)) {
+ // We need to extract values.
+ unsigned I = 0;
+ FirstField = Src->getAggregateElement(I++);
+ if (hasNonVirtualBaseAdjustmentField(IsFunc, SrcInheritance))
+ NonVirtualBaseAdjustment = Src->getAggregateElement(I++);
+ if (hasVBPtrOffsetField(SrcInheritance))
+ VBPtrOffset = Src->getAggregateElement(I++);
+ if (hasVirtualBaseAdjustmentField(SrcInheritance))
+ VirtualBaseAdjustmentOffset = Src->getAggregateElement(I++);
+ }
+
+ // For data pointers, we adjust the field offset directly. For functions, we
+ // have a separate field.
+ llvm::Constant *Adj = getMemberPointerAdjustment(E);
+ if (Adj) {
+ Adj = llvm::ConstantExpr::getTruncOrBitCast(Adj, CGM.IntTy);
+ llvm::Constant *&NVAdjustField =
+ IsFunc ? NonVirtualBaseAdjustment : FirstField;
+ bool IsDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer);
+ if (!NVAdjustField) // If this field didn't exist in src, it's zero.
+ NVAdjustField = getZeroInt();
+ if (IsDerivedToBase)
+ NVAdjustField = llvm::ConstantExpr::getNSWSub(NVAdjustField, Adj);
+ else
+ NVAdjustField = llvm::ConstantExpr::getNSWAdd(NVAdjustField, Adj);
+ }
+
+ // FIXME PR15713: Support conversions through virtually derived classes.
+
+ // Recompose dst from the null struct and the adjusted fields from src.
+ if (hasOnlyOneField(IsFunc, DstInheritance))
+ return FirstField;
+
+ llvm::SmallVector<llvm::Constant *, 4> Fields;
+ Fields.push_back(FirstField);
+ if (hasNonVirtualBaseAdjustmentField(IsFunc, DstInheritance))
+ Fields.push_back(getConstantOrZeroInt(NonVirtualBaseAdjustment));
+ if (hasVBPtrOffsetField(DstInheritance))
+ Fields.push_back(getConstantOrZeroInt(VBPtrOffset));
+ if (hasVirtualBaseAdjustmentField(DstInheritance))
+ Fields.push_back(getConstantOrZeroInt(VirtualBaseAdjustmentOffset));
+ return llvm::ConstantStruct::getAnon(Fields);
+}
+
llvm::Value *
MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
llvm::Value *&This,
@@ -855,4 +1939,3 @@ MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
CGCXXABI *clang::CodeGen::CreateMicrosoftCXXABI(CodeGenModule &CGM) {
return new MicrosoftCXXABI(CGM);
}
-
diff --git a/lib/CodeGen/MicrosoftVBTables.cpp b/lib/CodeGen/MicrosoftVBTables.cpp
new file mode 100644
index 0000000..dabf52c
--- /dev/null
+++ b/lib/CodeGen/MicrosoftVBTables.cpp
@@ -0,0 +1,233 @@
+//===--- MicrosoftVBTables.cpp - Virtual Base Table Emission --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class generates data about MSVC virtual base tables.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MicrosoftVBTables.h"
+#include "CodeGenModule.h"
+#include "CGCXXABI.h"
+
+namespace clang {
+namespace CodeGen {
+
+/// Holds intermediate data about a path to a vbptr inside a base subobject.
+struct VBTablePath {
+ VBTablePath(const VBTableInfo &VBInfo)
+ : VBInfo(VBInfo), NextBase(VBInfo.VBPtrSubobject.getBase()) { }
+
+ /// All the data needed to build a vbtable, minus the GlobalVariable whose
+ /// name we haven't computed yet.
+ VBTableInfo VBInfo;
+
+ /// Next base to use for disambiguation. Can be null if we've already
+ /// disambiguated this path once.
+ const CXXRecordDecl *NextBase;
+
+ /// Path is not really a full path like a CXXBasePath. It holds the subset of
+ /// records that need to be mangled into the vbtable symbol name in order to get
+ /// a unique name.
+ llvm::SmallVector<const CXXRecordDecl *, 1> Path;
+};
+
+VBTableBuilder::VBTableBuilder(CodeGenModule &CGM,
+ const CXXRecordDecl *MostDerived)
+ : CGM(CGM), MostDerived(MostDerived),
+ DerivedLayout(CGM.getContext().getASTRecordLayout(MostDerived)) {}
+
+void VBTableBuilder::enumerateVBTables(VBTableVector &VBTables) {
+ VBTablePathVector Paths;
+ findUnambiguousPaths(MostDerived, BaseSubobject(MostDerived,
+ CharUnits::Zero()), Paths);
+ for (VBTablePathVector::iterator I = Paths.begin(), E = Paths.end();
+ I != E; ++I) {
+ VBTablePath *P = *I;
+ P->VBInfo.GV = getAddrOfVBTable(P->VBInfo.ReusingBase, P->Path);
+ VBTables.push_back(P->VBInfo);
+ }
+}
+
+
+void VBTableBuilder::findUnambiguousPaths(const CXXRecordDecl *ReusingBase,
+ BaseSubobject CurSubobject,
+ VBTablePathVector &Paths) {
+ size_t PathsStart = Paths.size();
+ bool ReuseVBPtrFromBase = true;
+ const CXXRecordDecl *CurBase = CurSubobject.getBase();
+ const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(CurBase);
+
+ // If this base has a vbptr, then we've found a path. These are not full
+ // paths, so we don't use CXXBasePath.
+ if (Layout.hasOwnVBPtr()) {
+ ReuseVBPtrFromBase = false;
+ VBTablePath *Info = new VBTablePath(
+ VBTableInfo(ReusingBase, CurSubobject, /*GV=*/0));
+ Paths.push_back(Info);
+ }
+
+ // Recurse onto any bases which themselves have virtual bases.
+ for (CXXRecordDecl::base_class_const_iterator I = CurBase->bases_begin(),
+ E = CurBase->bases_end(); I != E; ++I) {
+ const CXXRecordDecl *Base = I->getType()->getAsCXXRecordDecl();
+ if (!Base->getNumVBases())
+ continue; // Bases without virtual bases have no vbptrs.
+ CharUnits NextOffset;
+ const CXXRecordDecl *NextReusingBase = Base;
+ if (I->isVirtual()) {
+ if (!VBasesSeen.insert(Base))
+ continue; // Don't visit virtual bases twice.
+ NextOffset = DerivedLayout.getVBaseClassOffset(Base);
+ } else {
+ NextOffset = (CurSubobject.getBaseOffset() +
+ Layout.getBaseClassOffset(Base));
+
+ // If CurBase didn't have a vbptr, then ReusingBase will reuse the vbptr
+ // from the first non-virtual base with vbases for its vbptr.
+ if (ReuseVBPtrFromBase) {
+ NextReusingBase = ReusingBase;
+ ReuseVBPtrFromBase = false;
+ }
+ }
+
+ size_t NumPaths = Paths.size();
+ findUnambiguousPaths(NextReusingBase, BaseSubobject(Base, NextOffset),
+ Paths);
+
+ // Tag paths through this base with the base itself. We might use it to
+ // disambiguate.
+ for (size_t I = NumPaths, E = Paths.size(); I != E; ++I)
+ Paths[I]->NextBase = Base;
+ }
+
+ bool AmbiguousPaths = rebucketPaths(Paths, PathsStart);
+ if (AmbiguousPaths)
+ rebucketPaths(Paths, PathsStart, /*SecondPass=*/true);
+
+#ifndef NDEBUG
+ // Check that the paths are in fact unique.
+ for (size_t I = PathsStart + 1, E = Paths.size(); I != E; ++I) {
+ assert(Paths[I]->Path != Paths[I - 1]->Path && "vbtable paths are not unique");
+ }
+#endif
+}
+
+static bool pathCompare(VBTablePath *LHS, VBTablePath *RHS) {
+ return LHS->Path < RHS->Path;
+}
+
+void VBTableBuilder::extendPath(VBTablePath *P, bool SecondPass) {
+ assert(P->NextBase || SecondPass);
+ if (P->NextBase) {
+ P->Path.push_back(P->NextBase);
+ P->NextBase = 0; // Prevent the path from being extended twice.
+ }
+}
+
+bool VBTableBuilder::rebucketPaths(VBTablePathVector &Paths, size_t PathsStart,
+ bool SecondPass) {
+ // What we're essentially doing here is bucketing together ambiguous paths.
+ // Any bucket with more than one path in it gets extended by NextBase, which
+ // is usually the direct base of the inherited the vbptr. This code uses a
+ // sorted vector to implement a multiset to form the buckets. Note that the
+ // ordering is based on pointers, but it doesn't change our output order. The
+ // current algorithm is designed to match MSVC 2012's names.
+ // TODO: Implement MSVC 2010 or earlier names to avoid extra vbtable cruft.
+ VBTablePathVector PathsSorted(&Paths[PathsStart], &Paths.back() + 1);
+ std::sort(PathsSorted.begin(), PathsSorted.end(), pathCompare);
+ bool AmbiguousPaths = false;
+ for (size_t I = 0, E = PathsSorted.size(); I != E;) {
+ // Scan forward to find the end of the bucket.
+ size_t BucketStart = I;
+ do {
+ ++I;
+ } while (I != E && PathsSorted[BucketStart]->Path == PathsSorted[I]->Path);
+
+ // If this bucket has multiple paths, extend them all.
+ if (I - BucketStart > 1) {
+ AmbiguousPaths = true;
+ for (size_t II = BucketStart; II != I; ++II)
+ extendPath(PathsSorted[II], SecondPass);
+ }
+ }
+ return AmbiguousPaths;
+}
+
+llvm::GlobalVariable *
+VBTableBuilder::getAddrOfVBTable(const CXXRecordDecl *ReusingBase,
+ ArrayRef<const CXXRecordDecl *> BasePath) {
+ // Caching at this layer is redundant with the caching in EnumerateVBTables().
+
+ SmallString<256> OutName;
+ llvm::raw_svector_ostream Out(OutName);
+ MicrosoftMangleContext &Mangler =
+ cast<MicrosoftMangleContext>(CGM.getCXXABI().getMangleContext());
+ Mangler.mangleCXXVBTable(MostDerived, BasePath, Out);
+ Out.flush();
+ StringRef Name = OutName.str();
+
+ llvm::ArrayType *VBTableType =
+ llvm::ArrayType::get(CGM.IntTy, 1 + ReusingBase->getNumVBases());
+
+ assert(!CGM.getModule().getNamedGlobal(Name) &&
+ "vbtable with this name already exists: mangling bug?");
+ llvm::GlobalVariable *VBTable =
+ CGM.CreateOrReplaceCXXRuntimeVariable(Name, VBTableType,
+ llvm::GlobalValue::ExternalLinkage);
+ VBTable->setUnnamedAddr(true);
+ return VBTable;
+}
+
+void VBTableInfo::EmitVBTableDefinition(
+ CodeGenModule &CGM, const CXXRecordDecl *RD,
+ llvm::GlobalVariable::LinkageTypes Linkage) const {
+ assert(RD->getNumVBases() && ReusingBase->getNumVBases() &&
+ "should only emit vbtables for classes with vbtables");
+
+ const ASTRecordLayout &BaseLayout =
+ CGM.getContext().getASTRecordLayout(VBPtrSubobject.getBase());
+ const ASTRecordLayout &DerivedLayout =
+ CGM.getContext().getASTRecordLayout(RD);
+
+ SmallVector<llvm::Constant *, 4> Offsets(1 + ReusingBase->getNumVBases(), 0);
+
+ // The offset from ReusingBase's vbptr to itself always leads.
+ CharUnits VBPtrOffset = BaseLayout.getVBPtrOffset();
+ Offsets[0] = llvm::ConstantInt::get(CGM.IntTy, -VBPtrOffset.getQuantity());
+
+ MicrosoftVTableContext &Context = CGM.getMicrosoftVTableContext();
+ for (CXXRecordDecl::base_class_const_iterator I = ReusingBase->vbases_begin(),
+ E = ReusingBase->vbases_end(); I != E; ++I) {
+ const CXXRecordDecl *VBase = I->getType()->getAsCXXRecordDecl();
+ CharUnits Offset = DerivedLayout.getVBaseClassOffset(VBase);
+ assert(!Offset.isNegative());
+ // Make it relative to the subobject vbptr.
+ Offset -= VBPtrSubobject.getBaseOffset() + VBPtrOffset;
+ unsigned VBIndex = Context.getVBTableIndex(ReusingBase, VBase);
+ assert(Offsets[VBIndex] == 0 && "The same vbindex seen twice?");
+ Offsets[VBIndex] = llvm::ConstantInt::get(CGM.IntTy, Offset.getQuantity());
+ }
+
+ assert(Offsets.size() ==
+ cast<llvm::ArrayType>(cast<llvm::PointerType>(GV->getType())
+ ->getElementType())->getNumElements());
+ llvm::ArrayType *VBTableType =
+ llvm::ArrayType::get(CGM.IntTy, Offsets.size());
+ llvm::Constant *Init = llvm::ConstantArray::get(VBTableType, Offsets);
+ GV->setInitializer(Init);
+
+ // Set the correct linkage.
+ GV->setLinkage(Linkage);
+
+ // Set the right visibility.
+ CGM.setTypeVisibility(GV, RD, CodeGenModule::TVK_ForVTable);
+}
+
+} // namespace CodeGen
+} // namespace clang
diff --git a/lib/CodeGen/MicrosoftVBTables.h b/lib/CodeGen/MicrosoftVBTables.h
new file mode 100644
index 0000000..4ad8e07
--- /dev/null
+++ b/lib/CodeGen/MicrosoftVBTables.h
@@ -0,0 +1,129 @@
+//===--- MicrosoftVBTables.h - Virtual Base Table Emission ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class generates data about MSVC virtual base tables.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/BaseSubobject.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/IR/GlobalVariable.h"
+#include <vector>
+
+namespace clang {
+
+class ASTRecordLayout;
+
+namespace CodeGen {
+
+class CodeGenModule;
+
+struct VBTableInfo {
+ VBTableInfo(const CXXRecordDecl *ReusingBase, BaseSubobject VBPtrSubobject,
+ llvm::GlobalVariable *GV)
+ : ReusingBase(ReusingBase), VBPtrSubobject(VBPtrSubobject), GV(GV) { }
+
+ /// The vbtable will hold all of the virtual bases of ReusingBase. This may
+ /// or may not be the same class as VBPtrSubobject.Base. A derived class will
+ /// reuse the vbptr of the first non-virtual base subobject that has one.
+ const CXXRecordDecl *ReusingBase;
+
+ /// The vbptr is stored inside this subobject.
+ BaseSubobject VBPtrSubobject;
+
+ /// The GlobalVariable for this vbtable.
+ llvm::GlobalVariable *GV;
+
+ /// \brief Emits a definition for GV by setting it's initializer.
+ void EmitVBTableDefinition(CodeGenModule &CGM, const CXXRecordDecl *RD,
+ llvm::GlobalVariable::LinkageTypes Linkage) const;
+};
+
+// These are embedded in a DenseMap and the elements are large, so we don't want
+// SmallVector.
+typedef std::vector<VBTableInfo> VBTableVector;
+
+struct VBTablePath;
+
+typedef llvm::SmallVector<VBTablePath *, 6> VBTablePathVector;
+
+/// Produces MSVC-compatible vbtable data. The symbols produced by this builder
+/// match those produced by MSVC 2012, which is different from MSVC 2010.
+///
+/// Unlike Itanium, which uses only one vtable per class, MSVC uses a different
+/// symbol for every "address point" installed in base subobjects. As a result,
+/// we have to compute unique symbols for every table. Since there can be
+/// multiple non-virtual base subobjects of the same class, combining the most
+/// derived class with the base containing the vtable is insufficient. The most
+/// trivial algorithm would be to mangle in the entire path from base to most
+/// derived, but that would be too easy and would create unnecessarily large
+/// symbols. ;)
+///
+/// MSVC 2012 appears to minimize the vbtable names using the following
+/// algorithm. First, walk the class hierarchy in the usual order, depth first,
+/// left to right, to find all of the subobjects which contain a vbptr field.
+/// Visiting each class node yields a list of inheritance paths to vbptrs. Each
+/// record with a vbptr creates an initially empty path.
+///
+/// To combine paths from child nodes, the paths are compared to check for
+/// ambiguity. Paths are "ambiguous" if multiple paths have the same set of
+/// components in the same order. Each group of ambiguous paths is extended by
+/// appending the class of the base from which it came. If the current class
+/// node produced an ambiguous path, its path is extended with the current class.
+/// After extending paths, MSVC again checks for ambiguity, and extends any
+/// ambiguous path which wasn't already extended. Because each node yields an
+/// unambiguous set of paths, MSVC doesn't need to extend any path more than once
+/// to produce an unambiguous set of paths.
+///
+/// The VBTableBuilder class attempts to implement this algorithm by repeatedly
+/// bucketing paths together by sorting them.
+///
+/// TODO: Presumably vftables use the same algorithm.
+///
+/// TODO: Implement the MSVC 2010 name mangling scheme to avoid emitting
+/// duplicate vbtables with different symbols.
+class VBTableBuilder {
+public:
+ VBTableBuilder(CodeGenModule &CGM, const CXXRecordDecl *MostDerived);
+
+ void enumerateVBTables(VBTableVector &VBTables);
+
+private:
+ bool hasVBPtr(const CXXRecordDecl *RD);
+
+ llvm::GlobalVariable *getAddrOfVBTable(const CXXRecordDecl *ReusingBase,
+ ArrayRef<const CXXRecordDecl *> BasePath);
+
+ /// Enumerates paths to bases with vbptrs. The paths elements are compressed
+ /// to contain only the classes necessary to form an unambiguous path.
+ void findUnambiguousPaths(const CXXRecordDecl *ReusingBase,
+ BaseSubobject CurSubobject,
+ VBTablePathVector &Paths);
+
+ void extendPath(VBTablePath *Info, bool SecondPass);
+
+ bool rebucketPaths(VBTablePathVector &Paths, size_t PathsStart,
+ bool SecondPass = false);
+
+ CodeGenModule &CGM;
+
+ const CXXRecordDecl *MostDerived;
+
+ /// Caches the layout of the most derived class.
+ const ASTRecordLayout &DerivedLayout;
+
+ /// Set of vbases to avoid re-visiting the same vbases.
+ llvm::SmallPtrSet<const CXXRecordDecl*, 4> VBasesSeen;
+};
+
+} // namespace CodeGen
+
+} // namespace clang
diff --git a/lib/CodeGen/ModuleBuilder.cpp b/lib/CodeGen/ModuleBuilder.cpp
index 69e5b32..bc7acbc 100644
--- a/lib/CodeGen/ModuleBuilder.cpp
+++ b/lib/CodeGen/ModuleBuilder.cpp
@@ -13,6 +13,7 @@
#include "clang/CodeGen/ModuleBuilder.h"
#include "CodeGenModule.h"
+#include "CGDebugInfo.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
@@ -20,6 +21,7 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
@@ -58,13 +60,22 @@ namespace {
TD.reset(new llvm::DataLayout(Ctx->getTargetInfo().getTargetDescription()));
Builder.reset(new CodeGen::CodeGenModule(Context, CodeGenOpts, *M, *TD,
Diags));
+
+ for (size_t i = 0, e = CodeGenOpts.DependentLibraries.size(); i < e; ++i)
+ HandleDependentLibrary(CodeGenOpts.DependentLibraries[i]);
}
virtual void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) {
+ if (Diags.hasErrorOccurred())
+ return;
+
Builder->HandleCXXStaticMemberVarInstantiation(VD);
}
virtual bool HandleTopLevelDecl(DeclGroupRef DG) {
+ if (Diags.hasErrorOccurred())
+ return true;
+
// Make sure to emit all elements of a Decl.
for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
Builder->EmitTopLevelDecl(*I);
@@ -76,6 +87,9 @@ namespace {
/// client hack on the type, which can occur at any point in the file
/// (because these can be defined in declspecs).
virtual void HandleTagDeclDefinition(TagDecl *D) {
+ if (Diags.hasErrorOccurred())
+ return;
+
Builder->UpdateCompletedType(D);
// In C++, we may have member functions that need to be emitted at this
@@ -92,6 +106,15 @@ namespace {
}
}
+ virtual void HandleTagDeclRequiredDefinition(const TagDecl *D) LLVM_OVERRIDE {
+ if (Diags.hasErrorOccurred())
+ return;
+
+ if (CodeGen::CGDebugInfo *DI = Builder->getModuleDebugInfo())
+ if (const RecordDecl *RD = dyn_cast<RecordDecl>(D))
+ DI->completeRequiredType(RD);
+ }
+
virtual void HandleTranslationUnit(ASTContext &Ctx) {
if (Diags.hasErrorOccurred()) {
M.reset();
@@ -115,6 +138,19 @@ namespace {
Builder->EmitVTable(RD, DefinitionRequired);
}
+
+ virtual void HandleLinkerOptionPragma(llvm::StringRef Opts) {
+ Builder->AppendLinkerOptions(Opts);
+ }
+
+ virtual void HandleDetectMismatch(llvm::StringRef Name,
+ llvm::StringRef Value) {
+ Builder->AddDetectMismatch(Name, Value);
+ }
+
+ virtual void HandleDependentLibrary(llvm::StringRef Lib) {
+ Builder->AddDependentLib(Lib);
+ }
};
}
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index 32b27b3..76acf87 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -17,6 +17,7 @@
#include "CGCXXABI.h"
#include "CodeGenFunction.h"
#include "clang/AST/RecordLayout.h"
+#include "clang/CodeGen/CGFunctionInfo.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/Triple.h"
#include "llvm/IR/DataLayout.h"
@@ -44,35 +45,40 @@ static bool isAggregateTypeForABI(QualType T) {
ABIInfo::~ABIInfo() {}
-static bool isRecordReturnIndirect(const RecordType *RT, CodeGen::CodeGenTypes &CGT) {
+static bool isRecordReturnIndirect(const RecordType *RT,
+ CGCXXABI &CXXABI) {
const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
if (!RD)
return false;
- return CGT.CGM.getCXXABI().isReturnTypeIndirect(RD);
+ return CXXABI.isReturnTypeIndirect(RD);
}
-static bool isRecordReturnIndirect(QualType T, CodeGen::CodeGenTypes &CGT) {
+static bool isRecordReturnIndirect(QualType T, CGCXXABI &CXXABI) {
const RecordType *RT = T->getAs<RecordType>();
if (!RT)
return false;
- return isRecordReturnIndirect(RT, CGT);
+ return isRecordReturnIndirect(RT, CXXABI);
}
static CGCXXABI::RecordArgABI getRecordArgABI(const RecordType *RT,
- CodeGen::CodeGenTypes &CGT) {
+ CGCXXABI &CXXABI) {
const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
if (!RD)
return CGCXXABI::RAA_Default;
- return CGT.CGM.getCXXABI().getRecordArgABI(RD);
+ return CXXABI.getRecordArgABI(RD);
}
static CGCXXABI::RecordArgABI getRecordArgABI(QualType T,
- CodeGen::CodeGenTypes &CGT) {
+ CGCXXABI &CXXABI) {
const RecordType *RT = T->getAs<RecordType>();
if (!RT)
return CGCXXABI::RAA_Default;
- return getRecordArgABI(RT, CGT);
+ return getRecordArgABI(RT, CXXABI);
+}
+
+CGCXXABI &ABIInfo::getCXXABI() const {
+ return CGT.getCXXABI();
}
ASTContext &ABIInfo::getContext() const {
@@ -143,6 +149,16 @@ bool TargetCodeGenInfo::isNoProtoCallVariadic(const CallArgList &args,
return false;
}
+void
+TargetCodeGenInfo::getDependentLibraryOption(llvm::StringRef Lib,
+ llvm::SmallString<24> &Opt) const {
+ // This assumes the user is passing a library name like "rt" instead of a
+ // filename like "librt.a/so", and that they don't care whether it's static or
+ // dynamic.
+ Opt = "-l";
+ Opt += Lib;
+}
+
static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays);
/// isEmptyField - Return true iff a the field is "empty", that is it
@@ -381,7 +397,7 @@ ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty) const {
if (isAggregateTypeForABI(Ty)) {
// Records with non trivial destructors/constructors should not be passed
// by value.
- if (isRecordReturnIndirect(Ty, CGT))
+ if (isRecordReturnIndirect(Ty, getCXXABI()))
return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
return ABIArgInfo::getIndirect(0);
@@ -451,7 +467,7 @@ llvm::Value *PNaClABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
/// \brief Classify argument of given type \p Ty.
ABIArgInfo PNaClABIInfo::classifyArgumentType(QualType Ty) const {
if (isAggregateTypeForABI(Ty)) {
- if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, CGT))
+ if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
return ABIArgInfo::getIndirect(0);
} else if (const EnumType *EnumTy = Ty->getAs<EnumType>()) {
@@ -493,8 +509,16 @@ bool IsX86_MMXType(llvm::Type *IRType) {
static llvm::Type* X86AdjustInlineAsmType(CodeGen::CodeGenFunction &CGF,
StringRef Constraint,
llvm::Type* Ty) {
- if ((Constraint == "y" || Constraint == "&y") && Ty->isVectorTy())
+ if ((Constraint == "y" || Constraint == "&y") && Ty->isVectorTy()) {
+ if (cast<llvm::VectorType>(Ty)->getBitWidth() != 64) {
+ // Invalid MMX constraint
+ return 0;
+ }
+
return llvm::Type::getX86_MMXTy(CGF.getLLVMContext());
+ }
+
+ // No operation needed
return Ty;
}
@@ -557,6 +581,9 @@ public:
bool d, bool p, bool w, unsigned r)
:TargetCodeGenInfo(new X86_32ABIInfo(CGT, d, p, w, r)) {}
+ static bool isStructReturnInRegABI(
+ const llvm::Triple &Triple, const CodeGenOptions &Opts);
+
void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &CGM) const;
@@ -575,6 +602,14 @@ public:
return X86AdjustInlineAsmType(CGF, Constraint, Ty);
}
+ llvm::Constant *getUBSanFunctionSignature(CodeGen::CodeGenModule &CGM) const {
+ unsigned Sig = (0xeb << 0) | // jmp rel8
+ (0x06 << 8) | // .+0x08
+ ('F' << 16) |
+ ('T' << 24);
+ return llvm::ConstantInt::get(CGM.Int32Ty, Sig);
+ }
+
};
}
@@ -674,7 +709,7 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
if (isAggregateTypeForABI(RetTy)) {
if (const RecordType *RT = RetTy->getAs<RecordType>()) {
- if (isRecordReturnIndirect(RT, CGT))
+ if (isRecordReturnIndirect(RT, getCXXABI()))
return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
// Structures with flexible arrays are always indirect.
@@ -859,7 +894,7 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
if (IsWin32StructABI)
return getIndirectResult(Ty, true, FreeRegs);
- if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, CGT))
+ if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI()))
return getIndirectResult(Ty, RAA == CGCXXABI::RAA_DirectInMemory, FreeRegs);
// Structures with flexible arrays are always indirect.
@@ -876,9 +911,7 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
bool NeedsPadding;
if (shouldUseInReg(Ty, FreeRegs, IsFastCall, NeedsPadding)) {
unsigned SizeInRegs = (getContext().getTypeSize(Ty) + 31) / 32;
- SmallVector<llvm::Type*, 3> Elements;
- for (unsigned I = 0; I < SizeInRegs; ++I)
- Elements.push_back(Int32);
+ SmallVector<llvm::Type*, 3> Elements(SizeInRegs, Int32);
llvm::Type *Result = llvm::StructType::get(LLVMContext, Elements);
return ABIArgInfo::getDirectInReg(Result);
}
@@ -1110,6 +1143,9 @@ class X86_64ABIInfo : public ABIInfo {
/// containing object. Some parameters are classified different
/// depending on whether they straddle an eightbyte boundary.
///
+ /// \param isNamedArg - Whether the argument in question is a "named"
+ /// argument, as used in AMD64-ABI 3.5.7.
+ ///
/// If a word is unused its result will be NoClass; if a type should
/// be passed in Memory then at least the classification of \arg Lo
/// will be Memory.
@@ -1118,7 +1154,8 @@ class X86_64ABIInfo : public ABIInfo {
///
/// If the \arg Lo class is ComplexX87, then the \arg Hi class will
/// also be ComplexX87.
- void classify(QualType T, uint64_t OffsetBase, Class &Lo, Class &Hi) const;
+ void classify(QualType T, uint64_t OffsetBase, Class &Lo, Class &Hi,
+ bool isNamedArg) const;
llvm::Type *GetByteVectorType(QualType Ty) const;
llvm::Type *GetSSETypeAtOffset(llvm::Type *IRType,
@@ -1144,7 +1181,8 @@ class X86_64ABIInfo : public ABIInfo {
ABIArgInfo classifyArgumentType(QualType Ty,
unsigned freeIntRegs,
unsigned &neededInt,
- unsigned &neededSSE) const;
+ unsigned &neededSSE,
+ bool isNamedArg) const;
bool IsIllegalVectorType(QualType Ty) const;
@@ -1171,7 +1209,8 @@ public:
bool isPassedUsingAVXType(QualType type) const {
unsigned neededInt, neededSSE;
// The freeIntRegs argument doesn't matter here.
- ABIArgInfo info = classifyArgumentType(type, 0, neededInt, neededSSE);
+ ABIArgInfo info = classifyArgumentType(type, 0, neededInt, neededSSE,
+ /*isNamedArg*/true);
if (info.isDirect()) {
llvm::Type *ty = info.getCoerceToType();
if (llvm::VectorType *vectorTy = dyn_cast_or_null<llvm::VectorType>(ty))
@@ -1237,7 +1276,7 @@ public:
// that when AVX types are involved: the ABI explicitly states it is
// undefined, and it doesn't work in practice because of how the ABI
// defines varargs anyway.
- if (fnType->getCallConv() == CC_Default || fnType->getCallConv() == CC_C) {
+ if (fnType->getCallConv() == CC_C) {
bool HasAVXType = false;
for (CallArgList::const_iterator
it = args.begin(), ie = args.end(); it != ie; ++it) {
@@ -1254,6 +1293,42 @@ public:
return TargetCodeGenInfo::isNoProtoCallVariadic(args, fnType);
}
+ llvm::Constant *getUBSanFunctionSignature(CodeGen::CodeGenModule &CGM) const {
+ unsigned Sig = (0xeb << 0) | // jmp rel8
+ (0x0a << 8) | // .+0x0c
+ ('F' << 16) |
+ ('T' << 24);
+ return llvm::ConstantInt::get(CGM.Int32Ty, Sig);
+ }
+
+};
+
+static std::string qualifyWindowsLibrary(llvm::StringRef Lib) {
+ // If the argument does not end in .lib, automatically add the suffix. This
+ // matches the behavior of MSVC.
+ std::string ArgStr = Lib;
+ if (!Lib.endswith_lower(".lib"))
+ ArgStr += ".lib";
+ return ArgStr;
+}
+
+class WinX86_32TargetCodeGenInfo : public X86_32TargetCodeGenInfo {
+public:
+ WinX86_32TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT,
+ bool d, bool p, bool w, unsigned RegParms)
+ : X86_32TargetCodeGenInfo(CGT, d, p, w, RegParms) {}
+
+ void getDependentLibraryOption(llvm::StringRef Lib,
+ llvm::SmallString<24> &Opt) const {
+ Opt = "/DEFAULTLIB:";
+ Opt += qualifyWindowsLibrary(Lib);
+ }
+
+ void getDetectMismatchOption(llvm::StringRef Name,
+ llvm::StringRef Value,
+ llvm::SmallString<32> &Opt) const {
+ Opt = "/FAILIFMISMATCH:\"" + Name.str() + "=" + Value.str() + "\"";
+ }
};
class WinX86_64TargetCodeGenInfo : public TargetCodeGenInfo {
@@ -1274,6 +1349,18 @@ public:
AssignToArrayRange(CGF.Builder, Address, Eight8, 0, 16);
return false;
}
+
+ void getDependentLibraryOption(llvm::StringRef Lib,
+ llvm::SmallString<24> &Opt) const {
+ Opt = "/DEFAULTLIB:";
+ Opt += qualifyWindowsLibrary(Lib);
+ }
+
+ void getDetectMismatchOption(llvm::StringRef Name,
+ llvm::StringRef Value,
+ llvm::SmallString<32> &Opt) const {
+ Opt = "/FAILIFMISMATCH:\"" + Name.str() + "=" + Value.str() + "\"";
+ }
};
}
@@ -1352,7 +1439,7 @@ X86_64ABIInfo::Class X86_64ABIInfo::merge(Class Accum, Class Field) {
}
void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
- Class &Lo, Class &Hi) const {
+ Class &Lo, Class &Hi, bool isNamedArg) const {
// FIXME: This code can be simplified by introducing a simple value class for
// Class pairs with appropriate constructor methods for the various
// situations.
@@ -1378,7 +1465,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
Current = Integer;
} else if ((k == BuiltinType::Float || k == BuiltinType::Double) ||
(k == BuiltinType::LongDouble &&
- getTarget().getTriple().getOS() == llvm::Triple::NaCl)) {
+ getTarget().getTriple().isOSNaCl())) {
Current = SSE;
} else if (k == BuiltinType::LongDouble) {
Lo = X87;
@@ -1391,7 +1478,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
if (const EnumType *ET = Ty->getAs<EnumType>()) {
// Classify the underlying integer type.
- classify(ET->getDecl()->getIntegerType(), OffsetBase, Lo, Hi);
+ classify(ET->getDecl()->getIntegerType(), OffsetBase, Lo, Hi, isNamedArg);
return;
}
@@ -1439,7 +1526,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
// split.
if (OffsetBase && OffsetBase != 64)
Hi = Lo;
- } else if (Size == 128 || (HasAVX && Size == 256)) {
+ } else if (Size == 128 || (HasAVX && isNamedArg && Size == 256)) {
// Arguments of 256-bits are split into four eightbyte chunks. The
// least significant one belongs to class SSE and all the others to class
// SSEUP. The original Lo and Hi design considers that types can't be
@@ -1447,6 +1534,10 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
// This design isn't correct for 256-bits, but since there're no cases
// where the upper parts would need to be inspected, avoid adding
// complexity and just consider Hi to match the 64-256 part.
+ //
+ // Note that per 3.5.7 of AMD64-ABI, 256-bit args are only passed in
+ // registers if they are "named", i.e. not part of the "..." of a
+ // variadic function.
Lo = SSE;
Hi = SSEUp;
}
@@ -1466,7 +1557,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
Current = SSE;
else if (ET == getContext().DoubleTy ||
(ET == getContext().LongDoubleTy &&
- getTarget().getTriple().getOS() == llvm::Triple::NaCl))
+ getTarget().getTriple().isOSNaCl()))
Lo = Hi = SSE;
else if (ET == getContext().LongDoubleTy)
Current = ComplexX87;
@@ -1512,7 +1603,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
for (uint64_t i=0, Offset=OffsetBase; i<ArraySize; ++i, Offset += EltSize) {
Class FieldLo, FieldHi;
- classify(AT->getElementType(), Offset, FieldLo, FieldHi);
+ classify(AT->getElementType(), Offset, FieldLo, FieldHi, isNamedArg);
Lo = merge(Lo, FieldLo);
Hi = merge(Hi, FieldHi);
if (Lo == Memory || Hi == Memory)
@@ -1535,7 +1626,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
// AMD64-ABI 3.2.3p2: Rule 2. If a C++ object has either a non-trivial
// copy constructor or a non-trivial destructor, it is passed by invisible
// reference.
- if (getRecordArgABI(RT, CGT))
+ if (getRecordArgABI(RT, getCXXABI()))
return;
const RecordDecl *RD = RT->getDecl();
@@ -1566,7 +1657,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
Class FieldLo, FieldHi;
uint64_t Offset =
OffsetBase + getContext().toBits(Layout.getBaseClassOffset(Base));
- classify(i->getType(), Offset, FieldLo, FieldHi);
+ classify(i->getType(), Offset, FieldLo, FieldHi, isNamedArg);
Lo = merge(Lo, FieldLo);
Hi = merge(Hi, FieldHi);
if (Lo == Memory || Hi == Memory)
@@ -1619,7 +1710,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
uint64_t EB_Lo = Offset / 64;
uint64_t EB_Hi = (Offset + Size - 1) / 64;
- FieldLo = FieldHi = NoClass;
+
if (EB_Lo) {
assert(EB_Hi == EB_Lo && "Invalid classification, type > 16 bytes.");
FieldLo = NoClass;
@@ -1629,7 +1720,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
FieldHi = EB_Hi ? Integer : NoClass;
}
} else
- classify(i->getType(), Offset, FieldLo, FieldHi);
+ classify(i->getType(), Offset, FieldLo, FieldHi, isNamedArg);
Lo = merge(Lo, FieldLo);
Hi = merge(Hi, FieldHi);
if (Lo == Memory || Hi == Memory)
@@ -1685,7 +1776,7 @@ ABIArgInfo X86_64ABIInfo::getIndirectResult(QualType Ty,
ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
}
- if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, CGT))
+ if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
// Compute the byval alignment. We specify the alignment of the byval in all
@@ -2017,7 +2108,7 @@ classifyReturnType(QualType RetTy) const {
// AMD64-ABI 3.2.3p4: Rule 1. Classify the return type with the
// classification algorithm.
X86_64ABIInfo::Class Lo, Hi;
- classify(RetTy, 0, Lo, Hi);
+ classify(RetTy, 0, Lo, Hi, /*isNamedArg*/ true);
// Check some invariants.
assert((Hi != Memory || Lo == Memory) && "Invalid memory classification.");
@@ -2142,11 +2233,12 @@ classifyReturnType(QualType RetTy) const {
}
ABIArgInfo X86_64ABIInfo::classifyArgumentType(
- QualType Ty, unsigned freeIntRegs, unsigned &neededInt, unsigned &neededSSE)
+ QualType Ty, unsigned freeIntRegs, unsigned &neededInt, unsigned &neededSSE,
+ bool isNamedArg)
const
{
X86_64ABIInfo::Class Lo, Hi;
- classify(Ty, 0, Lo, Hi);
+ classify(Ty, 0, Lo, Hi, isNamedArg);
// Check some invariants.
// FIXME: Enforce these by construction.
@@ -2174,7 +2266,7 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(
// COMPLEX_X87, it is passed in memory.
case X87:
case ComplexX87:
- if (getRecordArgABI(Ty, CGT) == CGCXXABI::RAA_Indirect)
+ if (getRecordArgABI(Ty, getCXXABI()) == CGCXXABI::RAA_Indirect)
++neededInt;
return getIndirectResult(Ty, freeIntRegs);
@@ -2279,13 +2371,23 @@ void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
if (FI.getReturnInfo().isIndirect())
--freeIntRegs;
+ bool isVariadic = FI.isVariadic();
+ unsigned numRequiredArgs = 0;
+ if (isVariadic)
+ numRequiredArgs = FI.getRequiredArgs().getNumRequiredArgs();
+
// AMD64-ABI 3.2.3p3: Once arguments are classified, the registers
// get assigned (in left-to-right order) for passing as follows...
for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
it != ie; ++it) {
+ bool isNamedArg = true;
+ if (isVariadic)
+ isNamedArg = (it - FI.arg_begin()) <
+ static_cast<signed>(numRequiredArgs);
+
unsigned neededInt, neededSSE;
it->info = classifyArgumentType(it->type, freeIntRegs, neededInt,
- neededSSE);
+ neededSSE, isNamedArg);
// AMD64-ABI 3.2.3p3: If there are no registers available for any
// eightbyte of an argument, the whole argument is passed on the
@@ -2361,7 +2463,8 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
unsigned neededInt, neededSSE;
Ty = CGF.getContext().getCanonicalType(Ty);
- ABIArgInfo AI = classifyArgumentType(Ty, 0, neededInt, neededSSE);
+ ABIArgInfo AI = classifyArgumentType(Ty, 0, neededInt, neededSSE,
+ /*isNamedArg*/false);
// AMD64-ABI 3.5.7p5: Step 1. Determine whether type may be passed
// in the registers. If not go to step 7.
@@ -2425,7 +2528,8 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
// FIXME: Cleanup.
assert(AI.isDirect() && "Unexpected ABI info for mixed regs");
llvm::StructType *ST = cast<llvm::StructType>(AI.getCoerceToType());
- llvm::Value *Tmp = CGF.CreateTempAlloca(ST);
+ llvm::Value *Tmp = CGF.CreateMemTemp(Ty);
+ Tmp = CGF.Builder.CreateBitCast(Tmp, ST->getPointerTo());
assert(ST->getNumElements() == 2 && "Unexpected ABI info for mixed regs");
llvm::Type *TyLo = ST->getElementType(0);
llvm::Type *TyHi = ST->getElementType(1);
@@ -2449,6 +2553,17 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
RegAddr = CGF.Builder.CreateGEP(RegAddr, gp_offset);
RegAddr = CGF.Builder.CreateBitCast(RegAddr,
llvm::PointerType::getUnqual(LTy));
+
+ // Copy to a temporary if necessary to ensure the appropriate alignment.
+ std::pair<CharUnits, CharUnits> SizeAlign =
+ CGF.getContext().getTypeInfoInChars(Ty);
+ uint64_t TySize = SizeAlign.first.getQuantity();
+ unsigned TyAlign = SizeAlign.second.getQuantity();
+ if (TyAlign > 8) {
+ llvm::Value *Tmp = CGF.CreateMemTemp(Ty);
+ CGF.Builder.CreateMemCpy(Tmp, RegAddr, TySize, 8, false);
+ RegAddr = Tmp;
+ }
} else if (neededSSE == 1) {
RegAddr = CGF.Builder.CreateGEP(RegAddr, fp_offset);
RegAddr = CGF.Builder.CreateBitCast(RegAddr,
@@ -2462,9 +2577,9 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
llvm::Type *DoubleTy = CGF.DoubleTy;
llvm::Type *DblPtrTy =
llvm::PointerType::getUnqual(DoubleTy);
- llvm::StructType *ST = llvm::StructType::get(DoubleTy,
- DoubleTy, NULL);
- llvm::Value *V, *Tmp = CGF.CreateTempAlloca(ST);
+ llvm::StructType *ST = llvm::StructType::get(DoubleTy, DoubleTy, NULL);
+ llvm::Value *V, *Tmp = CGF.CreateMemTemp(Ty);
+ Tmp = CGF.Builder.CreateBitCast(Tmp, ST->getPointerTo());
V = CGF.Builder.CreateLoad(CGF.Builder.CreateBitCast(RegAddrLo,
DblPtrTy));
CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 0));
@@ -2517,10 +2632,10 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, bool IsReturnType) const {
if (const RecordType *RT = Ty->getAs<RecordType>()) {
if (IsReturnType) {
- if (isRecordReturnIndirect(RT, CGT))
+ if (isRecordReturnIndirect(RT, getCXXABI()))
return ABIArgInfo::getIndirect(0, false);
} else {
- if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, CGT))
+ if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI()))
return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
}
@@ -2702,11 +2817,11 @@ public:
it != ie; ++it) {
// We rely on the default argument classification for the most part.
// One exception: An aggregate containing a single floating-point
- // item must be passed in a register if one is available.
+ // or vector item must be passed in a register if one is available.
const Type *T = isSingleElementStruct(it->type, getContext());
if (T) {
const BuiltinType *BT = T->getAs<BuiltinType>();
- if (BT && BT->isFloatingPoint()) {
+ if (T->isVectorType() || (BT && BT->isFloatingPoint())) {
QualType QT(T, 0);
it->info = ABIArgInfo::getDirectInReg(CGT.ConvertType(QT));
continue;
@@ -2782,7 +2897,7 @@ PPC64_SVR4_ABIInfo::classifyArgumentType(QualType Ty) const {
return ABIArgInfo::getDirect();
if (isAggregateTypeForABI(Ty)) {
- if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, CGT))
+ if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
return ABIArgInfo::getIndirect(0);
@@ -2961,9 +3076,9 @@ public:
Env == "android" || Env == "androideabi");
}
-private:
ABIKind getABIKind() const { return Kind; }
+private:
ABIArgInfo classifyReturnType(QualType RetTy) const;
ABIArgInfo classifyArgumentType(QualType RetTy, int *VFPRegs,
unsigned &AllocatedVFP,
@@ -3010,6 +3125,45 @@ public:
if (getABIInfo().isEABI()) return 88;
return TargetCodeGenInfo::getSizeOfUnwindException();
}
+
+ void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &CGM) const {
+ const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+ if (!FD)
+ return;
+
+ const ARMInterruptAttr *Attr = FD->getAttr<ARMInterruptAttr>();
+ if (!Attr)
+ return;
+
+ const char *Kind;
+ switch (Attr->getInterrupt()) {
+ case ARMInterruptAttr::Generic: Kind = ""; break;
+ case ARMInterruptAttr::IRQ: Kind = "IRQ"; break;
+ case ARMInterruptAttr::FIQ: Kind = "FIQ"; break;
+ case ARMInterruptAttr::SWI: Kind = "SWI"; break;
+ case ARMInterruptAttr::ABORT: Kind = "ABORT"; break;
+ case ARMInterruptAttr::UNDEF: Kind = "UNDEF"; break;
+ }
+
+ llvm::Function *Fn = cast<llvm::Function>(GV);
+
+ Fn->addFnAttr("interrupt", Kind);
+
+ if (cast<ARMABIInfo>(getABIInfo()).getABIKind() == ARMABIInfo::APCS)
+ return;
+
+ // AAPCS guarantees that sp will be 8-byte aligned on any public interface,
+ // however this is not necessarily true on taking any interrupt. Instruct
+ // the backend to perform a realignment as part of the function prologue.
+ llvm::AttrBuilder B;
+ B.addStackAlignmentAttr(8);
+ Fn->addAttributes(llvm::AttributeSet::FunctionIndex,
+ llvm::AttributeSet::get(CGM.getLLVMContext(),
+ llvm::AttributeSet::FunctionIndex,
+ B));
+ }
+
};
}
@@ -3243,13 +3397,13 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, int *VFPRegs,
ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
}
+ if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
+ return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
+
// Ignore empty records.
if (isEmptyRecord(getContext(), Ty, true))
return ABIArgInfo::getIgnore();
- if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, CGT))
- return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
-
if (getABIKind() == ARMABIInfo::AAPCS_VFP) {
// Homogeneous Aggregates need to be expanded when we can fit the aggregate
// into VFP registers.
@@ -3411,7 +3565,7 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy) const {
// Structures with either a non-trivial destructor or a non-trivial
// copy constructor are always indirect.
- if (isRecordReturnIndirect(RetTy, CGT))
+ if (isRecordReturnIndirect(RetTy, getCXXABI()))
return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
// Are we following APCS?
@@ -3496,6 +3650,12 @@ llvm::Value *ARMABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP, "ap");
llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur");
+ if (isEmptyRecord(getContext(), Ty, true)) {
+ // These are ignored for parameter passing purposes.
+ llvm::Type *PTy = llvm::PointerType::getUnqual(CGF.ConvertType(Ty));
+ return Builder.CreateBitCast(Addr, PTy);
+ }
+
uint64_t Size = CGF.getContext().getTypeSize(Ty) / 8;
uint64_t TyAlign = CGF.getContext().getTypeAlign(Ty) / 8;
bool IsIndirect = false;
@@ -3735,7 +3895,7 @@ ABIArgInfo AArch64ABIInfo::classifyGenericType(QualType Ty,
return tryUseRegs(Ty, FreeIntRegs, RegsNeeded, /*IsInt=*/ true);
}
- if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, CGT)) {
+ if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
if (FreeIntRegs > 0 && RAA == CGCXXABI::RAA_Indirect)
--FreeIntRegs;
return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
@@ -4037,16 +4197,26 @@ private:
ABIArgInfo NVPTXABIInfo::classifyReturnType(QualType RetTy) const {
if (RetTy->isVoidType())
return ABIArgInfo::getIgnore();
- if (isAggregateTypeForABI(RetTy))
- return ABIArgInfo::getIndirect(0);
- return ABIArgInfo::getDirect();
+
+ // note: this is different from default ABI
+ if (!RetTy->isScalarType())
+ return ABIArgInfo::getDirect();
+
+ // Treat an enum type as its underlying type.
+ if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
+ RetTy = EnumTy->getDecl()->getIntegerType();
+
+ return (RetTy->isPromotableIntegerType() ?
+ ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
}
ABIArgInfo NVPTXABIInfo::classifyArgumentType(QualType Ty) const {
- if (isAggregateTypeForABI(Ty))
- return ABIArgInfo::getIndirect(0);
+ // Treat an enum type as its underlying type.
+ if (const EnumType *EnumTy = Ty->getAs<EnumType>())
+ Ty = EnumTy->getDecl()->getIntegerType();
- return ABIArgInfo::getDirect();
+ return (Ty->isPromotableIntegerType() ?
+ ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
}
void NVPTXABIInfo::computeInfo(CGFunctionInfo &FI) const {
@@ -4351,6 +4521,36 @@ llvm::Value *SystemZABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
return ResAddr;
}
+bool X86_32TargetCodeGenInfo::isStructReturnInRegABI(
+ const llvm::Triple &Triple, const CodeGenOptions &Opts) {
+ assert(Triple.getArch() == llvm::Triple::x86);
+
+ switch (Opts.getStructReturnConvention()) {
+ case CodeGenOptions::SRCK_Default:
+ break;
+ case CodeGenOptions::SRCK_OnStack: // -fpcc-struct-return
+ return false;
+ case CodeGenOptions::SRCK_InRegs: // -freg-struct-return
+ return true;
+ }
+
+ if (Triple.isOSDarwin())
+ return true;
+
+ switch (Triple.getOS()) {
+ case llvm::Triple::Cygwin:
+ case llvm::Triple::MinGW32:
+ case llvm::Triple::AuroraUX:
+ case llvm::Triple::DragonFly:
+ case llvm::Triple::FreeBSD:
+ case llvm::Triple::OpenBSD:
+ case llvm::Triple::Bitrig:
+ case llvm::Triple::Win32:
+ return true;
+ default:
+ return false;
+ }
+}
ABIArgInfo SystemZABIInfo::classifyReturnType(QualType RetTy) const {
if (RetTy->isVoidType())
@@ -4363,7 +4563,7 @@ ABIArgInfo SystemZABIInfo::classifyReturnType(QualType RetTy) const {
ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const {
// Handle the generic C++ ABI.
- if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, CGT))
+ if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
// Integers and enums are extended to full register width.
@@ -4373,7 +4573,7 @@ ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const {
// Values that are not 1, 2, 4 or 8 bytes in size are passed indirectly.
uint64_t Size = getContext().getTypeSize(Ty);
if (Size != 8 && Size != 16 && Size != 32 && Size != 64)
- return ABIArgInfo::getIndirect(0);
+ return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
// Handle small structures.
if (const RecordType *RT = Ty->getAs<RecordType>()) {
@@ -4381,7 +4581,7 @@ ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const {
// fail the size test above.
const RecordDecl *RD = RT->getDecl();
if (RD->hasFlexibleArrayMember())
- return ABIArgInfo::getIndirect(0);
+ return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
// The structure is passed as an unextended integer, a float, or a double.
llvm::Type *PassTy;
@@ -4398,122 +4598,12 @@ ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const {
// Non-structure compounds are passed indirectly.
if (isCompoundType(Ty))
- return ABIArgInfo::getIndirect(0);
+ return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
return ABIArgInfo::getDirect(0);
}
//===----------------------------------------------------------------------===//
-// MBlaze ABI Implementation
-//===----------------------------------------------------------------------===//
-
-namespace {
-
-class MBlazeABIInfo : public ABIInfo {
-public:
- MBlazeABIInfo(CodeGenTypes &CGT) : ABIInfo(CGT) {}
-
- bool isPromotableIntegerType(QualType Ty) const;
-
- ABIArgInfo classifyReturnType(QualType RetTy) const;
- ABIArgInfo classifyArgumentType(QualType RetTy) const;
-
- virtual void computeInfo(CGFunctionInfo &FI) const {
- FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
- for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
- it != ie; ++it)
- it->info = classifyArgumentType(it->type);
- }
-
- virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const;
-};
-
-class MBlazeTargetCodeGenInfo : public TargetCodeGenInfo {
-public:
- MBlazeTargetCodeGenInfo(CodeGenTypes &CGT)
- : TargetCodeGenInfo(new MBlazeABIInfo(CGT)) {}
- void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &M) const;
-};
-
-}
-
-bool MBlazeABIInfo::isPromotableIntegerType(QualType Ty) const {
- // MBlaze ABI requires all 8 and 16 bit quantities to be extended.
- if (const BuiltinType *BT = Ty->getAs<BuiltinType>())
- switch (BT->getKind()) {
- case BuiltinType::Bool:
- case BuiltinType::Char_S:
- case BuiltinType::Char_U:
- case BuiltinType::SChar:
- case BuiltinType::UChar:
- case BuiltinType::Short:
- case BuiltinType::UShort:
- return true;
- default:
- return false;
- }
- return false;
-}
-
-llvm::Value *MBlazeABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const {
- // FIXME: Implement
- return 0;
-}
-
-
-ABIArgInfo MBlazeABIInfo::classifyReturnType(QualType RetTy) const {
- if (RetTy->isVoidType())
- return ABIArgInfo::getIgnore();
- if (isAggregateTypeForABI(RetTy))
- return ABIArgInfo::getIndirect(0);
-
- return (isPromotableIntegerType(RetTy) ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
-}
-
-ABIArgInfo MBlazeABIInfo::classifyArgumentType(QualType Ty) const {
- if (isAggregateTypeForABI(Ty))
- return ABIArgInfo::getIndirect(0);
-
- return (isPromotableIntegerType(Ty) ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
-}
-
-void MBlazeTargetCodeGenInfo::SetTargetAttributes(const Decl *D,
- llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &M)
- const {
- const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
- if (!FD) return;
-
- llvm::CallingConv::ID CC = llvm::CallingConv::C;
- if (FD->hasAttr<MBlazeInterruptHandlerAttr>())
- CC = llvm::CallingConv::MBLAZE_INTR;
- else if (FD->hasAttr<MBlazeSaveVolatilesAttr>())
- CC = llvm::CallingConv::MBLAZE_SVOL;
-
- if (CC != llvm::CallingConv::C) {
- // Handle 'interrupt_handler' attribute:
- llvm::Function *F = cast<llvm::Function>(GV);
-
- // Step 1: Set ISR calling convention.
- F->setCallingConv(CC);
-
- // Step 2: Add attributes goodness.
- F->addFnAttr(llvm::Attribute::NoInline);
- }
-
- // Step 3: Emit _interrupt_handler alias.
- if (CC == llvm::CallingConv::MBLAZE_INTR)
- new llvm::GlobalAlias(GV->getType(), llvm::Function::ExternalLinkage,
- "_interrupt_handler", GV, &M.getModule());
-}
-
-
-//===----------------------------------------------------------------------===//
// MSP430 ABI Implementation
//===----------------------------------------------------------------------===//
@@ -4562,7 +4652,7 @@ class MipsABIInfo : public ABIInfo {
bool IsO32;
unsigned MinABIStackAlignInBytes, StackAlignInBytes;
void CoerceToIntArgs(uint64_t TySize,
- SmallVector<llvm::Type*, 8> &ArgList) const;
+ SmallVectorImpl<llvm::Type *> &ArgList) const;
llvm::Type* HandleAggregates(QualType Ty, uint64_t TySize) const;
llvm::Type* returnAggregateInRegs(QualType RetTy, uint64_t Size) const;
llvm::Type* getPaddingType(uint64_t Align, uint64_t Offset) const;
@@ -4612,7 +4702,7 @@ public:
}
void MipsABIInfo::CoerceToIntArgs(uint64_t TySize,
- SmallVector<llvm::Type*, 8> &ArgList) const {
+ SmallVectorImpl<llvm::Type *> &ArgList) const {
llvm::IntegerType *IntTy =
llvm::IntegerType::get(getVMContext(), MinABIStackAlignInBytes * 8);
@@ -4685,13 +4775,12 @@ llvm::Type* MipsABIInfo::HandleAggregates(QualType Ty, uint64_t TySize) const {
return llvm::StructType::get(getVMContext(), ArgList);
}
-llvm::Type *MipsABIInfo::getPaddingType(uint64_t Align, uint64_t Offset) const {
- assert((Offset % MinABIStackAlignInBytes) == 0);
-
- if ((Align - 1) & Offset)
- return llvm::IntegerType::get(getVMContext(), MinABIStackAlignInBytes * 8);
+llvm::Type *MipsABIInfo::getPaddingType(uint64_t OrigOffset,
+ uint64_t Offset) const {
+ if (OrigOffset + MinABIStackAlignInBytes > Offset)
+ return 0;
- return 0;
+ return llvm::IntegerType::get(getVMContext(), (Offset - OrigOffset) * 8);
}
ABIArgInfo
@@ -4702,15 +4791,15 @@ MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset) const {
Align = std::min(std::max(Align, (uint64_t)MinABIStackAlignInBytes),
(uint64_t)StackAlignInBytes);
- Offset = llvm::RoundUpToAlignment(Offset, Align);
- Offset += llvm::RoundUpToAlignment(TySize, Align * 8) / 8;
+ unsigned CurrOffset = llvm::RoundUpToAlignment(Offset, Align);
+ Offset = CurrOffset + llvm::RoundUpToAlignment(TySize, Align * 8) / 8;
if (isAggregateTypeForABI(Ty) || Ty->isVectorType()) {
// Ignore empty aggregates.
if (TySize == 0)
return ABIArgInfo::getIgnore();
- if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, CGT)) {
+ if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
Offset = OrigOffset + MinABIStackAlignInBytes;
return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
}
@@ -4719,7 +4808,7 @@ MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset) const {
// another structure type. Padding is inserted if the offset of the
// aggregate is unaligned.
return ABIArgInfo::getDirect(HandleAggregates(Ty, TySize), 0,
- getPaddingType(Align, OrigOffset));
+ getPaddingType(OrigOffset, CurrOffset));
}
// Treat an enum type as its underlying type.
@@ -4729,8 +4818,8 @@ MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset) const {
if (Ty->isPromotableIntegerType())
return ABIArgInfo::getExtend();
- return ABIArgInfo::getDirect(0, 0,
- IsO32 ? 0 : getPaddingType(Align, OrigOffset));
+ return ABIArgInfo::getDirect(
+ 0, 0, IsO32 ? 0 : getPaddingType(OrigOffset, CurrOffset));
}
llvm::Type*
@@ -4782,7 +4871,7 @@ ABIArgInfo MipsABIInfo::classifyReturnType(QualType RetTy) const {
return ABIArgInfo::getIgnore();
if (isAggregateTypeForABI(RetTy) || RetTy->isVectorType()) {
- if (isRecordReturnIndirect(RetTy, CGT))
+ if (isRecordReturnIndirect(RetTy, getCXXABI()))
return ABIArgInfo::getIndirect(0);
if (Size <= 128) {
@@ -5003,7 +5092,7 @@ ABIArgInfo HexagonABIInfo::classifyArgumentType(QualType Ty) const {
if (isEmptyRecord(getContext(), Ty, true))
return ABIArgInfo::getIgnore();
- if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, CGT))
+ if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
uint64_t Size = getContext().getTypeSize(Ty);
@@ -5039,7 +5128,7 @@ ABIArgInfo HexagonABIInfo::classifyReturnType(QualType RetTy) const {
// Structures with either a non-trivial destructor or a non-trivial
// copy constructor are always indirect.
- if (isRecordReturnIndirect(RetTy, CGT))
+ if (isRecordReturnIndirect(RetTy, getCXXABI()))
return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
if (isEmptyRecord(getContext(), RetTy, true))
@@ -5086,6 +5175,335 @@ llvm::Value *HexagonABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
}
+//===----------------------------------------------------------------------===//
+// SPARC v9 ABI Implementation.
+// Based on the SPARC Compliance Definition version 2.4.1.
+//
+// Function arguments a mapped to a nominal "parameter array" and promoted to
+// registers depending on their type. Each argument occupies 8 or 16 bytes in
+// the array, structs larger than 16 bytes are passed indirectly.
+//
+// One case requires special care:
+//
+// struct mixed {
+// int i;
+// float f;
+// };
+//
+// When a struct mixed is passed by value, it only occupies 8 bytes in the
+// parameter array, but the int is passed in an integer register, and the float
+// is passed in a floating point register. This is represented as two arguments
+// with the LLVM IR inreg attribute:
+//
+// declare void f(i32 inreg %i, float inreg %f)
+//
+// The code generator will only allocate 4 bytes from the parameter array for
+// the inreg arguments. All other arguments are allocated a multiple of 8
+// bytes.
+//
+namespace {
+class SparcV9ABIInfo : public ABIInfo {
+public:
+ SparcV9ABIInfo(CodeGenTypes &CGT) : ABIInfo(CGT) {}
+
+private:
+ ABIArgInfo classifyType(QualType RetTy, unsigned SizeLimit) const;
+ virtual void computeInfo(CGFunctionInfo &FI) const;
+ virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+ CodeGenFunction &CGF) const;
+
+ // Coercion type builder for structs passed in registers. The coercion type
+ // serves two purposes:
+ //
+ // 1. Pad structs to a multiple of 64 bits, so they are passed 'left-aligned'
+ // in registers.
+ // 2. Expose aligned floating point elements as first-level elements, so the
+ // code generator knows to pass them in floating point registers.
+ //
+ // We also compute the InReg flag which indicates that the struct contains
+ // aligned 32-bit floats.
+ //
+ struct CoerceBuilder {
+ llvm::LLVMContext &Context;
+ const llvm::DataLayout &DL;
+ SmallVector<llvm::Type*, 8> Elems;
+ uint64_t Size;
+ bool InReg;
+
+ CoerceBuilder(llvm::LLVMContext &c, const llvm::DataLayout &dl)
+ : Context(c), DL(dl), Size(0), InReg(false) {}
+
+ // Pad Elems with integers until Size is ToSize.
+ void pad(uint64_t ToSize) {
+ assert(ToSize >= Size && "Cannot remove elements");
+ if (ToSize == Size)
+ return;
+
+ // Finish the current 64-bit word.
+ uint64_t Aligned = llvm::RoundUpToAlignment(Size, 64);
+ if (Aligned > Size && Aligned <= ToSize) {
+ Elems.push_back(llvm::IntegerType::get(Context, Aligned - Size));
+ Size = Aligned;
+ }
+
+ // Add whole 64-bit words.
+ while (Size + 64 <= ToSize) {
+ Elems.push_back(llvm::Type::getInt64Ty(Context));
+ Size += 64;
+ }
+
+ // Final in-word padding.
+ if (Size < ToSize) {
+ Elems.push_back(llvm::IntegerType::get(Context, ToSize - Size));
+ Size = ToSize;
+ }
+ }
+
+ // Add a floating point element at Offset.
+ void addFloat(uint64_t Offset, llvm::Type *Ty, unsigned Bits) {
+ // Unaligned floats are treated as integers.
+ if (Offset % Bits)
+ return;
+ // The InReg flag is only required if there are any floats < 64 bits.
+ if (Bits < 64)
+ InReg = true;
+ pad(Offset);
+ Elems.push_back(Ty);
+ Size = Offset + Bits;
+ }
+
+ // Add a struct type to the coercion type, starting at Offset (in bits).
+ void addStruct(uint64_t Offset, llvm::StructType *StrTy) {
+ const llvm::StructLayout *Layout = DL.getStructLayout(StrTy);
+ for (unsigned i = 0, e = StrTy->getNumElements(); i != e; ++i) {
+ llvm::Type *ElemTy = StrTy->getElementType(i);
+ uint64_t ElemOffset = Offset + Layout->getElementOffsetInBits(i);
+ switch (ElemTy->getTypeID()) {
+ case llvm::Type::StructTyID:
+ addStruct(ElemOffset, cast<llvm::StructType>(ElemTy));
+ break;
+ case llvm::Type::FloatTyID:
+ addFloat(ElemOffset, ElemTy, 32);
+ break;
+ case llvm::Type::DoubleTyID:
+ addFloat(ElemOffset, ElemTy, 64);
+ break;
+ case llvm::Type::FP128TyID:
+ addFloat(ElemOffset, ElemTy, 128);
+ break;
+ case llvm::Type::PointerTyID:
+ if (ElemOffset % 64 == 0) {
+ pad(ElemOffset);
+ Elems.push_back(ElemTy);
+ Size += 64;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ // Check if Ty is a usable substitute for the coercion type.
+ bool isUsableType(llvm::StructType *Ty) const {
+ if (Ty->getNumElements() != Elems.size())
+ return false;
+ for (unsigned i = 0, e = Elems.size(); i != e; ++i)
+ if (Elems[i] != Ty->getElementType(i))
+ return false;
+ return true;
+ }
+
+ // Get the coercion type as a literal struct type.
+ llvm::Type *getType() const {
+ if (Elems.size() == 1)
+ return Elems.front();
+ else
+ return llvm::StructType::get(Context, Elems);
+ }
+ };
+};
+} // end anonymous namespace
+
+ABIArgInfo
+SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit) const {
+ if (Ty->isVoidType())
+ return ABIArgInfo::getIgnore();
+
+ uint64_t Size = getContext().getTypeSize(Ty);
+
+ // Anything too big to fit in registers is passed with an explicit indirect
+ // pointer / sret pointer.
+ if (Size > SizeLimit)
+ return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+
+ // Treat an enum type as its underlying type.
+ if (const EnumType *EnumTy = Ty->getAs<EnumType>())
+ Ty = EnumTy->getDecl()->getIntegerType();
+
+ // Integer types smaller than a register are extended.
+ if (Size < 64 && Ty->isIntegerType())
+ return ABIArgInfo::getExtend();
+
+ // Other non-aggregates go in registers.
+ if (!isAggregateTypeForABI(Ty))
+ return ABIArgInfo::getDirect();
+
+ // This is a small aggregate type that should be passed in registers.
+ // Build a coercion type from the LLVM struct type.
+ llvm::StructType *StrTy = dyn_cast<llvm::StructType>(CGT.ConvertType(Ty));
+ if (!StrTy)
+ return ABIArgInfo::getDirect();
+
+ CoerceBuilder CB(getVMContext(), getDataLayout());
+ CB.addStruct(0, StrTy);
+ CB.pad(llvm::RoundUpToAlignment(CB.DL.getTypeSizeInBits(StrTy), 64));
+
+ // Try to use the original type for coercion.
+ llvm::Type *CoerceTy = CB.isUsableType(StrTy) ? StrTy : CB.getType();
+
+ if (CB.InReg)
+ return ABIArgInfo::getDirectInReg(CoerceTy);
+ else
+ return ABIArgInfo::getDirect(CoerceTy);
+}
+
+llvm::Value *SparcV9ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+ CodeGenFunction &CGF) const {
+ ABIArgInfo AI = classifyType(Ty, 16 * 8);
+ llvm::Type *ArgTy = CGT.ConvertType(Ty);
+ if (AI.canHaveCoerceToType() && !AI.getCoerceToType())
+ AI.setCoerceToType(ArgTy);
+
+ llvm::Type *BPP = CGF.Int8PtrPtrTy;
+ CGBuilderTy &Builder = CGF.Builder;
+ llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP, "ap");
+ llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur");
+ llvm::Type *ArgPtrTy = llvm::PointerType::getUnqual(ArgTy);
+ llvm::Value *ArgAddr;
+ unsigned Stride;
+
+ switch (AI.getKind()) {
+ case ABIArgInfo::Expand:
+ llvm_unreachable("Unsupported ABI kind for va_arg");
+
+ case ABIArgInfo::Extend:
+ Stride = 8;
+ ArgAddr = Builder
+ .CreateConstGEP1_32(Addr, 8 - getDataLayout().getTypeAllocSize(ArgTy),
+ "extend");
+ break;
+
+ case ABIArgInfo::Direct:
+ Stride = getDataLayout().getTypeAllocSize(AI.getCoerceToType());
+ ArgAddr = Addr;
+ break;
+
+ case ABIArgInfo::Indirect:
+ Stride = 8;
+ ArgAddr = Builder.CreateBitCast(Addr,
+ llvm::PointerType::getUnqual(ArgPtrTy),
+ "indirect");
+ ArgAddr = Builder.CreateLoad(ArgAddr, "indirect.arg");
+ break;
+
+ case ABIArgInfo::Ignore:
+ return llvm::UndefValue::get(ArgPtrTy);
+ }
+
+ // Update VAList.
+ Addr = Builder.CreateConstGEP1_32(Addr, Stride, "ap.next");
+ Builder.CreateStore(Addr, VAListAddrAsBPP);
+
+ return Builder.CreatePointerCast(ArgAddr, ArgPtrTy, "arg.addr");
+}
+
+void SparcV9ABIInfo::computeInfo(CGFunctionInfo &FI) const {
+ FI.getReturnInfo() = classifyType(FI.getReturnType(), 32 * 8);
+ for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
+ it != ie; ++it)
+ it->info = classifyType(it->type, 16 * 8);
+}
+
+namespace {
+class SparcV9TargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+ SparcV9TargetCodeGenInfo(CodeGenTypes &CGT)
+ : TargetCodeGenInfo(new SparcV9ABIInfo(CGT)) {}
+};
+} // end anonymous namespace
+
+
+//===----------------------------------------------------------------------===//
+// Xcore ABI Implementation
+//===----------------------------------------------------------------------===//
+namespace {
+class XCoreABIInfo : public DefaultABIInfo {
+public:
+ XCoreABIInfo(CodeGen::CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}
+ virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+ CodeGenFunction &CGF) const;
+};
+
+class XcoreTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+ XcoreTargetCodeGenInfo(CodeGenTypes &CGT)
+ :TargetCodeGenInfo(new XCoreABIInfo(CGT)) {}
+};
+} // End anonymous namespace.
+
+llvm::Value *XCoreABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+ CodeGenFunction &CGF) const {
+ CGBuilderTy &Builder = CGF.Builder;
+
+ // Get the VAList.
+ llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr,
+ CGF.Int8PtrPtrTy);
+ llvm::Value *AP = Builder.CreateLoad(VAListAddrAsBPP);
+
+ // Handle the argument.
+ ABIArgInfo AI = classifyArgumentType(Ty);
+ llvm::Type *ArgTy = CGT.ConvertType(Ty);
+ if (AI.canHaveCoerceToType() && !AI.getCoerceToType())
+ AI.setCoerceToType(ArgTy);
+ llvm::Type *ArgPtrTy = llvm::PointerType::getUnqual(ArgTy);
+ llvm::Value *Val;
+ uint64_t ArgSize = 0;
+ switch (AI.getKind()) {
+ case ABIArgInfo::Expand:
+ llvm_unreachable("Unsupported ABI kind for va_arg");
+ case ABIArgInfo::Ignore:
+ Val = llvm::UndefValue::get(ArgPtrTy);
+ ArgSize = 0;
+ break;
+ case ABIArgInfo::Extend:
+ case ABIArgInfo::Direct:
+ Val = Builder.CreatePointerCast(AP, ArgPtrTy);
+ ArgSize = getDataLayout().getTypeAllocSize(AI.getCoerceToType());
+ if (ArgSize < 4)
+ ArgSize = 4;
+ break;
+ case ABIArgInfo::Indirect:
+ llvm::Value *ArgAddr;
+ ArgAddr = Builder.CreateBitCast(AP, llvm::PointerType::getUnqual(ArgPtrTy));
+ ArgAddr = Builder.CreateLoad(ArgAddr);
+ Val = Builder.CreatePointerCast(ArgAddr, ArgPtrTy);
+ ArgSize = 4;
+ break;
+ }
+
+ // Increment the VAList.
+ if (ArgSize) {
+ llvm::Value *APN = Builder.CreateConstGEP1_32(AP, ArgSize);
+ Builder.CreateStore(APN, VAListAddrAsBPP);
+ }
+ return Val;
+}
+
+//===----------------------------------------------------------------------===//
+// Driver code
+//===----------------------------------------------------------------------===//
+
const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
if (TheTargetCodeGenInfo)
return *TheTargetCodeGenInfo;
@@ -5136,14 +5554,14 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
return *(TheTargetCodeGenInfo = new PPC64_SVR4_TargetCodeGenInfo(Types));
else
return *(TheTargetCodeGenInfo = new PPC64TargetCodeGenInfo(Types));
+ case llvm::Triple::ppc64le:
+ assert(Triple.isOSBinFormatELF() && "PPC64 LE non-ELF not supported!");
+ return *(TheTargetCodeGenInfo = new PPC64_SVR4_TargetCodeGenInfo(Types));
case llvm::Triple::nvptx:
case llvm::Triple::nvptx64:
return *(TheTargetCodeGenInfo = new NVPTXTargetCodeGenInfo(Types));
- case llvm::Triple::mblaze:
- return *(TheTargetCodeGenInfo = new MBlazeTargetCodeGenInfo(Types));
-
case llvm::Triple::msp430:
return *(TheTargetCodeGenInfo = new MSP430TargetCodeGenInfo(Types));
@@ -5154,31 +5572,22 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
return *(TheTargetCodeGenInfo = new TCETargetCodeGenInfo(Types));
case llvm::Triple::x86: {
- if (Triple.isOSDarwin())
- return *(TheTargetCodeGenInfo =
- new X86_32TargetCodeGenInfo(Types, true, true, false,
- CodeGenOpts.NumRegisterParameters));
-
- switch (Triple.getOS()) {
- case llvm::Triple::Cygwin:
- case llvm::Triple::MinGW32:
- case llvm::Triple::AuroraUX:
- case llvm::Triple::DragonFly:
- case llvm::Triple::FreeBSD:
- case llvm::Triple::OpenBSD:
- case llvm::Triple::Bitrig:
- return *(TheTargetCodeGenInfo =
- new X86_32TargetCodeGenInfo(Types, false, true, false,
- CodeGenOpts.NumRegisterParameters));
+ bool IsDarwinVectorABI = Triple.isOSDarwin();
+ bool IsSmallStructInRegABI =
+ X86_32TargetCodeGenInfo::isStructReturnInRegABI(Triple, CodeGenOpts);
+ bool IsWin32FloatStructABI = (Triple.getOS() == llvm::Triple::Win32);
- case llvm::Triple::Win32:
+ if (Triple.getOS() == llvm::Triple::Win32) {
return *(TheTargetCodeGenInfo =
- new X86_32TargetCodeGenInfo(Types, false, true, true,
- CodeGenOpts.NumRegisterParameters));
-
- default:
+ new WinX86_32TargetCodeGenInfo(Types,
+ IsDarwinVectorABI, IsSmallStructInRegABI,
+ IsWin32FloatStructABI,
+ CodeGenOpts.NumRegisterParameters));
+ } else {
return *(TheTargetCodeGenInfo =
- new X86_32TargetCodeGenInfo(Types, false, false, false,
+ new X86_32TargetCodeGenInfo(Types,
+ IsDarwinVectorABI, IsSmallStructInRegABI,
+ IsWin32FloatStructABI,
CodeGenOpts.NumRegisterParameters));
}
}
@@ -5201,5 +5610,10 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
}
case llvm::Triple::hexagon:
return *(TheTargetCodeGenInfo = new HexagonTargetCodeGenInfo(Types));
+ case llvm::Triple::sparcv9:
+ return *(TheTargetCodeGenInfo = new SparcV9TargetCodeGenInfo(Types));
+ case llvm::Triple::xcore:
+ return *(TheTargetCodeGenInfo = new XcoreTargetCodeGenInfo(Types));
+
}
}
diff --git a/lib/CodeGen/TargetInfo.h b/lib/CodeGen/TargetInfo.h
index bb50ce6..f631f31 100644
--- a/lib/CodeGen/TargetInfo.h
+++ b/lib/CodeGen/TargetInfo.h
@@ -18,8 +18,10 @@
#include "clang/AST/Type.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/SmallString.h"
namespace llvm {
+ class Constant;
class GlobalValue;
class Type;
class Value;
@@ -110,8 +112,13 @@ namespace clang {
return Address;
}
+ /// Corrects the low-level LLVM type for a given constraint and "usual"
+ /// type.
+ ///
+ /// \returns A pointer to a new LLVM type, possibly the same as the original
+ /// on success; 0 on failure.
virtual llvm::Type* adjustInlineAsmType(CodeGen::CodeGenFunction &CGF,
- StringRef Constraint,
+ StringRef Constraint,
llvm::Type* Ty) const {
return Ty;
}
@@ -130,6 +137,13 @@ namespace clang {
return "";
}
+ /// Return a constant used by UBSan as a signature to identify functions
+ /// possessing type information, or 0 if the platform is unsupported.
+ virtual llvm::Constant *getUBSanFunctionSignature(
+ CodeGen::CodeGenModule &CGM) const {
+ return 0;
+ }
+
/// Determine whether a call to an unprototyped functions under
/// the given calling convention should use the variadic
/// convention or the non-variadic convention.
@@ -165,8 +179,26 @@ namespace clang {
/// arguments in %al. On these platforms, it is desireable to
/// call unprototyped functions using the variadic convention so
/// that unprototyped calls to varargs functions still succeed.
+ ///
+ /// Relatedly, platforms which pass the fixed arguments to this:
+ /// A foo(B, C, D);
+ /// differently than they would pass them to this:
+ /// A foo(B, C, D, ...);
+ /// may need to adjust the debugger-support code in Sema to do the
+ /// right thing when calling a function with no know signature.
virtual bool isNoProtoCallVariadic(const CodeGen::CallArgList &args,
const FunctionNoProtoType *fnType) const;
+
+ /// Gets the linker options necessary to link a dependent library on this
+ /// platform.
+ virtual void getDependentLibraryOption(llvm::StringRef Lib,
+ llvm::SmallString<24> &Opt) const;
+
+ /// Gets the linker options necessary to detect object file mismatches on
+ /// this platform.
+ virtual void getDetectMismatchOption(llvm::StringRef Name,
+ llvm::StringRef Value,
+ llvm::SmallString<32> &Opt) const {}
};
}
OpenPOWER on IntegriCloud