Update Clang for rebase to r212749.
This also fixes a small issue with arm_neon.h not being generated always.
Includes a cherry-pick of:
r213450 - fixes mac-specific header issue
r213126 - removes a default -Bsymbolic on Android
Change-Id: I2a790a0f5d3b2aab11de596fc3a74e7cbc99081d
diff --git a/lib/CodeGen/Android.mk b/lib/CodeGen/Android.mk
index 85805e4..0a82640 100644
--- a/lib/CodeGen/Android.mk
+++ b/lib/CodeGen/Android.mk
@@ -2,6 +2,7 @@
clang_codegen_TBLGEN_TABLES := \
AttrList.inc \
+ AttrParsedAttrList.inc \
Attrs.inc \
AttrVisitor.inc \
CommentCommandList.inc \
@@ -42,7 +43,6 @@
CGOpenCLRuntime.cpp \
CGOpenMPRuntime.cpp \
CGLoopInfo.cpp \
- CGRTTI.cpp \
CGRecordLayoutBuilder.cpp \
CGStmt.cpp \
CGStmtOpenMP.cpp \
@@ -57,8 +57,8 @@
CodeGenTypes.cpp \
ItaniumCXXABI.cpp \
MicrosoftCXXABI.cpp \
- MicrosoftRTTI.cpp \
ModuleBuilder.cpp \
+ SanitizerBlacklist.cpp \
TargetInfo.cpp
# For the host only
diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp
index fc6c594..a1521dc 100644
--- a/lib/CodeGen/BackendUtil.cpp
+++ b/lib/CodeGen/BackendUtil.cpp
@@ -180,18 +180,8 @@
static void addAddressSanitizerPasses(const PassManagerBuilder &Builder,
PassManagerBase &PM) {
- const PassManagerBuilderWrapper &BuilderWrapper =
- static_cast<const PassManagerBuilderWrapper&>(Builder);
- const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
- const LangOptions &LangOpts = BuilderWrapper.getLangOpts();
- PM.add(createAddressSanitizerFunctionPass(
- LangOpts.Sanitize.InitOrder,
- LangOpts.Sanitize.UseAfterReturn,
- LangOpts.Sanitize.UseAfterScope,
- CGOpts.SanitizerBlacklistFile));
- PM.add(createAddressSanitizerModulePass(
- LangOpts.Sanitize.InitOrder,
- CGOpts.SanitizerBlacklistFile));
+ PM.add(createAddressSanitizerFunctionPass());
+ PM.add(createAddressSanitizerModulePass());
}
static void addMemorySanitizerPass(const PassManagerBuilder &Builder,
@@ -199,8 +189,7 @@
const PassManagerBuilderWrapper &BuilderWrapper =
static_cast<const PassManagerBuilderWrapper&>(Builder);
const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
- PM.add(createMemorySanitizerPass(CGOpts.SanitizeMemoryTrackOrigins,
- CGOpts.SanitizerBlacklistFile));
+ PM.add(createMemorySanitizerPass(CGOpts.SanitizeMemoryTrackOrigins));
// MemorySanitizer inserts complex instrumentation that mostly follows
// the logic of the original code, but operates on "shadow" values.
@@ -217,10 +206,7 @@
static void addThreadSanitizerPass(const PassManagerBuilder &Builder,
PassManagerBase &PM) {
- const PassManagerBuilderWrapper &BuilderWrapper =
- static_cast<const PassManagerBuilderWrapper&>(Builder);
- const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
- PM.add(createThreadSanitizerPass(CGOpts.SanitizerBlacklistFile));
+ PM.add(createThreadSanitizerPass());
}
static void addDataFlowSanitizerPass(const PassManagerBuilder &Builder,
diff --git a/lib/CodeGen/CGAtomic.cpp b/lib/CodeGen/CGAtomic.cpp
index 18eb065..89bde2c 100644
--- a/lib/CodeGen/CGAtomic.cpp
+++ b/lib/CodeGen/CGAtomic.cpp
@@ -174,7 +174,7 @@
return true;
}
-static void emitAtomicCmpXchg(CodeGenFunction &CGF, AtomicExpr *E,
+static void emitAtomicCmpXchg(CodeGenFunction &CGF, AtomicExpr *E, bool IsWeak,
llvm::Value *Dest, llvm::Value *Ptr,
llvm::Value *Val1, llvm::Value *Val2,
uint64_t Size, unsigned Align,
@@ -186,13 +186,15 @@
llvm::LoadInst *Desired = CGF.Builder.CreateLoad(Val2);
Desired->setAlignment(Align);
- llvm::AtomicCmpXchgInst *Old = CGF.Builder.CreateAtomicCmpXchg(
+ llvm::AtomicCmpXchgInst *Pair = CGF.Builder.CreateAtomicCmpXchg(
Ptr, Expected, Desired, SuccessOrder, FailureOrder);
- Old->setVolatile(E->isVolatile());
+ Pair->setVolatile(E->isVolatile());
+ Pair->setWeak(IsWeak);
// Cmp holds the result of the compare-exchange operation: true on success,
// false on failure.
- llvm::Value *Cmp = CGF.Builder.CreateICmpEQ(Old, Expected);
+ llvm::Value *Old = CGF.Builder.CreateExtractValue(Pair, 0);
+ llvm::Value *Cmp = CGF.Builder.CreateExtractValue(Pair, 1);
// This basic block is used to hold the store instruction if the operation
// failed.
@@ -225,8 +227,9 @@
/// instructions to cope with the provided (but possibly only dynamically known)
/// FailureOrder.
static void emitAtomicCmpXchgFailureSet(CodeGenFunction &CGF, AtomicExpr *E,
- llvm::Value *Dest, llvm::Value *Ptr,
- llvm::Value *Val1, llvm::Value *Val2,
+ bool IsWeak, llvm::Value *Dest,
+ llvm::Value *Ptr, llvm::Value *Val1,
+ llvm::Value *Val2,
llvm::Value *FailureOrderVal,
uint64_t Size, unsigned Align,
llvm::AtomicOrdering SuccessOrder) {
@@ -249,8 +252,8 @@
FailureOrder =
llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(SuccessOrder);
}
- emitAtomicCmpXchg(CGF, E, Dest, Ptr, Val1, Val2, Size, Align, SuccessOrder,
- FailureOrder);
+ emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, Size, Align,
+ SuccessOrder, FailureOrder);
return;
}
@@ -273,13 +276,13 @@
// doesn't matter unless someone is crazy enough to use something that
// doesn't fold to a constant for the ordering.
CGF.Builder.SetInsertPoint(MonotonicBB);
- emitAtomicCmpXchg(CGF, E, Dest, Ptr, Val1, Val2,
+ emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2,
Size, Align, SuccessOrder, llvm::Monotonic);
CGF.Builder.CreateBr(ContBB);
if (AcquireBB) {
CGF.Builder.SetInsertPoint(AcquireBB);
- emitAtomicCmpXchg(CGF, E, Dest, Ptr, Val1, Val2,
+ emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2,
Size, Align, SuccessOrder, llvm::Acquire);
CGF.Builder.CreateBr(ContBB);
SI->addCase(CGF.Builder.getInt32(AtomicExpr::AO_ABI_memory_order_consume),
@@ -289,7 +292,7 @@
}
if (SeqCstBB) {
CGF.Builder.SetInsertPoint(SeqCstBB);
- emitAtomicCmpXchg(CGF, E, Dest, Ptr, Val1, Val2,
+ emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2,
Size, Align, SuccessOrder, llvm::SequentiallyConsistent);
CGF.Builder.CreateBr(ContBB);
SI->addCase(CGF.Builder.getInt32(AtomicExpr::AO_ABI_memory_order_seq_cst),
@@ -301,8 +304,9 @@
static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, llvm::Value *Dest,
llvm::Value *Ptr, llvm::Value *Val1, llvm::Value *Val2,
- llvm::Value *FailureOrder, uint64_t Size,
- unsigned Align, llvm::AtomicOrdering Order) {
+ llvm::Value *IsWeak, llvm::Value *FailureOrder,
+ uint64_t Size, unsigned Align,
+ llvm::AtomicOrdering Order) {
llvm::AtomicRMWInst::BinOp Op = llvm::AtomicRMWInst::Add;
llvm::Instruction::BinaryOps PostOp = (llvm::Instruction::BinaryOps)0;
@@ -311,12 +315,43 @@
llvm_unreachable("Already handled!");
case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
- case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
- case AtomicExpr::AO__atomic_compare_exchange:
- case AtomicExpr::AO__atomic_compare_exchange_n:
- emitAtomicCmpXchgFailureSet(CGF, E, Dest, Ptr, Val1, Val2, FailureOrder,
- Size, Align, Order);
+ emitAtomicCmpXchgFailureSet(CGF, E, false, Dest, Ptr, Val1, Val2,
+ FailureOrder, Size, Align, Order);
return;
+ case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
+ emitAtomicCmpXchgFailureSet(CGF, E, true, Dest, Ptr, Val1, Val2,
+ FailureOrder, Size, Align, Order);
+ return;
+ case AtomicExpr::AO__atomic_compare_exchange:
+ case AtomicExpr::AO__atomic_compare_exchange_n: {
+ if (llvm::ConstantInt *IsWeakC = dyn_cast<llvm::ConstantInt>(IsWeak)) {
+ emitAtomicCmpXchgFailureSet(CGF, E, IsWeakC->getZExtValue(), Dest, Ptr,
+ Val1, Val2, FailureOrder, Size, Align, Order);
+ } else {
+ // Create all the relevant BB's
+ llvm::BasicBlock *StrongBB =
+ CGF.createBasicBlock("cmpxchg.strong", CGF.CurFn);
+ llvm::BasicBlock *WeakBB = CGF.createBasicBlock("cmxchg.weak", CGF.CurFn);
+ llvm::BasicBlock *ContBB =
+ CGF.createBasicBlock("cmpxchg.continue", CGF.CurFn);
+
+ llvm::SwitchInst *SI = CGF.Builder.CreateSwitch(IsWeak, WeakBB);
+ SI->addCase(CGF.Builder.getInt1(false), StrongBB);
+
+ CGF.Builder.SetInsertPoint(StrongBB);
+ emitAtomicCmpXchgFailureSet(CGF, E, false, Dest, Ptr, Val1, Val2,
+ FailureOrder, Size, Align, Order);
+ CGF.Builder.CreateBr(ContBB);
+
+ CGF.Builder.SetInsertPoint(WeakBB);
+ emitAtomicCmpXchgFailureSet(CGF, E, true, Dest, Ptr, Val1, Val2,
+ FailureOrder, Size, Align, Order);
+ CGF.Builder.CreateBr(ContBB);
+
+ CGF.Builder.SetInsertPoint(ContBB);
+ }
+ return;
+ }
case AtomicExpr::AO__c11_atomic_load:
case AtomicExpr::AO__atomic_load_n:
case AtomicExpr::AO__atomic_load: {
@@ -453,7 +488,8 @@
bool UseLibcall = (Size != Align ||
getContext().toBits(sizeChars) > MaxInlineWidthInBits);
- llvm::Value *OrderFail = nullptr, *Val1 = nullptr, *Val2 = nullptr;
+ llvm::Value *IsWeak = nullptr, *OrderFail = nullptr, *Val1 = nullptr,
+ *Val2 = nullptr;
llvm::Value *Ptr = EmitScalarExpr(E->getPtr());
if (E->getOp() == AtomicExpr::AO__c11_atomic_init) {
@@ -496,9 +532,8 @@
else
Val2 = EmitValToTemp(*this, E->getVal2());
OrderFail = EmitScalarExpr(E->getOrderFail());
- // Evaluate and discard the 'weak' argument.
if (E->getNumSubExprs() == 6)
- EmitScalarExpr(E->getWeak());
+ IsWeak = EmitScalarExpr(E->getWeak());
break;
case AtomicExpr::AO__c11_atomic_fetch_add:
@@ -720,30 +755,30 @@
int ord = cast<llvm::ConstantInt>(Order)->getZExtValue();
switch (ord) {
case AtomicExpr::AO_ABI_memory_order_relaxed:
- EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, OrderFail,
+ EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail,
Size, Align, llvm::Monotonic);
break;
case AtomicExpr::AO_ABI_memory_order_consume:
case AtomicExpr::AO_ABI_memory_order_acquire:
if (IsStore)
break; // Avoid crashing on code with undefined behavior
- EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, OrderFail,
+ EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail,
Size, Align, llvm::Acquire);
break;
case AtomicExpr::AO_ABI_memory_order_release:
if (IsLoad)
break; // Avoid crashing on code with undefined behavior
- EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, OrderFail,
+ EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail,
Size, Align, llvm::Release);
break;
case AtomicExpr::AO_ABI_memory_order_acq_rel:
if (IsLoad || IsStore)
break; // Avoid crashing on code with undefined behavior
- EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, OrderFail,
+ EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail,
Size, Align, llvm::AcquireRelease);
break;
case AtomicExpr::AO_ABI_memory_order_seq_cst:
- EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, OrderFail,
+ EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail,
Size, Align, llvm::SequentiallyConsistent);
break;
default: // invalid order
@@ -781,12 +816,12 @@
// Emit all the different atomics
Builder.SetInsertPoint(MonotonicBB);
- EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, OrderFail,
+ EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail,
Size, Align, llvm::Monotonic);
Builder.CreateBr(ContBB);
if (!IsStore) {
Builder.SetInsertPoint(AcquireBB);
- EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, OrderFail,
+ EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail,
Size, Align, llvm::Acquire);
Builder.CreateBr(ContBB);
SI->addCase(Builder.getInt32(AtomicExpr::AO_ABI_memory_order_consume),
@@ -796,7 +831,7 @@
}
if (!IsLoad) {
Builder.SetInsertPoint(ReleaseBB);
- EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, OrderFail,
+ EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail,
Size, Align, llvm::Release);
Builder.CreateBr(ContBB);
SI->addCase(Builder.getInt32(AtomicExpr::AO_ABI_memory_order_release),
@@ -804,14 +839,14 @@
}
if (!IsLoad && !IsStore) {
Builder.SetInsertPoint(AcqRelBB);
- EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, OrderFail,
+ EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail,
Size, Align, llvm::AcquireRelease);
Builder.CreateBr(ContBB);
SI->addCase(Builder.getInt32(AtomicExpr::AO_ABI_memory_order_acq_rel),
AcqRelBB);
}
Builder.SetInsertPoint(SeqCstBB);
- EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, OrderFail,
+ EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail,
Size, Align, llvm::SequentiallyConsistent);
Builder.CreateBr(ContBB);
SI->addCase(Builder.getInt32(AtomicExpr::AO_ABI_memory_order_seq_cst),
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index 21896da..7ffebe2 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -1127,11 +1127,9 @@
llvm::FunctionType *fnLLVMType = CGM.getTypes().GetFunctionType(fnInfo);
- MangleBuffer name;
- CGM.getBlockMangledName(GD, name, blockDecl);
- llvm::Function *fn =
- llvm::Function::Create(fnLLVMType, llvm::GlobalValue::InternalLinkage,
- name.getString(), &CGM.getModule());
+ StringRef name = CGM.getBlockMangledName(GD, blockDecl);
+ llvm::Function *fn = llvm::Function::Create(
+ fnLLVMType, llvm::GlobalValue::InternalLinkage, name, &CGM.getModule());
CGM.SetInternalFunctionAttributes(blockDecl, fn, fnInfo);
// Begin generating the function.
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index c6ac3cc..ded75c1 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -975,6 +975,7 @@
Value *Result = Builder.CreateAtomicCmpXchg(Args[0], Args[1], Args[2],
llvm::SequentiallyConsistent,
llvm::SequentiallyConsistent);
+ Result = Builder.CreateExtractValue(Result, 0);
Result = EmitFromInt(*this, Result, T, ValueType);
return RValue::get(Result);
}
@@ -998,11 +999,10 @@
Args[1] = EmitToInt(*this, EmitScalarExpr(E->getArg(1)), T, IntType);
Args[2] = EmitToInt(*this, EmitScalarExpr(E->getArg(2)), T, IntType);
- Value *OldVal = Args[1];
- Value *PrevVal = Builder.CreateAtomicCmpXchg(Args[0], Args[1], Args[2],
- llvm::SequentiallyConsistent,
- llvm::SequentiallyConsistent);
- Value *Result = Builder.CreateICmpEQ(PrevVal, OldVal);
+ Value *Pair = Builder.CreateAtomicCmpXchg(Args[0], Args[1], Args[2],
+ llvm::SequentiallyConsistent,
+ llvm::SequentiallyConsistent);
+ Value *Result = Builder.CreateExtractValue(Pair, 1);
// zext bool to int.
Result = Builder.CreateZExt(Result, ConvertType(E->getType()));
return RValue::get(Result);
@@ -1508,8 +1508,43 @@
}
case Builtin::BI__builtin_addressof:
return RValue::get(EmitLValue(E->getArg(0)).getAddress());
+ case Builtin::BI__builtin_operator_new:
+ return EmitBuiltinNewDeleteCall(FD->getType()->castAs<FunctionProtoType>(),
+ E->getArg(0), false);
+ case Builtin::BI__builtin_operator_delete:
+ return EmitBuiltinNewDeleteCall(FD->getType()->castAs<FunctionProtoType>(),
+ E->getArg(0), true);
case Builtin::BI__noop:
return RValue::get(nullptr);
+ case Builtin::BI_InterlockedExchange:
+ case Builtin::BI_InterlockedExchangePointer:
+ return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Xchg, E);
+ case Builtin::BI_InterlockedCompareExchangePointer: {
+ llvm::Type *RTy;
+ llvm::IntegerType *IntType =
+ IntegerType::get(getLLVMContext(),
+ getContext().getTypeSize(E->getType()));
+ llvm::Type *IntPtrType = IntType->getPointerTo();
+
+ llvm::Value *Destination =
+ Builder.CreateBitCast(EmitScalarExpr(E->getArg(0)), IntPtrType);
+
+ llvm::Value *Exchange = EmitScalarExpr(E->getArg(1));
+ RTy = Exchange->getType();
+ Exchange = Builder.CreatePtrToInt(Exchange, IntType);
+
+ llvm::Value *Comparand =
+ Builder.CreatePtrToInt(EmitScalarExpr(E->getArg(2)), IntType);
+
+ auto Result = Builder.CreateAtomicCmpXchg(Destination, Comparand, Exchange,
+ SequentiallyConsistent,
+ SequentiallyConsistent);
+ Result->setVolatile(true);
+
+ return RValue::get(Builder.CreateIntToPtr(Builder.CreateExtractValue(Result,
+ 0),
+ RTy));
+ }
case Builtin::BI_InterlockedCompareExchange: {
AtomicCmpXchgInst *CXI = Builder.CreateAtomicCmpXchg(
EmitScalarExpr(E->getArg(0)),
@@ -1518,7 +1553,7 @@
SequentiallyConsistent,
SequentiallyConsistent);
CXI->setVolatile(true);
- return RValue::get(CXI);
+ return RValue::get(Builder.CreateExtractValue(CXI, 0));
}
case Builtin::BI_InterlockedIncrement: {
AtomicRMWInst *RMWI = Builder.CreateAtomicRMW(
@@ -1565,8 +1600,14 @@
const char *Name = getContext().BuiltinInfo.GetName(BuiltinID);
Intrinsic::ID IntrinsicID = Intrinsic::not_intrinsic;
if (const char *Prefix =
- llvm::Triple::getArchTypePrefix(getTarget().getTriple().getArch()))
+ llvm::Triple::getArchTypePrefix(getTarget().getTriple().getArch())) {
IntrinsicID = Intrinsic::getIntrinsicForGCCBuiltin(Prefix, Name);
+ // NOTE we dont need to perform a compatibility flag check here since the
+ // intrinsics are declared in Builtins*.def via LANGBUILTIN which filter the
+ // MS builtins via ALL_MS_LANGUAGES and are filtered earlier.
+ if (IntrinsicID == Intrinsic::not_intrinsic)
+ IntrinsicID = Intrinsic::getIntrinsicForMSBuiltin(Prefix, Name);
+ }
if (IntrinsicID != Intrinsic::not_intrinsic) {
SmallVector<Value*, 16> Args;
@@ -1654,6 +1695,8 @@
case llvm::Triple::ppc64:
case llvm::Triple::ppc64le:
return EmitPPCBuiltinExpr(BuiltinID, E);
+ case llvm::Triple::r600:
+ return EmitR600BuiltinExpr(BuiltinID, E);
default:
return nullptr;
}
@@ -1751,36 +1794,6 @@
return Builder.CreateAShr(Vec, Shift, name);
}
-Value *CodeGenFunction::EmitConcatVectors(Value *Lo, Value *Hi,
- llvm::Type *ArgTy) {
- unsigned NumElts = ArgTy->getVectorNumElements();
- SmallVector<Constant *, 16> Indices;
- for (unsigned i = 0; i < 2 * NumElts; ++i)
- Indices.push_back(ConstantInt::get(Int32Ty, i));
-
- Constant *Mask = ConstantVector::get(Indices);
- Value *LoCast = Builder.CreateBitCast(Lo, ArgTy);
- Value *HiCast = Builder.CreateBitCast(Hi, ArgTy);
- return Builder.CreateShuffleVector(LoCast, HiCast, Mask, "concat");
-}
-
-Value *CodeGenFunction::EmitExtractHigh(Value *Vec, llvm::Type *ResTy) {
- unsigned NumElts = ResTy->getVectorNumElements();
- SmallVector<Constant *, 8> Indices;
-
- llvm::Type *InTy = llvm::VectorType::get(ResTy->getVectorElementType(),
- NumElts * 2);
- Value *VecCast = Builder.CreateBitCast(Vec, InTy);
-
- // extract_high is a shuffle on the second half of the input indices: E.g. 4,
- // 5, 6, 7 if we're extracting <4 x i16> from <8 x i16>.
- for (unsigned i = 0; i < NumElts; ++i)
- Indices.push_back(ConstantInt::get(Int32Ty, NumElts + i));
-
- Constant *Mask = ConstantVector::get(Indices);
- return Builder.CreateShuffleVector(VecCast, VecCast, Mask, "concat");
-}
-
/// GetPointeeAlignment - Given an expression with a pointer type, find the
/// alignment of the type referenced by the pointer. Skip over implicit
/// casts.
@@ -2396,7 +2409,7 @@
static const NeonIntrinsicInfo *
-findNeonIntrinsicInMap(llvm::ArrayRef<NeonIntrinsicInfo> IntrinsicMap,
+findNeonIntrinsicInMap(ArrayRef<NeonIntrinsicInfo> IntrinsicMap,
unsigned BuiltinID, bool &MapProvenSorted) {
#ifndef NDEBUG
@@ -2493,7 +2506,7 @@
Function *F = CGF.LookupNeonLLVMIntrinsic(Int, Modifier, ArgTy, E);
int j = 0;
- ConstantInt *C0 = ConstantInt::get(CGF.Int32Ty, 0);
+ ConstantInt *C0 = ConstantInt::get(CGF.SizeTy, 0);
for (Function::const_arg_iterator ai = F->arg_begin(), ae = F->arg_end();
ai != ae; ++ai, ++j) {
llvm::Type *ArgTy = ai->getType();
@@ -2733,7 +2746,7 @@
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
LoadInst *Ld = Builder.CreateLoad(Ops[0]);
Ld->setAlignment(cast<ConstantInt>(Align)->getZExtValue());
- llvm::Constant *CI = ConstantInt::get(Int32Ty, 0);
+ llvm::Constant *CI = ConstantInt::get(SizeTy, 0);
Ops[0] = Builder.CreateInsertElement(V, Ld, CI);
return EmitNeonSplat(Ops[0], CI);
}
@@ -3026,18 +3039,23 @@
unsigned HintID = static_cast<unsigned>(-1);
switch (BuiltinID) {
default: break;
+ case ARM::BI__builtin_arm_yield:
case ARM::BI__yield:
HintID = 1;
break;
+ case ARM::BI__builtin_arm_wfe:
case ARM::BI__wfe:
HintID = 2;
break;
+ case ARM::BI__builtin_arm_wfi:
case ARM::BI__wfi:
HintID = 3;
break;
+ case ARM::BI__builtin_arm_sev:
case ARM::BI__sev:
HintID = 4;
break;
+ case ARM::BI__builtin_arm_sevl:
case ARM::BI__sevl:
HintID = 5;
break;
@@ -3048,6 +3066,12 @@
return Builder.CreateCall(F, llvm::ConstantInt::get(Int32Ty, HintID));
}
+ if (BuiltinID == ARM::BI__builtin_arm_rbit) {
+ return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::arm_rbit),
+ EmitScalarExpr(E->getArg(0)),
+ "rbit");
+ }
+
if (BuiltinID == ARM::BI__clear_cache) {
assert(E->getNumArgs() == 2 && "__clear_cache takes 2 arguments");
const FunctionDecl *FD = E->getDirectCallee();
@@ -3061,9 +3085,23 @@
}
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);
+ ((BuiltinID == ARM::BI__builtin_arm_ldrex ||
+ BuiltinID == ARM::BI__builtin_arm_ldaex) &&
+ getContext().getTypeSize(E->getType()) == 64) ||
+ BuiltinID == ARM::BI__ldrexd) {
+ Function *F;
+
+ switch (BuiltinID) {
+ default: llvm_unreachable("unexpected builtin");
+ case ARM::BI__builtin_arm_ldaex:
+ F = CGM.getIntrinsic(Intrinsic::arm_ldaexd);
+ break;
+ case ARM::BI__builtin_arm_ldrexd:
+ case ARM::BI__builtin_arm_ldrex:
+ case ARM::BI__ldrexd:
+ F = CGM.getIntrinsic(Intrinsic::arm_ldrexd);
+ break;
+ }
Value *LdPtr = EmitScalarExpr(E->getArg(0));
Value *Val = Builder.CreateCall(F, Builder.CreateBitCast(LdPtr, Int8PtrTy),
@@ -3080,7 +3118,8 @@
return Builder.CreateBitCast(Val, ConvertType(E->getType()));
}
- if (BuiltinID == ARM::BI__builtin_arm_ldrex) {
+ if (BuiltinID == ARM::BI__builtin_arm_ldrex ||
+ BuiltinID == ARM::BI__builtin_arm_ldaex) {
Value *LoadAddr = EmitScalarExpr(E->getArg(0));
QualType Ty = E->getType();
@@ -3089,7 +3128,10 @@
getContext().getTypeSize(Ty));
LoadAddr = Builder.CreateBitCast(LoadAddr, IntResTy->getPointerTo());
- Function *F = CGM.getIntrinsic(Intrinsic::arm_ldrex, LoadAddr->getType());
+ Function *F = CGM.getIntrinsic(BuiltinID == ARM::BI__builtin_arm_ldaex
+ ? Intrinsic::arm_ldaex
+ : Intrinsic::arm_ldrex,
+ LoadAddr->getType());
Value *Val = Builder.CreateCall(F, LoadAddr, "ldrex");
if (RealResTy->isPointerTy())
@@ -3101,9 +3143,12 @@
}
if (BuiltinID == ARM::BI__builtin_arm_strexd ||
- (BuiltinID == ARM::BI__builtin_arm_strex &&
+ ((BuiltinID == ARM::BI__builtin_arm_stlex ||
+ BuiltinID == ARM::BI__builtin_arm_strex) &&
getContext().getTypeSize(E->getArg(0)->getType()) == 64)) {
- Function *F = CGM.getIntrinsic(Intrinsic::arm_strexd);
+ Function *F = CGM.getIntrinsic(BuiltinID == ARM::BI__builtin_arm_stlex
+ ? Intrinsic::arm_stlexd
+ : Intrinsic::arm_strexd);
llvm::Type *STy = llvm::StructType::get(Int32Ty, Int32Ty, NULL);
Value *Tmp = CreateMemTemp(E->getArg(0)->getType());
@@ -3119,7 +3164,8 @@
return Builder.CreateCall3(F, Arg0, Arg1, StPtr, "strexd");
}
- if (BuiltinID == ARM::BI__builtin_arm_strex) {
+ if (BuiltinID == ARM::BI__builtin_arm_strex ||
+ BuiltinID == ARM::BI__builtin_arm_stlex) {
Value *StoreVal = EmitScalarExpr(E->getArg(0));
Value *StoreAddr = EmitScalarExpr(E->getArg(1));
@@ -3135,7 +3181,10 @@
StoreVal = Builder.CreateZExtOrBitCast(StoreVal, Int32Ty);
}
- Function *F = CGM.getIntrinsic(Intrinsic::arm_strex, StoreAddr->getType());
+ Function *F = CGM.getIntrinsic(BuiltinID == ARM::BI__builtin_arm_stlex
+ ? Intrinsic::arm_stlex
+ : Intrinsic::arm_strex,
+ StoreAddr->getType());
return Builder.CreateCall2(F, StoreVal, StoreAddr, "strex");
}
@@ -3336,7 +3385,7 @@
// Many NEON builtins have identical semantics and uses in ARM and
// AArch64. Emit these in a single function.
- llvm::ArrayRef<NeonIntrinsicInfo> IntrinsicMap(ARMSIMDIntrinsicMap);
+ ArrayRef<NeonIntrinsicInfo> IntrinsicMap(ARMSIMDIntrinsicMap);
const NeonIntrinsicInfo *Builtin = findNeonIntrinsicInMap(
IntrinsicMap, BuiltinID, NEONSIMDIntrinsicsProvenSorted);
if (Builtin)
@@ -3703,7 +3752,7 @@
llvm::Type *VTy = llvm::VectorType::get(Int16Ty, 4);
Op = Builder.CreateBitCast(Op, Int16Ty);
Value *V = UndefValue::get(VTy);
- llvm::Constant *CI = ConstantInt::get(Int32Ty, 0);
+ llvm::Constant *CI = ConstantInt::get(SizeTy, 0);
Op = Builder.CreateInsertElement(V, Op, CI);
return Op;
}
@@ -3712,7 +3761,7 @@
llvm::Type *VTy = llvm::VectorType::get(Int8Ty, 8);
Op = Builder.CreateBitCast(Op, Int8Ty);
Value *V = UndefValue::get(VTy);
- llvm::Constant *CI = ConstantInt::get(Int32Ty, 0);
+ llvm::Constant *CI = ConstantInt::get(SizeTy, 0);
Op = Builder.CreateInsertElement(V, Op, CI);
return Op;
}
@@ -3721,7 +3770,7 @@
emitVectorWrappedScalar8Intrinsic(unsigned Int, SmallVectorImpl<Value*> &Ops,
const char *Name) {
// i8 is not a legal types for AArch64, so we can't just use
- // a normal overloaed intrinsic call for these scalar types. Instead
+ // a normal overloaded intrinsic call for these scalar types. Instead
// we'll build 64-bit vectors w/ lane zero being our input values and
// perform the operation on that. The back end can pattern match directly
// to the scalar instruction.
@@ -3729,7 +3778,7 @@
Ops[1] = vectorWrapScalar8(Ops[1]);
llvm::Type *VTy = llvm::VectorType::get(Int8Ty, 8);
Value *V = EmitNeonCall(CGM.getIntrinsic(Int, VTy), Ops, Name);
- Constant *CI = ConstantInt::get(Int32Ty, 0);
+ Constant *CI = ConstantInt::get(SizeTy, 0);
return Builder.CreateExtractElement(V, CI, "lane0");
}
@@ -3737,7 +3786,7 @@
emitVectorWrappedScalar16Intrinsic(unsigned Int, SmallVectorImpl<Value*> &Ops,
const char *Name) {
// i16 is not a legal types for AArch64, so we can't just use
- // a normal overloaed intrinsic call for these scalar types. Instead
+ // a normal overloaded intrinsic call for these scalar types. Instead
// we'll build 64-bit vectors w/ lane zero being our input values and
// perform the operation on that. The back end can pattern match directly
// to the scalar instruction.
@@ -3745,12 +3794,27 @@
Ops[1] = vectorWrapScalar16(Ops[1]);
llvm::Type *VTy = llvm::VectorType::get(Int16Ty, 4);
Value *V = EmitNeonCall(CGM.getIntrinsic(Int, VTy), Ops, Name);
- Constant *CI = ConstantInt::get(Int32Ty, 0);
+ Constant *CI = ConstantInt::get(SizeTy, 0);
return Builder.CreateExtractElement(V, CI, "lane0");
}
Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
const CallExpr *E) {
+ if (BuiltinID == AArch64::BI__builtin_arm_rbit) {
+ assert((getContext().getTypeSize(E->getType()) == 32) &&
+ "rbit of unusual size!");
+ llvm::Value *Arg = EmitScalarExpr(E->getArg(0));
+ return Builder.CreateCall(
+ CGM.getIntrinsic(Intrinsic::aarch64_rbit, Arg->getType()), Arg, "rbit");
+ }
+ if (BuiltinID == AArch64::BI__builtin_arm_rbit64) {
+ assert((getContext().getTypeSize(E->getType()) == 64) &&
+ "rbit of unusual size!");
+ llvm::Value *Arg = EmitScalarExpr(E->getArg(0));
+ return Builder.CreateCall(
+ CGM.getIntrinsic(Intrinsic::aarch64_rbit, Arg->getType()), Arg, "rbit");
+ }
+
if (BuiltinID == AArch64::BI__clear_cache) {
assert(E->getNumArgs() == 2 && "__clear_cache takes 2 arguments");
const FunctionDecl *FD = E->getDirectCallee();
@@ -3763,9 +3827,12 @@
return EmitNounwindRuntimeCall(CGM.CreateRuntimeFunction(FTy, Name), Ops);
}
- if (BuiltinID == AArch64::BI__builtin_arm_ldrex &&
+ if ((BuiltinID == AArch64::BI__builtin_arm_ldrex ||
+ BuiltinID == AArch64::BI__builtin_arm_ldaex) &&
getContext().getTypeSize(E->getType()) == 128) {
- Function *F = CGM.getIntrinsic(Intrinsic::aarch64_ldxp);
+ Function *F = CGM.getIntrinsic(BuiltinID == AArch64::BI__builtin_arm_ldaex
+ ? Intrinsic::aarch64_ldaxp
+ : Intrinsic::aarch64_ldxp);
Value *LdPtr = EmitScalarExpr(E->getArg(0));
Value *Val = Builder.CreateCall(F, Builder.CreateBitCast(LdPtr, Int8PtrTy),
@@ -3781,7 +3848,8 @@
Val = Builder.CreateShl(Val0, ShiftCst, "shl", true /* nuw */);
Val = Builder.CreateOr(Val, Val1);
return Builder.CreateBitCast(Val, ConvertType(E->getType()));
- } else if (BuiltinID == AArch64::BI__builtin_arm_ldrex) {
+ } else if (BuiltinID == AArch64::BI__builtin_arm_ldrex ||
+ BuiltinID == AArch64::BI__builtin_arm_ldaex) {
Value *LoadAddr = EmitScalarExpr(E->getArg(0));
QualType Ty = E->getType();
@@ -3790,7 +3858,10 @@
getContext().getTypeSize(Ty));
LoadAddr = Builder.CreateBitCast(LoadAddr, IntResTy->getPointerTo());
- Function *F = CGM.getIntrinsic(Intrinsic::aarch64_ldxr, LoadAddr->getType());
+ Function *F = CGM.getIntrinsic(BuiltinID == AArch64::BI__builtin_arm_ldaex
+ ? Intrinsic::aarch64_ldaxr
+ : Intrinsic::aarch64_ldxr,
+ LoadAddr->getType());
Value *Val = Builder.CreateCall(F, LoadAddr, "ldxr");
if (RealResTy->isPointerTy())
@@ -3800,9 +3871,12 @@
return Builder.CreateBitCast(Val, RealResTy);
}
- if (BuiltinID == AArch64::BI__builtin_arm_strex &&
+ if ((BuiltinID == AArch64::BI__builtin_arm_strex ||
+ BuiltinID == AArch64::BI__builtin_arm_stlex) &&
getContext().getTypeSize(E->getArg(0)->getType()) == 128) {
- Function *F = CGM.getIntrinsic(Intrinsic::aarch64_stxp);
+ Function *F = CGM.getIntrinsic(BuiltinID == AArch64::BI__builtin_arm_stlex
+ ? Intrinsic::aarch64_stlxp
+ : Intrinsic::aarch64_stxp);
llvm::Type *STy = llvm::StructType::get(Int64Ty, Int64Ty, NULL);
Value *One = llvm::ConstantInt::get(Int32Ty, 1);
@@ -3819,7 +3893,8 @@
Value *StPtr = Builder.CreateBitCast(EmitScalarExpr(E->getArg(1)),
Int8PtrTy);
return Builder.CreateCall3(F, Arg0, Arg1, StPtr, "stxp");
- } else if (BuiltinID == AArch64::BI__builtin_arm_strex) {
+ } else if (BuiltinID == AArch64::BI__builtin_arm_strex ||
+ BuiltinID == AArch64::BI__builtin_arm_stlex) {
Value *StoreVal = EmitScalarExpr(E->getArg(0));
Value *StoreAddr = EmitScalarExpr(E->getArg(1));
@@ -3835,7 +3910,10 @@
StoreVal = Builder.CreateZExtOrBitCast(StoreVal, Int64Ty);
}
- Function *F = CGM.getIntrinsic(Intrinsic::aarch64_stxr, StoreAddr->getType());
+ Function *F = CGM.getIntrinsic(BuiltinID == AArch64::BI__builtin_arm_stlex
+ ? Intrinsic::aarch64_stlxr
+ : Intrinsic::aarch64_stxr,
+ StoreAddr->getType());
return Builder.CreateCall2(F, StoreVal, StoreAddr, "stxr");
}
@@ -3880,7 +3958,7 @@
for (unsigned i = 0, e = E->getNumArgs() - 1; i != e; i++)
Ops.push_back(EmitScalarExpr(E->getArg(i)));
- llvm::ArrayRef<NeonIntrinsicInfo> SISDMap(AArch64SISDIntrinsicMap);
+ ArrayRef<NeonIntrinsicInfo> SISDMap(AArch64SISDIntrinsicMap);
const NeonIntrinsicInfo *Builtin = findNeonIntrinsicInMap(
SISDMap, BuiltinID, AArch64SISDIntrinsicsProvenSorted);
@@ -3950,8 +4028,8 @@
Value *Vec = EmitScalarExpr(E->getArg(0));
// The vector is v2f64, so make sure it's bitcast to that.
Vec = Builder.CreateBitCast(Vec, Ty, "v2i64");
- llvm::Value *Idx0 = llvm::ConstantInt::get(Int32Ty, 0);
- llvm::Value *Idx1 = llvm::ConstantInt::get(Int32Ty, 1);
+ llvm::Value *Idx0 = llvm::ConstantInt::get(SizeTy, 0);
+ llvm::Value *Idx1 = llvm::ConstantInt::get(SizeTy, 1);
Value *Op0 = Builder.CreateExtractElement(Vec, Idx0, "lane0");
Value *Op1 = Builder.CreateExtractElement(Vec, Idx1, "lane1");
// Pairwise addition of a v2f64 into a scalar f64.
@@ -3963,8 +4041,8 @@
Value *Vec = EmitScalarExpr(E->getArg(0));
// The vector is v2f64, so make sure it's bitcast to that.
Vec = Builder.CreateBitCast(Vec, Ty, "v2f64");
- llvm::Value *Idx0 = llvm::ConstantInt::get(Int32Ty, 0);
- llvm::Value *Idx1 = llvm::ConstantInt::get(Int32Ty, 1);
+ llvm::Value *Idx0 = llvm::ConstantInt::get(SizeTy, 0);
+ llvm::Value *Idx1 = llvm::ConstantInt::get(SizeTy, 1);
Value *Op0 = Builder.CreateExtractElement(Vec, Idx0, "lane0");
Value *Op1 = Builder.CreateExtractElement(Vec, Idx1, "lane1");
// Pairwise addition of a v2f64 into a scalar f64.
@@ -3976,8 +4054,8 @@
Value *Vec = EmitScalarExpr(E->getArg(0));
// The vector is v2f32, so make sure it's bitcast to that.
Vec = Builder.CreateBitCast(Vec, Ty, "v2f32");
- llvm::Value *Idx0 = llvm::ConstantInt::get(Int32Ty, 0);
- llvm::Value *Idx1 = llvm::ConstantInt::get(Int32Ty, 1);
+ llvm::Value *Idx0 = llvm::ConstantInt::get(SizeTy, 0);
+ llvm::Value *Idx1 = llvm::ConstantInt::get(SizeTy, 1);
Value *Op0 = Builder.CreateExtractElement(Vec, Idx0, "lane0");
Value *Op1 = Builder.CreateExtractElement(Vec, Idx1, "lane1");
// Pairwise addition of a v2f32 into a scalar f32.
@@ -4228,7 +4306,7 @@
llvm::Type *VTy = llvm::VectorType::get(Int32Ty, 4);
Ops[1] = EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_sqdmull, VTy),
ProductOps, "vqdmlXl");
- Constant *CI = ConstantInt::get(Int32Ty, 0);
+ Constant *CI = ConstantInt::get(SizeTy, 0);
Ops[1] = Builder.CreateExtractElement(Ops[1], CI, "lane0");
unsigned AccumInt = BuiltinID == NEON::BI__builtin_neon_vqdmlalh_s16
@@ -4325,7 +4403,7 @@
llvm::Type *VTy = llvm::VectorType::get(Int32Ty, 4);
Ops[1] = EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_sqdmull, VTy),
ProductOps, "vqdmlXl");
- Constant *CI = ConstantInt::get(Int32Ty, 0);
+ Constant *CI = ConstantInt::get(SizeTy, 0);
Ops[1] = Builder.CreateExtractElement(Ops[1], CI, "lane0");
Ops.pop_back();
@@ -5611,7 +5689,7 @@
// extract (0, 1)
unsigned Index = BuiltinID == X86::BI__builtin_ia32_storelps ? 0 : 1;
- llvm::Value *Idx = llvm::ConstantInt::get(Int32Ty, Index);
+ llvm::Value *Idx = llvm::ConstantInt::get(SizeTy, Index);
Ops[1] = Builder.CreateExtractElement(Ops[1], Idx, "extract");
// cast pointer to i64 & store
@@ -5896,3 +5974,38 @@
}
}
}
+
+Value *CodeGenFunction::EmitR600BuiltinExpr(unsigned BuiltinID,
+ const CallExpr *E) {
+ switch (BuiltinID) {
+ case R600::BI__builtin_amdgpu_div_scale:
+ case R600::BI__builtin_amdgpu_div_scalef: {
+ // Translate from the intrinsics's struct return to the builtin's out
+ // argument.
+
+ std::pair<llvm::Value *, unsigned> FlagOutPtr
+ = EmitPointerWithAlignment(E->getArg(3));
+
+ llvm::Value *X = EmitScalarExpr(E->getArg(0));
+ llvm::Value *Y = EmitScalarExpr(E->getArg(1));
+ llvm::Value *Z = EmitScalarExpr(E->getArg(2));
+
+ llvm::Value *Callee = CGM.getIntrinsic(Intrinsic::AMDGPU_div_scale,
+ X->getType());
+
+ llvm::Value *Tmp = Builder.CreateCall3(Callee, X, Y, Z);
+
+ llvm::Value *Result = Builder.CreateExtractValue(Tmp, 0);
+ llvm::Value *Flag = Builder.CreateExtractValue(Tmp, 1);
+
+ llvm::Type *RealFlagType
+ = FlagOutPtr.first->getType()->getPointerElementType();
+
+ llvm::Value *FlagExt = Builder.CreateZExt(Flag, RealFlagType);
+ llvm::StoreInst *FlagStore = Builder.CreateStore(FlagExt, FlagOutPtr.first);
+ FlagStore->setAlignment(FlagOutPtr.second);
+ return Result;
+ } default:
+ return nullptr;
+ }
+}
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index 55c06f6..545c5ef 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -44,6 +44,10 @@
if (!D->hasTrivialBody())
return true;
+ // For exported destructors, we need a full definition.
+ if (D->hasAttr<DLLExportAttr>())
+ return true;
+
const CXXRecordDecl *Class = D->getParent();
// If we need to manipulate a VTT parameter, give up.
@@ -138,9 +142,9 @@
// which case the caller is responsible for ensuring the soundness
// of these semantics.
auto *Ref = cast<llvm::GlobalValue>(GetAddrOfGlobal(TargetDecl));
- auto *Aliasee = dyn_cast<llvm::GlobalObject>(Ref);
- if (!Aliasee)
- Aliasee = cast<llvm::GlobalAlias>(Ref)->getAliasee();
+ llvm::Constant *Aliasee = Ref;
+ 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 aliasee.
@@ -152,10 +156,7 @@
// members with attribute "AlwaysInline" and expect no reference to
// be generated. It is desirable to reenable this optimisation after
// corresponding LLVM changes.
- llvm::Constant *Replacement = Aliasee;
- if (Aliasee->getType() != AliasType)
- Replacement = llvm::ConstantExpr::getBitCast(Aliasee, AliasType);
- Replacements[MangledName] = Replacement;
+ Replacements[MangledName] = Aliasee;
return false;
}
@@ -163,7 +164,7 @@
/// 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 (Aliasee->isDeclaration())
+ if (Ref->isDeclaration())
return true;
}
@@ -176,7 +177,7 @@
// Create the alias with no name.
auto *Alias = llvm::GlobalAlias::create(AliasType->getElementType(), 0,
- Linkage, "", Aliasee);
+ Linkage, "", Aliasee, &getModule());
// Switch any previous uses to the alias.
if (Entry) {
diff --git a/lib/CodeGen/CGCXXABI.cpp b/lib/CodeGen/CGCXXABI.cpp
index 1f0de31..55ddd66 100644
--- a/lib/CodeGen/CGCXXABI.cpp
+++ b/lib/CodeGen/CGCXXABI.cpp
@@ -311,7 +311,7 @@
}
void CGCXXABI::EmitThreadLocalInitFuncs(
- llvm::ArrayRef<std::pair<const VarDecl *, llvm::GlobalVariable *> > Decls,
+ ArrayRef<std::pair<const VarDecl *, llvm::GlobalVariable *> > Decls,
llvm::Function *InitFunc) {
}
@@ -325,31 +325,3 @@
bool CGCXXABI::NeedsVTTParameter(GlobalDecl GD) {
return false;
}
-
-/// What sort of uniqueness rules should we use for the RTTI for the
-/// given type?
-CGCXXABI::RTTIUniquenessKind
-CGCXXABI::classifyRTTIUniqueness(QualType CanTy,
- llvm::GlobalValue::LinkageTypes Linkage) {
- if (shouldRTTIBeUnique())
- return RUK_Unique;
-
- // It's only necessary for linkonce_odr or weak_odr linkage.
- if (Linkage != llvm::GlobalValue::LinkOnceODRLinkage &&
- Linkage != llvm::GlobalValue::WeakODRLinkage)
- return RUK_Unique;
-
- // It's only necessary with default visibility.
- if (CanTy->getVisibility() != DefaultVisibility)
- return RUK_Unique;
-
- // If we're not required to publish this symbol, hide it.
- if (Linkage == llvm::GlobalValue::LinkOnceODRLinkage)
- return RUK_NonUniqueHidden;
-
- // If we're required to publish this symbol, as we might be under an
- // explicit instantiation, leave it with default visibility but
- // enable string-comparisons.
- assert(Linkage == llvm::GlobalValue::WeakODRLinkage);
- return RUK_NonUniqueVisible;
-}
diff --git a/lib/CodeGen/CGCXXABI.h b/lib/CodeGen/CGCXXABI.h
index 615ec23..b49c68a 100644
--- a/lib/CodeGen/CGCXXABI.h
+++ b/lib/CodeGen/CGCXXABI.h
@@ -207,6 +207,30 @@
llvm::Value *ptr,
QualType type) = 0;
+ virtual llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) = 0;
+
+ virtual bool shouldTypeidBeNullChecked(bool IsDeref,
+ QualType SrcRecordTy) = 0;
+ virtual void EmitBadTypeidCall(CodeGenFunction &CGF) = 0;
+ virtual llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy,
+ llvm::Value *ThisPtr,
+ llvm::Type *StdTypeInfoPtrTy) = 0;
+
+ virtual bool shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
+ QualType SrcRecordTy) = 0;
+
+ virtual llvm::Value *
+ EmitDynamicCastCall(CodeGenFunction &CGF, llvm::Value *Value,
+ QualType SrcRecordTy, QualType DestTy,
+ QualType DestRecordTy, llvm::BasicBlock *CastEnd) = 0;
+
+ virtual llvm::Value *EmitDynamicCastToVoid(CodeGenFunction &CGF,
+ llvm::Value *Value,
+ QualType SrcRecordTy,
+ QualType DestTy) = 0;
+
+ virtual bool EmitBadCastCall(CodeGenFunction &CGF) = 0;
+
virtual llvm::Value *GetVirtualBaseClassOffset(CodeGenFunction &CGF,
llvm::Value *This,
const CXXRecordDecl *ClassDecl,
@@ -359,7 +383,8 @@
/// base tables.
virtual void emitVirtualInheritanceTables(const CXXRecordDecl *RD) = 0;
- virtual void setThunkLinkage(llvm::Function *Thunk, bool ForVTable) = 0;
+ virtual void setThunkLinkage(llvm::Function *Thunk, bool ForVTable,
+ GlobalDecl GD, bool ReturnAdjustment) = 0;
virtual llvm::Value *performThisAdjustment(CodeGenFunction &CGF,
llvm::Value *This,
@@ -484,7 +509,7 @@
/// initialization or non-trivial destruction for thread_local
/// variables, a function to perform the initialization. Otherwise, 0.
virtual void EmitThreadLocalInitFuncs(
- llvm::ArrayRef<std::pair<const VarDecl *, llvm::GlobalVariable *> > Decls,
+ ArrayRef<std::pair<const VarDecl *, llvm::GlobalVariable *> > Decls,
llvm::Function *InitFunc);
/// Emit a reference to a non-local thread_local variable (including
@@ -493,36 +518,6 @@
virtual LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF,
const VarDecl *VD,
QualType LValType);
-
- /**************************** RTTI Uniqueness ******************************/
-
-protected:
- /// Returns true if the ABI requires RTTI type_info objects to be unique
- /// across a program.
- virtual bool shouldRTTIBeUnique() { return true; }
-
-public:
- /// What sort of unique-RTTI behavior should we use?
- enum RTTIUniquenessKind {
- /// We are guaranteeing, or need to guarantee, that the RTTI string
- /// is unique.
- RUK_Unique,
-
- /// We are not guaranteeing uniqueness for the RTTI string, so we
- /// can demote to hidden visibility but must use string comparisons.
- RUK_NonUniqueHidden,
-
- /// We are not guaranteeing uniqueness for the RTTI string, so we
- /// have to use string comparisons, but we also have to emit it with
- /// non-hidden visibility.
- RUK_NonUniqueVisible
- };
-
- /// Return the required visibility status for the given type and linkage in
- /// the current ABI.
- RTTIUniquenessKind
- classifyRTTIUniqueness(QualType CanTy,
- llvm::GlobalValue::LinkageTypes Linkage);
};
// Create an instance of a C++ ABI class:
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index d0849d3..44fd4d8 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -1200,6 +1200,9 @@
llvm_unreachable("Invalid ABI kind for return argument");
}
+ if (RetTy->isReferenceType())
+ RetAttrs.addAttribute(llvm::Attribute::NonNull);
+
if (RetAttrs.hasAttributes())
PAL.push_back(llvm::
AttributeSet::get(getLLVMContext(),
@@ -1288,6 +1291,9 @@
}
}
+ if (ParamType->isReferenceType())
+ Attrs.addAttribute(llvm::Attribute::NonNull);
+
if (Attrs.hasAttributes())
PAL.push_back(llvm::AttributeSet::get(getLLVMContext(), Index, Attrs));
++Index;
@@ -2853,28 +2859,33 @@
if (ArgMemory) {
llvm::Value *Arg = ArgMemory;
- llvm::Type *LastParamTy =
- IRFuncTy->getParamType(IRFuncTy->getNumParams() - 1);
- if (Arg->getType() != LastParamTy) {
+ if (CallInfo.isVariadic()) {
+ // When passing non-POD arguments by value to variadic functions, we will
+ // end up with a variadic prototype and an inalloca call site. In such
+ // cases, we can't do any parameter mismatch checks. Give up and bitcast
+ // the callee.
+ unsigned CalleeAS =
+ cast<llvm::PointerType>(Callee->getType())->getAddressSpace();
+ Callee = Builder.CreateBitCast(
+ Callee, getTypes().GetFunctionType(CallInfo)->getPointerTo(CalleeAS));
+ } else {
+ llvm::Type *LastParamTy =
+ IRFuncTy->getParamType(IRFuncTy->getNumParams() - 1);
+ if (Arg->getType() != LastParamTy) {
#ifndef NDEBUG
- // Assert that these structs have equivalent element types.
- llvm::StructType *FullTy = CallInfo.getArgStruct();
- llvm::StructType *Prefix = cast<llvm::StructType>(
- cast<llvm::PointerType>(LastParamTy)->getElementType());
-
- // For variadic functions, the caller might supply a larger struct than
- // the callee expects, and that's OK.
- assert(Prefix->getNumElements() == FullTy->getNumElements() ||
- (CallInfo.isVariadic() &&
- Prefix->getNumElements() <= FullTy->getNumElements()));
-
- for (llvm::StructType::element_iterator PI = Prefix->element_begin(),
- PE = Prefix->element_end(),
- FI = FullTy->element_begin();
- PI != PE; ++PI, ++FI)
- assert(*PI == *FI);
+ // Assert that these structs have equivalent element types.
+ llvm::StructType *FullTy = CallInfo.getArgStruct();
+ llvm::StructType *DeclaredTy = cast<llvm::StructType>(
+ cast<llvm::PointerType>(LastParamTy)->getElementType());
+ assert(DeclaredTy->getNumElements() == FullTy->getNumElements());
+ for (llvm::StructType::element_iterator DI = DeclaredTy->element_begin(),
+ DE = DeclaredTy->element_end(),
+ FI = FullTy->element_begin();
+ DI != DE; ++DI, ++FI)
+ assert(*DI == *FI);
#endif
- Arg = Builder.CreateBitCast(Arg, LastParamTy);
+ Arg = Builder.CreateBitCast(Arg, LastParamTy);
+ }
}
Args.push_back(Arg);
}
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index 97bea97..9427de1 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -1425,8 +1425,8 @@
/// in reverse order of their construction.
void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD,
CXXDtorType DtorType) {
- assert(!DD->isTrivial() &&
- "Should not emit dtor epilogue for trivial dtor!");
+ assert((!DD->isTrivial() || DD->hasAttr<DLLExportAttr>()) &&
+ "Should not emit dtor epilogue for non-exported trivial dtor!");
// The deleting-destructor phase just needs to call the appropriate
// operator delete that Sema picked up.
@@ -2179,7 +2179,7 @@
FunctionTemplateDecl *CallOpTemplate = CallOp->getDescribedFunctionTemplate();
void *InsertPos = nullptr;
FunctionDecl *CorrespondingCallOpSpecialization =
- CallOpTemplate->findSpecialization(TAL->data(), TAL->size(), InsertPos);
+ CallOpTemplate->findSpecialization(TAL->asArray(), InsertPos);
assert(CorrespondingCallOpSpecialization);
CallOp = cast<CXXMethodDecl>(CorrespondingCallOpSpecialization);
}
diff --git a/lib/CodeGen/CGCleanup.h b/lib/CodeGen/CGCleanup.h
index 066cdb2..1d4606f 100644
--- a/lib/CodeGen/CGCleanup.h
+++ b/lib/CodeGen/CGCleanup.h
@@ -145,7 +145,7 @@
struct Handler {
/// A type info value, or null (C++ null, not an LLVM null pointer)
/// for a catch-all.
- llvm::Value *Type;
+ llvm::Constant *Type;
/// The catch handler for this type.
llvm::BasicBlock *Block;
@@ -183,7 +183,7 @@
setHandler(I, /*catchall*/ nullptr, Block);
}
- void setHandler(unsigned I, llvm::Value *Type, llvm::BasicBlock *Block) {
+ void setHandler(unsigned I, llvm::Constant *Type, llvm::BasicBlock *Block) {
assert(I < getNumHandlers());
getHandlers()[I].Type = Type;
getHandlers()[I].Block = Block;
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index e2ba70a..048c8f8 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -375,9 +375,10 @@
TheCU = DBuilder.createCompileUnit(
LangTag, Filename, getCurrentDirname(), Producer, LO.Optimize,
CGM.getCodeGenOpts().DwarfDebugFlags, RuntimeVers, SplitDwarfFilename,
- DebugKind == CodeGenOptions::DebugLineTablesOnly
+ DebugKind <= CodeGenOptions::DebugLineTablesOnly
? llvm::DIBuilder::LineTablesOnly
- : llvm::DIBuilder::FullDebug);
+ : llvm::DIBuilder::FullDebug,
+ DebugKind != CodeGenOptions::LocTrackingOnly);
}
/// CreateType - Get the Basic type from the cache or create a new
@@ -2341,7 +2342,7 @@
/// 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)
+ if (!D || DebugKind <= CodeGenOptions::DebugLineTablesOnly)
return llvm::DISubprogram();
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
@@ -2386,7 +2387,7 @@
llvm::DICompositeType CGDebugInfo::getOrCreateFunctionType(const Decl *D,
QualType FnType,
llvm::DIFile F) {
- if (!D || DebugKind == CodeGenOptions::DebugLineTablesOnly)
+ 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
@@ -2579,14 +2580,11 @@
/// CreateLexicalBlock - Creates a new lexical block node and pushes it on
/// the stack.
void CGDebugInfo::CreateLexicalBlock(SourceLocation Loc) {
- llvm::DIDescriptor D =
- DBuilder.createLexicalBlock(LexicalBlockStack.empty() ?
- llvm::DIDescriptor() :
- llvm::DIDescriptor(LexicalBlockStack.back()),
- getOrCreateFile(CurLoc),
- getLineNumber(CurLoc),
- getColumnNumber(CurLoc),
- 0);
+ llvm::DIDescriptor D = DBuilder.createLexicalBlock(
+ llvm::DIDescriptor(LexicalBlockStack.empty() ? nullptr
+ : LexicalBlockStack.back()),
+ getOrCreateFile(CurLoc), getLineNumber(CurLoc), getColumnNumber(CurLoc),
+ 0);
llvm::MDNode *DN = D;
LexicalBlockStack.push_back(DN);
}
@@ -3190,32 +3188,6 @@
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(DebugKind >= CodeGenOptions::LimitedDebugInfo);
- // Create global variable debug descriptor.
- llvm::DIFile Unit = getOrCreateFile(ID->getLocation());
- unsigned LineNo = getLineNumber(ID->getLocation());
-
- StringRef Name = ID->getName();
-
- QualType T = CGM.getContext().getObjCInterfaceType(ID);
- if (T->isIncompleteArrayType()) {
-
- // CodeGen turns int[] into int[1] so we'll do the same here.
- llvm::APInt ConstVal(32, 1);
- QualType ET = CGM.getContext().getAsArrayType(T)->getElementType();
-
- T = CGM.getContext().getConstantArrayType(ET, ConstVal,
- ArrayType::Normal, 0);
- }
-
- DBuilder.createGlobalVariable(Name, Unit, LineNo,
- getOrCreateType(T, Unit),
- Var->hasInternalLinkage(), Var);
-}
-
/// EmitGlobalVariable - Emit global variable's debug info.
void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD,
llvm::Constant *Init) {
diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h
index 0da6179..fc3f434 100644
--- a/lib/CodeGen/CGDebugInfo.h
+++ b/lib/CodeGen/CGDebugInfo.h
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This is the source level debug info generator for llvm translation.
+// This is the source-level debug info generator for llvm translation.
//
//===----------------------------------------------------------------------===//
@@ -273,9 +273,6 @@
/// EmitGlobalVariable - Emit information about a global variable.
void EmitGlobalVariable(llvm::GlobalVariable *GV, const VarDecl *Decl);
- /// EmitGlobalVariable - Emit information about an objective-c interface.
- void EmitGlobalVariable(llvm::GlobalVariable *GV, ObjCInterfaceDecl *Decl);
-
/// EmitGlobalVariable - Emit global variable's debug info.
void EmitGlobalVariable(const ValueDecl *VD, llvm::Constant *Init);
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 1869c1c..9bd61d7 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -149,32 +149,27 @@
static std::string GetStaticDeclName(CodeGenFunction &CGF, const VarDecl &D,
const char *Separator) {
CodeGenModule &CGM = CGF.CGM;
- if (CGF.getLangOpts().CPlusPlus) {
- StringRef Name = CGM.getMangledName(&D);
- return Name.str();
- }
- std::string ContextName;
+ if (CGF.getLangOpts().CPlusPlus)
+ return CGM.getMangledName(&D).str();
+
+ StringRef ContextName;
if (!CGF.CurFuncDecl) {
// Better be in a block declared in global scope.
const NamedDecl *ND = cast<NamedDecl>(&D);
const DeclContext *DC = ND->getDeclContext();
- if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC)) {
- MangleBuffer Name;
- CGM.getBlockMangledName(GlobalDecl(), Name, BD);
- ContextName = Name.getString();
- }
+ if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC))
+ ContextName = CGM.getBlockMangledName(GlobalDecl(), BD);
else
llvm_unreachable("Unknown context for block static var decl");
- } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CGF.CurFuncDecl)) {
- StringRef Name = CGM.getMangledName(FD);
- ContextName = Name.str();
- } else if (isa<ObjCMethodDecl>(CGF.CurFuncDecl))
+ } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CGF.CurFuncDecl))
+ ContextName = CGM.getMangledName(FD);
+ else if (isa<ObjCMethodDecl>(CGF.CurFuncDecl))
ContextName = CGF.CurFn->getName();
else
llvm_unreachable("Unknown context for static var decl");
- return ContextName + Separator + D.getNameAsString();
+ return ContextName.str() + Separator + D.getNameAsString();
}
llvm::Constant *
@@ -206,6 +201,13 @@
if (D.getTLSKind())
CGM.setTLSMode(GV, D);
+ if (D.isExternallyVisible()) {
+ if (D.hasAttr<DLLImportAttr>())
+ GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass);
+ else if (D.hasAttr<DLLExportAttr>())
+ GV->setDLLStorageClass(llvm::GlobalVariable::DLLExportStorageClass);
+ }
+
// Make sure the result is of the correct type.
unsigned ExpectedAddrSpace = CGM.getContext().getTargetAddressSpace(Ty);
if (AddrSpace != ExpectedAddrSpace) {
@@ -343,6 +345,8 @@
DMEntry = castedAddr;
CGM.setStaticLocalDeclAddress(&D, castedAddr);
+ CGM.reportGlobalToASan(var, D.getLocation());
+
// Emit global variable debug descriptor for static vars.
CGDebugInfo *DI = getDebugInfo();
if (DI &&
@@ -800,9 +804,6 @@
/// Should we use the LLVM lifetime intrinsics for the given local variable?
static bool shouldUseLifetimeMarkers(CodeGenFunction &CGF, const VarDecl &D,
unsigned Size) {
- // Always emit lifetime markers in -fsanitize=use-after-scope mode.
- if (CGF.getLangOpts().Sanitize.UseAfterScope)
- return true;
// For now, only in optimized builds.
if (CGF.CGM.getCodeGenOpts().OptimizationLevel == 0)
return false;
diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp
index c287740..6a03e9a 100644
--- a/lib/CodeGen/CGDeclCXX.cpp
+++ b/lib/CodeGen/CGDeclCXX.cpp
@@ -245,12 +245,14 @@
if (!CGM.getLangOpts().Exceptions)
Fn->setDoesNotThrow();
- if (CGM.getSanOpts().Address)
- Fn->addFnAttr(llvm::Attribute::SanitizeAddress);
- if (CGM.getSanOpts().Thread)
- Fn->addFnAttr(llvm::Attribute::SanitizeThread);
- if (CGM.getSanOpts().Memory)
- Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
+ if (!CGM.getSanitizerBlacklist().isIn(*Fn)) {
+ if (CGM.getLangOpts().Sanitize.Address)
+ Fn->addFnAttr(llvm::Attribute::SanitizeAddress);
+ if (CGM.getLangOpts().Sanitize.Thread)
+ Fn->addFnAttr(llvm::Attribute::SanitizeThread);
+ if (CGM.getLangOpts().Sanitize.Memory)
+ Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
+ }
return Fn;
}
diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp
index 9fa478c..1bbda5c 100644
--- a/lib/CodeGen/CGException.cpp
+++ b/lib/CodeGen/CGException.cpp
@@ -97,24 +97,6 @@
return CGM.CreateRuntimeFunction(FTy, "__cxa_call_unexpected");
}
-llvm::Constant *CodeGenFunction::getUnwindResumeFn() {
- llvm::FunctionType *FTy =
- llvm::FunctionType::get(VoidTy, Int8PtrTy, /*IsVarArgs=*/false);
-
- if (CGM.getLangOpts().SjLjExceptions)
- return CGM.CreateRuntimeFunction(FTy, "_Unwind_SjLj_Resume");
- return CGM.CreateRuntimeFunction(FTy, "_Unwind_Resume");
-}
-
-llvm::Constant *CodeGenFunction::getUnwindResumeOrRethrowFn() {
- llvm::FunctionType *FTy =
- llvm::FunctionType::get(VoidTy, Int8PtrTy, /*IsVarArgs=*/false);
-
- if (CGM.getLangOpts().SjLjExceptions)
- return CGM.CreateRuntimeFunction(FTy, "_Unwind_SjLj_Resume_or_Rethrow");
- return CGM.CreateRuntimeFunction(FTy, "_Unwind_Resume_or_Rethrow");
-}
-
static llvm::Constant *getTerminateFn(CodeGenModule &CGM) {
// void __terminate();
@@ -622,7 +604,7 @@
QualType CaughtType = C->getCaughtType();
CaughtType = CaughtType.getNonReferenceType().getUnqualifiedType();
- llvm::Value *TypeInfo = nullptr;
+ llvm::Constant *TypeInfo = nullptr;
if (CaughtType->isObjCObjectPointerType())
TypeInfo = CGM.getObjCRuntime().GetEHType(CaughtType);
else
@@ -721,56 +703,6 @@
return LP;
}
-// This code contains a hack to work around a design flaw in
-// LLVM's EH IR which breaks semantics after inlining. This same
-// hack is implemented in llvm-gcc.
-//
-// The LLVM EH abstraction is basically a thin veneer over the
-// traditional GCC zero-cost design: for each range of instructions
-// in the function, there is (at most) one "landing pad" with an
-// associated chain of EH actions. A language-specific personality
-// function interprets this chain of actions and (1) decides whether
-// or not to resume execution at the landing pad and (2) if so,
-// provides an integer indicating why it's stopping. In LLVM IR,
-// the association of a landing pad with a range of instructions is
-// achieved via an invoke instruction, the chain of actions becomes
-// the arguments to the @llvm.eh.selector call, and the selector
-// call returns the integer indicator. Other than the required
-// presence of two intrinsic function calls in the landing pad,
-// the IR exactly describes the layout of the output code.
-//
-// A principal advantage of this design is that it is completely
-// language-agnostic; in theory, the LLVM optimizers can treat
-// landing pads neutrally, and targets need only know how to lower
-// the intrinsics to have a functioning exceptions system (assuming
-// that platform exceptions follow something approximately like the
-// GCC design). Unfortunately, landing pads cannot be combined in a
-// language-agnostic way: given selectors A and B, there is no way
-// to make a single landing pad which faithfully represents the
-// semantics of propagating an exception first through A, then
-// through B, without knowing how the personality will interpret the
-// (lowered form of the) selectors. This means that inlining has no
-// choice but to crudely chain invokes (i.e., to ignore invokes in
-// the inlined function, but to turn all unwindable calls into
-// invokes), which is only semantically valid if every unwind stops
-// at every landing pad.
-//
-// Therefore, the invoke-inline hack is to guarantee that every
-// landing pad has a catch-all.
-enum CleanupHackLevel_t {
- /// A level of hack that requires that all landing pads have
- /// catch-alls.
- CHL_MandatoryCatchall,
-
- /// A level of hack that requires that all landing pads handle
- /// cleanups.
- CHL_MandatoryCleanup,
-
- /// No hacks at all; ideal IR generation.
- CHL_Ideal
-};
-const CleanupHackLevel_t CleanupHackLevel = CHL_MandatoryCleanup;
-
llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
assert(EHStack.requiresLandingPad());
@@ -897,11 +829,8 @@
LPadInst->setCleanup(true);
// Otherwise, signal that we at least have cleanups.
- } else if (CleanupHackLevel == CHL_MandatoryCatchall || hasCleanup) {
- if (CleanupHackLevel == CHL_MandatoryCatchall)
- LPadInst->addClause(getCatchAllValue(*this));
- else
- LPadInst->setCleanup(true);
+ } else if (hasCleanup) {
+ LPadInst->setCleanup(true);
}
assert((LPadInst->getNumClauses() > 0 || LPadInst->isCleanup()) &&
@@ -1678,52 +1607,32 @@
const char *RethrowName = Personality.CatchallRethrowFn;
if (RethrowName != nullptr && !isCleanup) {
EmitRuntimeCall(getCatchallRethrowFn(CGM, RethrowName),
- getExceptionFromSlot())
+ getExceptionFromSlot())
->setDoesNotReturn();
- } else {
- switch (CleanupHackLevel) {
- case CHL_MandatoryCatchall:
- // In mandatory-catchall mode, we need to use
- // _Unwind_Resume_or_Rethrow, or whatever the personality's
- // equivalent is.
- EmitRuntimeCall(getUnwindResumeOrRethrowFn(),
- getExceptionFromSlot())
- ->setDoesNotReturn();
- break;
- case CHL_MandatoryCleanup: {
- // In mandatory-cleanup mode, we should use 'resume'.
-
- // Recreate the landingpad's return value for the 'resume' instruction.
- llvm::Value *Exn = getExceptionFromSlot();
- llvm::Value *Sel = getSelectorFromSlot();
-
- llvm::Type *LPadType = llvm::StructType::get(Exn->getType(),
- Sel->getType(), NULL);
- llvm::Value *LPadVal = llvm::UndefValue::get(LPadType);
- LPadVal = Builder.CreateInsertValue(LPadVal, Exn, 0, "lpad.val");
- LPadVal = Builder.CreateInsertValue(LPadVal, Sel, 1, "lpad.val");
-
- Builder.CreateResume(LPadVal);
- Builder.restoreIP(SavedIP);
- return EHResumeBlock;
- }
- case CHL_Ideal:
- // In an idealized mode where we don't have to worry about the
- // optimizer combining landing pads, we should just use
- // _Unwind_Resume (or the personality's equivalent).
- EmitRuntimeCall(getUnwindResumeFn(), getExceptionFromSlot())
- ->setDoesNotReturn();
- break;
- }
+ Builder.CreateUnreachable();
+ Builder.restoreIP(SavedIP);
+ return EHResumeBlock;
}
- Builder.CreateUnreachable();
+ // Recreate the landingpad's return value for the 'resume' instruction.
+ llvm::Value *Exn = getExceptionFromSlot();
+ llvm::Value *Sel = getSelectorFromSlot();
+ llvm::Type *LPadType = llvm::StructType::get(Exn->getType(),
+ Sel->getType(), NULL);
+ llvm::Value *LPadVal = llvm::UndefValue::get(LPadType);
+ LPadVal = Builder.CreateInsertValue(LPadVal, Exn, 0, "lpad.val");
+ LPadVal = Builder.CreateInsertValue(LPadVal, Sel, 1, "lpad.val");
+
+ Builder.CreateResume(LPadVal);
Builder.restoreIP(SavedIP);
-
return EHResumeBlock;
}
void CodeGenFunction::EmitSEHTryStmt(const SEHTryStmt &S) {
CGM.ErrorUnsupported(&S, "SEH __try");
}
+
+void CodeGenFunction::EmitSEHLeaveStmt(const SEHLeaveStmt &S) {
+ CGM.ErrorUnsupported(&S, "SEH __leave");
+}
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 966edc4..c99e669 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -407,7 +407,7 @@
assert(LV.isSimple());
llvm::Value *Value = LV.getAddress();
- if (SanitizePerformTypeCheck && !E->getType()->isFunctionType()) {
+ 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
// an existing object or function of an appropriate type nor a region of
@@ -441,10 +441,15 @@
return Builder.CreateMul(B1, KMul);
}
+bool CodeGenFunction::sanitizePerformTypeCheck() const {
+ return SanOpts->Null | SanOpts->Alignment | SanOpts->ObjectSize |
+ SanOpts->Vptr;
+}
+
void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
llvm::Value *Address,
QualType Ty, CharUnits Alignment) {
- if (!SanitizePerformTypeCheck)
+ if (!sanitizePerformTypeCheck())
return;
// Don't check pointers outside the default address space. The null check
@@ -1331,7 +1336,7 @@
const VectorType *ExprVT = LV.getType()->getAs<VectorType>();
if (!ExprVT) {
unsigned InIdx = getAccessedFieldNo(0, Elts);
- llvm::Value *Elt = llvm::ConstantInt::get(Int32Ty, InIdx);
+ llvm::Value *Elt = llvm::ConstantInt::get(SizeTy, InIdx);
return RValue::get(Builder.CreateExtractElement(Vec, Elt));
}
@@ -1350,12 +1355,22 @@
/// @brief Load of global gamed gegisters are always calls to intrinsics.
RValue CodeGenFunction::EmitLoadOfGlobalRegLValue(LValue LV) {
- assert(LV.getType()->isIntegerType() && "Bad type for register variable");
+ assert((LV.getType()->isIntegerType() || LV.getType()->isPointerType()) &&
+ "Bad type for register variable");
llvm::MDNode *RegName = dyn_cast<llvm::MDNode>(LV.getGlobalReg());
assert(RegName && "Register LValue is not metadata");
- llvm::Type *Types[] = { CGM.getTypes().ConvertType(LV.getType()) };
+
+ // We accept integer and pointer types only
+ llvm::Type *OrigTy = CGM.getTypes().ConvertType(LV.getType());
+ llvm::Type *Ty = OrigTy;
+ if (OrigTy->isPointerTy())
+ Ty = CGM.getTypes().getDataLayout().getIntPtrType(OrigTy);
+ llvm::Type *Types[] = { Ty };
+
llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::read_register, Types);
- llvm::Value* Call = Builder.CreateCall(F, RegName);
+ llvm::Value *Call = Builder.CreateCall(F, RegName);
+ if (OrigTy->isPointerTy())
+ Call = Builder.CreateIntToPtr(Call, OrigTy);
return RValue::get(Call);
}
@@ -1590,7 +1605,7 @@
} else {
// If the Src is a scalar (not a vector) it must be updating one element.
unsigned InIdx = getAccessedFieldNo(0, Elts);
- llvm::Value *Elt = llvm::ConstantInt::get(Int32Ty, InIdx);
+ llvm::Value *Elt = llvm::ConstantInt::get(SizeTy, InIdx);
Vec = Builder.CreateInsertElement(Vec, SrcVal, Elt);
}
@@ -1601,12 +1616,22 @@
/// @brief Store of global named registers are always calls to intrinsics.
void CodeGenFunction::EmitStoreThroughGlobalRegLValue(RValue Src, LValue Dst) {
- assert(Dst.getType()->isIntegerType() && "Bad type for register variable");
+ assert((Dst.getType()->isIntegerType() || Dst.getType()->isPointerType()) &&
+ "Bad type for register variable");
llvm::MDNode *RegName = dyn_cast<llvm::MDNode>(Dst.getGlobalReg());
assert(RegName && "Register LValue is not metadata");
- llvm::Type *Types[] = { CGM.getTypes().ConvertType(Dst.getType()) };
+
+ // We accept integer and pointer types only
+ llvm::Type *OrigTy = CGM.getTypes().ConvertType(Dst.getType());
+ llvm::Type *Ty = OrigTy;
+ if (OrigTy->isPointerTy())
+ Ty = CGM.getTypes().getDataLayout().getIntPtrType(OrigTy);
+ llvm::Type *Types[] = { Ty };
+
llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::write_register, Types);
llvm::Value *Value = Src.getScalarVal();
+ if (OrigTy->isPointerTy())
+ Value = Builder.CreatePtrToInt(Value, Ty);
Builder.CreateCall2(F, RegName, Value);
}
@@ -1968,28 +1993,6 @@
E->getType());
}
-static llvm::Constant*
-GetAddrOfConstantWideString(StringRef Str,
- const char *GlobalName,
- ASTContext &Context,
- QualType Ty, SourceLocation Loc,
- CodeGenModule &CGM) {
-
- StringLiteral *SL = StringLiteral::Create(Context,
- Str,
- StringLiteral::Wide,
- /*Pascal = */false,
- Ty, Loc);
- llvm::Constant *C = CGM.GetConstantArrayFromStringLiteral(SL);
- auto *GV = new llvm::GlobalVariable(
- CGM.getModule(), C->getType(), !CGM.getLangOpts().WritableStrings,
- llvm::GlobalValue::PrivateLinkage, C, GlobalName);
- const unsigned WideAlignment =
- Context.getTypeAlignInChars(Ty).getQuantity();
- GV->setAlignment(WideAlignment);
- return GV;
-}
-
static void ConvertUTF8ToWideString(unsigned CharByteWidth, StringRef Source,
SmallString<32>& Target) {
Target.resize(CharByteWidth * (Source.size() + 1));
@@ -2058,14 +2061,12 @@
if (ElemType->isWideCharType()) {
SmallString<32> RawChars;
ConvertUTF8ToWideString(
- getContext().getTypeSizeInChars(ElemType).getQuantity(),
- FunctionName, RawChars);
- C = GetAddrOfConstantWideString(RawChars,
- GVName.c_str(),
- getContext(),
- E->getType(),
- E->getLocation(),
- CGM);
+ getContext().getTypeSizeInChars(ElemType).getQuantity(), FunctionName,
+ RawChars);
+ StringLiteral *SL = StringLiteral::Create(
+ getContext(), RawChars, StringLiteral::Wide,
+ /*Pascal = */ false, E->getType(), E->getLocation());
+ C = CGM.GetAddrOfConstantStringFromLiteral(SL);
} else {
C = CGM.GetAddrOfConstantCString(FunctionName, GVName.c_str(), 1);
}
@@ -2105,7 +2106,7 @@
SmallString<32> Buffer;
CGM.getDiags().ConvertArgToString(DiagnosticsEngine::ak_qualtype,
(intptr_t)T.getAsOpaquePtr(),
- nullptr, 0, nullptr, 0, nullptr, 0, Buffer,
+ StringRef(), StringRef(), None, Buffer,
ArrayRef<intptr_t>());
llvm::Constant *Components[] = {
@@ -2220,9 +2221,9 @@
ArgTypes.push_back(IntPtrTy);
}
- bool Recover = (RecoverKind == CRK_AlwaysRecoverable) ||
- ((RecoverKind == CRK_Recoverable) &&
- CGM.getCodeGenOpts().SanitizeRecover);
+ bool Recover = RecoverKind == CRK_AlwaysRecoverable ||
+ (RecoverKind == CRK_Recoverable &&
+ CGM.getCodeGenOpts().SanitizeRecover);
llvm::FunctionType *FnType =
llvm::FunctionType::get(CGM.VoidTy, ArgTypes, false);
@@ -2234,15 +2235,14 @@
B.addAttribute(llvm::Attribute::UWTable);
// Checks that have two variants use a suffix to differentiate them
- bool NeedsAbortSuffix = (RecoverKind != CRK_Unrecoverable) &&
- !CGM.getCodeGenOpts().SanitizeRecover;
+ bool NeedsAbortSuffix = RecoverKind != CRK_Unrecoverable &&
+ !CGM.getCodeGenOpts().SanitizeRecover;
std::string FunctionName = ("__ubsan_handle_" + CheckName +
(NeedsAbortSuffix? "_abort" : "")).str();
- llvm::Value *Fn =
- CGM.CreateRuntimeFunction(FnType, FunctionName,
- llvm::AttributeSet::get(getLLVMContext(),
- llvm::AttributeSet::FunctionIndex,
- B));
+ llvm::Value *Fn = CGM.CreateRuntimeFunction(
+ FnType, FunctionName,
+ llvm::AttributeSet::get(getLLVMContext(),
+ llvm::AttributeSet::FunctionIndex, B));
llvm::CallInst *HandlerCall = EmitNounwindRuntimeCall(Fn, Args);
if (Recover) {
Builder.CreateBr(Cont);
@@ -2281,7 +2281,7 @@
// If this isn't just an array->pointer decay, bail out.
const auto *CE = dyn_cast<CastExpr>(E);
if (!CE || CE->getCastKind() != CK_ArrayToPointerDecay)
- return 0;
+ return nullptr;
// If this is a decay from variable width array, bail out.
const Expr *SubExpr = CE->getSubExpr();
@@ -2307,7 +2307,6 @@
// Emit the vector as an lvalue to get its address.
LValue LHS = EmitLValue(E->getBase());
assert(LHS.isSimple() && "Can only subscript lvalue vectors here!");
- Idx = Builder.CreateIntCast(Idx, Int32Ty, IdxSigned, "vidx");
return LValue::MakeVectorElt(LHS.getAddress(), Idx,
E->getBase()->getType(), LHS.getAlignment());
}
@@ -2690,6 +2689,19 @@
return EmitLValue(E->getInit(0));
}
+/// Emit the operand of a glvalue conditional operator. This is either a glvalue
+/// or a (possibly-parenthesized) throw-expression. If this is a throw, no
+/// LValue is returned and the current block has been terminated.
+static Optional<LValue> EmitLValueOrThrowExpression(CodeGenFunction &CGF,
+ const Expr *Operand) {
+ if (auto *ThrowExpr = dyn_cast<CXXThrowExpr>(Operand->IgnoreParens())) {
+ CGF.EmitCXXThrowExpr(ThrowExpr, /*KeepInsertionPoint*/false);
+ return None;
+ }
+
+ return CGF.EmitLValue(Operand);
+}
+
LValue CodeGenFunction::
EmitConditionalOperatorLValue(const AbstractConditionalOperator *expr) {
if (!expr->isGLValue()) {
@@ -2727,31 +2739,40 @@
EmitBlock(lhsBlock);
Cnt.beginRegion(Builder);
eval.begin(*this);
- LValue lhs = EmitLValue(expr->getTrueExpr());
+ Optional<LValue> lhs =
+ EmitLValueOrThrowExpression(*this, expr->getTrueExpr());
eval.end(*this);
- if (!lhs.isSimple())
+ if (lhs && !lhs->isSimple())
return EmitUnsupportedLValue(expr, "conditional operator");
lhsBlock = Builder.GetInsertBlock();
- Builder.CreateBr(contBlock);
+ if (lhs)
+ Builder.CreateBr(contBlock);
// Any temporaries created here are conditional.
EmitBlock(rhsBlock);
eval.begin(*this);
- LValue rhs = EmitLValue(expr->getFalseExpr());
+ Optional<LValue> rhs =
+ EmitLValueOrThrowExpression(*this, expr->getFalseExpr());
eval.end(*this);
- if (!rhs.isSimple())
+ if (rhs && !rhs->isSimple())
return EmitUnsupportedLValue(expr, "conditional operator");
rhsBlock = Builder.GetInsertBlock();
EmitBlock(contBlock);
- llvm::PHINode *phi = Builder.CreatePHI(lhs.getAddress()->getType(), 2,
- "cond-lvalue");
- phi->addIncoming(lhs.getAddress(), lhsBlock);
- phi->addIncoming(rhs.getAddress(), rhsBlock);
- return MakeAddrLValue(phi, expr->getType());
+ if (lhs && rhs) {
+ llvm::PHINode *phi = Builder.CreatePHI(lhs->getAddress()->getType(),
+ 2, "cond-lvalue");
+ phi->addIncoming(lhs->getAddress(), lhsBlock);
+ phi->addIncoming(rhs->getAddress(), rhsBlock);
+ return MakeAddrLValue(phi, expr->getType());
+ } else {
+ assert((lhs || rhs) &&
+ "both operands of glvalue conditional are throw-expressions?");
+ return lhs ? *lhs : *rhs;
+ }
}
/// EmitCastLValue - Casts are never lvalues unless that cast is to a reference
@@ -2861,7 +2882,7 @@
// 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)
+ if (sanitizePerformTypeCheck())
EmitTypeCheck(TCK_DowncastReference, E->getExprLoc(),
Derived, E->getType());
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index 760e6f1..b1406cd 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -370,6 +370,29 @@
}
}
+/// \brief Determine if E is a trivial array filler, that is, one that is
+/// equivalent to zero-initialization.
+static bool isTrivialFiller(Expr *E) {
+ if (!E)
+ return true;
+
+ if (isa<ImplicitValueInitExpr>(E))
+ return true;
+
+ if (auto *ILE = dyn_cast<InitListExpr>(E)) {
+ if (ILE->getNumInits())
+ return false;
+ return isTrivialFiller(ILE->getArrayFiller());
+ }
+
+ if (auto *Cons = dyn_cast_or_null<CXXConstructExpr>(E))
+ return Cons->getConstructor()->isDefaultConstructor() &&
+ Cons->getConstructor()->isTrivial();
+
+ // FIXME: Are there other cases where we can avoid emitting an initializer?
+ return false;
+}
+
/// \brief Emit initialization of an array from an initializer list.
void AggExprEmitter::EmitArrayInit(llvm::Value *DestPtr, llvm::ArrayType *AType,
QualType elementType, InitListExpr *E) {
@@ -435,14 +458,8 @@
}
// Check whether there's a non-trivial array-fill expression.
- // Note that this will be a CXXConstructExpr even if the element
- // type is an array (or array of array, etc.) of class type.
Expr *filler = E->getArrayFiller();
- bool hasTrivialFiller = true;
- if (CXXConstructExpr *cons = dyn_cast_or_null<CXXConstructExpr>(filler)) {
- assert(cons->getConstructor()->isDefaultConstructor());
- hasTrivialFiller = cons->getConstructor()->isTrivial();
- }
+ bool hasTrivialFiller = isTrivialFiller(filler);
// Any remaining elements need to be zero-initialized, possibly
// using the filler expression. We can skip this if the we're
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp
index 548cd48..47dc9fb 100644
--- a/lib/CodeGen/CGExprCXX.cpp
+++ b/lib/CodeGen/CGExprCXX.cpp
@@ -749,207 +749,249 @@
}
void
-CodeGenFunction::EmitNewArrayInitializer(const CXXNewExpr *E,
- QualType elementType,
- llvm::Value *beginPtr,
- llvm::Value *numElements) {
+CodeGenFunction::EmitNewArrayInitializer(const CXXNewExpr *E,
+ QualType ElementType,
+ llvm::Value *BeginPtr,
+ llvm::Value *NumElements,
+ llvm::Value *AllocSizeWithoutCookie) {
+ // If we have a type with trivial initialization and no initializer,
+ // there's nothing to do.
if (!E->hasInitializer())
- return; // We have a POD type.
+ return;
- llvm::Value *explicitPtr = beginPtr;
- // Find the end of the array, hoisted out of the loop.
- llvm::Value *endPtr =
- Builder.CreateInBoundsGEP(beginPtr, numElements, "array.end");
+ llvm::Value *CurPtr = BeginPtr;
- unsigned initializerElements = 0;
+ unsigned InitListElements = 0;
const Expr *Init = E->getInitializer();
- llvm::AllocaInst *endOfInit = nullptr;
- QualType::DestructionKind dtorKind = elementType.isDestructedType();
- EHScopeStack::stable_iterator cleanup;
- llvm::Instruction *cleanupDominator = nullptr;
+ llvm::AllocaInst *EndOfInit = nullptr;
+ QualType::DestructionKind DtorKind = ElementType.isDestructedType();
+ EHScopeStack::stable_iterator Cleanup;
+ llvm::Instruction *CleanupDominator = nullptr;
// If the initializer is an initializer list, first do the explicit elements.
if (const InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
- initializerElements = ILE->getNumInits();
+ InitListElements = 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();
+ unsigned AS = CurPtr->getType()->getPointerAddressSpace();
llvm::Type *AllocPtrTy = ConvertTypeForMem(AllocType)->getPointerTo(AS);
- explicitPtr = Builder.CreateBitCast(explicitPtr, AllocPtrTy);
- initializerElements *= getContext().getConstantArrayElementCount(CAT);
+ CurPtr = Builder.CreateBitCast(CurPtr, AllocPtrTy);
+ InitListElements *= getContext().getConstantArrayElementCount(CAT);
}
- // Enter a partial-destruction cleanup if necessary.
- if (needsEHCleanup(dtorKind)) {
- // In principle we could tell the cleanup where we are more
+ // Enter a partial-destruction Cleanup if necessary.
+ if (needsEHCleanup(DtorKind)) {
+ // In principle we could tell the Cleanup where we are more
// directly, but the control flow can get so varied here that it
// would actually be quite complex. Therefore we go through an
// alloca.
- endOfInit = CreateTempAlloca(beginPtr->getType(), "array.endOfInit");
- cleanupDominator = Builder.CreateStore(beginPtr, endOfInit);
- pushIrregularPartialArrayCleanup(beginPtr, endOfInit, elementType,
- getDestroyer(dtorKind));
- cleanup = EHStack.stable_begin();
+ EndOfInit = CreateTempAlloca(BeginPtr->getType(), "array.init.end");
+ CleanupDominator = Builder.CreateStore(BeginPtr, EndOfInit);
+ pushIrregularPartialArrayCleanup(BeginPtr, EndOfInit, ElementType,
+ getDestroyer(DtorKind));
+ Cleanup = EHStack.stable_begin();
}
for (unsigned i = 0, e = ILE->getNumInits(); i != e; ++i) {
// Tell the cleanup that it needs to destroy up to this
// element. TODO: some of these stores can be trivially
// observed to be unnecessary.
- if (endOfInit) Builder.CreateStore(explicitPtr, endOfInit);
+ if (EndOfInit)
+ Builder.CreateStore(Builder.CreateBitCast(CurPtr, BeginPtr->getType()),
+ EndOfInit);
+ // FIXME: If the last initializer is an incomplete initializer list for
+ // an array, and we have an array filler, we can fold together the two
+ // initialization loops.
StoreAnyExprIntoOneUnit(*this, ILE->getInit(i),
- ILE->getInit(i)->getType(), explicitPtr);
- explicitPtr = Builder.CreateConstGEP1_32(explicitPtr, 1,
- "array.exp.next");
+ ILE->getInit(i)->getType(), CurPtr);
+ CurPtr = Builder.CreateConstInBoundsGEP1_32(CurPtr, 1, "array.exp.next");
}
// The remaining elements are filled with the array filler expression.
Init = ILE->getArrayFiller();
- explicitPtr = Builder.CreateBitCast(explicitPtr, beginPtr->getType());
+ // Extract the initializer for the individual array elements by pulling
+ // out the array filler from all the nested initializer lists. This avoids
+ // generating a nested loop for the initialization.
+ while (Init && Init->getType()->isConstantArrayType()) {
+ auto *SubILE = dyn_cast<InitListExpr>(Init);
+ if (!SubILE)
+ break;
+ assert(SubILE->getNumInits() == 0 && "explicit inits in array filler?");
+ Init = SubILE->getArrayFiller();
+ }
+
+ // Switch back to initializing one base element at a time.
+ CurPtr = Builder.CreateBitCast(CurPtr, BeginPtr->getType());
}
- llvm::ConstantInt *constNum = dyn_cast<llvm::ConstantInt>(numElements);
+ // Attempt to perform zero-initialization using memset.
+ auto TryMemsetInitialization = [&]() -> bool {
+ // FIXME: If the type is a pointer-to-data-member under the Itanium ABI,
+ // we can initialize with a memset to -1.
+ if (!CGM.getTypes().isZeroInitializable(ElementType))
+ return false;
- // If all elements have already been initialized, skip the whole loop.
- if (constNum && constNum->getZExtValue() <= initializerElements) {
- // If there was a cleanup, deactivate it.
- if (cleanupDominator)
- DeactivateCleanupBlock(cleanup, cleanupDominator);
+ // Optimization: since zero initialization will just set the memory
+ // to all zeroes, generate a single memset to do it in one shot.
+
+ // Subtract out the size of any elements we've already initialized.
+ auto *RemainingSize = AllocSizeWithoutCookie;
+ if (InitListElements) {
+ // We know this can't overflow; we check this when doing the allocation.
+ auto *InitializedSize = llvm::ConstantInt::get(
+ RemainingSize->getType(),
+ getContext().getTypeSizeInChars(ElementType).getQuantity() *
+ InitListElements);
+ RemainingSize = Builder.CreateSub(RemainingSize, InitializedSize);
+ }
+
+ // Create the memset.
+ CharUnits Alignment = getContext().getTypeAlignInChars(ElementType);
+ Builder.CreateMemSet(CurPtr, Builder.getInt8(0), RemainingSize,
+ Alignment.getQuantity(), false);
+ return true;
+ };
+
+ // If all elements have already been initialized, skip any further
+ // initialization.
+ llvm::ConstantInt *ConstNum = dyn_cast<llvm::ConstantInt>(NumElements);
+ if (ConstNum && ConstNum->getZExtValue() <= InitListElements) {
+ // If there was a Cleanup, deactivate it.
+ if (CleanupDominator)
+ DeactivateCleanupBlock(Cleanup, CleanupDominator);
return;
}
- // Create the continuation block.
- llvm::BasicBlock *contBB = createBasicBlock("new.loop.end");
+ assert(Init && "have trailing elements to initialize but no initializer");
+
+ // If this is a constructor call, try to optimize it out, and failing that
+ // emit a single loop to initialize all remaining elements.
+ if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init)) {
+ CXXConstructorDecl *Ctor = CCE->getConstructor();
+ if (Ctor->isTrivial()) {
+ // If new expression did not specify value-initialization, then there
+ // is no initialization.
+ if (!CCE->requiresZeroInitialization() || Ctor->getParent()->isEmpty())
+ return;
+
+ if (TryMemsetInitialization())
+ return;
+ }
+
+ // Store the new Cleanup position for irregular Cleanups.
+ //
+ // FIXME: Share this cleanup with the constructor call emission rather than
+ // having it create a cleanup of its own.
+ if (EndOfInit) Builder.CreateStore(CurPtr, EndOfInit);
+
+ // Emit a constructor call loop to initialize the remaining elements.
+ if (InitListElements)
+ NumElements = Builder.CreateSub(
+ NumElements,
+ llvm::ConstantInt::get(NumElements->getType(), InitListElements));
+ EmitCXXAggrConstructorCall(Ctor, NumElements, CurPtr,
+ CCE->arg_begin(), CCE->arg_end(),
+ CCE->requiresZeroInitialization());
+ return;
+ }
+
+ // If this is value-initialization, we can usually use memset.
+ ImplicitValueInitExpr IVIE(ElementType);
+ if (isa<ImplicitValueInitExpr>(Init)) {
+ if (TryMemsetInitialization())
+ return;
+
+ // Switch to an ImplicitValueInitExpr for the element type. This handles
+ // only one case: multidimensional array new of pointers to members. In
+ // all other cases, we already have an initializer for the array element.
+ Init = &IVIE;
+ }
+
+ // At this point we should have found an initializer for the individual
+ // elements of the array.
+ assert(getContext().hasSameUnqualifiedType(ElementType, Init->getType()) &&
+ "got wrong type of element to initialize");
+
+ // If we have an empty initializer list, we can usually use memset.
+ if (auto *ILE = dyn_cast<InitListExpr>(Init))
+ if (ILE->getNumInits() == 0 && TryMemsetInitialization())
+ return;
+
+ // Create the loop blocks.
+ llvm::BasicBlock *EntryBB = Builder.GetInsertBlock();
+ llvm::BasicBlock *LoopBB = createBasicBlock("new.loop");
+ llvm::BasicBlock *ContBB = createBasicBlock("new.loop.end");
+
+ // Find the end of the array, hoisted out of the loop.
+ llvm::Value *EndPtr =
+ Builder.CreateInBoundsGEP(BeginPtr, NumElements, "array.end");
// If the number of elements isn't constant, we have to now check if there is
// anything left to initialize.
- if (!constNum) {
- llvm::BasicBlock *nonEmptyBB = createBasicBlock("new.loop.nonempty");
- llvm::Value *isEmpty = Builder.CreateICmpEQ(explicitPtr, endPtr,
+ if (!ConstNum) {
+ llvm::Value *IsEmpty = Builder.CreateICmpEQ(CurPtr, EndPtr,
"array.isempty");
- Builder.CreateCondBr(isEmpty, contBB, nonEmptyBB);
- EmitBlock(nonEmptyBB);
+ Builder.CreateCondBr(IsEmpty, ContBB, LoopBB);
}
// Enter the loop.
- llvm::BasicBlock *entryBB = Builder.GetInsertBlock();
- llvm::BasicBlock *loopBB = createBasicBlock("new.loop");
-
- EmitBlock(loopBB);
+ EmitBlock(LoopBB);
// Set up the current-element phi.
- llvm::PHINode *curPtr =
- Builder.CreatePHI(explicitPtr->getType(), 2, "array.cur");
- curPtr->addIncoming(explicitPtr, entryBB);
+ llvm::PHINode *CurPtrPhi =
+ Builder.CreatePHI(CurPtr->getType(), 2, "array.cur");
+ CurPtrPhi->addIncoming(CurPtr, EntryBB);
+ CurPtr = CurPtrPhi;
- // Store the new cleanup position for irregular cleanups.
- if (endOfInit) Builder.CreateStore(curPtr, endOfInit);
+ // Store the new Cleanup position for irregular Cleanups.
+ if (EndOfInit) Builder.CreateStore(CurPtr, EndOfInit);
- // Enter a partial-destruction cleanup if necessary.
- if (!cleanupDominator && needsEHCleanup(dtorKind)) {
- pushRegularPartialArrayCleanup(beginPtr, curPtr, elementType,
- getDestroyer(dtorKind));
- cleanup = EHStack.stable_begin();
- cleanupDominator = Builder.CreateUnreachable();
+ // Enter a partial-destruction Cleanup if necessary.
+ if (!CleanupDominator && needsEHCleanup(DtorKind)) {
+ pushRegularPartialArrayCleanup(BeginPtr, CurPtr, ElementType,
+ getDestroyer(DtorKind));
+ Cleanup = EHStack.stable_begin();
+ CleanupDominator = Builder.CreateUnreachable();
}
// Emit the initializer into this element.
- StoreAnyExprIntoOneUnit(*this, Init, E->getAllocatedType(), curPtr);
+ StoreAnyExprIntoOneUnit(*this, Init, Init->getType(), CurPtr);
- // Leave the cleanup if we entered one.
- if (cleanupDominator) {
- DeactivateCleanupBlock(cleanup, cleanupDominator);
- cleanupDominator->eraseFromParent();
+ // Leave the Cleanup if we entered one.
+ if (CleanupDominator) {
+ DeactivateCleanupBlock(Cleanup, CleanupDominator);
+ CleanupDominator->eraseFromParent();
}
- // FIXME: The code below intends to initialize the individual array base
- // elements, one at a time - but when dealing with multi-dimensional arrays -
- // the pointer arithmetic can get confused - so the fix below entails casting
- // to the allocated type to ensure that we get the pointer arithmetic right.
- // It seems like the right approach here, it to really initialize the
- // individual array base elements one at a time since it'll generate less
- // code. I think the problem is that the wrong type is being passed into
- // StoreAnyExprIntoOneUnit, but directly fixing that doesn't really work,
- // because the Init expression has the wrong type at this point.
- // So... this is ok for a quick fix, but we can and should do a lot better
- // here long-term.
-
// Advance to the next element by adjusting the pointer type as necessary.
- // For new int[10][20][30], alloc type is int[20][30], base type is 'int'.
- QualType AllocType = E->getAllocatedType();
- llvm::Type *AllocPtrTy = ConvertTypeForMem(AllocType)->getPointerTo(
- curPtr->getType()->getPointerAddressSpace());
- llvm::Value *curPtrAllocTy = Builder.CreateBitCast(curPtr, AllocPtrTy);
- llvm::Value *nextPtrAllocTy =
- Builder.CreateConstGEP1_32(curPtrAllocTy, 1, "array.next");
- // Cast it back to the base type so that we can compare it to the endPtr.
- llvm::Value *nextPtr =
- Builder.CreateBitCast(nextPtrAllocTy, endPtr->getType());
+ llvm::Value *NextPtr =
+ Builder.CreateConstInBoundsGEP1_32(CurPtr, 1, "array.next");
+
// Check whether we've gotten to the end of the array and, if so,
// exit the loop.
- llvm::Value *isEnd = Builder.CreateICmpEQ(nextPtr, endPtr, "array.atend");
- Builder.CreateCondBr(isEnd, contBB, loopBB);
- curPtr->addIncoming(nextPtr, Builder.GetInsertBlock());
+ llvm::Value *IsEnd = Builder.CreateICmpEQ(NextPtr, EndPtr, "array.atend");
+ Builder.CreateCondBr(IsEnd, ContBB, LoopBB);
+ CurPtrPhi->addIncoming(NextPtr, Builder.GetInsertBlock());
- EmitBlock(contBB);
+ EmitBlock(ContBB);
}
-static void EmitZeroMemSet(CodeGenFunction &CGF, QualType T,
- llvm::Value *NewPtr, llvm::Value *Size) {
- CGF.EmitCastToVoidPtr(NewPtr);
- CharUnits Alignment = CGF.getContext().getTypeAlignInChars(T);
- CGF.Builder.CreateMemSet(NewPtr, CGF.Builder.getInt8(0), Size,
- Alignment.getQuantity(), false);
-}
-
static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E,
QualType ElementType,
llvm::Value *NewPtr,
llvm::Value *NumElements,
llvm::Value *AllocSizeWithoutCookie) {
- const Expr *Init = E->getInitializer();
- if (E->isArray()) {
- if (const CXXConstructExpr *CCE = dyn_cast_or_null<CXXConstructExpr>(Init)){
- CXXConstructorDecl *Ctor = CCE->getConstructor();
- if (Ctor->isTrivial()) {
- // If new expression did not specify value-initialization, then there
- // is no initialization.
- if (!CCE->requiresZeroInitialization() || Ctor->getParent()->isEmpty())
- return;
-
- if (CGF.CGM.getTypes().isZeroInitializable(ElementType)) {
- // Optimization: since zero initialization will just set the memory
- // to all zeroes, generate a single memset to do it in one shot.
- EmitZeroMemSet(CGF, ElementType, NewPtr, AllocSizeWithoutCookie);
- return;
- }
- }
-
- CGF.EmitCXXAggrConstructorCall(Ctor, NumElements, NewPtr,
- CCE->arg_begin(), CCE->arg_end(),
- CCE->requiresZeroInitialization());
- return;
- } else if (Init && isa<ImplicitValueInitExpr>(Init) &&
- CGF.CGM.getTypes().isZeroInitializable(ElementType)) {
- // Optimization: since zero initialization will just set the memory
- // to all zeroes, generate a single memset to do it in one shot.
- EmitZeroMemSet(CGF, ElementType, NewPtr, AllocSizeWithoutCookie);
- return;
- }
- CGF.EmitNewArrayInitializer(E, ElementType, NewPtr, NumElements);
- return;
- }
-
- if (!Init)
- return;
-
- StoreAnyExprIntoOneUnit(CGF, Init, E->getAllocatedType(), NewPtr);
+ if (E->isArray())
+ CGF.EmitNewArrayInitializer(E, ElementType, NewPtr, NumElements,
+ AllocSizeWithoutCookie);
+ else if (const Expr *Init = E->getInitializer())
+ StoreAnyExprIntoOneUnit(CGF, Init, E->getAllocatedType(), NewPtr);
}
/// Emit a call to an operator new or operator delete function, as implicitly
@@ -987,6 +1029,24 @@
return RV;
}
+RValue CodeGenFunction::EmitBuiltinNewDeleteCall(const FunctionProtoType *Type,
+ const Expr *Arg,
+ bool IsDelete) {
+ CallArgList Args;
+ const Stmt *ArgS = Arg;
+ EmitCallArgs(Args, *Type->param_type_begin(),
+ ConstExprIterator(&ArgS), ConstExprIterator(&ArgS + 1));
+ // Find the allocation or deallocation function that we're calling.
+ ASTContext &Ctx = getContext();
+ DeclarationName Name = Ctx.DeclarationNames
+ .getCXXOperatorName(IsDelete ? OO_Delete : OO_New);
+ for (auto *Decl : Ctx.getTranslationUnitDecl()->lookup(Name))
+ if (auto *FD = dyn_cast<FunctionDecl>(Decl))
+ if (Ctx.hasSameType(FD->getType(), QualType(Type, 0)))
+ return EmitNewDeleteCall(*this, cast<FunctionDecl>(Decl), Type, Args);
+ llvm_unreachable("predeclared global operator new/delete is missing");
+}
+
namespace {
/// A cleanup to call the given 'operator delete' function upon
/// abnormal exit from a new expression.
@@ -1555,21 +1615,7 @@
EmitBlock(DeleteEnd);
}
-static llvm::Constant *getBadTypeidFn(CodeGenFunction &CGF) {
- // void __cxa_bad_typeid();
- llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.VoidTy, false);
-
- return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_bad_typeid");
-}
-
-static void EmitBadTypeidCall(CodeGenFunction &CGF) {
- llvm::Value *Fn = getBadTypeidFn(CGF);
- CGF.EmitRuntimeCallOrInvoke(Fn).setDoesNotReturn();
- CGF.Builder.CreateUnreachable();
-}
-
-static llvm::Value *EmitTypeidFromVTable(CodeGenFunction &CGF,
- const Expr *E,
+static llvm::Value *EmitTypeidFromVTable(CodeGenFunction &CGF, const Expr *E,
llvm::Type *StdTypeInfoPtrTy) {
// Get the vtable pointer.
llvm::Value *ThisPtr = CGF.EmitLValue(E).getAddress();
@@ -1578,28 +1624,27 @@
// If the glvalue expression is obtained by applying the unary * operator to
// a pointer and the pointer is a null pointer value, the typeid expression
// throws the std::bad_typeid exception.
- if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(E->IgnoreParens())) {
- if (UO->getOpcode() == UO_Deref) {
- llvm::BasicBlock *BadTypeidBlock =
+ bool IsDeref = false;
+ if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(E->IgnoreParens()))
+ if (UO->getOpcode() == UO_Deref)
+ IsDeref = true;
+
+ QualType SrcRecordTy = E->getType();
+ if (CGF.CGM.getCXXABI().shouldTypeidBeNullChecked(IsDeref, SrcRecordTy)) {
+ llvm::BasicBlock *BadTypeidBlock =
CGF.createBasicBlock("typeid.bad_typeid");
- llvm::BasicBlock *EndBlock =
- CGF.createBasicBlock("typeid.end");
+ llvm::BasicBlock *EndBlock = CGF.createBasicBlock("typeid.end");
- llvm::Value *IsNull = CGF.Builder.CreateIsNull(ThisPtr);
- CGF.Builder.CreateCondBr(IsNull, BadTypeidBlock, EndBlock);
+ llvm::Value *IsNull = CGF.Builder.CreateIsNull(ThisPtr);
+ CGF.Builder.CreateCondBr(IsNull, BadTypeidBlock, EndBlock);
- CGF.EmitBlock(BadTypeidBlock);
- EmitBadTypeidCall(CGF);
- CGF.EmitBlock(EndBlock);
- }
+ CGF.EmitBlock(BadTypeidBlock);
+ CGF.CGM.getCXXABI().EmitBadTypeidCall(CGF);
+ CGF.EmitBlock(EndBlock);
}
- llvm::Value *Value = CGF.GetVTablePtr(ThisPtr,
- StdTypeInfoPtrTy->getPointerTo());
-
- // Load the type info.
- Value = CGF.Builder.CreateConstInBoundsGEP1_64(Value, -1ULL);
- return CGF.Builder.CreateLoad(Value);
+ return CGF.CGM.getCXXABI().EmitTypeid(CGF, SrcRecordTy, ThisPtr,
+ StdTypeInfoPtrTy);
}
llvm::Value *CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) {
@@ -1626,173 +1671,6 @@
StdTypeInfoPtrTy);
}
-static llvm::Constant *getDynamicCastFn(CodeGenFunction &CGF) {
- // void *__dynamic_cast(const void *sub,
- // const abi::__class_type_info *src,
- // const abi::__class_type_info *dst,
- // std::ptrdiff_t src2dst_offset);
-
- llvm::Type *Int8PtrTy = CGF.Int8PtrTy;
- llvm::Type *PtrDiffTy =
- CGF.ConvertType(CGF.getContext().getPointerDiffType());
-
- llvm::Type *Args[4] = { Int8PtrTy, Int8PtrTy, Int8PtrTy, PtrDiffTy };
-
- llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args, false);
-
- // Mark the function as nounwind readonly.
- llvm::Attribute::AttrKind FuncAttrs[] = { llvm::Attribute::NoUnwind,
- llvm::Attribute::ReadOnly };
- llvm::AttributeSet Attrs = llvm::AttributeSet::get(
- CGF.getLLVMContext(), llvm::AttributeSet::FunctionIndex, FuncAttrs);
-
- return CGF.CGM.CreateRuntimeFunction(FTy, "__dynamic_cast", Attrs);
-}
-
-static llvm::Constant *getBadCastFn(CodeGenFunction &CGF) {
- // void __cxa_bad_cast();
- llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.VoidTy, false);
- return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_bad_cast");
-}
-
-static void EmitBadCastCall(CodeGenFunction &CGF) {
- llvm::Value *Fn = getBadCastFn(CGF);
- CGF.EmitRuntimeCallOrInvoke(Fn).setDoesNotReturn();
- CGF.Builder.CreateUnreachable();
-}
-
-/// \brief Compute the src2dst_offset hint as described in the
-/// Itanium C++ ABI [2.9.7]
-static CharUnits computeOffsetHint(ASTContext &Context,
- const CXXRecordDecl *Src,
- const CXXRecordDecl *Dst) {
- CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
- /*DetectVirtual=*/false);
-
- // If Dst is not derived from Src we can skip the whole computation below and
- // return that Src is not a public base of Dst. Record all inheritance paths.
- if (!Dst->isDerivedFrom(Src, Paths))
- return CharUnits::fromQuantity(-2ULL);
-
- unsigned NumPublicPaths = 0;
- CharUnits Offset;
-
- // Now walk all possible inheritance paths.
- for (CXXBasePaths::paths_iterator I = Paths.begin(), E = Paths.end();
- I != E; ++I) {
- if (I->Access != AS_public) // Ignore non-public inheritance.
- continue;
-
- ++NumPublicPaths;
-
- for (CXXBasePath::iterator J = I->begin(), JE = I->end(); J != JE; ++J) {
- // If the path contains a virtual base class we can't give any hint.
- // -1: no hint.
- if (J->Base->isVirtual())
- return CharUnits::fromQuantity(-1ULL);
-
- if (NumPublicPaths > 1) // Won't use offsets, skip computation.
- continue;
-
- // Accumulate the base class offsets.
- const ASTRecordLayout &L = Context.getASTRecordLayout(J->Class);
- Offset += L.getBaseClassOffset(J->Base->getType()->getAsCXXRecordDecl());
- }
- }
-
- // -2: Src is not a public base of Dst.
- if (NumPublicPaths == 0)
- return CharUnits::fromQuantity(-2ULL);
-
- // -3: Src is a multiple public base type but never a virtual base type.
- if (NumPublicPaths > 1)
- return CharUnits::fromQuantity(-3ULL);
-
- // Otherwise, the Src type is a unique public nonvirtual base type of Dst.
- // Return the offset of Src from the origin of Dst.
- return Offset;
-}
-
-static llvm::Value *
-EmitDynamicCastCall(CodeGenFunction &CGF, llvm::Value *Value,
- QualType SrcTy, QualType DestTy,
- llvm::BasicBlock *CastEnd) {
- llvm::Type *PtrDiffLTy =
- CGF.ConvertType(CGF.getContext().getPointerDiffType());
- llvm::Type *DestLTy = CGF.ConvertType(DestTy);
-
- if (const PointerType *PTy = DestTy->getAs<PointerType>()) {
- if (PTy->getPointeeType()->isVoidType()) {
- // C++ [expr.dynamic.cast]p7:
- // If T is "pointer to cv void," then the result is a pointer to the
- // most derived object pointed to by v.
-
- // Get the vtable pointer.
- llvm::Value *VTable = CGF.GetVTablePtr(Value, PtrDiffLTy->getPointerTo());
-
- // Get the offset-to-top from the vtable.
- llvm::Value *OffsetToTop =
- CGF.Builder.CreateConstInBoundsGEP1_64(VTable, -2ULL);
- OffsetToTop = CGF.Builder.CreateLoad(OffsetToTop, "offset.to.top");
-
- // Finally, add the offset to the pointer.
- Value = CGF.EmitCastToVoidPtr(Value);
- Value = CGF.Builder.CreateInBoundsGEP(Value, OffsetToTop);
-
- return CGF.Builder.CreateBitCast(Value, DestLTy);
- }
- }
-
- QualType SrcRecordTy;
- QualType DestRecordTy;
-
- if (const PointerType *DestPTy = DestTy->getAs<PointerType>()) {
- SrcRecordTy = SrcTy->castAs<PointerType>()->getPointeeType();
- DestRecordTy = DestPTy->getPointeeType();
- } else {
- SrcRecordTy = SrcTy;
- DestRecordTy = DestTy->castAs<ReferenceType>()->getPointeeType();
- }
-
- assert(SrcRecordTy->isRecordType() && "source type must be a record type!");
- assert(DestRecordTy->isRecordType() && "dest type must be a record type!");
-
- llvm::Value *SrcRTTI =
- CGF.CGM.GetAddrOfRTTIDescriptor(SrcRecordTy.getUnqualifiedType());
- llvm::Value *DestRTTI =
- CGF.CGM.GetAddrOfRTTIDescriptor(DestRecordTy.getUnqualifiedType());
-
- // Compute the offset hint.
- const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl();
- const CXXRecordDecl *DestDecl = DestRecordTy->getAsCXXRecordDecl();
- llvm::Value *OffsetHint =
- llvm::ConstantInt::get(PtrDiffLTy,
- computeOffsetHint(CGF.getContext(), SrcDecl,
- DestDecl).getQuantity());
-
- // Emit the call to __dynamic_cast.
- Value = CGF.EmitCastToVoidPtr(Value);
-
- llvm::Value *args[] = { Value, SrcRTTI, DestRTTI, OffsetHint };
- Value = CGF.EmitNounwindRuntimeCall(getDynamicCastFn(CGF), args);
- Value = CGF.Builder.CreateBitCast(Value, DestLTy);
-
- /// C++ [expr.dynamic.cast]p9:
- /// A failed cast to reference type throws std::bad_cast
- if (DestTy->isReferenceType()) {
- llvm::BasicBlock *BadCastBlock =
- CGF.createBasicBlock("dynamic_cast.bad_cast");
-
- llvm::Value *IsNull = CGF.Builder.CreateIsNull(Value);
- CGF.Builder.CreateCondBr(IsNull, BadCastBlock, CastEnd);
-
- CGF.EmitBlock(BadCastBlock);
- EmitBadCastCall(CGF);
- }
-
- return Value;
-}
-
static llvm::Value *EmitDynamicCastToNull(CodeGenFunction &CGF,
QualType DestTy) {
llvm::Type *DestLTy = CGF.ConvertType(DestTy);
@@ -1801,7 +1679,8 @@
/// C++ [expr.dynamic.cast]p9:
/// A failed cast to reference type throws std::bad_cast
- EmitBadCastCall(CGF);
+ if (!CGF.CGM.getCXXABI().EmitBadCastCall(CGF))
+ return nullptr;
CGF.EmitBlock(CGF.createBasicBlock("dynamic_cast.end"));
return llvm::UndefValue::get(DestLTy);
@@ -1812,14 +1691,37 @@
QualType DestTy = DCE->getTypeAsWritten();
if (DCE->isAlwaysNull())
- return EmitDynamicCastToNull(*this, DestTy);
+ if (llvm::Value *T = EmitDynamicCastToNull(*this, DestTy))
+ return T;
QualType SrcTy = DCE->getSubExpr()->getType();
+ // C++ [expr.dynamic.cast]p7:
+ // If T is "pointer to cv void," then the result is a pointer to the most
+ // derived object pointed to by v.
+ const PointerType *DestPTy = DestTy->getAs<PointerType>();
+
+ bool isDynamicCastToVoid;
+ QualType SrcRecordTy;
+ QualType DestRecordTy;
+ if (DestPTy) {
+ isDynamicCastToVoid = DestPTy->getPointeeType()->isVoidType();
+ SrcRecordTy = SrcTy->castAs<PointerType>()->getPointeeType();
+ DestRecordTy = DestPTy->getPointeeType();
+ } else {
+ isDynamicCastToVoid = false;
+ SrcRecordTy = SrcTy;
+ DestRecordTy = DestTy->castAs<ReferenceType>()->getPointeeType();
+ }
+
+ assert(SrcRecordTy->isRecordType() && "source type must be a record type!");
+
// C++ [expr.dynamic.cast]p4:
// If the value of v is a null pointer value in the pointer case, the result
// is the null pointer value of type T.
- bool ShouldNullCheckSrcValue = SrcTy->isPointerType();
+ bool ShouldNullCheckSrcValue =
+ CGM.getCXXABI().shouldDynamicCastCallBeNullChecked(SrcTy->isPointerType(),
+ SrcRecordTy);
llvm::BasicBlock *CastNull = nullptr;
llvm::BasicBlock *CastNotNull = nullptr;
@@ -1834,7 +1736,15 @@
EmitBlock(CastNotNull);
}
- Value = EmitDynamicCastCall(*this, Value, SrcTy, DestTy, CastEnd);
+ if (isDynamicCastToVoid) {
+ Value = CGM.getCXXABI().EmitDynamicCastToVoid(*this, Value, SrcRecordTy,
+ DestTy);
+ } else {
+ assert(DestRecordTy->isRecordType() &&
+ "destination type must be a record type!");
+ Value = CGM.getCXXABI().EmitDynamicCastCall(*this, Value, SrcRecordTy,
+ DestTy, DestRecordTy, CastEnd);
+ }
if (ShouldNullCheckSrcValue) {
EmitBranch(CastEnd);
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index 1ee3ce8..1be7b42 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -358,7 +358,10 @@
Value *VisitExprWithCleanups(ExprWithCleanups *E) {
CGF.enterFullExpression(E);
CodeGenFunction::RunCleanupsScope Scope(CGF);
- return Visit(E->getSubExpr());
+ auto *V = Visit(E->getSubExpr());
+ if (CGDebugInfo *DI = CGF.getDebugInfo())
+ DI->EmitLocation(Builder, E->getLocEnd(), false);
+ return V;
}
Value *VisitCXXNewExpr(const CXXNewExpr *E) {
return CGF.EmitCXXNewExpr(E);
@@ -940,9 +943,8 @@
MTy->getNumElements());
Value* NewV = llvm::UndefValue::get(RTy);
for (unsigned i = 0, e = MTy->getNumElements(); i != e; ++i) {
- Value *IIndx = Builder.getInt32(i);
+ Value *IIndx = llvm::ConstantInt::get(CGF.SizeTy, i);
Value *Indx = Builder.CreateExtractElement(Mask, IIndx, "shuf_idx");
- Indx = Builder.CreateZExt(Indx, CGF.Int32Ty, "idx_zext");
Value *VExt = Builder.CreateExtractElement(LHS, Indx, "shuf_elt");
NewV = Builder.CreateInsertElement(NewV, VExt, IIndx, "shuf_ins");
@@ -1073,8 +1075,6 @@
if (CGF.SanOpts->ArrayBounds)
CGF.EmitBoundsCheck(E, E->getBase(), Idx, IdxTy, /*Accessed*/true);
- bool IdxSigned = IdxTy->isSignedIntegerOrEnumerationType();
- Idx = Builder.CreateIntCast(Idx, CGF.Int32Ty, IdxSigned, "vecidxcast");
return Builder.CreateExtractElement(Base, Idx, "vecext");
}
@@ -1328,7 +1328,7 @@
// 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)
+ if (CGF.sanitizePerformTypeCheck())
CGF.EmitTypeCheck(CodeGenFunction::TCK_DowncastPointer, CE->getExprLoc(),
Derived, DestTy->getPointeeType());
@@ -1618,12 +1618,11 @@
// Note that signed integer inc/dec with width less than int can't
// overflow because of promotion rules; we're just eliding a few steps here.
- if (value->getType()->getPrimitiveSizeInBits() >=
- CGF.IntTy->getBitWidth() &&
- type->isSignedIntegerOrEnumerationType()) {
+ bool CanOverflow = value->getType()->getIntegerBitWidth() >=
+ CGF.IntTy->getIntegerBitWidth();
+ if (CanOverflow && type->isSignedIntegerOrEnumerationType()) {
value = EmitAddConsiderOverflowBehavior(E, value, amt, isInc);
- } else if (value->getType()->getPrimitiveSizeInBits() >=
- CGF.IntTy->getBitWidth() && type->isUnsignedIntegerType() &&
+ } else if (CanOverflow && type->isUnsignedIntegerType() &&
CGF.SanOpts->UnsignedIntegerOverflow) {
BinOpInfo BinOp;
BinOp.LHS = value;
@@ -1735,11 +1734,12 @@
if (atomicPHI) {
llvm::BasicBlock *opBB = Builder.GetInsertBlock();
llvm::BasicBlock *contBB = CGF.createBasicBlock("atomic_cont", CGF.CurFn);
- llvm::Value *old = Builder.CreateAtomicCmpXchg(
+ llvm::Value *pair = Builder.CreateAtomicCmpXchg(
LV.getAddress(), atomicPHI, CGF.EmitToMemory(value, type),
llvm::SequentiallyConsistent, llvm::SequentiallyConsistent);
+ llvm::Value *old = Builder.CreateExtractValue(pair, 0);
+ llvm::Value *success = Builder.CreateExtractValue(pair, 1);
atomicPHI->addIncoming(old, opBB);
- llvm::Value *success = Builder.CreateICmpEQ(old, atomicPHI);
Builder.CreateCondBr(success, contBB, opBB);
Builder.SetInsertPoint(contBB);
return isPre ? value : input;
@@ -2078,11 +2078,12 @@
if (atomicPHI) {
llvm::BasicBlock *opBB = Builder.GetInsertBlock();
llvm::BasicBlock *contBB = CGF.createBasicBlock("atomic_cont", CGF.CurFn);
- llvm::Value *old = Builder.CreateAtomicCmpXchg(
+ llvm::Value *pair = Builder.CreateAtomicCmpXchg(
LHSLV.getAddress(), atomicPHI, CGF.EmitToMemory(Result, LHSTy),
llvm::SequentiallyConsistent, llvm::SequentiallyConsistent);
+ llvm::Value *old = Builder.CreateExtractValue(pair, 0);
+ llvm::Value *success = Builder.CreateExtractValue(pair, 1);
atomicPHI->addIncoming(old, opBB);
- llvm::Value *success = Builder.CreateICmpEQ(old, atomicPHI);
Builder.CreateCondBr(success, contBB, opBB);
Builder.SetInsertPoint(contBB);
return LHSLV;
diff --git a/lib/CodeGen/CGLoopInfo.cpp b/lib/CodeGen/CGLoopInfo.cpp
index 7b154b2..1bc6d20 100644
--- a/lib/CodeGen/CGLoopInfo.cpp
+++ b/lib/CodeGen/CGLoopInfo.cpp
@@ -31,7 +31,7 @@
// Setting vectorizer.width
if (Attrs.VectorizerWidth > 0) {
- Value *Vals[] = { MDString::get(Ctx, "llvm.vectorizer.width"),
+ Value *Vals[] = { MDString::get(Ctx, "llvm.loop.vectorize.width"),
ConstantInt::get(Type::getInt32Ty(Ctx),
Attrs.VectorizerWidth) };
Args.push_back(MDNode::get(Ctx, Vals));
@@ -39,7 +39,7 @@
// Setting vectorizer.unroll
if (Attrs.VectorizerUnroll > 0) {
- Value *Vals[] = { MDString::get(Ctx, "llvm.vectorizer.unroll"),
+ Value *Vals[] = { MDString::get(Ctx, "llvm.loop.vectorize.unroll"),
ConstantInt::get(Type::getInt32Ty(Ctx),
Attrs.VectorizerUnroll) };
Args.push_back(MDNode::get(Ctx, Vals));
@@ -47,7 +47,7 @@
// Setting vectorizer.enable
if (Attrs.VectorizerEnable != LoopAttributes::VecUnspecified) {
- Value *Vals[] = { MDString::get(Ctx, "llvm.vectorizer.enable"),
+ Value *Vals[] = { MDString::get(Ctx, "llvm.loop.vectorize.enable"),
ConstantInt::get(Type::getInt1Ty(Ctx),
(Attrs.VectorizerEnable ==
LoopAttributes::VecEnable)) };
diff --git a/lib/CodeGen/CGLoopInfo.h b/lib/CodeGen/CGLoopInfo.h
index f4a8dca..2461368 100644
--- a/lib/CodeGen/CGLoopInfo.h
+++ b/lib/CodeGen/CGLoopInfo.h
@@ -37,16 +37,16 @@
/// \brief Generate llvm.loop.parallel metadata for loads and stores.
bool IsParallel;
- /// \brief Values of llvm.vectorizer.enable metadata.
+ /// \brief Values of llvm.loop.vectorize.enable metadata.
enum LVEnableState { VecUnspecified, VecEnable, VecDisable };
- /// \brief llvm.vectorizer.enable
+ /// \brief llvm.loop.vectorize.enable
LVEnableState VectorizerEnable;
- /// \brief llvm.vectorizer.width
+ /// \brief llvm.loop.vectorize.width
unsigned VectorizerWidth;
- /// \brief llvm.vectorizer.unroll
+ /// \brief llvm.loop.vectorize.unroll
unsigned VectorizerUnroll;
};
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp
index 3ca0378..619a66a 100644
--- a/lib/CodeGen/CGObjCGNU.cpp
+++ b/lib/CodeGen/CGObjCGNU.cpp
@@ -237,9 +237,8 @@
NameAndAttributes += TypeStr;
NameAndAttributes += '\0';
NameAndAttributes += PD->getNameAsString();
- NameAndAttributes += '\0';
return llvm::ConstantExpr::getGetElementPtr(
- CGM.GetAddrOfConstantString(NameAndAttributes), Zeros);
+ CGM.GetAddrOfConstantCString(NameAndAttributes), Zeros);
}
return MakeConstantString(PD->getNameAsString());
}
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index 95503cc..88ad7f1 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -1018,14 +1018,12 @@
/// \param Name - The variable name.
/// \param Init - The variable initializer; this is also used to
/// define the type of the variable.
- /// \param Section - The section the variable should go into, or 0.
+ /// \param Section - The section the variable should go into, or empty.
/// \param Align - The alignment for the variable, or 0.
/// \param AddToUsed - Whether the variable should be added to
/// "llvm.used".
- llvm::GlobalVariable *CreateMetadataVar(Twine Name,
- llvm::Constant *Init,
- const char *Section,
- unsigned Align,
+ llvm::GlobalVariable *CreateMetadataVar(Twine Name, llvm::Constant *Init,
+ StringRef Section, unsigned Align,
bool AddToUsed);
CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
@@ -1391,7 +1389,7 @@
/// EmitMetaClassRef - Return a Value * of the address of _class_t
/// meta-data
llvm::Value *EmitMetaClassRef(CodeGenFunction &CGF,
- const ObjCInterfaceDecl *ID);
+ const ObjCInterfaceDecl *ID, bool Weak);
/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
/// the given ivar.
@@ -2723,9 +2721,8 @@
llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
// No special section, but goes in llvm.used
- return CreateMetadataVar("\01l_OBJC_PROTOCOLEXT_" + PD->getName(),
- Init,
- nullptr, 0, true);
+ return CreateMetadataVar("\01l_OBJC_PROTOCOLEXT_" + PD->getName(), Init,
+ StringRef(), 0, true);
}
/*
@@ -2858,11 +2855,9 @@
MethodTypes.size());
llvm::Constant *Init = llvm::ConstantArray::get(AT, MethodTypes);
- llvm::GlobalVariable *GV =
- CreateMetadataVar(Name, Init,
- (ObjCABI == 2) ? "__DATA, __objc_const" : nullptr,
- (ObjCABI == 2) ? 8 : 4,
- true);
+ llvm::GlobalVariable *GV = CreateMetadataVar(
+ Name, Init, (ObjCABI == 2) ? "__DATA, __objc_const" : StringRef(),
+ (ObjCABI == 2) ? 8 : 4, true);
return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.Int8PtrPtrTy);
}
@@ -3395,18 +3390,17 @@
return Method;
}
-llvm::GlobalVariable *
-CGObjCCommonMac::CreateMetadataVar(Twine Name,
- llvm::Constant *Init,
- const char *Section,
- unsigned Align,
- bool AddToUsed) {
+llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
+ llvm::Constant *Init,
+ StringRef Section,
+ unsigned Align,
+ bool AddToUsed) {
llvm::Type *Ty = Init->getType();
llvm::GlobalVariable *GV =
new llvm::GlobalVariable(CGM.getModule(), Ty, false,
llvm::GlobalValue::PrivateLinkage, Init, Name);
assertPrivateName(GV);
- if (Section)
+ if (!Section.empty())
GV->setSection(Section);
if (Align)
GV->setAlignment(Align);
@@ -4457,13 +4451,12 @@
llvm::GlobalVariable *&Entry = ClassNames[Ident];
if (!Entry)
- Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
- llvm::ConstantDataArray::getString(VMContext,
- Ident->getNameStart()),
- ((ObjCABI == 2) ?
- "__TEXT,__objc_classname,cstring_literals" :
- "__TEXT,__cstring,cstring_literals"),
- 1, true);
+ Entry = CreateMetadataVar(
+ "\01L_OBJC_CLASS_NAME_",
+ llvm::ConstantDataArray::getString(VMContext, Ident->getName()),
+ ((ObjCABI == 2) ? "__TEXT,__objc_classname,cstring_literals"
+ : "__TEXT,__cstring,cstring_literals"),
+ 1, true);
return getConstantGEP(VMContext, Entry, 0, 0);
}
@@ -4926,11 +4919,10 @@
llvm::GlobalVariable *&Entry = PropertyNames[Ident];
if (!Entry)
- Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_",
- llvm::ConstantDataArray::getString(VMContext,
- Ident->getNameStart()),
- "__TEXT,__cstring,cstring_literals",
- 1, true);
+ Entry = CreateMetadataVar(
+ "\01L_OBJC_PROP_NAME_ATTR_",
+ llvm::ConstantDataArray::getString(VMContext, Ident->getName()),
+ "__TEXT,__cstring,cstring_literals", 1, true);
return getConstantGEP(VMContext, Entry, 0, 0);
}
@@ -6710,13 +6702,15 @@
/// meta-data
///
llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CodeGenFunction &CGF,
- const ObjCInterfaceDecl *ID) {
+ const ObjCInterfaceDecl *ID,
+ bool Weak) {
llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
if (!Entry) {
std::string MetaClassName(getMetaclassSymbolPrefix() +
ID->getNameAsString());
- llvm::GlobalVariable *MetaClassGV = GetClassGlobal(MetaClassName);
+ llvm::GlobalVariable *MetaClassGV =
+ GetClassGlobal(MetaClassName, Weak);
Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
false, llvm::GlobalValue::PrivateLinkage,
MetaClassGV,
@@ -6774,7 +6768,8 @@
// If this is a class message the metaclass is passed as the target.
llvm::Value *Target;
if (IsClassMessage)
- Target = EmitMetaClassRef(CGF, Class);
+ Target = EmitMetaClassRef(CGF, Class,
+ (isCategoryImpl && Class->isWeakImported()));
else
Target = EmitSuperClassRef(CGF, Class);
diff --git a/lib/CodeGen/CGObjCRuntime.cpp b/lib/CodeGen/CGObjCRuntime.cpp
index 1a5db9b..3d013da 100644
--- a/lib/CodeGen/CGObjCRuntime.cpp
+++ b/lib/CodeGen/CGObjCRuntime.cpp
@@ -149,7 +149,7 @@
const VarDecl *Variable;
const Stmt *Body;
llvm::BasicBlock *Block;
- llvm::Value *TypeInfo;
+ llvm::Constant *TypeInfo;
};
struct CallObjCEndCatch : EHScopeStack::Cleanup {
diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp
index da86e2b..12a3a77 100644
--- a/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -19,7 +19,7 @@
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/raw_ostream.h"
-#include <assert.h>
+#include <cassert>
using namespace clang;
using namespace CodeGen;
@@ -31,8 +31,8 @@
CGM.Int32Ty /* reserved_2 */, CGM.Int32Ty /* reserved_3 */,
CGM.Int8PtrTy /* psource */, NULL);
// Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...)
- llvm::Type *MicroParams[] = { llvm::PointerType::getUnqual(CGM.Int32Ty),
- llvm::PointerType::getUnqual(CGM.Int32Ty) };
+ llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty),
+ llvm::PointerType::getUnqual(CGM.Int32Ty)};
Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
}
@@ -57,9 +57,9 @@
DefaultOpenMPLocation->setLinkage(llvm::GlobalValue::PrivateLinkage);
llvm::Constant *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0, true);
- llvm::Constant *Values[] = { Zero,
- llvm::ConstantInt::get(CGM.Int32Ty, Flags),
- Zero, Zero, DefaultOpenMPPSource };
+ llvm::Constant *Values[] = {Zero,
+ llvm::ConstantInt::get(CGM.Int32Ty, Flags),
+ Zero, Zero, DefaultOpenMPPSource};
llvm::Constant *Init = llvm::ConstantStruct::get(IdentTy, Values);
DefaultOpenMPLocation->setInitializer(Init);
return DefaultOpenMPLocation;
@@ -98,19 +98,24 @@
llvm::Value *PSource =
CGF.Builder.CreateConstInBoundsGEP2_32(LocValue, 0, IdentField_PSource);
- SmallString<128> Buffer2;
- llvm::raw_svector_ostream OS2(Buffer2);
- // Build debug location
- PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
- OS2 << ";" << PLoc.getFilename() << ";";
- if (const FunctionDecl *FD =
- dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) {
- OS2 << FD->getQualifiedNameAsString();
+ auto OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding());
+ if (OMPDebugLoc == nullptr) {
+ SmallString<128> Buffer2;
+ llvm::raw_svector_ostream OS2(Buffer2);
+ // Build debug location
+ PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
+ OS2 << ";" << PLoc.getFilename() << ";";
+ if (const FunctionDecl *FD =
+ dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) {
+ OS2 << FD->getQualifiedNameAsString();
+ }
+ OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
+ OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str());
+ OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc;
}
- OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
// *psource = ";<File>;<Function>;<Line>;<Column>;;";
- CGF.Builder.CreateStore(CGF.Builder.CreateGlobalStringPtr(OS2.str()),
- PSource);
+ CGF.Builder.CreateStore(OMPDebugLoc, PSource);
+
return LocValue;
}
@@ -126,7 +131,7 @@
// Generate "int32 .kmpc_global_thread_num.addr;"
CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
- llvm::Value *Args[] = { EmitOpenMPUpdateLocation(CGF, Loc) };
+ llvm::Value *Args[] = {EmitOpenMPUpdateLocation(CGF, Loc)};
GTid = CGF.EmitRuntimeCall(
CreateRuntimeFunction(OMPRTL__kmpc_global_thread_num), Args);
OpenMPGtidMap[CGF.CurFn] = GTid;
@@ -157,8 +162,8 @@
case OMPRTL__kmpc_fork_call: {
// Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro
// microtask, ...);
- llvm::Type *TypeParams[] = { getIdentTyPointerTy(), CGM.Int32Ty,
- getKmpc_MicroPointerTy() };
+ llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
+ getKmpc_MicroPointerTy()};
llvm::FunctionType *FnTy =
llvm::FunctionType::get(CGM.VoidTy, TypeParams, true);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call");
@@ -166,7 +171,7 @@
}
case OMPRTL__kmpc_global_thread_num: {
// Build kmp_int32 __kmpc_global_thread_num(ident_t *loc);
- llvm::Type *TypeParams[] = { getIdentTyPointerTy() };
+ llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
llvm::FunctionType *FnTy =
llvm::FunctionType::get(CGM.Int32Ty, TypeParams, false);
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num");
diff --git a/lib/CodeGen/CGOpenMPRuntime.h b/lib/CodeGen/CGOpenMPRuntime.h
index 06103cf..862e8a1 100644
--- a/lib/CodeGen/CGOpenMPRuntime.h
+++ b/lib/CodeGen/CGOpenMPRuntime.h
@@ -31,7 +31,7 @@
class StructType;
class Type;
class Value;
-}
+} // namespace llvm
namespace clang {
@@ -121,6 +121,9 @@
IdentField_PSource
};
llvm::StructType *IdentTy;
+ /// \brief Map for Sourcelocation and OpenMP runtime library debug locations.
+ typedef llvm::DenseMap<unsigned, llvm::Value *> OpenMPDebugLocMapTy;
+ OpenMPDebugLocMapTy OpenMPDebugLocMap;
/// \brief The type for a microtask which gets passed to __kmpc_fork_call().
/// Original representation is:
/// typedef void (kmpc_micro)(kmp_int32 global_tid, kmp_int32 bound_tid,...);
@@ -133,7 +136,7 @@
OpenMPGtidMapTy OpenMPGtidMap;
public:
- CGOpenMPRuntime(CodeGenModule &CGM);
+ explicit CGOpenMPRuntime(CodeGenModule &CGM);
~CGOpenMPRuntime() {}
/// \brief Cleans up references to the objects in finished function.
@@ -168,7 +171,7 @@
/// \return Specified function.
llvm::Constant *CreateRuntimeFunction(OpenMPRTLFunction Function);
};
-}
-}
+} // namespace CodeGen
+} // namespace clang
#endif
diff --git a/lib/CodeGen/CGRTTI.cpp b/lib/CodeGen/CGRTTI.cpp
deleted file mode 100644
index 4ca315c..0000000
--- a/lib/CodeGen/CGRTTI.cpp
+++ /dev/null
@@ -1,998 +0,0 @@
-//===--- CGCXXRTTI.cpp - Emit LLVM Code for C++ RTTI descriptors ----------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This contains code dealing with C++ code generation of RTTI descriptors.
-//
-//===----------------------------------------------------------------------===//
-
-#include "CodeGenModule.h"
-#include "CGCXXABI.h"
-#include "CGObjCRuntime.h"
-#include "clang/AST/RecordLayout.h"
-#include "clang/AST/Type.h"
-#include "clang/Frontend/CodeGenOptions.h"
-
-using namespace clang;
-using namespace CodeGen;
-
-namespace {
-class ItaniumRTTIBuilder {
- CodeGenModule &CGM; // Per-module state.
- llvm::LLVMContext &VMContext;
-
- /// Fields - The fields of the RTTI descriptor currently being built.
- SmallVector<llvm::Constant *, 16> Fields;
-
- /// GetAddrOfTypeName - Returns the mangled type name of the given type.
- llvm::GlobalVariable *
- GetAddrOfTypeName(QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage);
-
- /// GetAddrOfExternalRTTIDescriptor - Returns the constant for the RTTI
- /// descriptor of the given type.
- llvm::Constant *GetAddrOfExternalRTTIDescriptor(QualType Ty);
-
- /// BuildVTablePointer - Build the vtable pointer for the given type.
- void BuildVTablePointer(const Type *Ty);
-
- /// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single
- /// inheritance, according to the Itanium C++ ABI, 2.9.5p6b.
- void BuildSIClassTypeInfo(const CXXRecordDecl *RD);
-
- /// BuildVMIClassTypeInfo - Build an abi::__vmi_class_type_info, used for
- /// classes with bases that do not satisfy the abi::__si_class_type_info
- /// constraints, according ti the Itanium C++ ABI, 2.9.5p5c.
- void BuildVMIClassTypeInfo(const CXXRecordDecl *RD);
-
- /// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct, used
- /// for pointer types.
- void BuildPointerTypeInfo(QualType PointeeTy);
-
- /// BuildObjCObjectTypeInfo - Build the appropriate kind of
- /// type_info for an object type.
- void BuildObjCObjectTypeInfo(const ObjCObjectType *Ty);
-
- /// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info
- /// struct, used for member pointer types.
- void BuildPointerToMemberTypeInfo(const MemberPointerType *Ty);
-
-public:
- ItaniumRTTIBuilder(CodeGenModule &CGM) : CGM(CGM),
- VMContext(CGM.getModule().getContext()) { }
-
- // Pointer type info flags.
- enum {
- /// PTI_Const - Type has const qualifier.
- PTI_Const = 0x1,
-
- /// PTI_Volatile - Type has volatile qualifier.
- PTI_Volatile = 0x2,
-
- /// PTI_Restrict - Type has restrict qualifier.
- PTI_Restrict = 0x4,
-
- /// PTI_Incomplete - Type is incomplete.
- PTI_Incomplete = 0x8,
-
- /// PTI_ContainingClassIncomplete - Containing class is incomplete.
- /// (in pointer to member).
- PTI_ContainingClassIncomplete = 0x10
- };
-
- // VMI type info flags.
- enum {
- /// VMI_NonDiamondRepeat - Class has non-diamond repeated inheritance.
- VMI_NonDiamondRepeat = 0x1,
-
- /// VMI_DiamondShaped - Class is diamond shaped.
- VMI_DiamondShaped = 0x2
- };
-
- // Base class type info flags.
- enum {
- /// BCTI_Virtual - Base class is virtual.
- BCTI_Virtual = 0x1,
-
- /// BCTI_Public - Base class is public.
- BCTI_Public = 0x2
- };
-
- /// BuildTypeInfo - Build the RTTI type info struct for the given type.
- ///
- /// \param Force - true to force the creation of this RTTI value
- llvm::Constant *BuildTypeInfo(QualType Ty, bool Force = false);
-};
-}
-
-llvm::GlobalVariable *
-ItaniumRTTIBuilder::GetAddrOfTypeName(QualType Ty,
- llvm::GlobalVariable::LinkageTypes Linkage) {
- SmallString<256> OutName;
- llvm::raw_svector_ostream Out(OutName);
- CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(Ty, Out);
- Out.flush();
- StringRef Name = OutName.str();
-
- // We know that the mangled name of the type starts at index 4 of the
- // mangled name of the typename, so we can just index into it in order to
- // get the mangled name of the type.
- llvm::Constant *Init = llvm::ConstantDataArray::getString(VMContext,
- Name.substr(4));
-
- llvm::GlobalVariable *GV =
- CGM.CreateOrReplaceCXXRuntimeVariable(Name, Init->getType(), Linkage);
-
- GV->setInitializer(Init);
-
- return GV;
-}
-
-llvm::Constant *
-ItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) {
- // Mangle the RTTI name.
- SmallString<256> OutName;
- llvm::raw_svector_ostream Out(OutName);
- CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out);
- Out.flush();
- StringRef Name = OutName.str();
-
- // Look for an existing global.
- llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name);
-
- if (!GV) {
- // Create a new global variable.
- GV = new llvm::GlobalVariable(CGM.getModule(), CGM.Int8PtrTy,
- /*Constant=*/true,
- llvm::GlobalValue::ExternalLinkage, nullptr,
- Name);
- }
-
- return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
-}
-
-/// TypeInfoIsInStandardLibrary - Given a builtin type, returns whether the type
-/// info for that type is defined in the standard library.
-static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
- // Itanium C++ ABI 2.9.2:
- // Basic type information (e.g. for "int", "bool", etc.) will be kept in
- // the run-time support library. Specifically, the run-time support
- // library should contain type_info objects for the types X, X* and
- // X const*, for every X in: void, std::nullptr_t, bool, wchar_t, char,
- // unsigned char, signed char, short, unsigned short, int, unsigned int,
- // long, unsigned long, long long, unsigned long long, float, double,
- // long double, char16_t, char32_t, and the IEEE 754r decimal and
- // half-precision floating point types.
- switch (Ty->getKind()) {
- case BuiltinType::Void:
- case BuiltinType::NullPtr:
- case BuiltinType::Bool:
- case BuiltinType::WChar_S:
- case BuiltinType::WChar_U:
- case BuiltinType::Char_U:
- case BuiltinType::Char_S:
- case BuiltinType::UChar:
- case BuiltinType::SChar:
- case BuiltinType::Short:
- case BuiltinType::UShort:
- case BuiltinType::Int:
- case BuiltinType::UInt:
- case BuiltinType::Long:
- case BuiltinType::ULong:
- case BuiltinType::LongLong:
- case BuiltinType::ULongLong:
- case BuiltinType::Half:
- case BuiltinType::Float:
- case BuiltinType::Double:
- case BuiltinType::LongDouble:
- case BuiltinType::Char16:
- case BuiltinType::Char32:
- case BuiltinType::Int128:
- case BuiltinType::UInt128:
- case BuiltinType::OCLImage1d:
- case BuiltinType::OCLImage1dArray:
- case BuiltinType::OCLImage1dBuffer:
- case BuiltinType::OCLImage2d:
- case BuiltinType::OCLImage2dArray:
- case BuiltinType::OCLImage3d:
- case BuiltinType::OCLSampler:
- case BuiltinType::OCLEvent:
- return true;
-
- case BuiltinType::Dependent:
-#define BUILTIN_TYPE(Id, SingletonId)
-#define PLACEHOLDER_TYPE(Id, SingletonId) \
- case BuiltinType::Id:
-#include "clang/AST/BuiltinTypes.def"
- llvm_unreachable("asking for RRTI for a placeholder type!");
-
- case BuiltinType::ObjCId:
- case BuiltinType::ObjCClass:
- case BuiltinType::ObjCSel:
- llvm_unreachable("FIXME: Objective-C types are unsupported!");
- }
-
- llvm_unreachable("Invalid BuiltinType Kind!");
-}
-
-static bool TypeInfoIsInStandardLibrary(const PointerType *PointerTy) {
- QualType PointeeTy = PointerTy->getPointeeType();
- const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(PointeeTy);
- if (!BuiltinTy)
- return false;
-
- // Check the qualifiers.
- Qualifiers Quals = PointeeTy.getQualifiers();
- Quals.removeConst();
-
- if (!Quals.empty())
- return false;
-
- return TypeInfoIsInStandardLibrary(BuiltinTy);
-}
-
-/// IsStandardLibraryRTTIDescriptor - Returns whether the type
-/// information for the given type exists in the standard library.
-static bool IsStandardLibraryRTTIDescriptor(QualType Ty) {
- // Type info for builtin types is defined in the standard library.
- if (const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(Ty))
- return TypeInfoIsInStandardLibrary(BuiltinTy);
-
- // Type info for some pointer types to builtin types is defined in the
- // standard library.
- if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
- return TypeInfoIsInStandardLibrary(PointerTy);
-
- return false;
-}
-
-/// ShouldUseExternalRTTIDescriptor - Returns whether the type information for
-/// the given type exists somewhere else, and that we should not emit the type
-/// information in this translation unit. Assumes that it is not a
-/// standard-library type.
-static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM,
- QualType Ty) {
- ASTContext &Context = CGM.getContext();
-
- // If RTTI is disabled, assume it might be disabled in the
- // translation unit that defines any potential key function, too.
- if (!Context.getLangOpts().RTTI) return false;
-
- if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
- if (!RD->hasDefinition())
- return false;
-
- if (!RD->isDynamicClass())
- return false;
-
- // FIXME: this may need to be reconsidered if the key function
- // changes.
- return CGM.getVTables().isVTableExternal(RD);
- }
-
- return false;
-}
-
-/// IsIncompleteClassType - Returns whether the given record type is incomplete.
-static bool IsIncompleteClassType(const RecordType *RecordTy) {
- return !RecordTy->getDecl()->isCompleteDefinition();
-}
-
-/// ContainsIncompleteClassType - Returns whether the given type contains an
-/// incomplete class type. This is true if
-///
-/// * The given type is an incomplete class type.
-/// * The given type is a pointer type whose pointee type contains an
-/// incomplete class type.
-/// * The given type is a member pointer type whose class is an incomplete
-/// class type.
-/// * The given type is a member pointer type whoise pointee type contains an
-/// incomplete class type.
-/// is an indirect or direct pointer to an incomplete class type.
-static bool ContainsIncompleteClassType(QualType Ty) {
- if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
- if (IsIncompleteClassType(RecordTy))
- return true;
- }
-
- if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
- return ContainsIncompleteClassType(PointerTy->getPointeeType());
-
- if (const MemberPointerType *MemberPointerTy =
- dyn_cast<MemberPointerType>(Ty)) {
- // Check if the class type is incomplete.
- const RecordType *ClassType = cast<RecordType>(MemberPointerTy->getClass());
- if (IsIncompleteClassType(ClassType))
- return true;
-
- return ContainsIncompleteClassType(MemberPointerTy->getPointeeType());
- }
-
- return false;
-}
-
-/// getTypeInfoLinkage - Return the linkage that the type info and type info
-/// name constants should have for the given type.
-llvm::GlobalVariable::LinkageTypes
-CodeGenModule::getTypeInfoLinkage(QualType Ty) {
- // Itanium C++ ABI 2.9.5p7:
- // In addition, it and all of the intermediate abi::__pointer_type_info
- // structs in the chain down to the abi::__class_type_info for the
- // incomplete class type must be prevented from resolving to the
- // corresponding type_info structs for the complete class type, possibly
- // by making them local static objects. Finally, a dummy class RTTI is
- // generated for the incomplete type that will not resolve to the final
- // complete class RTTI (because the latter need not exist), possibly by
- // making it a local static object.
- if (ContainsIncompleteClassType(Ty))
- return llvm::GlobalValue::InternalLinkage;
-
- switch (Ty->getLinkage()) {
- case NoLinkage:
- case InternalLinkage:
- case UniqueExternalLinkage:
- return llvm::GlobalValue::InternalLinkage;
-
- case VisibleNoLinkage:
- case ExternalLinkage:
- if (!getLangOpts().RTTI) {
- // RTTI is not enabled, which means that this type info struct is going
- // to be used for exception handling. Give it linkonce_odr linkage.
- return llvm::GlobalValue::LinkOnceODRLinkage;
- }
-
- if (const RecordType *Record = dyn_cast<RecordType>(Ty)) {
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
- if (RD->hasAttr<WeakAttr>())
- return llvm::GlobalValue::WeakODRLinkage;
- if (RD->isDynamicClass())
- return getVTableLinkage(RD);
- }
-
- return llvm::GlobalValue::LinkOnceODRLinkage;
- }
-
- llvm_unreachable("Invalid linkage!");
-}
-
-// CanUseSingleInheritance - Return whether the given record decl has a "single,
-// public, non-virtual base at offset zero (i.e. the derived class is dynamic
-// iff the base is)", according to Itanium C++ ABI, 2.95p6b.
-static bool CanUseSingleInheritance(const CXXRecordDecl *RD) {
- // Check the number of bases.
- if (RD->getNumBases() != 1)
- return false;
-
- // Get the base.
- CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin();
-
- // Check that the base is not virtual.
- if (Base->isVirtual())
- return false;
-
- // Check that the base is public.
- if (Base->getAccessSpecifier() != AS_public)
- return false;
-
- // Check that the class is dynamic iff the base is.
- const CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
- if (!BaseDecl->isEmpty() &&
- BaseDecl->isDynamicClass() != RD->isDynamicClass())
- return false;
-
- return true;
-}
-
-void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) {
- // abi::__class_type_info.
- static const char * const ClassTypeInfo =
- "_ZTVN10__cxxabiv117__class_type_infoE";
- // abi::__si_class_type_info.
- static const char * const SIClassTypeInfo =
- "_ZTVN10__cxxabiv120__si_class_type_infoE";
- // abi::__vmi_class_type_info.
- static const char * const VMIClassTypeInfo =
- "_ZTVN10__cxxabiv121__vmi_class_type_infoE";
-
- const char *VTableName = nullptr;
-
- switch (Ty->getTypeClass()) {
-#define TYPE(Class, Base)
-#define ABSTRACT_TYPE(Class, Base)
-#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
-#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
-#define DEPENDENT_TYPE(Class, Base) case Type::Class:
-#include "clang/AST/TypeNodes.def"
- llvm_unreachable("Non-canonical and dependent types shouldn't get here");
-
- case Type::LValueReference:
- case Type::RValueReference:
- llvm_unreachable("References shouldn't get here");
-
- case Type::Auto:
- llvm_unreachable("Undeduced auto type shouldn't get here");
-
- case Type::Builtin:
- // GCC treats vector and complex types as fundamental types.
- case Type::Vector:
- case Type::ExtVector:
- case Type::Complex:
- case Type::Atomic:
- // FIXME: GCC treats block pointers as fundamental types?!
- case Type::BlockPointer:
- // abi::__fundamental_type_info.
- VTableName = "_ZTVN10__cxxabiv123__fundamental_type_infoE";
- break;
-
- case Type::ConstantArray:
- case Type::IncompleteArray:
- case Type::VariableArray:
- // abi::__array_type_info.
- VTableName = "_ZTVN10__cxxabiv117__array_type_infoE";
- break;
-
- case Type::FunctionNoProto:
- case Type::FunctionProto:
- // abi::__function_type_info.
- VTableName = "_ZTVN10__cxxabiv120__function_type_infoE";
- break;
-
- case Type::Enum:
- // abi::__enum_type_info.
- VTableName = "_ZTVN10__cxxabiv116__enum_type_infoE";
- break;
-
- case Type::Record: {
- const CXXRecordDecl *RD =
- cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
-
- if (!RD->hasDefinition() || !RD->getNumBases()) {
- VTableName = ClassTypeInfo;
- } else if (CanUseSingleInheritance(RD)) {
- VTableName = SIClassTypeInfo;
- } else {
- VTableName = VMIClassTypeInfo;
- }
-
- break;
- }
-
- case Type::ObjCObject:
- // Ignore protocol qualifiers.
- Ty = cast<ObjCObjectType>(Ty)->getBaseType().getTypePtr();
-
- // Handle id and Class.
- if (isa<BuiltinType>(Ty)) {
- VTableName = ClassTypeInfo;
- break;
- }
-
- assert(isa<ObjCInterfaceType>(Ty));
- // Fall through.
-
- case Type::ObjCInterface:
- if (cast<ObjCInterfaceType>(Ty)->getDecl()->getSuperClass()) {
- VTableName = SIClassTypeInfo;
- } else {
- VTableName = ClassTypeInfo;
- }
- break;
-
- case Type::ObjCObjectPointer:
- case Type::Pointer:
- // abi::__pointer_type_info.
- VTableName = "_ZTVN10__cxxabiv119__pointer_type_infoE";
- break;
-
- case Type::MemberPointer:
- // abi::__pointer_to_member_type_info.
- VTableName = "_ZTVN10__cxxabiv129__pointer_to_member_type_infoE";
- break;
- }
-
- llvm::Constant *VTable =
- CGM.getModule().getOrInsertGlobal(VTableName, CGM.Int8PtrTy);
-
- llvm::Type *PtrDiffTy =
- CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
-
- // The vtable address point is 2.
- llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2);
- VTable = llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Two);
- VTable = llvm::ConstantExpr::getBitCast(VTable, CGM.Int8PtrTy);
-
- Fields.push_back(VTable);
-}
-
-llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) {
- // We want to operate on the canonical type.
- Ty = CGM.getContext().getCanonicalType(Ty);
-
- // Check if we've already emitted an RTTI descriptor for this type.
- SmallString<256> OutName;
- llvm::raw_svector_ostream Out(OutName);
- CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out);
- Out.flush();
- StringRef Name = OutName.str();
-
- llvm::GlobalVariable *OldGV = CGM.getModule().getNamedGlobal(Name);
- if (OldGV && !OldGV->isDeclaration()) {
- assert(!OldGV->hasAvailableExternallyLinkage() &&
- "available_externally typeinfos not yet implemented");
-
- return llvm::ConstantExpr::getBitCast(OldGV, CGM.Int8PtrTy);
- }
-
- // Check if there is already an external RTTI descriptor for this type.
- bool IsStdLib = IsStandardLibraryRTTIDescriptor(Ty);
- if (!Force && (IsStdLib || ShouldUseExternalRTTIDescriptor(CGM, Ty)))
- return GetAddrOfExternalRTTIDescriptor(Ty);
-
- // Emit the standard library with external linkage.
- llvm::GlobalVariable::LinkageTypes Linkage;
- if (IsStdLib)
- Linkage = llvm::GlobalValue::ExternalLinkage;
- else
- Linkage = CGM.getTypeInfoLinkage(Ty);
-
- // Add the vtable pointer.
- BuildVTablePointer(cast<Type>(Ty));
-
- // And the name.
- llvm::GlobalVariable *TypeName = GetAddrOfTypeName(Ty, Linkage);
- llvm::Constant *TypeNameField;
-
- // If we're supposed to demote the visibility, be sure to set a flag
- // to use a string comparison for type_info comparisons.
- CGCXXABI::RTTIUniquenessKind RTTIUniqueness =
- CGM.getCXXABI().classifyRTTIUniqueness(Ty, Linkage);
- if (RTTIUniqueness != CGCXXABI::RUK_Unique) {
- // The flag is the sign bit, which on ARM64 is defined to be clear
- // for global pointers. This is very ARM64-specific.
- TypeNameField = llvm::ConstantExpr::getPtrToInt(TypeName, CGM.Int64Ty);
- llvm::Constant *flag =
- llvm::ConstantInt::get(CGM.Int64Ty, ((uint64_t)1) << 63);
- TypeNameField = llvm::ConstantExpr::getAdd(TypeNameField, flag);
- TypeNameField =
- llvm::ConstantExpr::getIntToPtr(TypeNameField, CGM.Int8PtrTy);
- } else {
- TypeNameField = llvm::ConstantExpr::getBitCast(TypeName, CGM.Int8PtrTy);
- }
- Fields.push_back(TypeNameField);
-
- switch (Ty->getTypeClass()) {
-#define TYPE(Class, Base)
-#define ABSTRACT_TYPE(Class, Base)
-#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
-#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
-#define DEPENDENT_TYPE(Class, Base) case Type::Class:
-#include "clang/AST/TypeNodes.def"
- llvm_unreachable("Non-canonical and dependent types shouldn't get here");
-
- // GCC treats vector types as fundamental types.
- case Type::Builtin:
- case Type::Vector:
- case Type::ExtVector:
- case Type::Complex:
- case Type::BlockPointer:
- // Itanium C++ ABI 2.9.5p4:
- // abi::__fundamental_type_info adds no data members to std::type_info.
- break;
-
- case Type::LValueReference:
- case Type::RValueReference:
- llvm_unreachable("References shouldn't get here");
-
- case Type::Auto:
- llvm_unreachable("Undeduced auto type shouldn't get here");
-
- case Type::ConstantArray:
- case Type::IncompleteArray:
- case Type::VariableArray:
- // Itanium C++ ABI 2.9.5p5:
- // abi::__array_type_info adds no data members to std::type_info.
- break;
-
- case Type::FunctionNoProto:
- case Type::FunctionProto:
- // Itanium C++ ABI 2.9.5p5:
- // abi::__function_type_info adds no data members to std::type_info.
- break;
-
- case Type::Enum:
- // Itanium C++ ABI 2.9.5p5:
- // abi::__enum_type_info adds no data members to std::type_info.
- break;
-
- case Type::Record: {
- const CXXRecordDecl *RD =
- cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
- if (!RD->hasDefinition() || !RD->getNumBases()) {
- // We don't need to emit any fields.
- break;
- }
-
- if (CanUseSingleInheritance(RD))
- BuildSIClassTypeInfo(RD);
- else
- BuildVMIClassTypeInfo(RD);
-
- break;
- }
-
- case Type::ObjCObject:
- case Type::ObjCInterface:
- BuildObjCObjectTypeInfo(cast<ObjCObjectType>(Ty));
- break;
-
- case Type::ObjCObjectPointer:
- BuildPointerTypeInfo(cast<ObjCObjectPointerType>(Ty)->getPointeeType());
- break;
-
- case Type::Pointer:
- BuildPointerTypeInfo(cast<PointerType>(Ty)->getPointeeType());
- break;
-
- case Type::MemberPointer:
- BuildPointerToMemberTypeInfo(cast<MemberPointerType>(Ty));
- break;
-
- case Type::Atomic:
- // No fields, at least for the moment.
- break;
- }
-
- llvm::Constant *Init = llvm::ConstantStruct::getAnon(Fields);
-
- llvm::GlobalVariable *GV =
- new llvm::GlobalVariable(CGM.getModule(), Init->getType(),
- /*Constant=*/true, Linkage, Init, Name);
-
- // If there's already an old global variable, replace it with the new one.
- if (OldGV) {
- GV->takeName(OldGV);
- llvm::Constant *NewPtr =
- llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
- OldGV->replaceAllUsesWith(NewPtr);
- OldGV->eraseFromParent();
- }
-
- // The Itanium ABI specifies that type_info objects must be globally
- // unique, with one exception: if the type is an incomplete class
- // type or a (possibly indirect) pointer to one. That exception
- // affects the general case of comparing type_info objects produced
- // by the typeid operator, which is why the comparison operators on
- // std::type_info generally use the type_info name pointers instead
- // of the object addresses. However, the language's built-in uses
- // of RTTI generally require class types to be complete, even when
- // manipulating pointers to those class types. This allows the
- // implementation of dynamic_cast to rely on address equality tests,
- // which is much faster.
-
- // All of this is to say that it's important that both the type_info
- // object and the type_info name be uniqued when weakly emitted.
-
- // Give the type_info object and name the formal visibility of the
- // type itself.
- llvm::GlobalValue::VisibilityTypes llvmVisibility;
- if (llvm::GlobalValue::isLocalLinkage(Linkage))
- // If the linkage is local, only default visibility makes sense.
- llvmVisibility = llvm::GlobalValue::DefaultVisibility;
- else if (RTTIUniqueness == CGCXXABI::RUK_NonUniqueHidden)
- llvmVisibility = llvm::GlobalValue::HiddenVisibility;
- else
- llvmVisibility = CodeGenModule::GetLLVMVisibility(Ty->getVisibility());
- TypeName->setVisibility(llvmVisibility);
- GV->setVisibility(llvmVisibility);
-
- return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
-}
-
-/// ComputeQualifierFlags - Compute the pointer type info flags from the
-/// given qualifier.
-static unsigned ComputeQualifierFlags(Qualifiers Quals) {
- unsigned Flags = 0;
-
- if (Quals.hasConst())
- Flags |= ItaniumRTTIBuilder::PTI_Const;
- if (Quals.hasVolatile())
- Flags |= ItaniumRTTIBuilder::PTI_Volatile;
- if (Quals.hasRestrict())
- Flags |= ItaniumRTTIBuilder::PTI_Restrict;
-
- return Flags;
-}
-
-/// BuildObjCObjectTypeInfo - Build the appropriate kind of type_info
-/// for the given Objective-C object type.
-void ItaniumRTTIBuilder::BuildObjCObjectTypeInfo(const ObjCObjectType *OT) {
- // Drop qualifiers.
- const Type *T = OT->getBaseType().getTypePtr();
- assert(isa<BuiltinType>(T) || isa<ObjCInterfaceType>(T));
-
- // The builtin types are abi::__class_type_infos and don't require
- // extra fields.
- if (isa<BuiltinType>(T)) return;
-
- ObjCInterfaceDecl *Class = cast<ObjCInterfaceType>(T)->getDecl();
- ObjCInterfaceDecl *Super = Class->getSuperClass();
-
- // Root classes are also __class_type_info.
- if (!Super) return;
-
- QualType SuperTy = CGM.getContext().getObjCInterfaceType(Super);
-
- // Everything else is single inheritance.
- llvm::Constant *BaseTypeInfo = ItaniumRTTIBuilder(CGM).BuildTypeInfo(SuperTy);
- Fields.push_back(BaseTypeInfo);
-}
-
-/// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single
-/// inheritance, according to the Itanium C++ ABI, 2.95p6b.
-void ItaniumRTTIBuilder::BuildSIClassTypeInfo(const CXXRecordDecl *RD) {
- // Itanium C++ ABI 2.9.5p6b:
- // It adds to abi::__class_type_info a single member pointing to the
- // type_info structure for the base type,
- llvm::Constant *BaseTypeInfo =
- ItaniumRTTIBuilder(CGM).BuildTypeInfo(RD->bases_begin()->getType());
- Fields.push_back(BaseTypeInfo);
-}
-
-namespace {
- /// SeenBases - Contains virtual and non-virtual bases seen when traversing
- /// a class hierarchy.
- struct SeenBases {
- llvm::SmallPtrSet<const CXXRecordDecl *, 16> NonVirtualBases;
- llvm::SmallPtrSet<const CXXRecordDecl *, 16> VirtualBases;
- };
-}
-
-/// ComputeVMIClassTypeInfoFlags - Compute the value of the flags member in
-/// abi::__vmi_class_type_info.
-///
-static unsigned ComputeVMIClassTypeInfoFlags(const CXXBaseSpecifier *Base,
- SeenBases &Bases) {
-
- unsigned Flags = 0;
-
- const CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
-
- if (Base->isVirtual()) {
- // Mark the virtual base as seen.
- if (!Bases.VirtualBases.insert(BaseDecl)) {
- // If this virtual base has been seen before, then the class is diamond
- // shaped.
- Flags |= ItaniumRTTIBuilder::VMI_DiamondShaped;
- } else {
- if (Bases.NonVirtualBases.count(BaseDecl))
- Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
- }
- } else {
- // Mark the non-virtual base as seen.
- if (!Bases.NonVirtualBases.insert(BaseDecl)) {
- // If this non-virtual base has been seen before, then the class has non-
- // diamond shaped repeated inheritance.
- Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
- } else {
- if (Bases.VirtualBases.count(BaseDecl))
- Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
- }
- }
-
- // Walk all bases.
- for (const auto &I : BaseDecl->bases())
- Flags |= ComputeVMIClassTypeInfoFlags(&I, Bases);
-
- return Flags;
-}
-
-static unsigned ComputeVMIClassTypeInfoFlags(const CXXRecordDecl *RD) {
- unsigned Flags = 0;
- SeenBases Bases;
-
- // Walk all bases.
- for (const auto &I : RD->bases())
- Flags |= ComputeVMIClassTypeInfoFlags(&I, Bases);
-
- return Flags;
-}
-
-/// BuildVMIClassTypeInfo - Build an abi::__vmi_class_type_info, used for
-/// classes with bases that do not satisfy the abi::__si_class_type_info
-/// constraints, according ti the Itanium C++ ABI, 2.9.5p5c.
-void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
- llvm::Type *UnsignedIntLTy =
- CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
-
- // Itanium C++ ABI 2.9.5p6c:
- // __flags is a word with flags describing details about the class
- // structure, which may be referenced by using the __flags_masks
- // enumeration. These flags refer to both direct and indirect bases.
- unsigned Flags = ComputeVMIClassTypeInfoFlags(RD);
- Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
-
- // Itanium C++ ABI 2.9.5p6c:
- // __base_count is a word with the number of direct proper base class
- // descriptions that follow.
- Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, RD->getNumBases()));
-
- if (!RD->getNumBases())
- return;
-
- llvm::Type *LongLTy =
- CGM.getTypes().ConvertType(CGM.getContext().LongTy);
-
- // Now add the base class descriptions.
-
- // Itanium C++ ABI 2.9.5p6c:
- // __base_info[] is an array of base class descriptions -- one for every
- // direct proper base. Each description is of the type:
- //
- // struct abi::__base_class_type_info {
- // public:
- // const __class_type_info *__base_type;
- // long __offset_flags;
- //
- // enum __offset_flags_masks {
- // __virtual_mask = 0x1,
- // __public_mask = 0x2,
- // __offset_shift = 8
- // };
- // };
- for (const auto &Base : RD->bases()) {
- // The __base_type member points to the RTTI for the base type.
- Fields.push_back(ItaniumRTTIBuilder(CGM).BuildTypeInfo(Base.getType()));
-
- const CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
-
- int64_t OffsetFlags = 0;
-
- // All but the lower 8 bits of __offset_flags are a signed offset.
- // For a non-virtual base, this is the offset in the object of the base
- // subobject. For a virtual base, this is the offset in the virtual table of
- // the virtual base offset for the virtual base referenced (negative).
- CharUnits Offset;
- if (Base.isVirtual())
- Offset =
- CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(RD, BaseDecl);
- else {
- const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
- Offset = Layout.getBaseClassOffset(BaseDecl);
- };
-
- OffsetFlags = uint64_t(Offset.getQuantity()) << 8;
-
- // The low-order byte of __offset_flags contains flags, as given by the
- // masks from the enumeration __offset_flags_masks.
- if (Base.isVirtual())
- OffsetFlags |= BCTI_Virtual;
- if (Base.getAccessSpecifier() == AS_public)
- OffsetFlags |= BCTI_Public;
-
- Fields.push_back(llvm::ConstantInt::get(LongLTy, OffsetFlags));
- }
-}
-
-/// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct,
-/// used for pointer types.
-void ItaniumRTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) {
- Qualifiers Quals;
- QualType UnqualifiedPointeeTy =
- CGM.getContext().getUnqualifiedArrayType(PointeeTy, Quals);
-
- // Itanium C++ ABI 2.9.5p7:
- // __flags is a flag word describing the cv-qualification and other
- // attributes of the type pointed to
- unsigned Flags = ComputeQualifierFlags(Quals);
-
- // Itanium C++ ABI 2.9.5p7:
- // When the abi::__pbase_type_info is for a direct or indirect pointer to an
- // incomplete class type, the incomplete target type flag is set.
- if (ContainsIncompleteClassType(UnqualifiedPointeeTy))
- Flags |= PTI_Incomplete;
-
- llvm::Type *UnsignedIntLTy =
- CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
- Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
-
- // Itanium C++ ABI 2.9.5p7:
- // __pointee is a pointer to the std::type_info derivation for the
- // unqualified type being pointed to.
- llvm::Constant *PointeeTypeInfo =
- ItaniumRTTIBuilder(CGM).BuildTypeInfo(UnqualifiedPointeeTy);
- Fields.push_back(PointeeTypeInfo);
-}
-
-/// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info
-/// struct, used for member pointer types.
-void
-ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {
- QualType PointeeTy = Ty->getPointeeType();
-
- Qualifiers Quals;
- QualType UnqualifiedPointeeTy =
- CGM.getContext().getUnqualifiedArrayType(PointeeTy, Quals);
-
- // Itanium C++ ABI 2.9.5p7:
- // __flags is a flag word describing the cv-qualification and other
- // attributes of the type pointed to.
- unsigned Flags = ComputeQualifierFlags(Quals);
-
- const RecordType *ClassType = cast<RecordType>(Ty->getClass());
-
- // Itanium C++ ABI 2.9.5p7:
- // When the abi::__pbase_type_info is for a direct or indirect pointer to an
- // incomplete class type, the incomplete target type flag is set.
- if (ContainsIncompleteClassType(UnqualifiedPointeeTy))
- Flags |= PTI_Incomplete;
-
- if (IsIncompleteClassType(ClassType))
- Flags |= PTI_ContainingClassIncomplete;
-
- llvm::Type *UnsignedIntLTy =
- CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
- Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
-
- // Itanium C++ ABI 2.9.5p7:
- // __pointee is a pointer to the std::type_info derivation for the
- // unqualified type being pointed to.
- llvm::Constant *PointeeTypeInfo =
- ItaniumRTTIBuilder(CGM).BuildTypeInfo(UnqualifiedPointeeTy);
- Fields.push_back(PointeeTypeInfo);
-
- // Itanium C++ ABI 2.9.5p9:
- // __context is a pointer to an abi::__class_type_info corresponding to the
- // class type containing the member pointed to
- // (e.g., the "A" in "int A::*").
- Fields.push_back(
- ItaniumRTTIBuilder(CGM).BuildTypeInfo(QualType(ClassType, 0)));
-}
-
-llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty,
- bool ForEH) {
- // Return a bogus pointer if RTTI is disabled, unless it's for EH.
- // FIXME: should we even be calling this method if RTTI is disabled
- // and it's not for EH?
- if (!ForEH && !getLangOpts().RTTI)
- return llvm::Constant::getNullValue(Int8PtrTy);
-
- if (ForEH && Ty->isObjCObjectPointerType() &&
- LangOpts.ObjCRuntime.isGNUFamily())
- return ObjCRuntime->GetEHType(Ty);
-
- if (getTarget().getCXXABI().isMicrosoft())
- return getMSTypeDescriptor(Ty);
- return ItaniumRTTIBuilder(*this).BuildTypeInfo(Ty);
-}
-
-void CodeGenModule::EmitFundamentalRTTIDescriptor(QualType Type) {
- QualType PointerType = Context.getPointerType(Type);
- QualType PointerTypeConst = Context.getPointerType(Type.withConst());
- ItaniumRTTIBuilder(*this).BuildTypeInfo(Type, true);
- ItaniumRTTIBuilder(*this).BuildTypeInfo(PointerType, true);
- ItaniumRTTIBuilder(*this).BuildTypeInfo(PointerTypeConst, true);
-}
-
-void CodeGenModule::EmitFundamentalRTTIDescriptors() {
- QualType FundamentalTypes[] = { Context.VoidTy, Context.NullPtrTy,
- Context.BoolTy, Context.WCharTy,
- Context.CharTy, Context.UnsignedCharTy,
- Context.SignedCharTy, Context.ShortTy,
- Context.UnsignedShortTy, Context.IntTy,
- Context.UnsignedIntTy, Context.LongTy,
- Context.UnsignedLongTy, Context.LongLongTy,
- Context.UnsignedLongLongTy,
- Context.HalfTy, Context.FloatTy,
- Context.DoubleTy, Context.LongDoubleTy,
- Context.Char16Ty, Context.Char32Ty };
- for (unsigned i = 0; i < llvm::array_lengthof(FundamentalTypes); ++i)
- EmitFundamentalRTTIDescriptor(FundamentalTypes[i]);
-}
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index 573973a..cd86eeb 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -18,6 +18,7 @@
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/PrettyStackTrace.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Sema/LoopHint.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/CallSite.h"
@@ -172,12 +173,33 @@
case Stmt::SEHTryStmtClass:
EmitSEHTryStmt(cast<SEHTryStmt>(*S));
break;
+ case Stmt::SEHLeaveStmtClass:
+ EmitSEHLeaveStmt(cast<SEHLeaveStmt>(*S));
+ break;
case Stmt::OMPParallelDirectiveClass:
EmitOMPParallelDirective(cast<OMPParallelDirective>(*S));
break;
case Stmt::OMPSimdDirectiveClass:
EmitOMPSimdDirective(cast<OMPSimdDirective>(*S));
break;
+ case Stmt::OMPForDirectiveClass:
+ EmitOMPForDirective(cast<OMPForDirective>(*S));
+ break;
+ case Stmt::OMPSectionsDirectiveClass:
+ EmitOMPSectionsDirective(cast<OMPSectionsDirective>(*S));
+ break;
+ case Stmt::OMPSectionDirectiveClass:
+ EmitOMPSectionDirective(cast<OMPSectionDirective>(*S));
+ break;
+ case Stmt::OMPSingleDirectiveClass:
+ EmitOMPSingleDirective(cast<OMPSingleDirective>(*S));
+ break;
+ case Stmt::OMPParallelForDirectiveClass:
+ EmitOMPParallelForDirective(cast<OMPParallelForDirective>(*S));
+ break;
+ case Stmt::OMPParallelSectionsDirectiveClass:
+ EmitOMPParallelSectionsDirective(cast<OMPParallelSectionsDirective>(*S));
+ break;
}
}
@@ -398,7 +420,23 @@
}
void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) {
- EmitStmt(S.getSubStmt());
+ const Stmt *SubStmt = S.getSubStmt();
+ switch (SubStmt->getStmtClass()) {
+ case Stmt::DoStmtClass:
+ EmitDoStmt(cast<DoStmt>(*SubStmt), S.getAttrs());
+ break;
+ case Stmt::ForStmtClass:
+ EmitForStmt(cast<ForStmt>(*SubStmt), S.getAttrs());
+ break;
+ case Stmt::WhileStmtClass:
+ EmitWhileStmt(cast<WhileStmt>(*SubStmt), S.getAttrs());
+ break;
+ case Stmt::CXXForRangeStmtClass:
+ EmitCXXForRangeStmt(cast<CXXForRangeStmt>(*SubStmt), S.getAttrs());
+ break;
+ default:
+ EmitStmt(SubStmt);
+ }
}
void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) {
@@ -436,7 +474,7 @@
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.
- LexicalScope ConditionScope(*this, S.getSourceRange());
+ LexicalScope ConditionScope(*this, S.getCond()->getSourceRange());
RegionCounter Cnt = getPGORegionCounter(&S);
if (S.getConditionVariable())
@@ -504,7 +542,92 @@
EmitBlock(ContBlock, true);
}
-void CodeGenFunction::EmitWhileStmt(const WhileStmt &S) {
+void CodeGenFunction::EmitCondBrHints(llvm::LLVMContext &Context,
+ llvm::BranchInst *CondBr,
+ const ArrayRef<const Attr *> &Attrs) {
+ // Return if there are no hints.
+ if (Attrs.empty())
+ return;
+
+ // Add vectorize and unroll hints to the metadata on the conditional branch.
+ SmallVector<llvm::Value *, 2> Metadata(1);
+ for (const auto *Attr : Attrs) {
+ const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
+
+ // Skip non loop hint attributes
+ if (!LH)
+ continue;
+
+ LoopHintAttr::OptionType Option = LH->getOption();
+ int ValueInt = LH->getValue();
+
+ const char *MetadataName;
+ switch (Option) {
+ case LoopHintAttr::Vectorize:
+ case LoopHintAttr::VectorizeWidth:
+ MetadataName = "llvm.loop.vectorize.width";
+ break;
+ case LoopHintAttr::Interleave:
+ case LoopHintAttr::InterleaveCount:
+ MetadataName = "llvm.loop.vectorize.unroll";
+ break;
+ case LoopHintAttr::Unroll:
+ MetadataName = "llvm.loop.unroll.enable";
+ break;
+ case LoopHintAttr::UnrollCount:
+ MetadataName = "llvm.loop.unroll.count";
+ break;
+ }
+
+ llvm::Value *Value;
+ llvm::MDString *Name;
+ switch (Option) {
+ case LoopHintAttr::Vectorize:
+ case LoopHintAttr::Interleave:
+ if (ValueInt == 1) {
+ // FIXME: In the future I will modifiy the behavior of the metadata
+ // so we can enable/disable vectorization and interleaving separately.
+ Name = llvm::MDString::get(Context, "llvm.loop.vectorize.enable");
+ Value = Builder.getTrue();
+ break;
+ }
+ // Vectorization/interleaving is disabled, set width/count to 1.
+ ValueInt = 1;
+ // Fallthrough.
+ case LoopHintAttr::VectorizeWidth:
+ case LoopHintAttr::InterleaveCount:
+ Name = llvm::MDString::get(Context, MetadataName);
+ Value = llvm::ConstantInt::get(Int32Ty, ValueInt);
+ break;
+ case LoopHintAttr::Unroll:
+ Name = llvm::MDString::get(Context, MetadataName);
+ Value = (ValueInt == 0) ? Builder.getFalse() : Builder.getTrue();
+ break;
+ case LoopHintAttr::UnrollCount:
+ Name = llvm::MDString::get(Context, MetadataName);
+ Value = llvm::ConstantInt::get(Int32Ty, ValueInt);
+ break;
+ }
+
+ SmallVector<llvm::Value *, 2> OpValues;
+ OpValues.push_back(Name);
+ OpValues.push_back(Value);
+
+ // Set or overwrite metadata indicated by Name.
+ Metadata.push_back(llvm::MDNode::get(Context, OpValues));
+ }
+
+ if (!Metadata.empty()) {
+ // Add llvm.loop MDNode to CondBr.
+ llvm::MDNode *LoopID = llvm::MDNode::get(Context, Metadata);
+ LoopID->replaceOperandWith(0, LoopID); // First op points to itself.
+
+ CondBr->setMetadata("llvm.loop", LoopID);
+ }
+}
+
+void CodeGenFunction::EmitWhileStmt(const WhileStmt &S,
+ const ArrayRef<const Attr *> &WhileAttrs) {
RegionCounter Cnt = getPGORegionCounter(&S);
// Emit the header for the loop, which will also become
@@ -551,13 +674,17 @@
llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
if (ConditionScope.requiresCleanups())
ExitBlock = createBasicBlock("while.exit");
- Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock,
- PGO.createLoopWeights(S.getCond(), Cnt));
+ llvm::BranchInst *CondBr =
+ Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock,
+ PGO.createLoopWeights(S.getCond(), Cnt));
if (ExitBlock != LoopExit.getBlock()) {
EmitBlock(ExitBlock);
EmitBranchThroughCleanup(LoopExit);
}
+
+ // Attach metadata to loop body conditional branch.
+ EmitCondBrHints(LoopBody->getContext(), CondBr, WhileAttrs);
}
// Emit the loop body. We have to emit this in a cleanup scope
@@ -588,7 +715,8 @@
SimplifyForwardingBlocks(LoopHeader.getBlock());
}
-void CodeGenFunction::EmitDoStmt(const DoStmt &S) {
+void CodeGenFunction::EmitDoStmt(const DoStmt &S,
+ const ArrayRef<const Attr *> &DoAttrs) {
JumpDest LoopExit = getJumpDestInCurrentScope("do.end");
JumpDest LoopCond = getJumpDestInCurrentScope("do.cond");
@@ -628,9 +756,14 @@
EmitBoolCondBranch = false;
// As long as the condition is true, iterate the loop.
- if (EmitBoolCondBranch)
- Builder.CreateCondBr(BoolCondVal, LoopBody, LoopExit.getBlock(),
- PGO.createLoopWeights(S.getCond(), Cnt));
+ if (EmitBoolCondBranch) {
+ llvm::BranchInst *CondBr =
+ Builder.CreateCondBr(BoolCondVal, LoopBody, LoopExit.getBlock(),
+ PGO.createLoopWeights(S.getCond(), Cnt));
+
+ // Attach metadata to loop body conditional branch.
+ EmitCondBrHints(LoopBody->getContext(), CondBr, DoAttrs);
+ }
LoopStack.pop();
@@ -643,7 +776,8 @@
SimplifyForwardingBlocks(LoopCond.getBlock());
}
-void CodeGenFunction::EmitForStmt(const ForStmt &S) {
+void CodeGenFunction::EmitForStmt(const ForStmt &S,
+ const ArrayRef<const Attr *> &ForAttrs) {
JumpDest LoopExit = getJumpDestInCurrentScope("for.end");
RunCleanupsScope ForScope(*this);
@@ -699,8 +833,12 @@
// C99 6.8.5p2/p4: The first substatement is executed if the expression
// compares unequal to 0. The condition must be a scalar type.
llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
- Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock,
- PGO.createLoopWeights(S.getCond(), Cnt));
+ llvm::BranchInst *CondBr =
+ Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock,
+ PGO.createLoopWeights(S.getCond(), Cnt));
+
+ // Attach metadata to loop body conditional branch.
+ EmitCondBrHints(ForBody->getContext(), CondBr, ForAttrs);
if (ExitBlock != LoopExit.getBlock()) {
EmitBlock(ExitBlock);
@@ -743,7 +881,9 @@
EmitBlock(LoopExit.getBlock(), true);
}
-void CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S) {
+void
+CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S,
+ const ArrayRef<const Attr *> &ForAttrs) {
JumpDest LoopExit = getJumpDestInCurrentScope("for.end");
RunCleanupsScope ForScope(*this);
@@ -778,8 +918,11 @@
// The body is executed if the expression, contextually converted
// to bool, is true.
llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
- Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock,
- PGO.createLoopWeights(S.getCond(), Cnt));
+ llvm::BranchInst *CondBr = Builder.CreateCondBr(
+ BoolCondVal, ForBody, ExitBlock, PGO.createLoopWeights(S.getCond(), Cnt));
+
+ // Attach metadata to loop body conditional branch.
+ EmitCondBrHints(ForBody->getContext(), CondBr, ForAttrs);
if (ExitBlock != LoopExit.getBlock()) {
EmitBlock(ExitBlock);
@@ -1920,20 +2063,32 @@
return SlotLV;
}
+static void InitVLACaptures(CodeGenFunction &CGF, const CapturedStmt &S) {
+ for (auto &C : S.captures()) {
+ if (C.capturesVariable()) {
+ QualType QTy;
+ auto VD = C.getCapturedVar();
+ if (const ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(VD))
+ QTy = PVD->getOriginalType();
+ else
+ QTy = VD->getType();
+ if (QTy->isVariablyModifiedType()) {
+ CGF.EmitVariablyModifiedType(QTy);
+ }
+ }
+ }
+}
+
/// 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());
+ llvm::Function *F = CGF.GenerateCapturedStmtFunction(S);
delete CGF.CapturedStmtInfo;
// Emit call to the helper function.
@@ -1950,11 +2105,13 @@
/// Creates the outlined function for a CapturedStmt.
llvm::Function *
-CodeGenFunction::GenerateCapturedStmtFunction(const CapturedDecl *CD,
- const RecordDecl *RD,
- SourceLocation Loc) {
+CodeGenFunction::GenerateCapturedStmtFunction(const CapturedStmt &S) {
assert(CapturedStmtInfo &&
"CapturedStmtInfo should be set when generating the captured function");
+ const CapturedDecl *CD = S.getCapturedDecl();
+ const RecordDecl *RD = S.getCapturedRecordDecl();
+ SourceLocation Loc = S.getLocStart();
+ assert(CD->hasBody() && "missing CapturedDecl body");
// Build the argument list.
ASTContext &Ctx = CGM.getContext();
@@ -1977,12 +2134,14 @@
StartFunction(CD, Ctx.VoidTy, F, FuncInfo, Args,
CD->getLocation(),
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));
+ // Initialize variable-length arrays.
+ InitVLACaptures(*this, S);
+
// If 'this' is captured, load it into CXXThisValue.
if (CapturedStmtInfo->isCXXThisExprCaptured()) {
FieldDecl *FD = CapturedStmtInfo->getThisFieldDecl();
diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp
index 17d8dd1..e253efc 100644
--- a/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/lib/CodeGen/CGStmtOpenMP.cpp
@@ -32,19 +32,17 @@
CodeGenFunction CGF(CGM, true);
CGCapturedStmtInfo CGInfo(*CS, CS->getCapturedRegionKind());
CGF.CapturedStmtInfo = &CGInfo;
- OutlinedFn = CGF.GenerateCapturedStmtFunction(
- CS->getCapturedDecl(), CS->getCapturedRecordDecl(), CS->getLocStart());
+ OutlinedFn = CGF.GenerateCapturedStmtFunction(*CS);
}
// Build call __kmpc_fork_call(loc, 1, microtask, captured_struct/*context*/)
llvm::Value *Args[] = {
- CGM.getOpenMPRuntime().EmitOpenMPUpdateLocation(*this, S.getLocStart()),
- Builder.getInt32(1), // Number of arguments after 'microtask' argument
- // (there is only one additional argument - 'context')
- Builder.CreateBitCast(OutlinedFn,
- CGM.getOpenMPRuntime().getKmpc_MicroPointerTy()),
- EmitCastToVoidPtr(CapturedStruct)
- };
+ CGM.getOpenMPRuntime().EmitOpenMPUpdateLocation(*this, S.getLocStart()),
+ Builder.getInt32(1), // Number of arguments after 'microtask' argument
+ // (there is only one additional argument - 'context')
+ Builder.CreateBitCast(OutlinedFn,
+ CGM.getOpenMPRuntime().getKmpc_MicroPointerTy()),
+ EmitCastToVoidPtr(CapturedStruct)};
llvm::Constant *RTLFn = CGM.getOpenMPRuntime().CreateRuntimeFunction(
CGOpenMPRuntime::OMPRTL__kmpc_fork_call);
EmitRuntimeCall(RTLFn, Args);
@@ -76,3 +74,29 @@
EmitStmt(Body);
}
+void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &) {
+ llvm_unreachable("CodeGen for 'omp for' is not supported yet.");
+}
+
+void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &) {
+ llvm_unreachable("CodeGen for 'omp sections' is not supported yet.");
+}
+
+void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &) {
+ llvm_unreachable("CodeGen for 'omp section' is not supported yet.");
+}
+
+void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &) {
+ llvm_unreachable("CodeGen for 'omp single' is not supported yet.");
+}
+
+void
+CodeGenFunction::EmitOMPParallelForDirective(const OMPParallelForDirective &) {
+ llvm_unreachable("CodeGen for 'omp parallel for' is not supported yet.");
+}
+
+void CodeGenFunction::EmitOMPParallelSectionsDirective(
+ const OMPParallelSectionsDirective &) {
+ llvm_unreachable("CodeGen for 'omp parallel sections' is not supported yet.");
+}
+
diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp
index d10db5a..0df2c43 100644
--- a/lib/CodeGen/CGVTables.cpp
+++ b/lib/CodeGen/CGVTables.cpp
@@ -382,12 +382,14 @@
// FIXME: Do something better here; GenerateVarArgsThunk is extremely ugly.
if (!UseAvailableExternallyLinkage) {
CodeGenFunction(CGM).GenerateVarArgsThunk(ThunkFn, FnInfo, GD, Thunk);
- CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable);
+ CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable, GD,
+ !Thunk.Return.isEmpty());
}
} else {
// Normal thunk body generation.
CodeGenFunction(CGM).GenerateThunk(ThunkFn, FnInfo, GD, Thunk);
- CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable);
+ CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable, GD,
+ !Thunk.Return.isEmpty());
}
}
@@ -429,12 +431,10 @@
emitThunk(GD, (*ThunkInfoVector)[I], /*ForVTable=*/false);
}
-llvm::Constant *
-CodeGenVTables::CreateVTableInitializer(const CXXRecordDecl *RD,
- const VTableComponent *Components,
- unsigned NumComponents,
- const VTableLayout::VTableThunkTy *VTableThunks,
- unsigned NumVTableThunks) {
+llvm::Constant *CodeGenVTables::CreateVTableInitializer(
+ const CXXRecordDecl *RD, const VTableComponent *Components,
+ unsigned NumComponents, const VTableLayout::VTableThunkTy *VTableThunks,
+ unsigned NumVTableThunks, llvm::Constant *RTTI) {
SmallVector<llvm::Constant *, 64> Inits;
llvm::Type *Int8PtrTy = CGM.Int8PtrTy;
@@ -442,9 +442,6 @@
llvm::Type *PtrDiffTy =
CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
- QualType ClassType = CGM.getContext().getTagDeclType(RD);
- llvm::Constant *RTTI = CGM.GetAddrOfRTTIDescriptor(ClassType);
-
unsigned NextVTableThunkIndex = 0;
llvm::Constant *PureVirtualFn = nullptr, *DeletedVirtualFn = nullptr;
@@ -592,13 +589,14 @@
// V-tables are always unnamed_addr.
VTable->setUnnamedAddr(true);
+ llvm::Constant *RTTI = CGM.GetAddrOfRTTIDescriptor(
+ CGM.getContext().getTagDeclType(Base.getBase()));
+
// Create and set the initializer.
- llvm::Constant *Init =
- CreateVTableInitializer(Base.getBase(),
- VTLayout->vtable_component_begin(),
- VTLayout->getNumVTableComponents(),
- VTLayout->vtable_thunk_begin(),
- VTLayout->getNumVTableThunks());
+ llvm::Constant *Init = CreateVTableInitializer(
+ Base.getBase(), VTLayout->vtable_component_begin(),
+ VTLayout->getNumVTableComponents(), VTLayout->vtable_thunk_begin(),
+ VTLayout->getNumVTableThunks(), RTTI);
VTable->setInitializer(Init);
return VTable;
@@ -651,18 +649,31 @@
// internal linkage.
if (Context.getLangOpts().AppleKext)
return llvm::Function::InternalLinkage;
-
+
+ llvm::GlobalVariable::LinkageTypes DiscardableODRLinkage =
+ llvm::GlobalValue::LinkOnceODRLinkage;
+ llvm::GlobalVariable::LinkageTypes NonDiscardableODRLinkage =
+ llvm::GlobalValue::WeakODRLinkage;
+ if (RD->hasAttr<DLLExportAttr>()) {
+ // Cannot discard exported vtables.
+ DiscardableODRLinkage = NonDiscardableODRLinkage;
+ } else if (RD->hasAttr<DLLImportAttr>()) {
+ // Imported vtables are available externally.
+ DiscardableODRLinkage = llvm::GlobalVariable::AvailableExternallyLinkage;
+ NonDiscardableODRLinkage = llvm::GlobalVariable::AvailableExternallyLinkage;
+ }
+
switch (RD->getTemplateSpecializationKind()) {
case TSK_Undeclared:
case TSK_ExplicitSpecialization:
case TSK_ImplicitInstantiation:
- return llvm::GlobalVariable::LinkOnceODRLinkage;
+ return DiscardableODRLinkage;
case TSK_ExplicitInstantiationDeclaration:
llvm_unreachable("Should not have been asked to emit this");
case TSK_ExplicitInstantiationDefinition:
- return llvm::GlobalVariable::WeakODRLinkage;
+ return NonDiscardableODRLinkage;
}
llvm_unreachable("Invalid TemplateSpecializationKind!");
diff --git a/lib/CodeGen/CGVTables.h b/lib/CodeGen/CGVTables.h
index e1554be..69cf079 100644
--- a/lib/CodeGen/CGVTables.h
+++ b/lib/CodeGen/CGVTables.h
@@ -61,11 +61,10 @@
/// decl.
/// \param Components - The vtable components; this is really an array of
/// VTableComponents.
- llvm::Constant *CreateVTableInitializer(const CXXRecordDecl *RD,
- const VTableComponent *Components,
- unsigned NumComponents,
- const VTableLayout::VTableThunkTy *VTableThunks,
- unsigned NumVTableThunks);
+ llvm::Constant *CreateVTableInitializer(
+ const CXXRecordDecl *RD, const VTableComponent *Components,
+ unsigned NumComponents, const VTableLayout::VTableThunkTy *VTableThunks,
+ unsigned NumVTableThunks, llvm::Constant *RTTI);
CodeGenVTables(CodeGenModule &CGM);
@@ -99,7 +98,7 @@
VTableAddressPointsMapTy& AddressPoints);
- /// GetAddrOfVTable - Get the address of the VTT for the given record decl.
+ /// GetAddrOfVTT - Get the address of the VTT for the given record decl.
llvm::GlobalVariable *GetAddrOfVTT(const CXXRecordDecl *RD);
/// EmitVTTDefinition - Emit the definition of the given vtable.
diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt
index 4b7d51b..2bf82e8 100644
--- a/lib/CodeGen/CMakeLists.txt
+++ b/lib/CodeGen/CMakeLists.txt
@@ -13,7 +13,6 @@
ScalarOpts
Support
Target
- TransformUtils
)
add_clang_library(clangCodeGen
@@ -45,7 +44,6 @@
CGObjCRuntime.cpp
CGOpenCLRuntime.cpp
CGOpenMPRuntime.cpp
- CGRTTI.cpp
CGRecordLayoutBuilder.cpp
CGStmt.cpp
CGStmtOpenMP.cpp
@@ -60,8 +58,8 @@
CodeGenTypes.cpp
ItaniumCXXABI.cpp
MicrosoftCXXABI.cpp
- MicrosoftRTTI.cpp
ModuleBuilder.cpp
+ SanitizerBlacklist.cpp
TargetInfo.cpp
DEPENDS
diff --git a/lib/CodeGen/CodeGenABITypes.cpp b/lib/CodeGen/CodeGenABITypes.cpp
index fba7184..180cd51 100644
--- a/lib/CodeGen/CodeGenABITypes.cpp
+++ b/lib/CodeGen/CodeGenABITypes.cpp
@@ -61,7 +61,7 @@
const CGFunctionInfo &
CodeGenABITypes::arrangeFreeFunctionCall(CanQualType returnType,
- llvm::ArrayRef<CanQualType> argTypes,
+ ArrayRef<CanQualType> argTypes,
FunctionType::ExtInfo info,
RequiredArgs args) {
return CGM->getTypes().arrangeLLVMFunctionInfo(
diff --git a/lib/CodeGen/CodeGenAction.cpp b/lib/CodeGen/CodeGenAction.cpp
index 2fe9842..0f63759 100644
--- a/lib/CodeGen/CodeGenAction.cpp
+++ b/lib/CodeGen/CodeGenAction.cpp
@@ -235,11 +235,18 @@
/// \return True if the diagnostic has been successfully reported, false
/// otherwise.
bool StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D);
- /// \brief Specialized handler for the optimization diagnostic.
- /// Note that this handler only accepts remarks and it always handles
+ /// \brief Specialized handlers for optimization remarks.
+ /// Note that these handlers only accept remarks and they always handle
/// them.
void
+ EmitOptimizationRemark(const llvm::DiagnosticInfoOptimizationRemarkBase &D,
+ unsigned DiagID);
+ void
OptimizationRemarkHandler(const llvm::DiagnosticInfoOptimizationRemark &D);
+ void OptimizationRemarkHandler(
+ const llvm::DiagnosticInfoOptimizationRemarkMissed &D);
+ void OptimizationRemarkHandler(
+ const llvm::DiagnosticInfoOptimizationRemarkAnalysis &D);
};
void BackendConsumer::anchor() {}
@@ -260,13 +267,15 @@
LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
// Create the copy and transfer ownership to clang::SourceManager.
+ // TODO: Avoid copying files into memory.
llvm::MemoryBuffer *CBuf =
llvm::MemoryBuffer::getMemBufferCopy(LBuf->getBuffer(),
LBuf->getBufferIdentifier());
+ // FIXME: Keep a file ID map instead of creating new IDs for each location.
FileID FID = CSM.createFileID(CBuf);
// Translate the offset into the file.
- unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart();
+ unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart();
SourceLocation NewLoc =
CSM.getLocForStartOfFile(FID).getLocWithOffset(Offset);
return FullSourceLoc(NewLoc, CSM);
@@ -290,13 +299,24 @@
FullSourceLoc Loc;
if (D.getLoc() != SMLoc())
Loc = ConvertBackendLocation(D, Context->getSourceManager());
-
+ unsigned DiagID;
+ switch (D.getKind()) {
+ case llvm::SourceMgr::DK_Error:
+ DiagID = diag::err_fe_inline_asm;
+ break;
+ case llvm::SourceMgr::DK_Warning:
+ DiagID = diag::warn_fe_inline_asm;
+ break;
+ case llvm::SourceMgr::DK_Note:
+ DiagID = diag::note_fe_inline_asm;
+ break;
+ }
// If this problem has clang-level source location information, report the
- // issue as being an error in the source with a note showing the instantiated
+ // issue in the source with a note showing the instantiated
// code.
if (LocCookie.isValid()) {
- Diags.Report(LocCookie, diag::err_fe_inline_asm).AddString(Message);
+ Diags.Report(LocCookie, DiagID).AddString(Message);
if (D.getLoc().isValid()) {
DiagnosticBuilder B = Diags.Report(Loc, diag::note_fe_inline_asm_here);
@@ -312,10 +332,10 @@
return;
}
- // Otherwise, report the backend error as occurring in the generated .s file.
- // If Loc is invalid, we still need to report the error, it just gets no
+ // Otherwise, report the backend issue as occurring in the generated .s file.
+ // If Loc is invalid, we still need to report the issue, it just gets no
// location info.
- Diags.Report(Loc, diag::err_fe_inline_asm).AddString(Message);
+ Diags.Report(Loc, DiagID).AddString(Message);
}
#define ComputeDiagID(Severity, GroupName, DiagID) \
@@ -386,57 +406,83 @@
// We do not know how to format other severities.
return false;
- // FIXME: We should demangle the function name.
- // FIXME: Is there a way to get a location for that function?
- FullSourceLoc Loc;
- Diags.Report(Loc, diag::warn_fe_backend_frame_larger_than)
- << D.getStackSize() << D.getFunction().getName();
- return true;
+ if (const Decl *ND = Gen->GetDeclForMangledName(D.getFunction().getName())) {
+ Diags.Report(ND->getASTContext().getFullLoc(ND->getLocation()),
+ diag::warn_fe_frame_larger_than)
+ << D.getStackSize() << Decl::castToDeclContext(ND);
+ return true;
+ }
+
+ return false;
+}
+
+void BackendConsumer::EmitOptimizationRemark(
+ const llvm::DiagnosticInfoOptimizationRemarkBase &D, unsigned DiagID) {
+ // We only support remarks.
+ assert(D.getSeverity() == llvm::DS_Remark);
+
+ SourceManager &SourceMgr = Context->getSourceManager();
+ FileManager &FileMgr = SourceMgr.getFileManager();
+ StringRef Filename;
+ unsigned Line, Column;
+ D.getLocation(&Filename, &Line, &Column);
+ SourceLocation DILoc;
+ const FileEntry *FE = FileMgr.getFile(Filename);
+ if (FE && Line > 0) {
+ // If -gcolumn-info was not used, Column will be 0. This upsets the
+ // source manager, so pass 1 if Column is not set.
+ DILoc = SourceMgr.translateFileLineCol(FE, Line, Column ? Column : 1);
+ }
+
+ // If a location isn't available, try to approximate it using the associated
+ // function definition. We use the definition's right brace to differentiate
+ // from diagnostics that genuinely relate to the function itself.
+ FullSourceLoc Loc(DILoc, SourceMgr);
+ if (Loc.isInvalid())
+ if (const Decl *FD = Gen->GetDeclForMangledName(D.getFunction().getName()))
+ Loc = FD->getASTContext().getFullLoc(FD->getBodyRBrace());
+
+ Diags.Report(Loc, DiagID) << AddFlagValue(D.getPassName())
+ << D.getMsg().str();
+
+ if (DILoc.isInvalid())
+ // If we were not able to translate the file:line:col information
+ // back to a SourceLocation, at least emit a note stating that
+ // we could not translate this location. This can happen in the
+ // case of #line directives.
+ Diags.Report(Loc, diag::note_fe_backend_optimization_remark_invalid_loc)
+ << Filename << Line << Column;
}
void BackendConsumer::OptimizationRemarkHandler(
const llvm::DiagnosticInfoOptimizationRemark &D) {
- // We only support remarks.
- assert(D.getSeverity() == llvm::DS_Remark);
-
- // Optimization remarks are active only if -Rpass=regexp is given and the
- // regular expression pattern in 'regexp' matches the name of the pass
- // name in \p D.
+ // Optimization remarks are active only if the -Rpass flag has a regular
+ // expression that matches the name of the pass name in \p D.
if (CodeGenOpts.OptimizationRemarkPattern &&
- CodeGenOpts.OptimizationRemarkPattern->match(D.getPassName())) {
- SourceManager &SourceMgr = Context->getSourceManager();
- FileManager &FileMgr = SourceMgr.getFileManager();
- StringRef Filename;
- unsigned Line, Column;
- D.getLocation(&Filename, &Line, &Column);
- SourceLocation Loc;
- const FileEntry *FE = FileMgr.getFile(Filename);
- if (FE && Line > 0) {
- // If -gcolumn-info was not used, Column will be 0. This upsets the
- // source manager, so if Column is not set, set it to 1.
- if (Column == 0)
- Column = 1;
- Loc = SourceMgr.translateFileLineCol(FE, Line, Column);
- }
- Diags.Report(Loc, diag::remark_fe_backend_optimization_remark)
- << AddFlagValue(D.getPassName()) << D.getMsg().str();
+ CodeGenOpts.OptimizationRemarkPattern->match(D.getPassName()))
+ EmitOptimizationRemark(D, diag::remark_fe_backend_optimization_remark);
+}
- if (Line == 0)
- // If we could not extract a source location for the diagnostic,
- // inform the user how they can get source locations back.
- //
- // FIXME: We should really be generating !srcloc annotations when
- // -Rpass is used. !srcloc annotations need to be emitted in
- // approximately the same spots as !dbg nodes.
- Diags.Report(diag::note_fe_backend_optimization_remark_missing_loc);
- else if (Loc.isInvalid())
- // If we were not able to translate the file:line:col information
- // back to a SourceLocation, at least emit a note stating that
- // we could not translate this location. This can happen in the
- // case of #line directives.
- Diags.Report(diag::note_fe_backend_optimization_remark_invalid_loc)
- << Filename << Line << Column;
- }
+void BackendConsumer::OptimizationRemarkHandler(
+ const llvm::DiagnosticInfoOptimizationRemarkMissed &D) {
+ // Missed optimization remarks are active only if the -Rpass-missed
+ // flag has a regular expression that matches the name of the pass
+ // name in \p D.
+ if (CodeGenOpts.OptimizationRemarkMissedPattern &&
+ CodeGenOpts.OptimizationRemarkMissedPattern->match(D.getPassName()))
+ EmitOptimizationRemark(D,
+ diag::remark_fe_backend_optimization_remark_missed);
+}
+
+void BackendConsumer::OptimizationRemarkHandler(
+ const llvm::DiagnosticInfoOptimizationRemarkAnalysis &D) {
+ // Optimization analysis remarks are active only if the -Rpass-analysis
+ // flag has a regular expression that matches the name of the pass
+ // name in \p D.
+ if (CodeGenOpts.OptimizationRemarkAnalysisPattern &&
+ CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName()))
+ EmitOptimizationRemark(
+ D, diag::remark_fe_backend_optimization_remark_analysis);
}
/// \brief This function is invoked when the backend needs
@@ -461,6 +507,17 @@
// handler. There is no generic way of emitting them.
OptimizationRemarkHandler(cast<DiagnosticInfoOptimizationRemark>(DI));
return;
+ case llvm::DK_OptimizationRemarkMissed:
+ // Optimization remarks are always handled completely by this
+ // handler. There is no generic way of emitting them.
+ OptimizationRemarkHandler(cast<DiagnosticInfoOptimizationRemarkMissed>(DI));
+ return;
+ case llvm::DK_OptimizationRemarkAnalysis:
+ // Optimization remarks are always handled completely by this
+ // handler. There is no generic way of emitting them.
+ OptimizationRemarkHandler(
+ cast<DiagnosticInfoOptimizationRemarkAnalysis>(DI));
+ return;
default:
// Plugin IDs are not bound to any value as they are set dynamically.
ComputeDiagRemarkID(Severity, backend_plugin, DiagID);
@@ -525,6 +582,7 @@
case Backend_EmitNothing:
return nullptr;
case Backend_EmitMCNull:
+ return CI.createNullOutputFile();
case Backend_EmitObj:
return CI.createDefaultOutputFile(true, InFile, "o");
}
@@ -557,7 +615,7 @@
ErrorOr<llvm::Module *> ModuleOrErr =
getLazyBitcodeModule(BCBuf, *VMContext);
- if (error_code EC = ModuleOrErr.getError()) {
+ if (std::error_code EC = ModuleOrErr.getError()) {
CI.getDiagnostics().Report(diag::err_cannot_open_file)
<< LinkBCFile << EC.message();
return nullptr;
@@ -565,12 +623,9 @@
LinkModuleToUse = ModuleOrErr.get();
}
- StringRef MainFileName = getCompilerInstance().getCodeGenOpts().MainFileName;
- if (MainFileName.empty())
- MainFileName = InFile;
BEConsumer = new BackendConsumer(BA, CI.getDiagnostics(), CI.getCodeGenOpts(),
CI.getTargetOpts(), CI.getLangOpts(),
- CI.getFrontendOpts().ShowTimers, MainFileName,
+ CI.getFrontendOpts().ShowTimers, InFile,
LinkModuleToUse, OS.release(), *VMContext);
return BEConsumer;
}
@@ -586,23 +641,23 @@
bool Invalid;
SourceManager &SM = CI.getSourceManager();
- const llvm::MemoryBuffer *MainFile = SM.getBuffer(SM.getMainFileID(),
- &Invalid);
+ FileID FID = SM.getMainFileID();
+ llvm::MemoryBuffer *MainFile = SM.getBuffer(FID, &Invalid);
if (Invalid)
return;
- // FIXME: This is stupid, IRReader shouldn't take ownership.
- llvm::MemoryBuffer *MainFileCopy =
- llvm::MemoryBuffer::getMemBufferCopy(MainFile->getBuffer(),
- getCurrentFile());
-
llvm::SMDiagnostic Err;
- TheModule.reset(ParseIR(MainFileCopy, Err, *VMContext));
+ TheModule.reset(ParseIR(MainFile, Err, *VMContext));
if (!TheModule) {
- // Translate from the diagnostic info to the SourceManager location.
- SourceLocation Loc = SM.translateFileLineCol(
- SM.getFileEntryForID(SM.getMainFileID()), Err.getLineNo(),
- Err.getColumnNo() + 1);
+ // Translate from the diagnostic info to the SourceManager location if
+ // available.
+ // TODO: Unify this with ConvertBackendLocation()
+ SourceLocation Loc;
+ if (Err.getLineNo() > 0) {
+ assert(Err.getColumnNo() >= 0);
+ Loc = SM.translateFileLineCol(SM.getFileEntryForID(FID),
+ Err.getLineNo(), Err.getColumnNo() + 1);
+ }
// Strip off a leading diagnostic code if there is one.
StringRef Msg = Err.getMessage();
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 7de619e..0987673 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -37,11 +37,7 @@
: CodeGenTypeCache(cgm), CGM(cgm), Target(cgm.getTarget()),
Builder(cgm.getModule().getContext(), llvm::ConstantFolder(),
CGBuilderInserterTy(this)), CapturedStmtInfo(nullptr),
- SanitizePerformTypeCheck(CGM.getSanOpts().Null |
- CGM.getSanOpts().Alignment |
- CGM.getSanOpts().ObjectSize |
- CGM.getSanOpts().Vptr),
- SanOpts(&CGM.getSanOpts()), AutoreleaseResult(false), BlockInfo(nullptr),
+ SanOpts(&CGM.getLangOpts().Sanitize), AutoreleaseResult(false), BlockInfo(nullptr),
BlockPointer(nullptr), LambdaThisCaptureField(nullptr),
NormalCleanupDest(nullptr), NextCleanupDestIndex(1),
FirstBlockInfo(nullptr), EHResumeBlock(nullptr), ExceptionSlot(nullptr),
@@ -539,10 +535,8 @@
CurFnInfo = &FnInfo;
assert(CurFn->isDeclaration() && "Function already has body?");
- if (CGM.getSanitizerBlacklist().isIn(*Fn)) {
+ if (CGM.getSanitizerBlacklist().isIn(*Fn))
SanOpts = &SanitizerOptions::Disabled;
- SanitizePerformTypeCheck = false;
- }
// Pass inline keyword to optimizer if it appears explicitly on any
// declaration. Also, in the case of -fno-inline attach NoInline
@@ -794,16 +788,13 @@
// of the declaration as the location for the subprogram. A function
// may lack a declaration in the source code if it is created by code
// gen. (examples: _GLOBAL__I_a, __cxx_global_array_dtor, thunk).
- SourceLocation Loc;
- if (FD) {
- Loc = FD->getLocation();
+ SourceLocation Loc = FD->getLocation();
- // If this is a function specialization then use the pattern body
- // as the location for the function.
- if (const FunctionDecl *SpecDecl = FD->getTemplateInstantiationPattern())
- if (SpecDecl->hasBody(SpecDecl))
- Loc = SpecDecl->getLocation();
- }
+ // If this is a function specialization then use the pattern body
+ // as the location for the function.
+ if (const FunctionDecl *SpecDecl = FD->getTemplateInstantiationPattern())
+ if (SpecDecl->hasBody(SpecDecl))
+ Loc = SpecDecl->getLocation();
// Emit the standard function prologue.
StartFunction(GD, ResTy, Fn, FnInfo, Args, Loc, BodyRange.getBegin());
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 750bec8..c04fc3e 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -231,10 +231,6 @@
/// potentially higher performance penalties.
unsigned char BoundsChecking;
- /// \brief Whether any type-checking sanitizers are enabled. If \c false,
- /// calls to EmitTypeCheck can be skipped.
- bool SanitizePerformTypeCheck;
-
/// \brief Sanitizer options to use for this function.
const SanitizerOptions *SanOpts;
@@ -1647,7 +1643,8 @@
llvm::Value *This);
void EmitNewArrayInitializer(const CXXNewExpr *E, QualType elementType,
- llvm::Value *NewPtr, llvm::Value *NumElements);
+ llvm::Value *NewPtr, llvm::Value *NumElements,
+ llvm::Value *AllocSizeWithoutCookie);
void EmitCXXTemporary(const CXXTemporary *Temporary, QualType TempType,
llvm::Value *Ptr);
@@ -1658,6 +1655,9 @@
void EmitDeleteCall(const FunctionDecl *DeleteFD, llvm::Value *Ptr,
QualType DeleteTy);
+ RValue EmitBuiltinNewDeleteCall(const FunctionProtoType *Type,
+ const Expr *Arg, bool IsDelete);
+
llvm::Value* EmitCXXTypeidExpr(const CXXTypeidExpr *E);
llvm::Value *EmitDynamicCast(llvm::Value *V, const CXXDynamicCastExpr *DCE);
llvm::Value* EmitCXXUuidofExpr(const CXXUuidofExpr *E);
@@ -1689,6 +1689,10 @@
TCK_DowncastReference
};
+ /// \brief Whether any type-checking sanitizers are enabled. If \c false,
+ /// calls to EmitTypeCheck can be skipped.
+ bool sanitizePerformTypeCheck() const;
+
/// \brief Emit a check that \p V is the address of storage of the
/// appropriate size and alignment for an object of type \p Type.
void EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, llvm::Value *V,
@@ -1856,9 +1860,14 @@
void EmitGotoStmt(const GotoStmt &S);
void EmitIndirectGotoStmt(const IndirectGotoStmt &S);
void EmitIfStmt(const IfStmt &S);
- void EmitWhileStmt(const WhileStmt &S);
- void EmitDoStmt(const DoStmt &S);
- void EmitForStmt(const ForStmt &S);
+
+ void EmitCondBrHints(llvm::LLVMContext &Context, llvm::BranchInst *CondBr,
+ const ArrayRef<const Attr *> &Attrs);
+ void EmitWhileStmt(const WhileStmt &S,
+ const ArrayRef<const Attr *> &Attrs = None);
+ void EmitDoStmt(const DoStmt &S, const ArrayRef<const Attr *> &Attrs = None);
+ void EmitForStmt(const ForStmt &S,
+ const ArrayRef<const Attr *> &Attrs = None);
void EmitReturnStmt(const ReturnStmt &S);
void EmitDeclStmt(const DeclStmt &S);
void EmitBreakStmt(const BreakStmt &S);
@@ -1875,23 +1884,27 @@
void EmitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt &S);
void EmitObjCAutoreleasePoolStmt(const ObjCAutoreleasePoolStmt &S);
- llvm::Constant *getUnwindResumeFn();
- llvm::Constant *getUnwindResumeOrRethrowFn();
void EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock = false);
void ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock = false);
void EmitCXXTryStmt(const CXXTryStmt &S);
void EmitSEHTryStmt(const SEHTryStmt &S);
- void EmitCXXForRangeStmt(const CXXForRangeStmt &S);
+ void EmitSEHLeaveStmt(const SEHLeaveStmt &S);
+ void EmitCXXForRangeStmt(const CXXForRangeStmt &S,
+ const ArrayRef<const Attr *> &Attrs = None);
llvm::Function *EmitCapturedStmt(const CapturedStmt &S, CapturedRegionKind K);
- llvm::Function *GenerateCapturedStmtFunction(const CapturedDecl *CD,
- const RecordDecl *RD,
- SourceLocation Loc);
+ llvm::Function *GenerateCapturedStmtFunction(const CapturedStmt &S);
llvm::Value *GenerateCapturedStmtArgument(const CapturedStmt &S);
void EmitOMPParallelDirective(const OMPParallelDirective &S);
void EmitOMPSimdDirective(const OMPSimdDirective &S);
+ void EmitOMPForDirective(const OMPForDirective &S);
+ void EmitOMPSectionsDirective(const OMPSectionsDirective &S);
+ void EmitOMPSectionDirective(const OMPSectionDirective &S);
+ void EmitOMPSingleDirective(const OMPSingleDirective &S);
+ void EmitOMPParallelForDirective(const OMPParallelForDirective &S);
+ void EmitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &S);
//===--------------------------------------------------------------------===//
// LValue Expression Emission
@@ -2223,9 +2236,6 @@
bool negateForRightShift);
llvm::Value *EmitNeonRShiftImm(llvm::Value *Vec, llvm::Value *Amt,
llvm::Type *Ty, bool usgn, const char *name);
- llvm::Value *EmitConcatVectors(llvm::Value *Lo, llvm::Value *Hi,
- llvm::Type *ArgTy);
- llvm::Value *EmitExtractHigh(llvm::Value *In, llvm::Type *ResTy);
// Helper functions for EmitAArch64BuiltinExpr.
llvm::Value *vectorWrapScalar8(llvm::Value *Op);
llvm::Value *vectorWrapScalar16(llvm::Value *Op);
@@ -2241,6 +2251,7 @@
llvm::Value *BuildVector(ArrayRef<llvm::Value*> Ops);
llvm::Value *EmitX86BuiltinExpr(unsigned BuiltinID, const CallExpr *E);
llvm::Value *EmitPPCBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
+ llvm::Value *EmitR600BuiltinExpr(unsigned BuiltinID, const CallExpr *E);
llvm::Value *EmitObjCProtocolExpr(const ObjCProtocolExpr *E);
llvm::Value *EmitObjCStringLiteral(const ObjCStringLiteral *E);
@@ -2300,7 +2311,7 @@
llvm::Value *EmitARCRetainScalarExpr(const Expr *expr);
llvm::Value *EmitARCRetainAutoreleaseScalarExpr(const Expr *expr);
- void EmitARCIntrinsicUse(llvm::ArrayRef<llvm::Value*> values);
+ void EmitARCIntrinsicUse(ArrayRef<llvm::Value*> values);
static Destroyer destroyARCStrongImprecise;
static Destroyer destroyARCStrongPrecise;
@@ -2640,7 +2651,8 @@
void EmitCallArgs(CallArgList &Args, ArrayRef<QualType> ArgTypes,
CallExpr::const_arg_iterator ArgBeg,
- CallExpr::const_arg_iterator ArgEnd, bool ForceColumnInfo);
+ CallExpr::const_arg_iterator ArgEnd,
+ bool ForceColumnInfo = false);
private:
const TargetCodeGenInfo &getTargetHooks() const {
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index c55e231..d0563b2 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -87,11 +87,8 @@
NSConcreteStackBlock(nullptr), BlockObjectAssign(nullptr),
BlockObjectDispose(nullptr), BlockDescriptorType(nullptr),
GenericBlockLiteralType(nullptr), LifetimeStartFn(nullptr),
- LifetimeEndFn(nullptr),
- SanitizerBlacklist(
- llvm::SpecialCaseList::createOrDie(CGO.SanitizerBlacklistFile)),
- SanOpts(SanitizerBlacklist->isIn(M) ? SanitizerOptions::Disabled
- : LangOpts.Sanitize) {
+ LifetimeEndFn(nullptr), SanitizerBL(llvm::SpecialCaseList::createOrDie(
+ CGO.SanitizerBlacklistFile)) {
// Initialize the type cache.
llvm::LLVMContext &LLVMContext = M.getContext();
@@ -122,7 +119,7 @@
createCUDARuntime();
// Enable TBAA unless it's suppressed. ThreadSanitizer needs TBAA even at O0.
- if (SanOpts.Thread ||
+ if (LangOpts.Sanitize.Thread ||
(!CodeGenOpts.RelaxedAliasing && CodeGenOpts.OptimizationLevel > 0))
TBAA = new CodeGenTBAA(Context, VMContext, CodeGenOpts, getLangOpts(),
getCXXABI().getMangleContext());
@@ -141,7 +138,7 @@
RRData = new RREntrypoints();
if (!CodeGenOpts.InstrProfileInput.empty()) {
- if (llvm::error_code EC = llvm::IndexedInstrProfReader::create(
+ if (std::error_code EC = llvm::IndexedInstrProfReader::create(
CodeGenOpts.InstrProfileInput, PGOReader)) {
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"Could not read profile: %0");
@@ -225,6 +222,25 @@
}
}
+// This is only used in aliases that we created and we know they have a
+// linear structure.
+static const llvm::GlobalObject *getAliasedGlobal(const llvm::GlobalAlias &GA) {
+ llvm::SmallPtrSet<const llvm::GlobalAlias*, 4> Visited;
+ const llvm::Constant *C = &GA;
+ for (;;) {
+ C = C->stripPointerCasts();
+ if (auto *GO = dyn_cast<llvm::GlobalObject>(C))
+ return GO;
+ // stripPointerCasts will not walk over weak aliases.
+ auto *GA2 = dyn_cast<llvm::GlobalAlias>(C);
+ if (!GA2)
+ return nullptr;
+ if (!Visited.insert(GA2))
+ return nullptr;
+ C = GA2->getAliasee();
+ }
+}
+
void CodeGenModule::checkAliases() {
// Check if the constructed aliases are well formed. It is really unfortunate
// that we have to do this in CodeGen, but we only construct mangled names
@@ -239,19 +255,43 @@
StringRef MangledName = getMangledName(GD);
llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
auto *Alias = cast<llvm::GlobalAlias>(Entry);
- llvm::GlobalValue *GV = Alias->getAliasee();
- if (GV->isDeclaration()) {
+ const llvm::GlobalValue *GV = getAliasedGlobal(*Alias);
+ if (!GV) {
+ Error = true;
+ Diags.Report(AA->getLocation(), diag::err_cyclic_alias);
+ } else if (GV->isDeclaration()) {
Error = true;
Diags.Report(AA->getLocation(), diag::err_alias_to_undefined);
}
- llvm::GlobalObject *Aliasee = Alias->getAliasee();
+ llvm::Constant *Aliasee = Alias->getAliasee();
+ llvm::GlobalValue *AliaseeGV;
+ if (auto CE = dyn_cast<llvm::ConstantExpr>(Aliasee))
+ AliaseeGV = cast<llvm::GlobalValue>(CE->getOperand(0));
+ else
+ AliaseeGV = cast<llvm::GlobalValue>(Aliasee);
+
if (const SectionAttr *SA = D->getAttr<SectionAttr>()) {
StringRef AliasSection = SA->getName();
- if (AliasSection != Aliasee->getSection())
+ if (AliasSection != AliaseeGV->getSection())
Diags.Report(SA->getLocation(), diag::warn_alias_with_section)
<< AliasSection;
}
+
+ // We have to handle alias to weak aliases in here. LLVM itself disallows
+ // this since the object semantics would not match the IL one. For
+ // compatibility with gcc we implement it by just pointing the alias
+ // to its aliasee's aliasee. We also warn, since the user is probably
+ // expecting the link to be weak.
+ if (auto GA = dyn_cast<llvm::GlobalAlias>(AliaseeGV)) {
+ if (GA->mayBeOverridden()) {
+ Diags.Report(AA->getLocation(), diag::warn_alias_to_weak_alias)
+ << GV->getName() << GA->getName();
+ Aliasee = llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(
+ GA->getAliasee(), Alias->getType());
+ Alias->setAliasee(Aliasee);
+ }
+ }
}
if (!Error)
return;
@@ -271,6 +311,19 @@
DeferredDeclsToEmit.clear();
}
+void InstrProfStats::reportDiagnostics(DiagnosticsEngine &Diags,
+ StringRef MainFile) {
+ if (!hasDiagnostics())
+ return;
+ if (VisitedInMainFile > 0 && VisitedInMainFile == MissingInMainFile) {
+ if (MainFile.empty())
+ MainFile = "<stdin>";
+ Diags.Report(diag::warn_profile_data_unprofiled) << MainFile;
+ } else
+ Diags.Report(diag::warn_profile_data_out_of_date) << Visited << Missing
+ << Mismatched;
+}
+
void CodeGenModule::Release() {
EmitDeferred();
applyReplacements();
@@ -284,9 +337,8 @@
if (getCodeGenOpts().ProfileInstrGenerate)
if (llvm::Function *PGOInit = CodeGenPGO::emitInitialization(*this))
AddGlobalCtor(PGOInit, 0);
- if (PGOReader && PGOStats.isOutOfDate())
- getDiags().Report(diag::warn_profile_data_out_of_date)
- << PGOStats.Visited << PGOStats.Missing << PGOStats.Mismatched;
+ if (PGOReader && PGOStats.hasDiagnostics())
+ PGOStats.reportDiagnostics(getDiags(), getCodeGenOpts().MainFileName);
EmitCtorList(GlobalCtors, "llvm.global_ctors");
EmitCtorList(GlobalDtors, "llvm.global_dtors");
EmitGlobalAnnotations();
@@ -309,6 +361,23 @@
getModule().addModuleFlag(llvm::Module::Warning, "Debug Info Version",
llvm::DEBUG_METADATA_VERSION);
+ // We need to record the widths of enums and wchar_t, so that we can generate
+ // the correct build attributes in the ARM backend.
+ llvm::Triple::ArchType Arch = Context.getTargetInfo().getTriple().getArch();
+ if ( Arch == llvm::Triple::arm
+ || Arch == llvm::Triple::armeb
+ || Arch == llvm::Triple::thumb
+ || Arch == llvm::Triple::thumbeb) {
+ // Width of wchar_t in bytes
+ uint64_t WCharWidth =
+ Context.getTypeSizeInChars(Context.getWideCharType()).getQuantity();
+ getModule().addModuleFlag(llvm::Module::Error, "wchar_size", WCharWidth);
+
+ // The minimum width of an enum in bytes
+ uint64_t EnumWidth = Context.getLangOpts().ShortEnums ? 1 : 4;
+ getModule().addModuleFlag(llvm::Module::Error, "min_enum_size", EnumWidth);
+ }
+
SimplifyPersonality();
if (getCodeGenOpts().EmitDeclMetadata)
@@ -321,6 +390,8 @@
DebugInfo->finalize();
EmitVersionIdentMetadata();
+
+ EmitTargetMetadata();
}
void CodeGenModule::UpdateCompletedType(const TagDecl *TD) {
@@ -455,45 +526,40 @@
}
StringRef CodeGenModule::getMangledName(GlobalDecl GD) {
+ StringRef &FoundStr = MangledDeclNames[GD.getCanonicalDecl()];
+ if (!FoundStr.empty())
+ return FoundStr;
+
const auto *ND = cast<NamedDecl>(GD.getDecl());
-
- StringRef &Str = MangledDeclNames[GD.getCanonicalDecl()];
- if (!Str.empty())
- return Str;
-
- if (!getCXXABI().getMangleContext().shouldMangleDeclName(ND)) {
+ SmallString<256> Buffer;
+ StringRef Str;
+ if (getCXXABI().getMangleContext().shouldMangleDeclName(ND)) {
+ llvm::raw_svector_ostream Out(Buffer);
+ if (const auto *D = dyn_cast<CXXConstructorDecl>(ND))
+ getCXXABI().getMangleContext().mangleCXXCtor(D, GD.getCtorType(), Out);
+ else if (const auto *D = dyn_cast<CXXDestructorDecl>(ND))
+ getCXXABI().getMangleContext().mangleCXXDtor(D, GD.getDtorType(), Out);
+ else
+ getCXXABI().getMangleContext().mangleName(ND, Out);
+ Str = Out.str();
+ } else {
IdentifierInfo *II = ND->getIdentifier();
assert(II && "Attempt to mangle unnamed decl.");
-
Str = II->getName();
- return Str;
}
-
- SmallString<256> Buffer;
- llvm::raw_svector_ostream Out(Buffer);
- if (const auto *D = dyn_cast<CXXConstructorDecl>(ND))
- getCXXABI().getMangleContext().mangleCXXCtor(D, GD.getCtorType(), Out);
- else if (const auto *D = dyn_cast<CXXDestructorDecl>(ND))
- getCXXABI().getMangleContext().mangleCXXDtor(D, GD.getDtorType(), Out);
- else
- getCXXABI().getMangleContext().mangleName(ND, Out);
- // Allocate space for the mangled name.
- Out.flush();
- size_t Length = Buffer.size();
- char *Name = MangledNamesAllocator.Allocate<char>(Length);
- std::copy(Buffer.begin(), Buffer.end(), Name);
-
- Str = StringRef(Name, Length);
-
- return Str;
+ auto &Mangled = Manglings.GetOrCreateValue(Str);
+ Mangled.second = GD;
+ return FoundStr = Mangled.first();
}
-void CodeGenModule::getBlockMangledName(GlobalDecl GD, MangleBuffer &Buffer,
- const BlockDecl *BD) {
+StringRef CodeGenModule::getBlockMangledName(GlobalDecl GD,
+ const BlockDecl *BD) {
MangleContext &MangleCtx = getCXXABI().getMangleContext();
const Decl *D = GD.getDecl();
- llvm::raw_svector_ostream Out(Buffer.getBuffer());
+
+ SmallString<256> Buffer;
+ llvm::raw_svector_ostream Out(Buffer);
if (!D)
MangleCtx.mangleGlobalBlock(BD,
dyn_cast_or_null<VarDecl>(initializedGlobalDecl.getDecl()), Out);
@@ -503,6 +569,10 @@
MangleCtx.mangleDtorBlock(DD, GD.getDtorType(), BD, Out);
else
MangleCtx.mangleBlock(cast<DeclContext>(D), BD, Out);
+
+ auto &Mangled = Manglings.GetOrCreateValue(Out.str());
+ Mangled.second = BD;
+ return Mangled.first();
}
llvm::GlobalValue *CodeGenModule::GetGlobalValue(StringRef Name) {
@@ -521,7 +591,7 @@
/// when the module is unloaded.
void CodeGenModule::AddGlobalDtor(llvm::Function *Dtor, int Priority) {
// FIXME: Type coercion of void()* types.
- GlobalDtors.push_back(Structor(Priority, Dtor, 0));
+ GlobalDtors.push_back(Structor(Priority, Dtor, nullptr));
}
void CodeGenModule::EmitCtorList(const CtorList &Fns, const char *GlobalName) {
@@ -659,17 +729,16 @@
B.addAttribute(llvm::Attribute::StackProtectReq);
// Add sanitizer attributes if function is not blacklisted.
- if (!SanitizerBlacklist->isIn(*F)) {
+ if (!SanitizerBL.isIn(*F)) {
// When AddressSanitizer is enabled, set SanitizeAddress attribute
// unless __attribute__((no_sanitize_address)) is used.
- if (SanOpts.Address && !D->hasAttr<NoSanitizeAddressAttr>())
+ if (LangOpts.Sanitize.Address && !D->hasAttr<NoSanitizeAddressAttr>())
B.addAttribute(llvm::Attribute::SanitizeAddress);
// Same for ThreadSanitizer and __attribute__((no_sanitize_thread))
- if (SanOpts.Thread && !D->hasAttr<NoSanitizeThreadAttr>()) {
+ if (LangOpts.Sanitize.Thread && !D->hasAttr<NoSanitizeThreadAttr>())
B.addAttribute(llvm::Attribute::SanitizeThread);
- }
// Same for MemorySanitizer and __attribute__((no_sanitize_memory))
- if (SanOpts.Memory && !D->hasAttr<NoSanitizeMemoryAttr>())
+ if (LangOpts.Sanitize.Memory && !D->hasAttr<NoSanitizeMemoryAttr>())
B.addAttribute(llvm::Attribute::SanitizeMemory);
}
@@ -1415,7 +1484,7 @@
// This is the first use or definition of a mangled name. If there is a
// deferred decl with this name, remember that we need to emit it at the end
// of the file.
- llvm::StringMap<GlobalDecl>::iterator DDI = DeferredDecls.find(MangledName);
+ auto DDI = DeferredDecls.find(MangledName);
if (DDI != DeferredDecls.end()) {
// Move the potentially referenced deferred decl to the
// DeferredDeclsToEmit list, and remove it from DeferredDecls (since we
@@ -1463,8 +1532,6 @@
}
}
- getTargetCodeGenInfo().emitTargetMD(D, F, *this);
-
// Make sure the result is of the requested type.
if (!IsIncompleteFunction) {
assert(F->getType()->getElementType() == Ty);
@@ -1575,7 +1642,7 @@
// This is the first use or definition of a mangled name. If there is a
// deferred decl with this name, remember that we need to emit it at the end
// of the file.
- llvm::StringMap<GlobalDecl>::iterator DDI = DeferredDecls.find(MangledName);
+ auto DDI = DeferredDecls.find(MangledName);
if (DDI != DeferredDecls.end()) {
// Move the potentially referenced deferred decl to the DeferredDeclsToEmit
// list, and remove it from DeferredDecls (since we don't need it anymore).
@@ -1614,8 +1681,6 @@
if (AddrSpace != Ty->getAddressSpace())
return llvm::ConstantExpr::getAddrSpaceCast(GV, Ty);
- getTargetCodeGenInfo().emitTargetMD(D, GV, *this);
-
return GV;
}
@@ -1861,6 +1926,16 @@
// Set the llvm linkage type as appropriate.
llvm::GlobalValue::LinkageTypes Linkage =
getLLVMLinkageVarDefinition(D, GV->isConstant());
+
+ // On Darwin, the backing variable for a C++11 thread_local variable always
+ // has internal linkage; all accesses should just be calls to the
+ // Itanium-specified entry point, which has the normal linkage of the
+ // variable.
+ if (const auto *VD = dyn_cast<VarDecl>(D))
+ if (!VD->isStaticLocal() && VD->getTLSKind() == VarDecl::TLS_Dynamic &&
+ Context.getTargetInfo().getTriple().isMacOSX())
+ Linkage = llvm::GlobalValue::InternalLinkage;
+
GV->setLinkage(Linkage);
if (D->hasAttr<DLLImportAttr>())
GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass);
@@ -1877,17 +1952,7 @@
if (NeedsGlobalCtor || NeedsGlobalDtor)
EmitCXXGlobalVarDeclInitFunc(D, GV, NeedsGlobalCtor);
- // If we are compiling with ASan, add metadata indicating dynamically
- // initialized globals.
- if (SanOpts.Address && NeedsGlobalCtor) {
- llvm::Module &M = getModule();
-
- llvm::NamedMDNode *DynamicInitializers =
- M.getOrInsertNamedMetadata("llvm.asan.dynamically_initialized_globals");
- llvm::Value *GlobalToAdd[] = { GV };
- llvm::MDNode *ThisGlobal = llvm::MDNode::get(VMContext, GlobalToAdd);
- DynamicInitializers->addOperand(ThisGlobal);
- }
+ reportGlobalToASan(GV, D->getLocation(), NeedsGlobalCtor);
// Emit global variable debug information.
if (CGDebugInfo *DI = getModuleDebugInfo())
@@ -1895,6 +1960,51 @@
DI->EmitGlobalVariable(GV, D);
}
+void CodeGenModule::reportGlobalToASan(llvm::GlobalVariable *GV,
+ SourceLocation Loc, bool IsDynInit) {
+ if (!LangOpts.Sanitize.Address)
+ return;
+ IsDynInit &= !SanitizerBL.isIn(*GV, "init");
+ bool IsBlacklisted = SanitizerBL.isIn(*GV);
+
+ llvm::LLVMContext &LLVMCtx = TheModule.getContext();
+
+ llvm::GlobalVariable *LocDescr = nullptr;
+ if (!IsBlacklisted) {
+ // Don't generate source location if a global is blacklisted - it won't
+ // be instrumented anyway.
+ PresumedLoc PLoc = Context.getSourceManager().getPresumedLoc(Loc);
+ if (PLoc.isValid()) {
+ llvm::Constant *LocData[] = {
+ GetAddrOfConstantCString(PLoc.getFilename()),
+ llvm::ConstantInt::get(llvm::Type::getInt32Ty(LLVMCtx), PLoc.getLine()),
+ llvm::ConstantInt::get(llvm::Type::getInt32Ty(LLVMCtx),
+ PLoc.getColumn()),
+ };
+ auto LocStruct = llvm::ConstantStruct::getAnon(LocData);
+ LocDescr = new llvm::GlobalVariable(TheModule, LocStruct->getType(), true,
+ llvm::GlobalValue::PrivateLinkage,
+ LocStruct, ".asan_loc_descr");
+ LocDescr->setUnnamedAddr(true);
+ // Add LocDescr to llvm.compiler.used, so that it won't be removed by
+ // the optimizer before the ASan instrumentation pass.
+ addCompilerUsedGlobal(LocDescr);
+ }
+ }
+
+ llvm::Value *GlobalMetadata[] = {
+ GV,
+ LocDescr,
+ llvm::ConstantInt::get(llvm::Type::getInt1Ty(LLVMCtx), IsDynInit),
+ llvm::ConstantInt::get(llvm::Type::getInt1Ty(LLVMCtx), IsBlacklisted)
+ };
+
+ llvm::MDNode *ThisGlobal = llvm::MDNode::get(VMContext, GlobalMetadata);
+ llvm::NamedMDNode *AsanGlobals =
+ TheModule.getOrInsertNamedMetadata("llvm.asan.globals");
+ AsanGlobals->addOperand(ThisGlobal);
+}
+
static bool isVarDeclStrongDefinition(const VarDecl *D, bool NoCommon) {
// Don't give variables common linkage if -fno-common was specified unless it
// was overridden by a NoCommon attribute.
@@ -1965,10 +2075,15 @@
// If required by the ABI, give definitions of static data members with inline
// initializers at least linkonce_odr linkage.
+ auto const VD = dyn_cast<VarDecl>(D);
if (getCXXABI().isInlineInitializedStaticDataMemberLinkOnce() &&
- isa<VarDecl>(D) &&
- isVarDeclInlineInitializedStaticDataMember(cast<VarDecl>(D)))
+ VD && isVarDeclInlineInitializedStaticDataMember(VD)) {
+ if (VD->hasAttr<DLLImportAttr>())
+ return llvm::GlobalValue::AvailableExternallyLinkage;
+ if (VD->hasAttr<DLLExportAttr>())
+ return llvm::GlobalValue::WeakODRLinkage;
return llvm::GlobalValue::LinkOnceODRLinkage;
+ }
// C++ doesn't have tentative definitions and thus cannot have common
// linkage.
@@ -2220,29 +2335,6 @@
AddGlobalAnnotations(D, Fn);
}
-static llvm::GlobalObject &getGlobalObjectInExpr(DiagnosticsEngine &Diags,
- const AliasAttr *AA,
- llvm::Constant *C) {
- if (auto *GO = dyn_cast<llvm::GlobalObject>(C))
- return *GO;
-
- auto *GA = dyn_cast<llvm::GlobalAlias>(C);
- if (GA) {
- if (GA->mayBeOverridden()) {
- Diags.Report(AA->getLocation(), diag::warn_alias_to_weak_alias)
- << GA->getAliasee()->getName() << GA->getName();
- }
-
- return *GA->getAliasee();
- }
-
- auto *CE = cast<llvm::ConstantExpr>(C);
- assert(CE->getOpcode() == llvm::Instruction::BitCast ||
- CE->getOpcode() == llvm::Instruction::GetElementPtr ||
- CE->getOpcode() == llvm::Instruction::AddrSpaceCast);
- return *cast<llvm::GlobalObject>(CE->getOperand(0));
-}
-
void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
const auto *D = cast<ValueDecl>(GD.getDecl());
const AliasAttr *AA = D->getAttr<AliasAttr>();
@@ -2274,8 +2366,7 @@
// Create the new alias itself, but don't set a name yet.
auto *GA = llvm::GlobalAlias::create(
cast<llvm::PointerType>(Aliasee->getType())->getElementType(), 0,
- llvm::Function::ExternalLinkage, "",
- &getGlobalObjectInExpr(Diags, AA, Aliasee));
+ llvm::Function::ExternalLinkage, "", Aliasee, &getModule());
if (Entry) {
if (GA->getAliasee() == Entry) {
@@ -2659,72 +2750,67 @@
return llvm::ConstantDataArray::get(VMContext, Elements);
}
+static llvm::GlobalVariable *
+GenerateStringLiteral(llvm::Constant *C, llvm::GlobalValue::LinkageTypes LT,
+ CodeGenModule &CGM, StringRef GlobalName,
+ unsigned Alignment) {
+ // OpenCL v1.2 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
+ auto *GV = new llvm::GlobalVariable(
+ CGM.getModule(), C->getType(), !CGM.getLangOpts().WritableStrings, LT, C,
+ GlobalName, nullptr, llvm::GlobalVariable::NotThreadLocal, AddrSpace);
+ GV->setAlignment(Alignment);
+ GV->setUnnamedAddr(true);
+ return GV;
+}
+
/// GetAddrOfConstantStringFromLiteral - Return a pointer to a
/// constant array for the given string literal.
llvm::Constant *
CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S) {
- CharUnits Align = getContext().getAlignOfGlobalVarInChars(S->getType());
+ auto Alignment =
+ getContext().getAlignOfGlobalVarInChars(S->getType()).getQuantity();
llvm::StringMapEntry<llvm::GlobalVariable *> *Entry = nullptr;
- llvm::GlobalVariable *GV = nullptr;
if (!LangOpts.WritableStrings) {
- llvm::StringMap<llvm::GlobalVariable *> *ConstantStringMap = nullptr;
- switch (S->getCharByteWidth()) {
- case 1:
- ConstantStringMap = &Constant1ByteStringMap;
- break;
- case 2:
- ConstantStringMap = &Constant2ByteStringMap;
- break;
- case 4:
- ConstantStringMap = &Constant4ByteStringMap;
- break;
- default:
- llvm_unreachable("unhandled byte width!");
+ Entry = getConstantStringMapEntry(S->getBytes(), S->getCharByteWidth());
+ if (auto GV = Entry->getValue()) {
+ if (Alignment > GV->getAlignment())
+ GV->setAlignment(Alignment);
+ return GV;
}
- Entry = &ConstantStringMap->GetOrCreateValue(S->getBytes());
- GV = Entry->getValue();
}
- if (!GV) {
- SmallString<256> MangledNameBuffer;
- StringRef GlobalVariableName;
- llvm::GlobalValue::LinkageTypes LT;
+ SmallString<256> MangledNameBuffer;
+ StringRef GlobalVariableName;
+ llvm::GlobalValue::LinkageTypes LT;
- // Mangle the string literal if the ABI allows for it. However, we cannot
- // do this if we are compiling with ASan or -fwritable-strings because they
- // rely on strings having normal linkage.
- if (!LangOpts.WritableStrings && !SanOpts.Address &&
- getCXXABI().getMangleContext().shouldMangleStringLiteral(S)) {
- llvm::raw_svector_ostream Out(MangledNameBuffer);
- getCXXABI().getMangleContext().mangleStringLiteral(S, Out);
- Out.flush();
+ // Mangle the string literal if the ABI allows for it. However, we cannot
+ // do this if we are compiling with ASan or -fwritable-strings because they
+ // rely on strings having normal linkage.
+ if (!LangOpts.WritableStrings && !LangOpts.Sanitize.Address &&
+ getCXXABI().getMangleContext().shouldMangleStringLiteral(S)) {
+ llvm::raw_svector_ostream Out(MangledNameBuffer);
+ getCXXABI().getMangleContext().mangleStringLiteral(S, Out);
+ Out.flush();
- LT = llvm::GlobalValue::LinkOnceODRLinkage;
- GlobalVariableName = MangledNameBuffer;
- } else {
- LT = llvm::GlobalValue::PrivateLinkage;
- GlobalVariableName = ".str";
- }
-
- // OpenCL v1.2 s6.5.3: a string literal is in the constant address space.
- unsigned AddrSpace = 0;
- if (getLangOpts().OpenCL)
- AddrSpace = getContext().getTargetAddressSpace(LangAS::opencl_constant);
-
- llvm::Constant *C = GetConstantArrayFromStringLiteral(S);
- GV = new llvm::GlobalVariable(
- getModule(), C->getType(), !LangOpts.WritableStrings, LT, C,
- GlobalVariableName, /*InsertBefore=*/nullptr,
- llvm::GlobalVariable::NotThreadLocal, AddrSpace);
- GV->setUnnamedAddr(true);
- if (Entry)
- Entry->setValue(GV);
+ LT = llvm::GlobalValue::LinkOnceODRLinkage;
+ GlobalVariableName = MangledNameBuffer;
+ } else {
+ LT = llvm::GlobalValue::PrivateLinkage;
+ GlobalVariableName = ".str";
}
- if (Align.getQuantity() > GV->getAlignment())
- GV->setAlignment(Align.getQuantity());
+ llvm::Constant *C = GetConstantArrayFromStringLiteral(S);
+ auto GV = GenerateStringLiteral(C, LT, *this, GlobalVariableName, Alignment);
+ if (Entry)
+ Entry->setValue(GV);
+ reportGlobalToASan(GV, S->getStrTokenLoc(0));
return GV;
}
@@ -2739,79 +2825,60 @@
}
-/// GenerateWritableString -- Creates storage for a string literal.
-static llvm::GlobalVariable *GenerateStringLiteral(StringRef str,
- bool constant,
- CodeGenModule &CGM,
- const char *GlobalName,
- unsigned Alignment) {
- // Create Constant for this string literal. Don't add a '\0'.
- llvm::Constant *C =
- llvm::ConstantDataArray::getString(CGM.getLLVMContext(), str, false);
-
- // OpenCL v1.2 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
- auto *GV = new llvm::GlobalVariable(
- CGM.getModule(), C->getType(), constant,
- llvm::GlobalValue::PrivateLinkage, C, GlobalName, nullptr,
- llvm::GlobalVariable::NotThreadLocal, AddrSpace);
- GV->setAlignment(Alignment);
- GV->setUnnamedAddr(true);
- return GV;
-}
-
-/// GetAddrOfConstantString - Returns a pointer to a character array
-/// containing the literal. This contents are exactly that of the
-/// given string, i.e. it will not be null terminated automatically;
-/// see GetAddrOfConstantCString. Note that whether the result is
-/// actually a pointer to an LLVM constant depends on
-/// Feature.WriteableStrings.
-///
-/// The result has pointer to array type.
-llvm::Constant *CodeGenModule::GetAddrOfConstantString(StringRef Str,
- const char *GlobalName,
- unsigned Alignment) {
- // Get the default prefix if a name wasn't specified.
- if (!GlobalName)
- GlobalName = ".str";
-
- if (Alignment == 0)
- Alignment = getContext().getAlignOfGlobalVarInChars(getContext().CharTy)
- .getQuantity();
-
- // Don't share any string literals if strings aren't constant.
- if (LangOpts.WritableStrings)
- return GenerateStringLiteral(Str, false, *this, GlobalName, Alignment);
-
- llvm::StringMapEntry<llvm::GlobalVariable *> &Entry =
- Constant1ByteStringMap.GetOrCreateValue(Str);
-
- if (llvm::GlobalVariable *GV = Entry.getValue()) {
- if (Alignment > GV->getAlignment()) {
- GV->setAlignment(Alignment);
- }
- return GV;
+llvm::StringMapEntry<llvm::GlobalVariable *> *CodeGenModule::getConstantStringMapEntry(
+ StringRef Str, int CharByteWidth) {
+ llvm::StringMap<llvm::GlobalVariable *> *ConstantStringMap = nullptr;
+ switch (CharByteWidth) {
+ case 1:
+ ConstantStringMap = &Constant1ByteStringMap;
+ break;
+ case 2:
+ ConstantStringMap = &Constant2ByteStringMap;
+ break;
+ case 4:
+ ConstantStringMap = &Constant4ByteStringMap;
+ break;
+ default:
+ llvm_unreachable("unhandled byte width!");
}
-
- // Create a global variable for this.
- llvm::GlobalVariable *GV = GenerateStringLiteral(Str, true, *this, GlobalName,
- Alignment);
- Entry.setValue(GV);
- return GV;
+ return &ConstantStringMap->GetOrCreateValue(Str);
}
-/// GetAddrOfConstantCString - Returns a pointer to a character
-/// array containing the literal and a terminating '\0'
-/// character. The result has pointer to array type.
+/// GetAddrOfConstantCString - Returns a pointer to a character array containing
+/// the literal and a terminating '\0' character.
+/// The result has pointer to array type.
llvm::Constant *CodeGenModule::GetAddrOfConstantCString(const std::string &Str,
const char *GlobalName,
unsigned Alignment) {
StringRef StrWithNull(Str.c_str(), Str.size() + 1);
- return GetAddrOfConstantString(StrWithNull, GlobalName, Alignment);
+ if (Alignment == 0) {
+ Alignment = getContext()
+ .getAlignOfGlobalVarInChars(getContext().CharTy)
+ .getQuantity();
+ }
+
+ // Don't share any string literals if strings aren't constant.
+ llvm::StringMapEntry<llvm::GlobalVariable *> *Entry = nullptr;
+ if (!LangOpts.WritableStrings) {
+ Entry = getConstantStringMapEntry(StrWithNull, 1);
+ if (auto GV = Entry->getValue()) {
+ if (Alignment > GV->getAlignment())
+ GV->setAlignment(Alignment);
+ return GV;
+ }
+ }
+
+ llvm::Constant *C =
+ llvm::ConstantDataArray::getString(getLLVMContext(), StrWithNull, false);
+ // Get the default prefix if a name wasn't specified.
+ if (!GlobalName)
+ GlobalName = ".str";
+ // Create a global variable for this.
+ auto GV = GenerateStringLiteral(C, llvm::GlobalValue::PrivateLinkage, *this,
+ GlobalName, Alignment);
+ if (Entry)
+ Entry->setValue(GV);
+ return GV;
}
llvm::Constant *CodeGenModule::GetAddrOfGlobalTemporary(
@@ -3200,11 +3267,19 @@
IdentifierInfo *Name = I->first;
llvm::GlobalValue *Val = I->second;
if (Val && !getModule().getNamedValue(Name->getName()))
- addUsedGlobal(llvm::GlobalAlias::create(Name->getName(),
- cast<llvm::GlobalObject>(Val)));
+ addUsedGlobal(llvm::GlobalAlias::create(Name->getName(), Val));
}
}
+bool CodeGenModule::lookupRepresentativeDecl(StringRef MangledName,
+ GlobalDecl &Result) const {
+ auto Res = Manglings.find(MangledName);
+ if (Res == Manglings.end())
+ return false;
+ Result = Res->getValue();
+ return true;
+}
+
/// Emits metadata nodes associating all the global values in the
/// current module with the Decls they came from. This is useful for
/// projects using IR gen as a subroutine.
@@ -3216,11 +3291,9 @@
llvm::NamedMDNode *GlobalMetadata = nullptr;
// StaticLocalDeclMap
- for (llvm::DenseMap<GlobalDecl,StringRef>::iterator
- I = MangledDeclNames.begin(), E = MangledDeclNames.end();
- I != E; ++I) {
- llvm::GlobalValue *Addr = getModule().getNamedValue(I->second);
- EmitGlobalDeclMetadata(*this, GlobalMetadata, I->first, Addr);
+ for (auto &I : MangledDeclNames) {
+ llvm::GlobalValue *Addr = getModule().getNamedValue(I.second);
+ EmitGlobalDeclMetadata(*this, GlobalMetadata, I.first, Addr);
}
}
@@ -3236,11 +3309,9 @@
llvm::NamedMDNode *GlobalMetadata = nullptr;
- for (llvm::DenseMap<const Decl*, llvm::Value*>::iterator
- I = LocalDeclMap.begin(), E = LocalDeclMap.end(); I != E; ++I) {
- const Decl *D = I->first;
- llvm::Value *Addr = I->second;
-
+ for (auto &I : LocalDeclMap) {
+ const Decl *D = I.first;
+ llvm::Value *Addr = I.second;
if (auto *Alloca = dyn_cast<llvm::AllocaInst>(Addr)) {
llvm::Value *DAddr = GetPointerConstant(getLLVMContext(), D);
Alloca->setMetadata(DeclPtrKind, llvm::MDNode::get(Context, DAddr));
@@ -3263,6 +3334,14 @@
IdentMetadata->addOperand(llvm::MDNode::get(Ctx, IdentNode));
}
+void CodeGenModule::EmitTargetMetadata() {
+ for (auto &I : MangledDeclNames) {
+ const Decl *D = I.first.getDecl()->getMostRecentDecl();
+ llvm::GlobalValue *GV = GetGlobalValue(I.second);
+ getTargetCodeGenInfo().emitTargetMD(D, GV, *this);
+ }
+}
+
void CodeGenModule::EmitCoverageFile() {
if (!getCodeGenOpts().CoverageFile.empty()) {
if (llvm::NamedMDNode *CUNode = TheModule.getNamedMetadata("llvm.dbg.cu")) {
@@ -3306,3 +3385,19 @@
return llvm::ConstantStruct::getAnon(Fields);
}
+
+llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty,
+ bool ForEH) {
+ // Return a bogus pointer if RTTI is disabled, unless it's for EH.
+ // FIXME: should we even be calling this method if RTTI is disabled
+ // and it's not for EH?
+ if (!ForEH && !getLangOpts().RTTI)
+ return llvm::Constant::getNullValue(Int8PtrTy);
+
+ if (ForEH && Ty->isObjCObjectPointerType() &&
+ LangOpts.ObjCRuntime.isGNUFamily())
+ return ObjCRuntime->GetEHType(Ty);
+
+ return getCXXABI().getAddrOfRTTIDescriptor(Ty);
+}
+
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index c54f6de..649b0e5 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -16,6 +16,7 @@
#include "CGVTables.h"
#include "CodeGenTypes.h"
+#include "SanitizerBlacklist.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
@@ -31,7 +32,6 @@
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ValueHandle.h"
-#include "llvm/Transforms/Utils/SpecialCaseList.h"
namespace llvm {
class Module;
@@ -71,7 +71,6 @@
class DiagnosticsEngine;
class AnnotateAttr;
class CXXDestructorDecl;
-class MangleBuffer;
class Module;
namespace CodeGen {
@@ -219,12 +218,36 @@
};
/// This class records statistics on instrumentation based profiling.
-struct InstrProfStats {
- InstrProfStats() : Visited(0), Missing(0), Mismatched(0) {}
- bool isOutOfDate() { return Missing || Mismatched; }
+class InstrProfStats {
+ uint32_t VisitedInMainFile;
+ uint32_t MissingInMainFile;
uint32_t Visited;
uint32_t Missing;
uint32_t Mismatched;
+
+public:
+ InstrProfStats()
+ : VisitedInMainFile(0), MissingInMainFile(0), Visited(0), Missing(0),
+ Mismatched(0) {}
+ /// Record that we've visited a function and whether or not that function was
+ /// in the main source file.
+ void addVisited(bool MainFile) {
+ if (MainFile)
+ ++VisitedInMainFile;
+ ++Visited;
+ }
+ /// Record that a function we've visited has no profile data.
+ void addMissing(bool MainFile) {
+ if (MainFile)
+ ++MissingInMainFile;
+ ++Missing;
+ }
+ /// Record that a function we've visited has mismatched profile data.
+ void addMismatched(bool MainFile) { ++Mismatched; }
+ /// Whether or not the stats we've gathered indicate any potential problems.
+ bool hasDiagnostics() { return Missing || Mismatched; }
+ /// Report potential problems we've found to \c Diags.
+ void reportDiagnostics(DiagnosticsEngine &Diags, StringRef MainFile);
};
/// This class organizes the cross-function state that is used while generating
@@ -288,7 +311,7 @@
/// for emission and therefore should only be output if they are actually
/// used. If a decl is in this, then it is known to have not been referenced
/// yet.
- llvm::StringMap<GlobalDecl> DeferredDecls;
+ std::map<StringRef, GlobalDecl> DeferredDecls;
/// This is a list of deferred decls which we have seen that *are* actually
/// referenced. These get code generated when the module is done.
@@ -326,10 +349,10 @@
/// emitted when the translation unit is complete.
CtorList GlobalDtors;
- /// A map of canonical GlobalDecls to their mangled names.
- llvm::DenseMap<GlobalDecl, StringRef> MangledDeclNames;
- llvm::BumpPtrAllocator MangledNamesAllocator;
-
+ /// An ordered map of canonical GlobalDecls to their mangled names.
+ llvm::MapVector<GlobalDecl, StringRef> MangledDeclNames;
+ llvm::StringMap<GlobalDecl, llvm::BumpPtrAllocator> Manglings;
+
/// Global annotations.
std::vector<llvm::Constant*> Annotations;
@@ -450,9 +473,7 @@
GlobalDecl initializedGlobalDecl;
- std::unique_ptr<llvm::SpecialCaseList> SanitizerBlacklist;
-
- const SanitizerOptions &SanOpts;
+ SanitizerBlacklist SanitizerBL;
/// @}
public:
@@ -523,6 +544,9 @@
StaticLocalDeclGuardMap[D] = C;
}
+ bool lookupRepresentativeDecl(StringRef MangledName,
+ GlobalDecl &Result) const;
+
llvm::Constant *getAtomicSetterHelperFnMap(QualType Ty) {
return AtomicSetterHelperFnMap[Ty];
}
@@ -721,12 +745,6 @@
/// The type of a generic block literal.
llvm::Type *getGenericBlockLiteralType();
- /// \brief Gets or a creats a Microsoft TypeDescriptor.
- llvm::Constant *getMSTypeDescriptor(QualType Ty);
- /// \brief Gets or a creats a Microsoft CompleteObjectLocator.
- llvm::GlobalVariable *getMSCompleteObjectLocator(const CXXRecordDecl *RD,
- const VPtrInfo *Info);
-
/// Gets the address of a block which requires no captures.
llvm::Constant *GetAddrOfGlobalBlock(const BlockExpr *BE, const char *);
@@ -747,28 +765,14 @@
/// Return a pointer to a constant array for the given ObjCEncodeExpr node.
llvm::Constant *GetAddrOfConstantStringFromObjCEncode(const ObjCEncodeExpr *);
- /// Returns a pointer to a character array containing the literal. This
- /// contents are exactly that of the given string, i.e. it will not be null
- /// terminated automatically; see GetAddrOfConstantCString. Note that whether
- /// the result is actually a pointer to an LLVM constant depends on
- /// Feature.WriteableStrings.
- ///
- /// The result has pointer to array type.
- ///
- /// \param GlobalName If provided, the name to use for the global
- /// (if one is created).
- llvm::Constant *GetAddrOfConstantString(StringRef Str,
- const char *GlobalName=nullptr,
- unsigned Alignment=0);
-
/// Returns a pointer to a character array containing the literal and a
/// terminating '\0' character. The result has pointer to array type.
///
/// \param GlobalName If provided, the name to use for the global (if one is
/// created).
llvm::Constant *GetAddrOfConstantCString(const std::string &str,
- const char *GlobalName=nullptr,
- unsigned Alignment=0);
+ const char *GlobalName = nullptr,
+ unsigned Alignment = 0);
/// Returns a pointer to a constant global variable for the given file-scope
/// compound literal expression.
@@ -937,8 +941,7 @@
bool AttrOnCallSite);
StringRef getMangledName(GlobalDecl GD);
- void getBlockMangledName(GlobalDecl GD, MangleBuffer &Buffer,
- const BlockDecl *BD);
+ StringRef getBlockMangledName(GlobalDecl GD, const BlockDecl *BD);
void EmitTentativeDefinition(const VarDecl *D);
@@ -962,9 +965,6 @@
F->setLinkage(getFunctionLinkage(GD));
}
- /// \brief Returns the appropriate linkage for the TypeInfo struct for a type.
- llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(QualType Ty);
-
/// Return the appropriate linkage for the vtable, VTT, and type information
/// of the given class.
llvm::GlobalVariable::LinkageTypes getVTableLinkage(const CXXRecordDecl *RD);
@@ -1008,11 +1008,12 @@
/// annotations are emitted during finalization of the LLVM code.
void AddGlobalAnnotations(const ValueDecl *D, llvm::GlobalValue *GV);
- const llvm::SpecialCaseList &getSanitizerBlacklist() const {
- return *SanitizerBlacklist;
+ const SanitizerBlacklist &getSanitizerBlacklist() const {
+ return SanitizerBL;
}
- const SanitizerOptions &getSanOpts() const { return SanOpts; }
+ void reportGlobalToASan(llvm::GlobalVariable *GV, SourceLocation Loc,
+ bool IsDynInit = false);
void addDeferredVTable(const CXXRecordDecl *RD) {
DeferredVTables.push_back(RD);
@@ -1034,6 +1035,9 @@
llvm::PointerType *PTy,
const VarDecl *D);
+ llvm::StringMapEntry<llvm::GlobalVariable *> *
+ getConstantStringMapEntry(StringRef Str, int CharByteWidth);
+
/// Set attributes which are common to any form of a global definition (alias,
/// Objective-C method, function, global variable).
///
@@ -1129,6 +1133,9 @@
/// \brief Emit the Clang version as llvm.ident metadata.
void EmitVersionIdentMetadata();
+ /// Emits target specific Metadata for global declarations.
+ void EmitTargetMetadata();
+
/// 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/CodeGenPGO.cpp b/lib/CodeGen/CodeGenPGO.cpp
index 22534b8..b233e3c 100644
--- a/lib/CodeGen/CodeGenPGO.cpp
+++ b/lib/CodeGen/CodeGenPGO.cpp
@@ -837,7 +837,8 @@
emitCounterVariables();
}
if (PGOReader) {
- loadRegionCounts(PGOReader);
+ SourceManager &SM = CGM.getContext().getSourceManager();
+ loadRegionCounts(PGOReader, SM.isInMainFile(D->getLocation()));
computeRegionCounts(D);
applyFunctionAttributes(PGOReader, Fn);
}
@@ -912,16 +913,17 @@
Builder.CreateStore(Count, Addr);
}
-void CodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader) {
- CGM.getPGOStats().Visited++;
+void CodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader,
+ bool IsInMainFile) {
+ CGM.getPGOStats().addVisited(IsInMainFile);
RegionCounts.reset(new std::vector<uint64_t>);
uint64_t Hash;
if (PGOReader->getFunctionCounts(getFuncName(), Hash, *RegionCounts)) {
- CGM.getPGOStats().Missing++;
+ CGM.getPGOStats().addMissing(IsInMainFile);
RegionCounts.reset();
} else if (Hash != FunctionHash ||
RegionCounts->size() != NumRegionCounters) {
- CGM.getPGOStats().Mismatched++;
+ CGM.getPGOStats().addMismatched(IsInMainFile);
RegionCounts.reset();
}
}
diff --git a/lib/CodeGen/CodeGenPGO.h b/lib/CodeGen/CodeGenPGO.h
index c434808..2f4aa66 100644
--- a/lib/CodeGen/CodeGenPGO.h
+++ b/lib/CodeGen/CodeGenPGO.h
@@ -118,7 +118,8 @@
void computeRegionCounts(const Decl *D);
void applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader,
llvm::Function *Fn);
- void loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader);
+ void loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader,
+ bool IsInMainFile);
void emitCounterVariables();
llvm::GlobalVariable *buildDataVar();
diff --git a/lib/CodeGen/CodeGenTypes.h b/lib/CodeGen/CodeGenTypes.h
index 59e3089..fe155b5 100644
--- a/lib/CodeGen/CodeGenTypes.h
+++ b/lib/CodeGen/CodeGenTypes.h
@@ -104,7 +104,7 @@
private:
/// TypeCache - This map keeps cache of llvm::Types
- /// and maps llvm::Types to corresponding clang::Type.
+ /// and maps clang::Type to corresponding llvm::Type.
llvm::DenseMap<const Type *, llvm::Type *> TypeCache;
public:
diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp
index f5d2372..baf0927 100644
--- a/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/lib/CodeGen/ItaniumCXXABI.cpp
@@ -25,6 +25,7 @@
#include "CodeGenModule.h"
#include "clang/AST/Mangle.h"
#include "clang/AST/Type.h"
+#include "llvm/IR/CallSite.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Value.h"
@@ -108,6 +109,30 @@
llvm::Value *adjustToCompleteObject(CodeGenFunction &CGF, llvm::Value *ptr,
QualType type) override;
+ void EmitFundamentalRTTIDescriptor(QualType Type);
+ void EmitFundamentalRTTIDescriptors();
+ llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) override;
+
+ bool shouldTypeidBeNullChecked(bool IsDeref, QualType SrcRecordTy) override;
+ void EmitBadTypeidCall(CodeGenFunction &CGF) override;
+ llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy,
+ llvm::Value *ThisPtr,
+ llvm::Type *StdTypeInfoPtrTy) override;
+
+ bool shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
+ QualType SrcRecordTy) override;
+
+ llvm::Value *EmitDynamicCastCall(CodeGenFunction &CGF, llvm::Value *Value,
+ QualType SrcRecordTy, QualType DestTy,
+ QualType DestRecordTy,
+ llvm::BasicBlock *CastEnd) override;
+
+ llvm::Value *EmitDynamicCastToVoid(CodeGenFunction &CGF, llvm::Value *Value,
+ QualType SrcRecordTy,
+ QualType DestTy) override;
+
+ bool EmitBadCastCall(CodeGenFunction &CGF) override;
+
llvm::Value *
GetVirtualBaseClassOffset(CodeGenFunction &CGF, llvm::Value *This,
const CXXRecordDecl *ClassDecl,
@@ -174,7 +199,8 @@
void emitVirtualInheritanceTables(const CXXRecordDecl *RD) override;
- void setThunkLinkage(llvm::Function *Thunk, bool ForVTable) override {
+ void setThunkLinkage(llvm::Function *Thunk, bool ForVTable, GlobalDecl GD,
+ bool ReturnAdjustment) override {
// Allow inlining of thunks by emitting them with available_externally
// linkage together with vtables when needed.
if (ForVTable)
@@ -210,12 +236,43 @@
llvm::Function *getOrCreateThreadLocalWrapper(const VarDecl *VD,
llvm::GlobalVariable *Var);
void EmitThreadLocalInitFuncs(
- llvm::ArrayRef<std::pair<const VarDecl *, llvm::GlobalVariable *> > Decls,
+ ArrayRef<std::pair<const VarDecl *, llvm::GlobalVariable *> > Decls,
llvm::Function *InitFunc) override;
LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD,
QualType LValType) override;
bool NeedsVTTParameter(GlobalDecl GD) override;
+
+ /**************************** RTTI Uniqueness ******************************/
+
+protected:
+ /// Returns true if the ABI requires RTTI type_info objects to be unique
+ /// across a program.
+ virtual bool shouldRTTIBeUnique() const { return true; }
+
+public:
+ /// What sort of unique-RTTI behavior should we use?
+ enum RTTIUniquenessKind {
+ /// We are guaranteeing, or need to guarantee, that the RTTI string
+ /// is unique.
+ RUK_Unique,
+
+ /// We are not guaranteeing uniqueness for the RTTI string, so we
+ /// can demote to hidden visibility but must use string comparisons.
+ RUK_NonUniqueHidden,
+
+ /// We are not guaranteeing uniqueness for the RTTI string, so we
+ /// have to use string comparisons, but we also have to emit it with
+ /// non-hidden visibility.
+ RUK_NonUniqueVisible
+ };
+
+ /// Return the required visibility status for the given type and linkage in
+ /// the current ABI.
+ RTTIUniquenessKind
+ classifyRTTIUniqueness(QualType CanTy,
+ llvm::GlobalValue::LinkageTypes Linkage) const;
+ friend class ItaniumRTTIBuilder;
};
class ARMCXXABI : public ItaniumCXXABI {
@@ -248,7 +305,7 @@
iOS64CXXABI(CodeGen::CodeGenModule &CGM) : ARMCXXABI(CGM) {}
// ARM64 libraries are prepared for non-unique RTTI.
- bool shouldRTTIBeUnique() override { return false; }
+ bool shouldRTTIBeUnique() const override { return false; }
};
}
@@ -799,6 +856,194 @@
return CGF.Builder.CreateInBoundsGEP(ptr, offset);
}
+static llvm::Constant *getItaniumDynamicCastFn(CodeGenFunction &CGF) {
+ // void *__dynamic_cast(const void *sub,
+ // const abi::__class_type_info *src,
+ // const abi::__class_type_info *dst,
+ // std::ptrdiff_t src2dst_offset);
+
+ llvm::Type *Int8PtrTy = CGF.Int8PtrTy;
+ llvm::Type *PtrDiffTy =
+ CGF.ConvertType(CGF.getContext().getPointerDiffType());
+
+ llvm::Type *Args[4] = { Int8PtrTy, Int8PtrTy, Int8PtrTy, PtrDiffTy };
+
+ llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args, false);
+
+ // Mark the function as nounwind readonly.
+ llvm::Attribute::AttrKind FuncAttrs[] = { llvm::Attribute::NoUnwind,
+ llvm::Attribute::ReadOnly };
+ llvm::AttributeSet Attrs = llvm::AttributeSet::get(
+ CGF.getLLVMContext(), llvm::AttributeSet::FunctionIndex, FuncAttrs);
+
+ return CGF.CGM.CreateRuntimeFunction(FTy, "__dynamic_cast", Attrs);
+}
+
+static llvm::Constant *getBadCastFn(CodeGenFunction &CGF) {
+ // void __cxa_bad_cast();
+ llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.VoidTy, false);
+ return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_bad_cast");
+}
+
+/// \brief Compute the src2dst_offset hint as described in the
+/// Itanium C++ ABI [2.9.7]
+static CharUnits computeOffsetHint(ASTContext &Context,
+ const CXXRecordDecl *Src,
+ const CXXRecordDecl *Dst) {
+ CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+ /*DetectVirtual=*/false);
+
+ // If Dst is not derived from Src we can skip the whole computation below and
+ // return that Src is not a public base of Dst. Record all inheritance paths.
+ if (!Dst->isDerivedFrom(Src, Paths))
+ return CharUnits::fromQuantity(-2ULL);
+
+ unsigned NumPublicPaths = 0;
+ CharUnits Offset;
+
+ // Now walk all possible inheritance paths.
+ for (CXXBasePaths::paths_iterator I = Paths.begin(), E = Paths.end(); I != E;
+ ++I) {
+ if (I->Access != AS_public) // Ignore non-public inheritance.
+ continue;
+
+ ++NumPublicPaths;
+
+ for (CXXBasePath::iterator J = I->begin(), JE = I->end(); J != JE; ++J) {
+ // If the path contains a virtual base class we can't give any hint.
+ // -1: no hint.
+ if (J->Base->isVirtual())
+ return CharUnits::fromQuantity(-1ULL);
+
+ if (NumPublicPaths > 1) // Won't use offsets, skip computation.
+ continue;
+
+ // Accumulate the base class offsets.
+ const ASTRecordLayout &L = Context.getASTRecordLayout(J->Class);
+ Offset += L.getBaseClassOffset(J->Base->getType()->getAsCXXRecordDecl());
+ }
+ }
+
+ // -2: Src is not a public base of Dst.
+ if (NumPublicPaths == 0)
+ return CharUnits::fromQuantity(-2ULL);
+
+ // -3: Src is a multiple public base type but never a virtual base type.
+ if (NumPublicPaths > 1)
+ return CharUnits::fromQuantity(-3ULL);
+
+ // Otherwise, the Src type is a unique public nonvirtual base type of Dst.
+ // Return the offset of Src from the origin of Dst.
+ return Offset;
+}
+
+static llvm::Constant *getBadTypeidFn(CodeGenFunction &CGF) {
+ // void __cxa_bad_typeid();
+ llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.VoidTy, false);
+
+ return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_bad_typeid");
+}
+
+bool ItaniumCXXABI::shouldTypeidBeNullChecked(bool IsDeref,
+ QualType SrcRecordTy) {
+ return IsDeref;
+}
+
+void ItaniumCXXABI::EmitBadTypeidCall(CodeGenFunction &CGF) {
+ llvm::Value *Fn = getBadTypeidFn(CGF);
+ CGF.EmitRuntimeCallOrInvoke(Fn).setDoesNotReturn();
+ CGF.Builder.CreateUnreachable();
+}
+
+llvm::Value *ItaniumCXXABI::EmitTypeid(CodeGenFunction &CGF,
+ QualType SrcRecordTy,
+ llvm::Value *ThisPtr,
+ llvm::Type *StdTypeInfoPtrTy) {
+ llvm::Value *Value =
+ CGF.GetVTablePtr(ThisPtr, StdTypeInfoPtrTy->getPointerTo());
+
+ // Load the type info.
+ Value = CGF.Builder.CreateConstInBoundsGEP1_64(Value, -1ULL);
+ return CGF.Builder.CreateLoad(Value);
+}
+
+bool ItaniumCXXABI::shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
+ QualType SrcRecordTy) {
+ return SrcIsPtr;
+}
+
+llvm::Value *ItaniumCXXABI::EmitDynamicCastCall(
+ CodeGenFunction &CGF, llvm::Value *Value, QualType SrcRecordTy,
+ QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastEnd) {
+ llvm::Type *PtrDiffLTy =
+ CGF.ConvertType(CGF.getContext().getPointerDiffType());
+ llvm::Type *DestLTy = CGF.ConvertType(DestTy);
+
+ llvm::Value *SrcRTTI =
+ CGF.CGM.GetAddrOfRTTIDescriptor(SrcRecordTy.getUnqualifiedType());
+ llvm::Value *DestRTTI =
+ CGF.CGM.GetAddrOfRTTIDescriptor(DestRecordTy.getUnqualifiedType());
+
+ // Compute the offset hint.
+ const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl();
+ const CXXRecordDecl *DestDecl = DestRecordTy->getAsCXXRecordDecl();
+ llvm::Value *OffsetHint = llvm::ConstantInt::get(
+ PtrDiffLTy,
+ computeOffsetHint(CGF.getContext(), SrcDecl, DestDecl).getQuantity());
+
+ // Emit the call to __dynamic_cast.
+ Value = CGF.EmitCastToVoidPtr(Value);
+
+ llvm::Value *args[] = {Value, SrcRTTI, DestRTTI, OffsetHint};
+ Value = CGF.EmitNounwindRuntimeCall(getItaniumDynamicCastFn(CGF), args);
+ Value = CGF.Builder.CreateBitCast(Value, DestLTy);
+
+ /// C++ [expr.dynamic.cast]p9:
+ /// A failed cast to reference type throws std::bad_cast
+ if (DestTy->isReferenceType()) {
+ llvm::BasicBlock *BadCastBlock =
+ CGF.createBasicBlock("dynamic_cast.bad_cast");
+
+ llvm::Value *IsNull = CGF.Builder.CreateIsNull(Value);
+ CGF.Builder.CreateCondBr(IsNull, BadCastBlock, CastEnd);
+
+ CGF.EmitBlock(BadCastBlock);
+ EmitBadCastCall(CGF);
+ }
+
+ return Value;
+}
+
+llvm::Value *ItaniumCXXABI::EmitDynamicCastToVoid(CodeGenFunction &CGF,
+ llvm::Value *Value,
+ QualType SrcRecordTy,
+ QualType DestTy) {
+ llvm::Type *PtrDiffLTy =
+ CGF.ConvertType(CGF.getContext().getPointerDiffType());
+ llvm::Type *DestLTy = CGF.ConvertType(DestTy);
+
+ // Get the vtable pointer.
+ llvm::Value *VTable = CGF.GetVTablePtr(Value, PtrDiffLTy->getPointerTo());
+
+ // Get the offset-to-top from the vtable.
+ llvm::Value *OffsetToTop =
+ CGF.Builder.CreateConstInBoundsGEP1_64(VTable, -2ULL);
+ OffsetToTop = CGF.Builder.CreateLoad(OffsetToTop, "offset.to.top");
+
+ // Finally, add the offset to the pointer.
+ Value = CGF.EmitCastToVoidPtr(Value);
+ Value = CGF.Builder.CreateInBoundsGEP(Value, OffsetToTop);
+
+ return CGF.Builder.CreateBitCast(Value, DestLTy);
+}
+
+bool ItaniumCXXABI::EmitBadCastCall(CodeGenFunction &CGF) {
+ llvm::Value *Fn = getBadCastFn(CGF);
+ CGF.EmitRuntimeCallOrInvoke(Fn).setDoesNotReturn();
+ CGF.Builder.CreateUnreachable();
+ return true;
+}
+
llvm::Value *
ItaniumCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF,
llvm::Value *This,
@@ -972,11 +1217,13 @@
ItaniumVTableContext &VTContext = CGM.getItaniumVTableContext();
const VTableLayout &VTLayout = VTContext.getVTableLayout(RD);
llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD);
+ llvm::Constant *RTTI =
+ CGM.GetAddrOfRTTIDescriptor(CGM.getContext().getTagDeclType(RD));
// Create and set the initializer.
llvm::Constant *Init = CGVT.CreateVTableInitializer(
RD, VTLayout.vtable_component_begin(), VTLayout.getNumVTableComponents(),
- VTLayout.vtable_thunk_begin(), VTLayout.getNumVTableThunks());
+ VTLayout.vtable_thunk_begin(), VTLayout.getNumVTableThunks(), RTTI);
VTable->setInitializer(Init);
// Set the correct linkage.
@@ -994,7 +1241,7 @@
isa<NamespaceDecl>(DC) && cast<NamespaceDecl>(DC)->getIdentifier() &&
cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__cxxabiv1") &&
DC->getParent()->isTranslationUnit())
- CGM.EmitFundamentalRTTIDescriptors();
+ EmitFundamentalRTTIDescriptors();
}
llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructor(
@@ -1069,6 +1316,12 @@
VTable = CGM.CreateOrReplaceCXXRuntimeVariable(
Name, ArrayType, llvm::GlobalValue::ExternalLinkage);
VTable->setUnnamedAddr(true);
+
+ if (RD->hasAttr<DLLImportAttr>())
+ VTable->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
+ else if (RD->hasAttr<DLLExportAttr>())
+ VTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
+
return VTable;
}
@@ -1566,13 +1819,23 @@
}
/// Get the appropriate linkage for the wrapper function. This is essentially
-/// the weak form of the variable's linkage; every translation unit which wneeds
+/// the weak form of the variable's linkage; every translation unit which needs
/// the wrapper emits a copy, and we want the linker to merge them.
-static llvm::GlobalValue::LinkageTypes getThreadLocalWrapperLinkage(
- llvm::GlobalValue::LinkageTypes VarLinkage) {
+static llvm::GlobalValue::LinkageTypes
+getThreadLocalWrapperLinkage(const VarDecl *VD, CodeGen::CodeGenModule &CGM) {
+ llvm::GlobalValue::LinkageTypes VarLinkage =
+ CGM.getLLVMLinkageVarDefinition(VD, /*isConstant=*/false);
+
// For internal linkage variables, we don't need an external or weak wrapper.
if (llvm::GlobalValue::isLocalLinkage(VarLinkage))
return VarLinkage;
+
+ // All accesses to the thread_local variable go through the thread wrapper.
+ // However, this means that we cannot allow the thread wrapper to get inlined
+ // into any functions.
+ if (VD->getTLSKind() == VarDecl::TLS_Dynamic &&
+ CGM.getTarget().getTriple().isMacOSX())
+ return llvm::GlobalValue::WeakAnyLinkage;
return llvm::GlobalValue::WeakODRLinkage;
}
@@ -1595,10 +1858,9 @@
RetTy = RetTy->getPointerElementType();
llvm::FunctionType *FnTy = llvm::FunctionType::get(RetTy, false);
- llvm::Function *Wrapper = llvm::Function::Create(
- FnTy, getThreadLocalWrapperLinkage(
- CGM.getLLVMLinkageVarDefinition(VD, /*isConstant=*/false)),
- WrapperName.str(), &CGM.getModule());
+ llvm::Function *Wrapper =
+ llvm::Function::Create(FnTy, getThreadLocalWrapperLinkage(VD, CGM),
+ WrapperName.str(), &CGM.getModule());
// Always resolve references to the wrapper at link time.
if (!Wrapper->hasLocalLinkage())
Wrapper->setVisibility(llvm::GlobalValue::HiddenVisibility);
@@ -1606,7 +1868,7 @@
}
void ItaniumCXXABI::EmitThreadLocalInitFuncs(
- llvm::ArrayRef<std::pair<const VarDecl *, llvm::GlobalVariable *> > Decls,
+ ArrayRef<std::pair<const VarDecl *, llvm::GlobalVariable *> > Decls,
llvm::Function *InitFunc) {
for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
const VarDecl *VD = Decls[I].first;
@@ -1717,3 +1979,996 @@
return false;
}
+
+namespace {
+class ItaniumRTTIBuilder {
+ CodeGenModule &CGM; // Per-module state.
+ llvm::LLVMContext &VMContext;
+ const ItaniumCXXABI &CXXABI; // Per-module state.
+
+ /// Fields - The fields of the RTTI descriptor currently being built.
+ SmallVector<llvm::Constant *, 16> Fields;
+
+ /// GetAddrOfTypeName - Returns the mangled type name of the given type.
+ llvm::GlobalVariable *
+ GetAddrOfTypeName(QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage);
+
+ /// GetAddrOfExternalRTTIDescriptor - Returns the constant for the RTTI
+ /// descriptor of the given type.
+ llvm::Constant *GetAddrOfExternalRTTIDescriptor(QualType Ty);
+
+ /// BuildVTablePointer - Build the vtable pointer for the given type.
+ void BuildVTablePointer(const Type *Ty);
+
+ /// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single
+ /// inheritance, according to the Itanium C++ ABI, 2.9.5p6b.
+ void BuildSIClassTypeInfo(const CXXRecordDecl *RD);
+
+ /// BuildVMIClassTypeInfo - Build an abi::__vmi_class_type_info, used for
+ /// classes with bases that do not satisfy the abi::__si_class_type_info
+ /// constraints, according ti the Itanium C++ ABI, 2.9.5p5c.
+ void BuildVMIClassTypeInfo(const CXXRecordDecl *RD);
+
+ /// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct, used
+ /// for pointer types.
+ void BuildPointerTypeInfo(QualType PointeeTy);
+
+ /// BuildObjCObjectTypeInfo - Build the appropriate kind of
+ /// type_info for an object type.
+ void BuildObjCObjectTypeInfo(const ObjCObjectType *Ty);
+
+ /// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info
+ /// struct, used for member pointer types.
+ void BuildPointerToMemberTypeInfo(const MemberPointerType *Ty);
+
+public:
+ ItaniumRTTIBuilder(const ItaniumCXXABI &ABI)
+ : CGM(ABI.CGM), VMContext(CGM.getModule().getContext()), CXXABI(ABI) {}
+
+ // Pointer type info flags.
+ enum {
+ /// PTI_Const - Type has const qualifier.
+ PTI_Const = 0x1,
+
+ /// PTI_Volatile - Type has volatile qualifier.
+ PTI_Volatile = 0x2,
+
+ /// PTI_Restrict - Type has restrict qualifier.
+ PTI_Restrict = 0x4,
+
+ /// PTI_Incomplete - Type is incomplete.
+ PTI_Incomplete = 0x8,
+
+ /// PTI_ContainingClassIncomplete - Containing class is incomplete.
+ /// (in pointer to member).
+ PTI_ContainingClassIncomplete = 0x10
+ };
+
+ // VMI type info flags.
+ enum {
+ /// VMI_NonDiamondRepeat - Class has non-diamond repeated inheritance.
+ VMI_NonDiamondRepeat = 0x1,
+
+ /// VMI_DiamondShaped - Class is diamond shaped.
+ VMI_DiamondShaped = 0x2
+ };
+
+ // Base class type info flags.
+ enum {
+ /// BCTI_Virtual - Base class is virtual.
+ BCTI_Virtual = 0x1,
+
+ /// BCTI_Public - Base class is public.
+ BCTI_Public = 0x2
+ };
+
+ /// BuildTypeInfo - Build the RTTI type info struct for the given type.
+ ///
+ /// \param Force - true to force the creation of this RTTI value
+ llvm::Constant *BuildTypeInfo(QualType Ty, bool Force = false);
+};
+}
+
+llvm::GlobalVariable *ItaniumRTTIBuilder::GetAddrOfTypeName(
+ QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage) {
+ SmallString<256> OutName;
+ llvm::raw_svector_ostream Out(OutName);
+ CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(Ty, Out);
+ Out.flush();
+ StringRef Name = OutName.str();
+
+ // We know that the mangled name of the type starts at index 4 of the
+ // mangled name of the typename, so we can just index into it in order to
+ // get the mangled name of the type.
+ llvm::Constant *Init = llvm::ConstantDataArray::getString(VMContext,
+ Name.substr(4));
+
+ llvm::GlobalVariable *GV =
+ CGM.CreateOrReplaceCXXRuntimeVariable(Name, Init->getType(), Linkage);
+
+ GV->setInitializer(Init);
+
+ return GV;
+}
+
+llvm::Constant *
+ItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) {
+ // Mangle the RTTI name.
+ SmallString<256> OutName;
+ llvm::raw_svector_ostream Out(OutName);
+ CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out);
+ Out.flush();
+ StringRef Name = OutName.str();
+
+ // Look for an existing global.
+ llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name);
+
+ if (!GV) {
+ // Create a new global variable.
+ GV = new llvm::GlobalVariable(CGM.getModule(), CGM.Int8PtrTy,
+ /*Constant=*/true,
+ llvm::GlobalValue::ExternalLinkage, nullptr,
+ Name);
+ }
+
+ return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
+}
+
+/// TypeInfoIsInStandardLibrary - Given a builtin type, returns whether the type
+/// info for that type is defined in the standard library.
+static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
+ // Itanium C++ ABI 2.9.2:
+ // Basic type information (e.g. for "int", "bool", etc.) will be kept in
+ // the run-time support library. Specifically, the run-time support
+ // library should contain type_info objects for the types X, X* and
+ // X const*, for every X in: void, std::nullptr_t, bool, wchar_t, char,
+ // unsigned char, signed char, short, unsigned short, int, unsigned int,
+ // long, unsigned long, long long, unsigned long long, float, double,
+ // long double, char16_t, char32_t, and the IEEE 754r decimal and
+ // half-precision floating point types.
+ switch (Ty->getKind()) {
+ case BuiltinType::Void:
+ case BuiltinType::NullPtr:
+ case BuiltinType::Bool:
+ case BuiltinType::WChar_S:
+ case BuiltinType::WChar_U:
+ case BuiltinType::Char_U:
+ case BuiltinType::Char_S:
+ case BuiltinType::UChar:
+ case BuiltinType::SChar:
+ case BuiltinType::Short:
+ case BuiltinType::UShort:
+ case BuiltinType::Int:
+ case BuiltinType::UInt:
+ case BuiltinType::Long:
+ case BuiltinType::ULong:
+ case BuiltinType::LongLong:
+ case BuiltinType::ULongLong:
+ case BuiltinType::Half:
+ case BuiltinType::Float:
+ case BuiltinType::Double:
+ case BuiltinType::LongDouble:
+ case BuiltinType::Char16:
+ case BuiltinType::Char32:
+ case BuiltinType::Int128:
+ case BuiltinType::UInt128:
+ case BuiltinType::OCLImage1d:
+ case BuiltinType::OCLImage1dArray:
+ case BuiltinType::OCLImage1dBuffer:
+ case BuiltinType::OCLImage2d:
+ case BuiltinType::OCLImage2dArray:
+ case BuiltinType::OCLImage3d:
+ case BuiltinType::OCLSampler:
+ case BuiltinType::OCLEvent:
+ return true;
+
+ case BuiltinType::Dependent:
+#define BUILTIN_TYPE(Id, SingletonId)
+#define PLACEHOLDER_TYPE(Id, SingletonId) \
+ case BuiltinType::Id:
+#include "clang/AST/BuiltinTypes.def"
+ llvm_unreachable("asking for RRTI for a placeholder type!");
+
+ case BuiltinType::ObjCId:
+ case BuiltinType::ObjCClass:
+ case BuiltinType::ObjCSel:
+ llvm_unreachable("FIXME: Objective-C types are unsupported!");
+ }
+
+ llvm_unreachable("Invalid BuiltinType Kind!");
+}
+
+static bool TypeInfoIsInStandardLibrary(const PointerType *PointerTy) {
+ QualType PointeeTy = PointerTy->getPointeeType();
+ const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(PointeeTy);
+ if (!BuiltinTy)
+ return false;
+
+ // Check the qualifiers.
+ Qualifiers Quals = PointeeTy.getQualifiers();
+ Quals.removeConst();
+
+ if (!Quals.empty())
+ return false;
+
+ return TypeInfoIsInStandardLibrary(BuiltinTy);
+}
+
+/// IsStandardLibraryRTTIDescriptor - Returns whether the type
+/// information for the given type exists in the standard library.
+static bool IsStandardLibraryRTTIDescriptor(QualType Ty) {
+ // Type info for builtin types is defined in the standard library.
+ if (const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(Ty))
+ return TypeInfoIsInStandardLibrary(BuiltinTy);
+
+ // Type info for some pointer types to builtin types is defined in the
+ // standard library.
+ if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
+ return TypeInfoIsInStandardLibrary(PointerTy);
+
+ return false;
+}
+
+/// ShouldUseExternalRTTIDescriptor - Returns whether the type information for
+/// the given type exists somewhere else, and that we should not emit the type
+/// information in this translation unit. Assumes that it is not a
+/// standard-library type.
+static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM,
+ QualType Ty) {
+ ASTContext &Context = CGM.getContext();
+
+ // If RTTI is disabled, assume it might be disabled in the
+ // translation unit that defines any potential key function, too.
+ if (!Context.getLangOpts().RTTI) return false;
+
+ if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
+ if (!RD->hasDefinition())
+ return false;
+
+ if (!RD->isDynamicClass())
+ return false;
+
+ // FIXME: this may need to be reconsidered if the key function
+ // changes.
+ return CGM.getVTables().isVTableExternal(RD);
+ }
+
+ return false;
+}
+
+/// IsIncompleteClassType - Returns whether the given record type is incomplete.
+static bool IsIncompleteClassType(const RecordType *RecordTy) {
+ return !RecordTy->getDecl()->isCompleteDefinition();
+}
+
+/// ContainsIncompleteClassType - Returns whether the given type contains an
+/// incomplete class type. This is true if
+///
+/// * The given type is an incomplete class type.
+/// * The given type is a pointer type whose pointee type contains an
+/// incomplete class type.
+/// * The given type is a member pointer type whose class is an incomplete
+/// class type.
+/// * The given type is a member pointer type whoise pointee type contains an
+/// incomplete class type.
+/// is an indirect or direct pointer to an incomplete class type.
+static bool ContainsIncompleteClassType(QualType Ty) {
+ if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
+ if (IsIncompleteClassType(RecordTy))
+ return true;
+ }
+
+ if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
+ return ContainsIncompleteClassType(PointerTy->getPointeeType());
+
+ if (const MemberPointerType *MemberPointerTy =
+ dyn_cast<MemberPointerType>(Ty)) {
+ // Check if the class type is incomplete.
+ const RecordType *ClassType = cast<RecordType>(MemberPointerTy->getClass());
+ if (IsIncompleteClassType(ClassType))
+ return true;
+
+ return ContainsIncompleteClassType(MemberPointerTy->getPointeeType());
+ }
+
+ return false;
+}
+
+// CanUseSingleInheritance - Return whether the given record decl has a "single,
+// public, non-virtual base at offset zero (i.e. the derived class is dynamic
+// iff the base is)", according to Itanium C++ ABI, 2.95p6b.
+static bool CanUseSingleInheritance(const CXXRecordDecl *RD) {
+ // Check the number of bases.
+ if (RD->getNumBases() != 1)
+ return false;
+
+ // Get the base.
+ CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin();
+
+ // Check that the base is not virtual.
+ if (Base->isVirtual())
+ return false;
+
+ // Check that the base is public.
+ if (Base->getAccessSpecifier() != AS_public)
+ return false;
+
+ // Check that the class is dynamic iff the base is.
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ if (!BaseDecl->isEmpty() &&
+ BaseDecl->isDynamicClass() != RD->isDynamicClass())
+ return false;
+
+ return true;
+}
+
+void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) {
+ // abi::__class_type_info.
+ static const char * const ClassTypeInfo =
+ "_ZTVN10__cxxabiv117__class_type_infoE";
+ // abi::__si_class_type_info.
+ static const char * const SIClassTypeInfo =
+ "_ZTVN10__cxxabiv120__si_class_type_infoE";
+ // abi::__vmi_class_type_info.
+ static const char * const VMIClassTypeInfo =
+ "_ZTVN10__cxxabiv121__vmi_class_type_infoE";
+
+ const char *VTableName = nullptr;
+
+ switch (Ty->getTypeClass()) {
+#define TYPE(Class, Base)
+#define ABSTRACT_TYPE(Class, Base)
+#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
+#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
+#define DEPENDENT_TYPE(Class, Base) case Type::Class:
+#include "clang/AST/TypeNodes.def"
+ llvm_unreachable("Non-canonical and dependent types shouldn't get here");
+
+ case Type::LValueReference:
+ case Type::RValueReference:
+ llvm_unreachable("References shouldn't get here");
+
+ case Type::Auto:
+ llvm_unreachable("Undeduced auto type shouldn't get here");
+
+ case Type::Builtin:
+ // GCC treats vector and complex types as fundamental types.
+ case Type::Vector:
+ case Type::ExtVector:
+ case Type::Complex:
+ case Type::Atomic:
+ // FIXME: GCC treats block pointers as fundamental types?!
+ case Type::BlockPointer:
+ // abi::__fundamental_type_info.
+ VTableName = "_ZTVN10__cxxabiv123__fundamental_type_infoE";
+ break;
+
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ case Type::VariableArray:
+ // abi::__array_type_info.
+ VTableName = "_ZTVN10__cxxabiv117__array_type_infoE";
+ break;
+
+ case Type::FunctionNoProto:
+ case Type::FunctionProto:
+ // abi::__function_type_info.
+ VTableName = "_ZTVN10__cxxabiv120__function_type_infoE";
+ break;
+
+ case Type::Enum:
+ // abi::__enum_type_info.
+ VTableName = "_ZTVN10__cxxabiv116__enum_type_infoE";
+ break;
+
+ case Type::Record: {
+ const CXXRecordDecl *RD =
+ cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
+
+ if (!RD->hasDefinition() || !RD->getNumBases()) {
+ VTableName = ClassTypeInfo;
+ } else if (CanUseSingleInheritance(RD)) {
+ VTableName = SIClassTypeInfo;
+ } else {
+ VTableName = VMIClassTypeInfo;
+ }
+
+ break;
+ }
+
+ case Type::ObjCObject:
+ // Ignore protocol qualifiers.
+ Ty = cast<ObjCObjectType>(Ty)->getBaseType().getTypePtr();
+
+ // Handle id and Class.
+ if (isa<BuiltinType>(Ty)) {
+ VTableName = ClassTypeInfo;
+ break;
+ }
+
+ assert(isa<ObjCInterfaceType>(Ty));
+ // Fall through.
+
+ case Type::ObjCInterface:
+ if (cast<ObjCInterfaceType>(Ty)->getDecl()->getSuperClass()) {
+ VTableName = SIClassTypeInfo;
+ } else {
+ VTableName = ClassTypeInfo;
+ }
+ break;
+
+ case Type::ObjCObjectPointer:
+ case Type::Pointer:
+ // abi::__pointer_type_info.
+ VTableName = "_ZTVN10__cxxabiv119__pointer_type_infoE";
+ break;
+
+ case Type::MemberPointer:
+ // abi::__pointer_to_member_type_info.
+ VTableName = "_ZTVN10__cxxabiv129__pointer_to_member_type_infoE";
+ break;
+ }
+
+ llvm::Constant *VTable =
+ CGM.getModule().getOrInsertGlobal(VTableName, CGM.Int8PtrTy);
+
+ llvm::Type *PtrDiffTy =
+ CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
+
+ // The vtable address point is 2.
+ llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2);
+ VTable = llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Two);
+ VTable = llvm::ConstantExpr::getBitCast(VTable, CGM.Int8PtrTy);
+
+ Fields.push_back(VTable);
+}
+
+/// \brief Return the linkage that the type info and type info name constants
+/// should have for the given type.
+static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(CodeGenModule &CGM,
+ QualType Ty) {
+ // Itanium C++ ABI 2.9.5p7:
+ // In addition, it and all of the intermediate abi::__pointer_type_info
+ // structs in the chain down to the abi::__class_type_info for the
+ // incomplete class type must be prevented from resolving to the
+ // corresponding type_info structs for the complete class type, possibly
+ // by making them local static objects. Finally, a dummy class RTTI is
+ // generated for the incomplete type that will not resolve to the final
+ // complete class RTTI (because the latter need not exist), possibly by
+ // making it a local static object.
+ if (ContainsIncompleteClassType(Ty))
+ return llvm::GlobalValue::InternalLinkage;
+
+ switch (Ty->getLinkage()) {
+ case NoLinkage:
+ case InternalLinkage:
+ case UniqueExternalLinkage:
+ return llvm::GlobalValue::InternalLinkage;
+
+ case VisibleNoLinkage:
+ case ExternalLinkage:
+ if (!CGM.getLangOpts().RTTI) {
+ // RTTI is not enabled, which means that this type info struct is going
+ // to be used for exception handling. Give it linkonce_odr linkage.
+ return llvm::GlobalValue::LinkOnceODRLinkage;
+ }
+
+ if (const RecordType *Record = dyn_cast<RecordType>(Ty)) {
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
+ if (RD->hasAttr<WeakAttr>())
+ return llvm::GlobalValue::WeakODRLinkage;
+ if (RD->isDynamicClass())
+ return CGM.getVTableLinkage(RD);
+ }
+
+ return llvm::GlobalValue::LinkOnceODRLinkage;
+ }
+
+ llvm_unreachable("Invalid linkage!");
+}
+
+llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) {
+ // We want to operate on the canonical type.
+ Ty = CGM.getContext().getCanonicalType(Ty);
+
+ // Check if we've already emitted an RTTI descriptor for this type.
+ SmallString<256> OutName;
+ llvm::raw_svector_ostream Out(OutName);
+ CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out);
+ Out.flush();
+ StringRef Name = OutName.str();
+
+ llvm::GlobalVariable *OldGV = CGM.getModule().getNamedGlobal(Name);
+ if (OldGV && !OldGV->isDeclaration()) {
+ assert(!OldGV->hasAvailableExternallyLinkage() &&
+ "available_externally typeinfos not yet implemented");
+
+ return llvm::ConstantExpr::getBitCast(OldGV, CGM.Int8PtrTy);
+ }
+
+ // Check if there is already an external RTTI descriptor for this type.
+ bool IsStdLib = IsStandardLibraryRTTIDescriptor(Ty);
+ if (!Force && (IsStdLib || ShouldUseExternalRTTIDescriptor(CGM, Ty)))
+ return GetAddrOfExternalRTTIDescriptor(Ty);
+
+ // Emit the standard library with external linkage.
+ llvm::GlobalVariable::LinkageTypes Linkage;
+ if (IsStdLib)
+ Linkage = llvm::GlobalValue::ExternalLinkage;
+ else
+ Linkage = getTypeInfoLinkage(CGM, Ty);
+
+ // Add the vtable pointer.
+ BuildVTablePointer(cast<Type>(Ty));
+
+ // And the name.
+ llvm::GlobalVariable *TypeName = GetAddrOfTypeName(Ty, Linkage);
+ llvm::Constant *TypeNameField;
+
+ // If we're supposed to demote the visibility, be sure to set a flag
+ // to use a string comparison for type_info comparisons.
+ ItaniumCXXABI::RTTIUniquenessKind RTTIUniqueness =
+ CXXABI.classifyRTTIUniqueness(Ty, Linkage);
+ if (RTTIUniqueness != ItaniumCXXABI::RUK_Unique) {
+ // The flag is the sign bit, which on ARM64 is defined to be clear
+ // for global pointers. This is very ARM64-specific.
+ TypeNameField = llvm::ConstantExpr::getPtrToInt(TypeName, CGM.Int64Ty);
+ llvm::Constant *flag =
+ llvm::ConstantInt::get(CGM.Int64Ty, ((uint64_t)1) << 63);
+ TypeNameField = llvm::ConstantExpr::getAdd(TypeNameField, flag);
+ TypeNameField =
+ llvm::ConstantExpr::getIntToPtr(TypeNameField, CGM.Int8PtrTy);
+ } else {
+ TypeNameField = llvm::ConstantExpr::getBitCast(TypeName, CGM.Int8PtrTy);
+ }
+ Fields.push_back(TypeNameField);
+
+ switch (Ty->getTypeClass()) {
+#define TYPE(Class, Base)
+#define ABSTRACT_TYPE(Class, Base)
+#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
+#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
+#define DEPENDENT_TYPE(Class, Base) case Type::Class:
+#include "clang/AST/TypeNodes.def"
+ llvm_unreachable("Non-canonical and dependent types shouldn't get here");
+
+ // GCC treats vector types as fundamental types.
+ case Type::Builtin:
+ case Type::Vector:
+ case Type::ExtVector:
+ case Type::Complex:
+ case Type::BlockPointer:
+ // Itanium C++ ABI 2.9.5p4:
+ // abi::__fundamental_type_info adds no data members to std::type_info.
+ break;
+
+ case Type::LValueReference:
+ case Type::RValueReference:
+ llvm_unreachable("References shouldn't get here");
+
+ case Type::Auto:
+ llvm_unreachable("Undeduced auto type shouldn't get here");
+
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ case Type::VariableArray:
+ // Itanium C++ ABI 2.9.5p5:
+ // abi::__array_type_info adds no data members to std::type_info.
+ break;
+
+ case Type::FunctionNoProto:
+ case Type::FunctionProto:
+ // Itanium C++ ABI 2.9.5p5:
+ // abi::__function_type_info adds no data members to std::type_info.
+ break;
+
+ case Type::Enum:
+ // Itanium C++ ABI 2.9.5p5:
+ // abi::__enum_type_info adds no data members to std::type_info.
+ break;
+
+ case Type::Record: {
+ const CXXRecordDecl *RD =
+ cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
+ if (!RD->hasDefinition() || !RD->getNumBases()) {
+ // We don't need to emit any fields.
+ break;
+ }
+
+ if (CanUseSingleInheritance(RD))
+ BuildSIClassTypeInfo(RD);
+ else
+ BuildVMIClassTypeInfo(RD);
+
+ break;
+ }
+
+ case Type::ObjCObject:
+ case Type::ObjCInterface:
+ BuildObjCObjectTypeInfo(cast<ObjCObjectType>(Ty));
+ break;
+
+ case Type::ObjCObjectPointer:
+ BuildPointerTypeInfo(cast<ObjCObjectPointerType>(Ty)->getPointeeType());
+ break;
+
+ case Type::Pointer:
+ BuildPointerTypeInfo(cast<PointerType>(Ty)->getPointeeType());
+ break;
+
+ case Type::MemberPointer:
+ BuildPointerToMemberTypeInfo(cast<MemberPointerType>(Ty));
+ break;
+
+ case Type::Atomic:
+ // No fields, at least for the moment.
+ break;
+ }
+
+ llvm::Constant *Init = llvm::ConstantStruct::getAnon(Fields);
+
+ llvm::GlobalVariable *GV =
+ new llvm::GlobalVariable(CGM.getModule(), Init->getType(),
+ /*Constant=*/true, Linkage, Init, Name);
+
+ // If there's already an old global variable, replace it with the new one.
+ if (OldGV) {
+ GV->takeName(OldGV);
+ llvm::Constant *NewPtr =
+ llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
+ OldGV->replaceAllUsesWith(NewPtr);
+ OldGV->eraseFromParent();
+ }
+
+ // The Itanium ABI specifies that type_info objects must be globally
+ // unique, with one exception: if the type is an incomplete class
+ // type or a (possibly indirect) pointer to one. That exception
+ // affects the general case of comparing type_info objects produced
+ // by the typeid operator, which is why the comparison operators on
+ // std::type_info generally use the type_info name pointers instead
+ // of the object addresses. However, the language's built-in uses
+ // of RTTI generally require class types to be complete, even when
+ // manipulating pointers to those class types. This allows the
+ // implementation of dynamic_cast to rely on address equality tests,
+ // which is much faster.
+
+ // All of this is to say that it's important that both the type_info
+ // object and the type_info name be uniqued when weakly emitted.
+
+ // Give the type_info object and name the formal visibility of the
+ // type itself.
+ llvm::GlobalValue::VisibilityTypes llvmVisibility;
+ if (llvm::GlobalValue::isLocalLinkage(Linkage))
+ // If the linkage is local, only default visibility makes sense.
+ llvmVisibility = llvm::GlobalValue::DefaultVisibility;
+ else if (RTTIUniqueness == ItaniumCXXABI::RUK_NonUniqueHidden)
+ llvmVisibility = llvm::GlobalValue::HiddenVisibility;
+ else
+ llvmVisibility = CodeGenModule::GetLLVMVisibility(Ty->getVisibility());
+ TypeName->setVisibility(llvmVisibility);
+ GV->setVisibility(llvmVisibility);
+
+ return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
+}
+
+/// ComputeQualifierFlags - Compute the pointer type info flags from the
+/// given qualifier.
+static unsigned ComputeQualifierFlags(Qualifiers Quals) {
+ unsigned Flags = 0;
+
+ if (Quals.hasConst())
+ Flags |= ItaniumRTTIBuilder::PTI_Const;
+ if (Quals.hasVolatile())
+ Flags |= ItaniumRTTIBuilder::PTI_Volatile;
+ if (Quals.hasRestrict())
+ Flags |= ItaniumRTTIBuilder::PTI_Restrict;
+
+ return Flags;
+}
+
+/// BuildObjCObjectTypeInfo - Build the appropriate kind of type_info
+/// for the given Objective-C object type.
+void ItaniumRTTIBuilder::BuildObjCObjectTypeInfo(const ObjCObjectType *OT) {
+ // Drop qualifiers.
+ const Type *T = OT->getBaseType().getTypePtr();
+ assert(isa<BuiltinType>(T) || isa<ObjCInterfaceType>(T));
+
+ // The builtin types are abi::__class_type_infos and don't require
+ // extra fields.
+ if (isa<BuiltinType>(T)) return;
+
+ ObjCInterfaceDecl *Class = cast<ObjCInterfaceType>(T)->getDecl();
+ ObjCInterfaceDecl *Super = Class->getSuperClass();
+
+ // Root classes are also __class_type_info.
+ if (!Super) return;
+
+ QualType SuperTy = CGM.getContext().getObjCInterfaceType(Super);
+
+ // Everything else is single inheritance.
+ llvm::Constant *BaseTypeInfo =
+ ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(SuperTy);
+ Fields.push_back(BaseTypeInfo);
+}
+
+/// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single
+/// inheritance, according to the Itanium C++ ABI, 2.95p6b.
+void ItaniumRTTIBuilder::BuildSIClassTypeInfo(const CXXRecordDecl *RD) {
+ // Itanium C++ ABI 2.9.5p6b:
+ // It adds to abi::__class_type_info a single member pointing to the
+ // type_info structure for the base type,
+ llvm::Constant *BaseTypeInfo =
+ ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(RD->bases_begin()->getType());
+ Fields.push_back(BaseTypeInfo);
+}
+
+namespace {
+ /// SeenBases - Contains virtual and non-virtual bases seen when traversing
+ /// a class hierarchy.
+ struct SeenBases {
+ llvm::SmallPtrSet<const CXXRecordDecl *, 16> NonVirtualBases;
+ llvm::SmallPtrSet<const CXXRecordDecl *, 16> VirtualBases;
+ };
+}
+
+/// ComputeVMIClassTypeInfoFlags - Compute the value of the flags member in
+/// abi::__vmi_class_type_info.
+///
+static unsigned ComputeVMIClassTypeInfoFlags(const CXXBaseSpecifier *Base,
+ SeenBases &Bases) {
+
+ unsigned Flags = 0;
+
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+
+ if (Base->isVirtual()) {
+ // Mark the virtual base as seen.
+ if (!Bases.VirtualBases.insert(BaseDecl)) {
+ // If this virtual base has been seen before, then the class is diamond
+ // shaped.
+ Flags |= ItaniumRTTIBuilder::VMI_DiamondShaped;
+ } else {
+ if (Bases.NonVirtualBases.count(BaseDecl))
+ Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
+ }
+ } else {
+ // Mark the non-virtual base as seen.
+ if (!Bases.NonVirtualBases.insert(BaseDecl)) {
+ // If this non-virtual base has been seen before, then the class has non-
+ // diamond shaped repeated inheritance.
+ Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
+ } else {
+ if (Bases.VirtualBases.count(BaseDecl))
+ Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
+ }
+ }
+
+ // Walk all bases.
+ for (const auto &I : BaseDecl->bases())
+ Flags |= ComputeVMIClassTypeInfoFlags(&I, Bases);
+
+ return Flags;
+}
+
+static unsigned ComputeVMIClassTypeInfoFlags(const CXXRecordDecl *RD) {
+ unsigned Flags = 0;
+ SeenBases Bases;
+
+ // Walk all bases.
+ for (const auto &I : RD->bases())
+ Flags |= ComputeVMIClassTypeInfoFlags(&I, Bases);
+
+ return Flags;
+}
+
+/// BuildVMIClassTypeInfo - Build an abi::__vmi_class_type_info, used for
+/// classes with bases that do not satisfy the abi::__si_class_type_info
+/// constraints, according ti the Itanium C++ ABI, 2.9.5p5c.
+void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
+ llvm::Type *UnsignedIntLTy =
+ CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
+
+ // Itanium C++ ABI 2.9.5p6c:
+ // __flags is a word with flags describing details about the class
+ // structure, which may be referenced by using the __flags_masks
+ // enumeration. These flags refer to both direct and indirect bases.
+ unsigned Flags = ComputeVMIClassTypeInfoFlags(RD);
+ Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
+
+ // Itanium C++ ABI 2.9.5p6c:
+ // __base_count is a word with the number of direct proper base class
+ // descriptions that follow.
+ Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, RD->getNumBases()));
+
+ if (!RD->getNumBases())
+ return;
+
+ llvm::Type *LongLTy =
+ CGM.getTypes().ConvertType(CGM.getContext().LongTy);
+
+ // Now add the base class descriptions.
+
+ // Itanium C++ ABI 2.9.5p6c:
+ // __base_info[] is an array of base class descriptions -- one for every
+ // direct proper base. Each description is of the type:
+ //
+ // struct abi::__base_class_type_info {
+ // public:
+ // const __class_type_info *__base_type;
+ // long __offset_flags;
+ //
+ // enum __offset_flags_masks {
+ // __virtual_mask = 0x1,
+ // __public_mask = 0x2,
+ // __offset_shift = 8
+ // };
+ // };
+ for (const auto &Base : RD->bases()) {
+ // The __base_type member points to the RTTI for the base type.
+ Fields.push_back(ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(Base.getType()));
+
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
+
+ int64_t OffsetFlags = 0;
+
+ // All but the lower 8 bits of __offset_flags are a signed offset.
+ // For a non-virtual base, this is the offset in the object of the base
+ // subobject. For a virtual base, this is the offset in the virtual table of
+ // the virtual base offset for the virtual base referenced (negative).
+ CharUnits Offset;
+ if (Base.isVirtual())
+ Offset =
+ CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(RD, BaseDecl);
+ else {
+ const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
+ Offset = Layout.getBaseClassOffset(BaseDecl);
+ };
+
+ OffsetFlags = uint64_t(Offset.getQuantity()) << 8;
+
+ // The low-order byte of __offset_flags contains flags, as given by the
+ // masks from the enumeration __offset_flags_masks.
+ if (Base.isVirtual())
+ OffsetFlags |= BCTI_Virtual;
+ if (Base.getAccessSpecifier() == AS_public)
+ OffsetFlags |= BCTI_Public;
+
+ Fields.push_back(llvm::ConstantInt::get(LongLTy, OffsetFlags));
+ }
+}
+
+/// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct,
+/// used for pointer types.
+void ItaniumRTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) {
+ Qualifiers Quals;
+ QualType UnqualifiedPointeeTy =
+ CGM.getContext().getUnqualifiedArrayType(PointeeTy, Quals);
+
+ // Itanium C++ ABI 2.9.5p7:
+ // __flags is a flag word describing the cv-qualification and other
+ // attributes of the type pointed to
+ unsigned Flags = ComputeQualifierFlags(Quals);
+
+ // Itanium C++ ABI 2.9.5p7:
+ // When the abi::__pbase_type_info is for a direct or indirect pointer to an
+ // incomplete class type, the incomplete target type flag is set.
+ if (ContainsIncompleteClassType(UnqualifiedPointeeTy))
+ Flags |= PTI_Incomplete;
+
+ llvm::Type *UnsignedIntLTy =
+ CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
+ Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
+
+ // Itanium C++ ABI 2.9.5p7:
+ // __pointee is a pointer to the std::type_info derivation for the
+ // unqualified type being pointed to.
+ llvm::Constant *PointeeTypeInfo =
+ ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(UnqualifiedPointeeTy);
+ Fields.push_back(PointeeTypeInfo);
+}
+
+/// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info
+/// struct, used for member pointer types.
+void
+ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {
+ QualType PointeeTy = Ty->getPointeeType();
+
+ Qualifiers Quals;
+ QualType UnqualifiedPointeeTy =
+ CGM.getContext().getUnqualifiedArrayType(PointeeTy, Quals);
+
+ // Itanium C++ ABI 2.9.5p7:
+ // __flags is a flag word describing the cv-qualification and other
+ // attributes of the type pointed to.
+ unsigned Flags = ComputeQualifierFlags(Quals);
+
+ const RecordType *ClassType = cast<RecordType>(Ty->getClass());
+
+ // Itanium C++ ABI 2.9.5p7:
+ // When the abi::__pbase_type_info is for a direct or indirect pointer to an
+ // incomplete class type, the incomplete target type flag is set.
+ if (ContainsIncompleteClassType(UnqualifiedPointeeTy))
+ Flags |= PTI_Incomplete;
+
+ if (IsIncompleteClassType(ClassType))
+ Flags |= PTI_ContainingClassIncomplete;
+
+ llvm::Type *UnsignedIntLTy =
+ CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
+ Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
+
+ // Itanium C++ ABI 2.9.5p7:
+ // __pointee is a pointer to the std::type_info derivation for the
+ // unqualified type being pointed to.
+ llvm::Constant *PointeeTypeInfo =
+ ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(UnqualifiedPointeeTy);
+ Fields.push_back(PointeeTypeInfo);
+
+ // Itanium C++ ABI 2.9.5p9:
+ // __context is a pointer to an abi::__class_type_info corresponding to the
+ // class type containing the member pointed to
+ // (e.g., the "A" in "int A::*").
+ Fields.push_back(
+ ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(QualType(ClassType, 0)));
+}
+
+llvm::Constant *ItaniumCXXABI::getAddrOfRTTIDescriptor(QualType Ty) {
+ return ItaniumRTTIBuilder(*this).BuildTypeInfo(Ty);
+}
+
+void ItaniumCXXABI::EmitFundamentalRTTIDescriptor(QualType Type) {
+ QualType PointerType = getContext().getPointerType(Type);
+ QualType PointerTypeConst = getContext().getPointerType(Type.withConst());
+ ItaniumRTTIBuilder(*this).BuildTypeInfo(Type, true);
+ ItaniumRTTIBuilder(*this).BuildTypeInfo(PointerType, true);
+ ItaniumRTTIBuilder(*this).BuildTypeInfo(PointerTypeConst, true);
+}
+
+void ItaniumCXXABI::EmitFundamentalRTTIDescriptors() {
+ QualType FundamentalTypes[] = {
+ getContext().VoidTy, getContext().NullPtrTy,
+ getContext().BoolTy, getContext().WCharTy,
+ getContext().CharTy, getContext().UnsignedCharTy,
+ getContext().SignedCharTy, getContext().ShortTy,
+ getContext().UnsignedShortTy, getContext().IntTy,
+ getContext().UnsignedIntTy, getContext().LongTy,
+ getContext().UnsignedLongTy, getContext().LongLongTy,
+ getContext().UnsignedLongLongTy, getContext().HalfTy,
+ getContext().FloatTy, getContext().DoubleTy,
+ getContext().LongDoubleTy, getContext().Char16Ty,
+ getContext().Char32Ty,
+ };
+ for (const QualType &FundamentalType : FundamentalTypes)
+ EmitFundamentalRTTIDescriptor(FundamentalType);
+}
+
+/// What sort of uniqueness rules should we use for the RTTI for the
+/// given type?
+ItaniumCXXABI::RTTIUniquenessKind ItaniumCXXABI::classifyRTTIUniqueness(
+ QualType CanTy, llvm::GlobalValue::LinkageTypes Linkage) const {
+ if (shouldRTTIBeUnique())
+ return RUK_Unique;
+
+ // It's only necessary for linkonce_odr or weak_odr linkage.
+ if (Linkage != llvm::GlobalValue::LinkOnceODRLinkage &&
+ Linkage != llvm::GlobalValue::WeakODRLinkage)
+ return RUK_Unique;
+
+ // It's only necessary with default visibility.
+ if (CanTy->getVisibility() != DefaultVisibility)
+ return RUK_Unique;
+
+ // If we're not required to publish this symbol, hide it.
+ if (Linkage == llvm::GlobalValue::LinkOnceODRLinkage)
+ return RUK_NonUniqueHidden;
+
+ // If we're required to publish this symbol, as we might be under an
+ // explicit instantiation, leave it with default visibility but
+ // enable string-comparisons.
+ assert(Linkage == llvm::GlobalValue::WeakODRLinkage);
+ return RUK_NonUniqueVisible;
+}
diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp
index dee565a..5243864 100644
--- a/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -20,7 +20,9 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/VTableBuilder.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/IR/CallSite.h"
using namespace clang;
using namespace CodeGen;
@@ -35,7 +37,10 @@
class MicrosoftCXXABI : public CGCXXABI {
public:
- MicrosoftCXXABI(CodeGenModule &CGM) : CGCXXABI(CGM) {}
+ MicrosoftCXXABI(CodeGenModule &CGM)
+ : CGCXXABI(CGM), BaseClassDescriptorType(nullptr),
+ ClassHierarchyDescriptorType(nullptr),
+ CompleteObjectLocatorType(nullptr) {}
bool HasThisReturn(GlobalDecl GD) const override;
@@ -56,6 +61,31 @@
llvm::Value *ptr,
QualType type) override;
+ llvm::GlobalVariable *getMSCompleteObjectLocator(const CXXRecordDecl *RD,
+ const VPtrInfo *Info);
+
+ llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) override;
+
+ bool shouldTypeidBeNullChecked(bool IsDeref, QualType SrcRecordTy) override;
+ void EmitBadTypeidCall(CodeGenFunction &CGF) override;
+ llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy,
+ llvm::Value *ThisPtr,
+ llvm::Type *StdTypeInfoPtrTy) override;
+
+ bool shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
+ QualType SrcRecordTy) override;
+
+ llvm::Value *EmitDynamicCastCall(CodeGenFunction &CGF, llvm::Value *Value,
+ QualType SrcRecordTy, QualType DestTy,
+ QualType DestRecordTy,
+ llvm::BasicBlock *CastEnd) override;
+
+ llvm::Value *EmitDynamicCastToVoid(CodeGenFunction &CGF, llvm::Value *Value,
+ QualType SrcRecordTy,
+ QualType DestTy) override;
+
+ bool EmitBadCastCall(CodeGenFunction &CGF) override;
+
llvm::Value *
GetVirtualBaseClassOffset(CodeGenFunction &CGF, llvm::Value *This,
const CXXRecordDecl *ClassDecl,
@@ -201,8 +231,20 @@
void emitVBTableDefinition(const VPtrInfo &VBT, const CXXRecordDecl *RD,
llvm::GlobalVariable *GV) const;
- void setThunkLinkage(llvm::Function *Thunk, bool ForVTable) override {
- Thunk->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
+ void setThunkLinkage(llvm::Function *Thunk, bool ForVTable,
+ GlobalDecl GD, bool ReturnAdjustment) override {
+ // Never dllimport/dllexport thunks.
+ Thunk->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
+
+ GVALinkage Linkage =
+ getContext().GetGVALinkageForFunction(cast<FunctionDecl>(GD.getDecl()));
+
+ if (Linkage == GVA_Internal)
+ Thunk->setLinkage(llvm::GlobalValue::InternalLinkage);
+ else if (ReturnAdjustment)
+ Thunk->setLinkage(llvm::GlobalValue::WeakODRLinkage);
+ else
+ Thunk->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage);
}
llvm::Value *performThisAdjustment(CodeGenFunction &CGF, llvm::Value *This,
@@ -251,6 +293,114 @@
llvm::Value *allocPtr,
CharUnits cookieSize) override;
+ friend struct MSRTTIBuilder;
+
+ bool isImageRelative() const {
+ return CGM.getTarget().getPointerWidth(/*AddressSpace=*/0) == 64;
+ }
+
+ // 5 routines for constructing the llvm types for MS RTTI structs.
+ llvm::StructType *getTypeDescriptorType(StringRef TypeInfoString) {
+ llvm::SmallString<32> TDTypeName("rtti.TypeDescriptor");
+ TDTypeName += llvm::utostr(TypeInfoString.size());
+ llvm::StructType *&TypeDescriptorType =
+ TypeDescriptorTypeMap[TypeInfoString.size()];
+ if (TypeDescriptorType)
+ return TypeDescriptorType;
+ llvm::Type *FieldTypes[] = {
+ CGM.Int8PtrPtrTy,
+ CGM.Int8PtrTy,
+ llvm::ArrayType::get(CGM.Int8Ty, TypeInfoString.size() + 1)};
+ TypeDescriptorType =
+ llvm::StructType::create(CGM.getLLVMContext(), FieldTypes, TDTypeName);
+ return TypeDescriptorType;
+ }
+
+ llvm::Type *getImageRelativeType(llvm::Type *PtrType) {
+ if (!isImageRelative())
+ return PtrType;
+ return CGM.IntTy;
+ }
+
+ llvm::StructType *getBaseClassDescriptorType() {
+ if (BaseClassDescriptorType)
+ return BaseClassDescriptorType;
+ llvm::Type *FieldTypes[] = {
+ getImageRelativeType(CGM.Int8PtrTy),
+ CGM.IntTy,
+ CGM.IntTy,
+ CGM.IntTy,
+ CGM.IntTy,
+ CGM.IntTy,
+ getImageRelativeType(getClassHierarchyDescriptorType()->getPointerTo()),
+ };
+ BaseClassDescriptorType = llvm::StructType::create(
+ CGM.getLLVMContext(), FieldTypes, "rtti.BaseClassDescriptor");
+ return BaseClassDescriptorType;
+ }
+
+ llvm::StructType *getClassHierarchyDescriptorType() {
+ if (ClassHierarchyDescriptorType)
+ return ClassHierarchyDescriptorType;
+ // Forward-declare RTTIClassHierarchyDescriptor to break a cycle.
+ ClassHierarchyDescriptorType = llvm::StructType::create(
+ CGM.getLLVMContext(), "rtti.ClassHierarchyDescriptor");
+ llvm::Type *FieldTypes[] = {
+ CGM.IntTy,
+ CGM.IntTy,
+ CGM.IntTy,
+ getImageRelativeType(
+ getBaseClassDescriptorType()->getPointerTo()->getPointerTo()),
+ };
+ ClassHierarchyDescriptorType->setBody(FieldTypes);
+ return ClassHierarchyDescriptorType;
+ }
+
+ llvm::StructType *getCompleteObjectLocatorType() {
+ if (CompleteObjectLocatorType)
+ return CompleteObjectLocatorType;
+ CompleteObjectLocatorType = llvm::StructType::create(
+ CGM.getLLVMContext(), "rtti.CompleteObjectLocator");
+ llvm::Type *FieldTypes[] = {
+ CGM.IntTy,
+ CGM.IntTy,
+ CGM.IntTy,
+ getImageRelativeType(CGM.Int8PtrTy),
+ getImageRelativeType(getClassHierarchyDescriptorType()->getPointerTo()),
+ getImageRelativeType(CompleteObjectLocatorType),
+ };
+ llvm::ArrayRef<llvm::Type *> FieldTypesRef(FieldTypes);
+ if (!isImageRelative())
+ FieldTypesRef = FieldTypesRef.drop_back();
+ CompleteObjectLocatorType->setBody(FieldTypesRef);
+ return CompleteObjectLocatorType;
+ }
+
+ llvm::GlobalVariable *getImageBase() {
+ StringRef Name = "__ImageBase";
+ if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name))
+ return GV;
+
+ return new llvm::GlobalVariable(CGM.getModule(), CGM.Int8Ty,
+ /*isConstant=*/true,
+ llvm::GlobalValue::ExternalLinkage,
+ /*Initializer=*/nullptr, Name);
+ }
+
+ llvm::Constant *getImageRelativeConstant(llvm::Constant *PtrVal) {
+ if (!isImageRelative())
+ return PtrVal;
+
+ llvm::Constant *ImageBaseAsInt =
+ llvm::ConstantExpr::getPtrToInt(getImageBase(), CGM.IntPtrTy);
+ llvm::Constant *PtrValAsInt =
+ llvm::ConstantExpr::getPtrToInt(PtrVal, CGM.IntPtrTy);
+ llvm::Constant *Diff =
+ llvm::ConstantExpr::getSub(PtrValAsInt, ImageBaseAsInt,
+ /*HasNUW=*/true, /*HasNSW=*/true);
+ return llvm::ConstantExpr::getTrunc(Diff, CGM.IntTy);
+ }
+
private:
MicrosoftMangleContext &getMangleContext() {
return cast<MicrosoftMangleContext>(CodeGen::CGCXXABI::getMangleContext());
@@ -370,9 +520,11 @@
private:
typedef std::pair<const CXXRecordDecl *, CharUnits> VFTableIdTy;
- typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalVariable *> VFTablesMapTy;
+ typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalVariable *> VTablesMapTy;
+ typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalValue *> VFTablesMapTy;
/// \brief All the vftables that have been referenced.
VFTablesMapTy VFTablesMap;
+ VTablesMapTy VTablesMap;
/// \brief This set holds the record decls we've deferred vtable emission for.
llvm::SmallPtrSet<const CXXRecordDecl *, 4> DeferredVFTables;
@@ -392,6 +544,11 @@
/// 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;
+
+ llvm::DenseMap<size_t, llvm::StructType *> TypeDescriptorTypeMap;
+ llvm::StructType *BaseClassDescriptorType;
+ llvm::StructType *ClassHierarchyDescriptorType;
+ llvm::StructType *CompleteObjectLocatorType;
};
}
@@ -457,6 +614,129 @@
return ptr;
}
+/// \brief Gets the offset to the virtual base that contains the vfptr for
+/// MS-ABI polymorphic types.
+static llvm::Value *getPolymorphicOffset(CodeGenFunction &CGF,
+ const CXXRecordDecl *RD,
+ llvm::Value *Value) {
+ const ASTContext &Context = RD->getASTContext();
+ for (const CXXBaseSpecifier &Base : RD->vbases())
+ if (Context.getASTRecordLayout(Base.getType()->getAsCXXRecordDecl())
+ .hasExtendableVFPtr())
+ return CGF.CGM.getCXXABI().GetVirtualBaseClassOffset(
+ CGF, Value, RD, Base.getType()->getAsCXXRecordDecl());
+ llvm_unreachable("One of our vbases should be polymorphic.");
+}
+
+static std::pair<llvm::Value *, llvm::Value *>
+performBaseAdjustment(CodeGenFunction &CGF, llvm::Value *Value,
+ QualType SrcRecordTy) {
+ Value = CGF.Builder.CreateBitCast(Value, CGF.Int8PtrTy);
+ const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl();
+
+ if (CGF.getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr())
+ return std::make_pair(Value, llvm::ConstantInt::get(CGF.Int32Ty, 0));
+
+ // Perform a base adjustment.
+ llvm::Value *Offset = getPolymorphicOffset(CGF, SrcDecl, Value);
+ Value = CGF.Builder.CreateInBoundsGEP(Value, Offset);
+ Offset = CGF.Builder.CreateTrunc(Offset, CGF.Int32Ty);
+ return std::make_pair(Value, Offset);
+}
+
+bool MicrosoftCXXABI::shouldTypeidBeNullChecked(bool IsDeref,
+ QualType SrcRecordTy) {
+ const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl();
+ return IsDeref &&
+ !CGM.getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr();
+}
+
+static llvm::CallSite emitRTtypeidCall(CodeGenFunction &CGF,
+ llvm::Value *Argument) {
+ llvm::Type *ArgTypes[] = {CGF.Int8PtrTy};
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(CGF.Int8PtrTy, ArgTypes, false);
+ llvm::Value *Args[] = {Argument};
+ llvm::Constant *Fn = CGF.CGM.CreateRuntimeFunction(FTy, "__RTtypeid");
+ return CGF.EmitRuntimeCallOrInvoke(Fn, Args);
+}
+
+void MicrosoftCXXABI::EmitBadTypeidCall(CodeGenFunction &CGF) {
+ llvm::CallSite Call =
+ emitRTtypeidCall(CGF, llvm::Constant::getNullValue(CGM.VoidPtrTy));
+ Call.setDoesNotReturn();
+ CGF.Builder.CreateUnreachable();
+}
+
+llvm::Value *MicrosoftCXXABI::EmitTypeid(CodeGenFunction &CGF,
+ QualType SrcRecordTy,
+ llvm::Value *ThisPtr,
+ llvm::Type *StdTypeInfoPtrTy) {
+ llvm::Value *Offset;
+ std::tie(ThisPtr, Offset) = performBaseAdjustment(CGF, ThisPtr, SrcRecordTy);
+ return CGF.Builder.CreateBitCast(
+ emitRTtypeidCall(CGF, ThisPtr).getInstruction(), StdTypeInfoPtrTy);
+}
+
+bool MicrosoftCXXABI::shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
+ QualType SrcRecordTy) {
+ const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl();
+ return SrcIsPtr &&
+ !CGM.getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr();
+}
+
+llvm::Value *MicrosoftCXXABI::EmitDynamicCastCall(
+ CodeGenFunction &CGF, llvm::Value *Value, QualType SrcRecordTy,
+ QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastEnd) {
+ llvm::Type *DestLTy = CGF.ConvertType(DestTy);
+
+ llvm::Value *SrcRTTI =
+ CGF.CGM.GetAddrOfRTTIDescriptor(SrcRecordTy.getUnqualifiedType());
+ llvm::Value *DestRTTI =
+ CGF.CGM.GetAddrOfRTTIDescriptor(DestRecordTy.getUnqualifiedType());
+
+ llvm::Value *Offset;
+ std::tie(Value, Offset) = performBaseAdjustment(CGF, Value, SrcRecordTy);
+
+ // PVOID __RTDynamicCast(
+ // PVOID inptr,
+ // LONG VfDelta,
+ // PVOID SrcType,
+ // PVOID TargetType,
+ // BOOL isReference)
+ llvm::Type *ArgTypes[] = {CGF.Int8PtrTy, CGF.Int32Ty, CGF.Int8PtrTy,
+ CGF.Int8PtrTy, CGF.Int32Ty};
+ llvm::Constant *Function = CGF.CGM.CreateRuntimeFunction(
+ llvm::FunctionType::get(CGF.Int8PtrTy, ArgTypes, false),
+ "__RTDynamicCast");
+ llvm::Value *Args[] = {
+ Value, Offset, SrcRTTI, DestRTTI,
+ llvm::ConstantInt::get(CGF.Int32Ty, DestTy->isReferenceType())};
+ Value = CGF.EmitRuntimeCallOrInvoke(Function, Args).getInstruction();
+ return CGF.Builder.CreateBitCast(Value, DestLTy);
+}
+
+llvm::Value *
+MicrosoftCXXABI::EmitDynamicCastToVoid(CodeGenFunction &CGF, llvm::Value *Value,
+ QualType SrcRecordTy,
+ QualType DestTy) {
+ llvm::Value *Offset;
+ std::tie(Value, Offset) = performBaseAdjustment(CGF, Value, SrcRecordTy);
+
+ // PVOID __RTCastToVoid(
+ // PVOID inptr)
+ llvm::Type *ArgTypes[] = {CGF.Int8PtrTy};
+ llvm::Constant *Function = CGF.CGM.CreateRuntimeFunction(
+ llvm::FunctionType::get(CGF.Int8PtrTy, ArgTypes, false),
+ "__RTCastToVoid");
+ llvm::Value *Args[] = {Value};
+ return CGF.EmitRuntimeCall(Function, Args);
+}
+
+bool MicrosoftCXXABI::EmitBadCastCall(CodeGenFunction &CGF) {
+ return false;
+}
+
llvm::Value *
MicrosoftCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF,
llvm::Value *This,
@@ -895,25 +1175,22 @@
const CXXRecordDecl *RD) {
MicrosoftVTableContext &VFTContext = CGM.getMicrosoftVTableContext();
VPtrInfoVector VFPtrs = VFTContext.getVFPtrOffsets(RD);
- llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD);
for (VPtrInfo *Info : VFPtrs) {
llvm::GlobalVariable *VTable = getAddrOfVTable(RD, Info->FullOffsetInMDC);
if (VTable->hasInitializer())
continue;
- if (getContext().getLangOpts().RTTI)
- CGM.getMSCompleteObjectLocator(RD, Info);
+
+ llvm::Constant *RTTI = getMSCompleteObjectLocator(RD, Info);
const VTableLayout &VTLayout =
VFTContext.getVFTableLayout(RD, Info->FullOffsetInMDC);
llvm::Constant *Init = CGVT.CreateVTableInitializer(
RD, VTLayout.vtable_component_begin(),
VTLayout.getNumVTableComponents(), VTLayout.vtable_thunk_begin(),
- VTLayout.getNumVTableThunks());
- VTable->setInitializer(Init);
+ VTLayout.getNumVTableThunks(), RTTI);
- VTable->setLinkage(Linkage);
- CGM.setGlobalVisibility(VTable, RD);
+ VTable->setInitializer(Init);
}
}
@@ -922,8 +1199,9 @@
const CXXRecordDecl *NearestVBase, bool &NeedsVirtualOffset) {
NeedsVirtualOffset = (NearestVBase != nullptr);
- llvm::Value *VTableAddressPoint =
- getAddrOfVTable(VTableClass, Base.getBaseOffset());
+ (void)getAddrOfVTable(VTableClass, Base.getBaseOffset());
+ VFTableIdTy ID(VTableClass, Base.getBaseOffset());
+ llvm::GlobalValue *VTableAddressPoint = VFTablesMap[ID];
if (!VTableAddressPoint) {
assert(Base.getBase()->getNumVBases() &&
!CGM.getContext().getASTRecordLayout(Base.getBase()).hasOwnVFPtr());
@@ -940,9 +1218,11 @@
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;
+ (void)getAddrOfVTable(VTableClass, Base.getBaseOffset());
+ VFTableIdTy ID(VTableClass, Base.getBaseOffset());
+ llvm::GlobalValue *VFTable = VFTablesMap[ID];
+ assert(VFTable && "Couldn't find a vftable for the given base?");
+ return VFTable;
}
llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
@@ -951,9 +1231,9 @@
// 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;
+ VTablesMapTy::iterator I;
bool Inserted;
- std::tie(I, Inserted) = VFTablesMap.insert(std::make_pair(ID, nullptr));
+ std::tie(I, Inserted) = VTablesMap.insert(std::make_pair(ID, nullptr));
if (!Inserted)
return I->second;
@@ -983,17 +1263,94 @@
for (size_t J = 0, F = VFPtrs.size(); J != F; ++J) {
if (VFPtrs[J]->FullOffsetInMDC != VPtrOffset)
continue;
+ SmallString<256> VFTableName;
+ mangleVFTableName(getMangleContext(), RD, VFPtrs[J], VFTableName);
+ StringRef VTableName = VFTableName;
- llvm::ArrayType *ArrayType = llvm::ArrayType::get(
- CGM.Int8PtrTy,
+ uint64_t NumVTableSlots =
VTContext.getVFTableLayout(RD, VFPtrs[J]->FullOffsetInMDC)
- .getNumVTableComponents());
+ .getNumVTableComponents();
+ llvm::GlobalValue::LinkageTypes VTableLinkage =
+ llvm::GlobalValue::ExternalLinkage;
+ llvm::ArrayType *VTableType =
+ llvm::ArrayType::get(CGM.Int8PtrTy, NumVTableSlots);
+ if (getContext().getLangOpts().RTTIData) {
+ VTableLinkage = llvm::GlobalValue::PrivateLinkage;
+ VTableName = "";
+ }
- SmallString<256> Name;
- mangleVFTableName(getMangleContext(), RD, VFPtrs[J], Name);
- VTable = CGM.CreateOrReplaceCXXRuntimeVariable(
- Name.str(), ArrayType, llvm::GlobalValue::ExternalLinkage);
- VTable->setUnnamedAddr(true);
+ VTable = CGM.getModule().getNamedGlobal(VFTableName);
+ if (!VTable) {
+ // Create a backing variable for the contents of VTable. The VTable may
+ // or may not include space for a pointer to RTTI data.
+ llvm::GlobalValue *VFTable = VTable = new llvm::GlobalVariable(
+ CGM.getModule(), VTableType, /*isConstant=*/true, VTableLinkage,
+ /*Initializer=*/nullptr, VTableName);
+ VTable->setUnnamedAddr(true);
+
+ // Only insert a pointer into the VFTable for RTTI data if we are not
+ // importing it. We never reference the RTTI data directly so there is no
+ // need to make room for it.
+ if (getContext().getLangOpts().RTTIData &&
+ !RD->hasAttr<DLLImportAttr>()) {
+ llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.IntTy, 0),
+ llvm::ConstantInt::get(CGM.IntTy, 1)};
+ // Create a GEP which points just after the first entry in the VFTable,
+ // this should be the location of the first virtual method.
+ llvm::Constant *VTableGEP =
+ llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, GEPIndices);
+ // The symbol for the VFTable is an alias to the GEP. It is
+ // transparent, to other modules, what the nature of this symbol is; all
+ // that matters is that the alias be the address of the first virtual
+ // method.
+ VFTable = llvm::GlobalAlias::create(
+ cast<llvm::SequentialType>(VTableGEP->getType())->getElementType(),
+ /*AddressSpace=*/0, llvm::GlobalValue::ExternalLinkage,
+ VFTableName.str(), VTableGEP, &CGM.getModule());
+ } else {
+ // We don't need a GlobalAlias to be a symbol for the VTable if we won't
+ // be referencing any RTTI data. The GlobalVariable will end up being
+ // an appropriate definition of the VFTable.
+ VTable->setName(VFTableName.str());
+ }
+
+ VFTable->setUnnamedAddr(true);
+ if (RD->hasAttr<DLLImportAttr>())
+ VFTable->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
+ else if (RD->hasAttr<DLLExportAttr>())
+ VFTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
+
+ llvm::GlobalValue::LinkageTypes VFTableLinkage = CGM.getVTableLinkage(RD);
+ if (VFTable != VTable) {
+ if (llvm::GlobalValue::isAvailableExternallyLinkage(VFTableLinkage)) {
+ // AvailableExternally implies that we grabbed the data from another
+ // executable. No need to stick the alias in a Comdat.
+ } else if (llvm::GlobalValue::isLocalLinkage(VFTableLinkage)) {
+ // If it's local, it means that the virtual function table can't be
+ // referenced in another translation unit. No need to stick the alias
+ // in a Comdat.
+ } else if (llvm::GlobalValue::isWeakODRLinkage(VFTableLinkage) ||
+ llvm::GlobalValue::isLinkOnceODRLinkage(VFTableLinkage)) {
+ // The alias is going to be dropped into a Comdat, no need to make it
+ // weak.
+ VFTableLinkage = llvm::GlobalValue::ExternalLinkage;
+ llvm::Comdat *C =
+ CGM.getModule().getOrInsertComdat(VFTable->getName());
+ // We must indicate which VFTable is larger to support linking between
+ // translation units which do and do not have RTTI data. The largest
+ // VFTable contains the RTTI data; translation units which reference
+ // the smaller VFTable always reference it relative to the first
+ // virtual method.
+ C->setSelectionKind(llvm::Comdat::Largest);
+ VTable->setComdat(C);
+ } else {
+ llvm_unreachable("unexpected linkage for vftable!");
+ }
+ }
+ VFTable->setLinkage(VFTableLinkage);
+ CGM.setGlobalVisibility(VFTable, RD);
+ VFTablesMap[ID] = VFTable;
+ }
break;
}
@@ -1155,9 +1512,7 @@
llvm::GlobalVariable::LinkageTypes Linkage) {
SmallString<256> OutName;
llvm::raw_svector_ostream Out(OutName);
- MicrosoftMangleContext &Mangler =
- cast<MicrosoftMangleContext>(CGM.getCXXABI().getMangleContext());
- Mangler.mangleCXXVBTable(RD, VBT.MangledPath, Out);
+ getMangleContext().mangleCXXVBTable(RD, VBT.MangledPath, Out);
Out.flush();
StringRef Name = OutName.str();
@@ -1169,6 +1524,12 @@
llvm::GlobalVariable *GV =
CGM.CreateOrReplaceCXXRuntimeVariable(Name, VBTableType, Linkage);
GV->setUnnamedAddr(true);
+
+ if (RD->hasAttr<DLLImportAttr>())
+ GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
+ else if (RD->hasAttr<DLLExportAttr>())
+ GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
+
return GV;
}
@@ -1402,12 +1763,13 @@
Out.flush();
}
- // Create the guard variable with a zero-initializer. Just absorb linkage
- // and visibility from the guarded variable.
+ // Create the guard variable with a zero-initializer. Just absorb linkage,
+ // visibility and dll storage class from the guarded variable.
GI->Guard =
new llvm::GlobalVariable(CGM.getModule(), GuardTy, false,
GV->getLinkage(), Zero, GuardName.str());
GI->Guard->setVisibility(GV->getVisibility());
+ GI->Guard->setDLLStorageClass(GV->getDLLStorageClass());
} else {
assert(GI->Guard->getLinkage() == GV->getLinkage() &&
"static local from the same function had different linkage");
@@ -2122,3 +2484,398 @@
CGCXXABI *clang::CodeGen::CreateMicrosoftCXXABI(CodeGenModule &CGM) {
return new MicrosoftCXXABI(CGM);
}
+
+// MS RTTI Overview:
+// The run time type information emitted by cl.exe contains 5 distinct types of
+// structures. Many of them reference each other.
+//
+// TypeInfo: Static classes that are returned by typeid.
+//
+// CompleteObjectLocator: Referenced by vftables. They contain information
+// required for dynamic casting, including OffsetFromTop. They also contain
+// a reference to the TypeInfo for the type and a reference to the
+// CompleteHierarchyDescriptor for the type.
+//
+// ClassHieararchyDescriptor: Contains information about a class hierarchy.
+// Used during dynamic_cast to walk a class hierarchy. References a base
+// class array and the size of said array.
+//
+// BaseClassArray: Contains a list of classes in a hierarchy. BaseClassArray is
+// somewhat of a misnomer because the most derived class is also in the list
+// as well as multiple copies of virtual bases (if they occur multiple times
+// in the hiearchy.) The BaseClassArray contains one BaseClassDescriptor for
+// every path in the hierarchy, in pre-order depth first order. Note, we do
+// not declare a specific llvm type for BaseClassArray, it's merely an array
+// of BaseClassDescriptor pointers.
+//
+// BaseClassDescriptor: Contains information about a class in a class hierarchy.
+// BaseClassDescriptor is also somewhat of a misnomer for the same reason that
+// BaseClassArray is. It contains information about a class within a
+// hierarchy such as: is this base is ambiguous and what is its offset in the
+// vbtable. The names of the BaseClassDescriptors have all of their fields
+// mangled into them so they can be aggressively deduplicated by the linker.
+
+static llvm::GlobalVariable *getTypeInfoVTable(CodeGenModule &CGM) {
+ StringRef MangledName("\01??_7type_info@@6B@");
+ if (auto VTable = CGM.getModule().getNamedGlobal(MangledName))
+ return VTable;
+ return new llvm::GlobalVariable(CGM.getModule(), CGM.Int8PtrTy,
+ /*Constant=*/true,
+ llvm::GlobalVariable::ExternalLinkage,
+ /*Initializer=*/nullptr, MangledName);
+}
+
+namespace {
+
+/// \brief A Helper struct that stores information about a class in a class
+/// hierarchy. The information stored in these structs struct is used during
+/// the generation of ClassHierarchyDescriptors and BaseClassDescriptors.
+// During RTTI creation, MSRTTIClasses are stored in a contiguous array with
+// implicit depth first pre-order tree connectivity. getFirstChild and
+// getNextSibling allow us to walk the tree efficiently.
+struct MSRTTIClass {
+ enum {
+ IsPrivateOnPath = 1 | 8,
+ IsAmbiguous = 2,
+ IsPrivate = 4,
+ IsVirtual = 16,
+ HasHierarchyDescriptor = 64
+ };
+ MSRTTIClass(const CXXRecordDecl *RD) : RD(RD) {}
+ uint32_t initialize(const MSRTTIClass *Parent,
+ const CXXBaseSpecifier *Specifier);
+
+ MSRTTIClass *getFirstChild() { return this + 1; }
+ static MSRTTIClass *getNextChild(MSRTTIClass *Child) {
+ return Child + 1 + Child->NumBases;
+ }
+
+ const CXXRecordDecl *RD, *VirtualRoot;
+ uint32_t Flags, NumBases, OffsetInVBase;
+};
+
+/// \brief Recursively initialize the base class array.
+uint32_t MSRTTIClass::initialize(const MSRTTIClass *Parent,
+ const CXXBaseSpecifier *Specifier) {
+ Flags = HasHierarchyDescriptor;
+ if (!Parent) {
+ VirtualRoot = nullptr;
+ OffsetInVBase = 0;
+ } else {
+ if (Specifier->getAccessSpecifier() != AS_public)
+ Flags |= IsPrivate | IsPrivateOnPath;
+ if (Specifier->isVirtual()) {
+ Flags |= IsVirtual;
+ VirtualRoot = RD;
+ OffsetInVBase = 0;
+ } else {
+ if (Parent->Flags & IsPrivateOnPath)
+ Flags |= IsPrivateOnPath;
+ VirtualRoot = Parent->VirtualRoot;
+ OffsetInVBase = Parent->OffsetInVBase + RD->getASTContext()
+ .getASTRecordLayout(Parent->RD).getBaseClassOffset(RD).getQuantity();
+ }
+ }
+ NumBases = 0;
+ MSRTTIClass *Child = getFirstChild();
+ for (const CXXBaseSpecifier &Base : RD->bases()) {
+ NumBases += Child->initialize(this, &Base) + 1;
+ Child = getNextChild(Child);
+ }
+ return NumBases;
+}
+
+static llvm::GlobalValue::LinkageTypes getLinkageForRTTI(QualType Ty) {
+ switch (Ty->getLinkage()) {
+ case NoLinkage:
+ case InternalLinkage:
+ case UniqueExternalLinkage:
+ return llvm::GlobalValue::InternalLinkage;
+
+ case VisibleNoLinkage:
+ case ExternalLinkage:
+ return llvm::GlobalValue::LinkOnceODRLinkage;
+ }
+ llvm_unreachable("Invalid linkage!");
+}
+
+/// \brief An ephemeral helper class for building MS RTTI types. It caches some
+/// calls to the module and information about the most derived class in a
+/// hierarchy.
+struct MSRTTIBuilder {
+ enum {
+ HasBranchingHierarchy = 1,
+ HasVirtualBranchingHierarchy = 2,
+ HasAmbiguousBases = 4
+ };
+
+ MSRTTIBuilder(MicrosoftCXXABI &ABI, const CXXRecordDecl *RD)
+ : CGM(ABI.CGM), Context(CGM.getContext()),
+ VMContext(CGM.getLLVMContext()), Module(CGM.getModule()), RD(RD),
+ Linkage(getLinkageForRTTI(CGM.getContext().getTagDeclType(RD))),
+ ABI(ABI) {}
+
+ llvm::GlobalVariable *getBaseClassDescriptor(const MSRTTIClass &Classes);
+ llvm::GlobalVariable *
+ getBaseClassArray(SmallVectorImpl<MSRTTIClass> &Classes);
+ llvm::GlobalVariable *getClassHierarchyDescriptor();
+ llvm::GlobalVariable *getCompleteObjectLocator(const VPtrInfo *Info);
+
+ CodeGenModule &CGM;
+ ASTContext &Context;
+ llvm::LLVMContext &VMContext;
+ llvm::Module &Module;
+ const CXXRecordDecl *RD;
+ llvm::GlobalVariable::LinkageTypes Linkage;
+ MicrosoftCXXABI &ABI;
+};
+
+} // namespace
+
+/// \brief Recursively serializes a class hierarchy in pre-order depth first
+/// order.
+static void serializeClassHierarchy(SmallVectorImpl<MSRTTIClass> &Classes,
+ const CXXRecordDecl *RD) {
+ Classes.push_back(MSRTTIClass(RD));
+ for (const CXXBaseSpecifier &Base : RD->bases())
+ serializeClassHierarchy(Classes, Base.getType()->getAsCXXRecordDecl());
+}
+
+/// \brief Find ambiguity among base classes.
+static void
+detectAmbiguousBases(SmallVectorImpl<MSRTTIClass> &Classes) {
+ llvm::SmallPtrSet<const CXXRecordDecl *, 8> VirtualBases;
+ llvm::SmallPtrSet<const CXXRecordDecl *, 8> UniqueBases;
+ llvm::SmallPtrSet<const CXXRecordDecl *, 8> AmbiguousBases;
+ for (MSRTTIClass *Class = &Classes.front(); Class <= &Classes.back();) {
+ if ((Class->Flags & MSRTTIClass::IsVirtual) &&
+ !VirtualBases.insert(Class->RD)) {
+ Class = MSRTTIClass::getNextChild(Class);
+ continue;
+ }
+ if (!UniqueBases.insert(Class->RD))
+ AmbiguousBases.insert(Class->RD);
+ Class++;
+ }
+ if (AmbiguousBases.empty())
+ return;
+ for (MSRTTIClass &Class : Classes)
+ if (AmbiguousBases.count(Class.RD))
+ Class.Flags |= MSRTTIClass::IsAmbiguous;
+}
+
+llvm::GlobalVariable *MSRTTIBuilder::getClassHierarchyDescriptor() {
+ SmallString<256> MangledName;
+ {
+ llvm::raw_svector_ostream Out(MangledName);
+ ABI.getMangleContext().mangleCXXRTTIClassHierarchyDescriptor(RD, Out);
+ }
+
+ // Check to see if we've already declared this ClassHierarchyDescriptor.
+ if (auto CHD = Module.getNamedGlobal(MangledName))
+ return CHD;
+
+ // Serialize the class hierarchy and initialize the CHD Fields.
+ SmallVector<MSRTTIClass, 8> Classes;
+ serializeClassHierarchy(Classes, RD);
+ Classes.front().initialize(/*Parent=*/nullptr, /*Specifier=*/nullptr);
+ detectAmbiguousBases(Classes);
+ int Flags = 0;
+ for (auto Class : Classes) {
+ if (Class.RD->getNumBases() > 1)
+ Flags |= HasBranchingHierarchy;
+ // Note: cl.exe does not calculate "HasAmbiguousBases" correctly. We
+ // believe the field isn't actually used.
+ if (Class.Flags & MSRTTIClass::IsAmbiguous)
+ Flags |= HasAmbiguousBases;
+ }
+ if ((Flags & HasBranchingHierarchy) && RD->getNumVBases() != 0)
+ Flags |= HasVirtualBranchingHierarchy;
+ // These gep indices are used to get the address of the first element of the
+ // base class array.
+ llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.IntTy, 0),
+ llvm::ConstantInt::get(CGM.IntTy, 0)};
+
+ // Forward-declare the class hierarchy descriptor
+ auto Type = ABI.getClassHierarchyDescriptorType();
+ auto CHD = new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage,
+ /*Initializer=*/nullptr,
+ MangledName.c_str());
+
+ // Initialize the base class ClassHierarchyDescriptor.
+ llvm::Constant *Fields[] = {
+ llvm::ConstantInt::get(CGM.IntTy, 0), // Unknown
+ llvm::ConstantInt::get(CGM.IntTy, Flags),
+ llvm::ConstantInt::get(CGM.IntTy, Classes.size()),
+ ABI.getImageRelativeConstant(llvm::ConstantExpr::getInBoundsGetElementPtr(
+ getBaseClassArray(Classes),
+ llvm::ArrayRef<llvm::Value *>(GEPIndices))),
+ };
+ CHD->setInitializer(llvm::ConstantStruct::get(Type, Fields));
+ return CHD;
+}
+
+llvm::GlobalVariable *
+MSRTTIBuilder::getBaseClassArray(SmallVectorImpl<MSRTTIClass> &Classes) {
+ SmallString<256> MangledName;
+ {
+ llvm::raw_svector_ostream Out(MangledName);
+ ABI.getMangleContext().mangleCXXRTTIBaseClassArray(RD, Out);
+ }
+
+ // Forward-declare the base class array.
+ // cl.exe pads the base class array with 1 (in 32 bit mode) or 4 (in 64 bit
+ // mode) bytes of padding. We provide a pointer sized amount of padding by
+ // adding +1 to Classes.size(). The sections have pointer alignment and are
+ // marked pick-any so it shouldn't matter.
+ llvm::Type *PtrType = ABI.getImageRelativeType(
+ ABI.getBaseClassDescriptorType()->getPointerTo());
+ auto *ArrType = llvm::ArrayType::get(PtrType, Classes.size() + 1);
+ auto *BCA = new llvm::GlobalVariable(
+ Module, ArrType,
+ /*Constant=*/true, Linkage, /*Initializer=*/nullptr, MangledName.c_str());
+
+ // Initialize the BaseClassArray.
+ SmallVector<llvm::Constant *, 8> BaseClassArrayData;
+ for (MSRTTIClass &Class : Classes)
+ BaseClassArrayData.push_back(
+ ABI.getImageRelativeConstant(getBaseClassDescriptor(Class)));
+ BaseClassArrayData.push_back(llvm::Constant::getNullValue(PtrType));
+ BCA->setInitializer(llvm::ConstantArray::get(ArrType, BaseClassArrayData));
+ return BCA;
+}
+
+llvm::GlobalVariable *
+MSRTTIBuilder::getBaseClassDescriptor(const MSRTTIClass &Class) {
+ // Compute the fields for the BaseClassDescriptor. They are computed up front
+ // because they are mangled into the name of the object.
+ uint32_t OffsetInVBTable = 0;
+ int32_t VBPtrOffset = -1;
+ if (Class.VirtualRoot) {
+ auto &VTableContext = CGM.getMicrosoftVTableContext();
+ OffsetInVBTable = VTableContext.getVBTableIndex(RD, Class.VirtualRoot) * 4;
+ VBPtrOffset = Context.getASTRecordLayout(RD).getVBPtrOffset().getQuantity();
+ }
+
+ SmallString<256> MangledName;
+ {
+ llvm::raw_svector_ostream Out(MangledName);
+ ABI.getMangleContext().mangleCXXRTTIBaseClassDescriptor(
+ Class.RD, Class.OffsetInVBase, VBPtrOffset, OffsetInVBTable,
+ Class.Flags, Out);
+ }
+
+ // Check to see if we've already declared this object.
+ if (auto BCD = Module.getNamedGlobal(MangledName))
+ return BCD;
+
+ // Forward-declare the base class descriptor.
+ auto Type = ABI.getBaseClassDescriptorType();
+ auto BCD = new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage,
+ /*Initializer=*/nullptr,
+ MangledName.c_str());
+
+ // Initialize the BaseClassDescriptor.
+ llvm::Constant *Fields[] = {
+ ABI.getImageRelativeConstant(
+ ABI.getAddrOfRTTIDescriptor(Context.getTypeDeclType(Class.RD))),
+ llvm::ConstantInt::get(CGM.IntTy, Class.NumBases),
+ llvm::ConstantInt::get(CGM.IntTy, Class.OffsetInVBase),
+ llvm::ConstantInt::get(CGM.IntTy, VBPtrOffset),
+ llvm::ConstantInt::get(CGM.IntTy, OffsetInVBTable),
+ llvm::ConstantInt::get(CGM.IntTy, Class.Flags),
+ ABI.getImageRelativeConstant(
+ MSRTTIBuilder(ABI, Class.RD).getClassHierarchyDescriptor()),
+ };
+ BCD->setInitializer(llvm::ConstantStruct::get(Type, Fields));
+ return BCD;
+}
+
+llvm::GlobalVariable *
+MSRTTIBuilder::getCompleteObjectLocator(const VPtrInfo *Info) {
+ SmallString<256> MangledName;
+ {
+ llvm::raw_svector_ostream Out(MangledName);
+ ABI.getMangleContext().mangleCXXRTTICompleteObjectLocator(RD, Info->MangledPath, Out);
+ }
+
+ // Check to see if we've already computed this complete object locator.
+ if (auto COL = Module.getNamedGlobal(MangledName))
+ return COL;
+
+ // Compute the fields of the complete object locator.
+ int OffsetToTop = Info->FullOffsetInMDC.getQuantity();
+ int VFPtrOffset = 0;
+ // The offset includes the vtordisp if one exists.
+ if (const CXXRecordDecl *VBase = Info->getVBaseWithVPtr())
+ if (Context.getASTRecordLayout(RD)
+ .getVBaseOffsetsMap()
+ .find(VBase)
+ ->second.hasVtorDisp())
+ VFPtrOffset = Info->NonVirtualOffset.getQuantity() + 4;
+
+ // Forward-declare the complete object locator.
+ llvm::StructType *Type = ABI.getCompleteObjectLocatorType();
+ auto COL = new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage,
+ /*Initializer=*/nullptr, MangledName.c_str());
+
+ // Initialize the CompleteObjectLocator.
+ llvm::Constant *Fields[] = {
+ llvm::ConstantInt::get(CGM.IntTy, ABI.isImageRelative()),
+ llvm::ConstantInt::get(CGM.IntTy, OffsetToTop),
+ llvm::ConstantInt::get(CGM.IntTy, VFPtrOffset),
+ ABI.getImageRelativeConstant(
+ CGM.GetAddrOfRTTIDescriptor(Context.getTypeDeclType(RD))),
+ ABI.getImageRelativeConstant(getClassHierarchyDescriptor()),
+ ABI.getImageRelativeConstant(COL),
+ };
+ llvm::ArrayRef<llvm::Constant *> FieldsRef(Fields);
+ if (!ABI.isImageRelative())
+ FieldsRef = FieldsRef.drop_back();
+ COL->setInitializer(llvm::ConstantStruct::get(Type, FieldsRef));
+ return COL;
+}
+
+/// \brief Gets a TypeDescriptor. Returns a llvm::Constant * rather than a
+/// llvm::GlobalVariable * because different type descriptors have different
+/// types, and need to be abstracted. They are abstracting by casting the
+/// address to an Int8PtrTy.
+llvm::Constant *MicrosoftCXXABI::getAddrOfRTTIDescriptor(QualType Type) {
+ SmallString<256> MangledName, TypeInfoString;
+ {
+ llvm::raw_svector_ostream Out(MangledName);
+ getMangleContext().mangleCXXRTTI(Type, Out);
+ }
+
+ // Check to see if we've already declared this TypeDescriptor.
+ if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(MangledName))
+ return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
+
+ // Compute the fields for the TypeDescriptor.
+ {
+ llvm::raw_svector_ostream Out(TypeInfoString);
+ getMangleContext().mangleCXXRTTIName(Type, Out);
+ }
+
+ // Declare and initialize the TypeDescriptor.
+ llvm::Constant *Fields[] = {
+ getTypeInfoVTable(CGM), // VFPtr
+ llvm::ConstantPointerNull::get(CGM.Int8PtrTy), // Runtime data
+ llvm::ConstantDataArray::getString(CGM.getLLVMContext(), TypeInfoString)};
+ llvm::StructType *TypeDescriptorType =
+ getTypeDescriptorType(TypeInfoString);
+ return llvm::ConstantExpr::getBitCast(
+ new llvm::GlobalVariable(
+ CGM.getModule(), TypeDescriptorType, /*Constant=*/false,
+ getLinkageForRTTI(Type),
+ llvm::ConstantStruct::get(TypeDescriptorType, Fields),
+ MangledName.c_str()),
+ CGM.Int8PtrTy);
+}
+
+/// \brief Gets or a creates a Microsoft CompleteObjectLocator.
+llvm::GlobalVariable *
+MicrosoftCXXABI::getMSCompleteObjectLocator(const CXXRecordDecl *RD,
+ const VPtrInfo *Info) {
+ return MSRTTIBuilder(*this, RD).getCompleteObjectLocator(Info);
+}
diff --git a/lib/CodeGen/MicrosoftRTTI.cpp b/lib/CodeGen/MicrosoftRTTI.cpp
deleted file mode 100644
index 0eb8100..0000000
--- a/lib/CodeGen/MicrosoftRTTI.cpp
+++ /dev/null
@@ -1,447 +0,0 @@
-//===--- CGCXXRTTI.cpp - Emit LLVM Code for C++ RTTI descriptors ----------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This contains code dealing with C++ code generation of RTTI descriptors.
-//
-//===----------------------------------------------------------------------===//
-
-#include "CodeGenModule.h"
-#include "CGCXXABI.h"
-#include "CGObjCRuntime.h"
-#include "clang/AST/RecordLayout.h"
-#include "clang/AST/Type.h"
-#include "clang/Frontend/CodeGenOptions.h"
-
-using namespace clang;
-using namespace CodeGen;
-
-// MS RTTI Overview:
-// The run time type information emitted by cl.exe contains 5 distinct types of
-// structures. Many of them reference each other.
-//
-// TypeInfo: Static classes that are returned by typeid.
-//
-// CompleteObjectLocator: Referenced by vftables. They contain information
-// required for dynamic casting, including OffsetFromTop. They also contain
-// a reference to the TypeInfo for the type and a reference to the
-// CompleteHierarchyDescriptor for the type.
-//
-// ClassHieararchyDescriptor: Contains information about a class hierarchy.
-// Used during dynamic_cast to walk a class hierarchy. References a base
-// class array and the size of said array.
-//
-// BaseClassArray: Contains a list of classes in a hierarchy. BaseClassArray is
-// somewhat of a misnomer because the most derived class is also in the list
-// as well as multiple copies of virtual bases (if they occur multiple times
-// in the hiearchy.) The BaseClassArray contains one BaseClassDescriptor for
-// every path in the hierarchy, in pre-order depth first order. Note, we do
-// not declare a specific llvm type for BaseClassArray, it's merely an array
-// of BaseClassDescriptor pointers.
-//
-// BaseClassDescriptor: Contains information about a class in a class hierarchy.
-// BaseClassDescriptor is also somewhat of a misnomer for the same reason that
-// BaseClassArray is. It contains information about a class within a
-// hierarchy such as: is this base is ambiguous and what is its offset in the
-// vbtable. The names of the BaseClassDescriptors have all of their fields
-// mangled into them so they can be aggressively deduplicated by the linker.
-
-// 5 routines for constructing the llvm types for MS RTTI structs.
-static llvm::StructType *getClassHierarchyDescriptorType(CodeGenModule &CGM);
-
-static llvm::StructType *getTypeDescriptorType(CodeGenModule &CGM,
- StringRef TypeInfoString) {
- llvm::SmallString<32> TDTypeName("MSRTTITypeDescriptor");
- TDTypeName += TypeInfoString.size();
- if (auto Type = CGM.getModule().getTypeByName(TDTypeName))
- return Type;
- llvm::Type *FieldTypes[] = {
- CGM.Int8PtrPtrTy,
- CGM.Int8PtrTy,
- llvm::ArrayType::get(CGM.Int8Ty, TypeInfoString.size() + 1)};
- return llvm::StructType::create(CGM.getLLVMContext(), FieldTypes, TDTypeName);
-}
-
-static llvm::StructType *getBaseClassDescriptorType(CodeGenModule &CGM) {
- static const char Name[] = "MSRTTIBaseClassDescriptor";
- if (auto Type = CGM.getModule().getTypeByName(Name))
- return Type;
- llvm::Type *FieldTypes[] = {
- CGM.Int8PtrTy,
- CGM.IntTy,
- CGM.IntTy,
- CGM.IntTy,
- CGM.IntTy,
- CGM.IntTy,
- getClassHierarchyDescriptorType(CGM)->getPointerTo()};
- return llvm::StructType::create(CGM.getLLVMContext(), FieldTypes, Name);
-}
-
-static llvm::StructType *getClassHierarchyDescriptorType(CodeGenModule &CGM) {
- static const char Name[] = "MSRTTIClassHierarchyDescriptor";
- if (auto Type = CGM.getModule().getTypeByName(Name))
- return Type;
- // Forward declare RTTIClassHierarchyDescriptor to break a cycle.
- llvm::StructType *Type = llvm::StructType::create(CGM.getLLVMContext(), Name);
- llvm::Type *FieldTypes[] = {
- CGM.IntTy,
- CGM.IntTy,
- CGM.IntTy,
- getBaseClassDescriptorType(CGM)->getPointerTo()->getPointerTo()};
- Type->setBody(FieldTypes);
- return Type;
-}
-
-static llvm::StructType *getCompleteObjectLocatorType(CodeGenModule &CGM) {
- static const char Name[] = "MSRTTICompleteObjectLocator";
- if (auto Type = CGM.getModule().getTypeByName(Name))
- return Type;
- llvm::Type *FieldTypes[] = {
- CGM.IntTy,
- CGM.IntTy,
- CGM.IntTy,
- CGM.Int8PtrTy,
- getClassHierarchyDescriptorType(CGM)->getPointerTo() };
- return llvm::StructType::create(CGM.getLLVMContext(), FieldTypes, Name);
-}
-
-static llvm::GlobalVariable *getTypeInfoVTable(CodeGenModule &CGM) {
- StringRef MangledName("\01??_7type_info@@6B@");
- if (auto VTable = CGM.getModule().getNamedGlobal(MangledName))
- return VTable;
- return new llvm::GlobalVariable(CGM.getModule(), CGM.Int8PtrTy,
- /*Constant=*/true,
- llvm::GlobalVariable::ExternalLinkage,
- /*Initializer=*/0, MangledName);
-}
-
-namespace {
-
-/// \brief A Helper struct that stores information about a class in a class
-/// hierarchy. The information stored in these structs struct is used during
-/// the generation of ClassHierarchyDescriptors and BaseClassDescriptors.
-// During RTTI creation, MSRTTIClasses are stored in a contiguous array with
-// implicit depth first pre-order tree connectivity. getFirstChild and
-// getNextSibling allow us to walk the tree efficiently.
-struct MSRTTIClass {
- enum {
- IsPrivateOnPath = 1 | 8,
- IsAmbiguous = 2,
- IsPrivate = 4,
- IsVirtual = 16,
- HasHierarchyDescriptor = 64
- };
- MSRTTIClass(const CXXRecordDecl *RD) : RD(RD) {}
- uint32_t initialize(const MSRTTIClass *Parent,
- const CXXBaseSpecifier *Specifier);
-
- MSRTTIClass *getFirstChild() { return this + 1; }
- static MSRTTIClass *getNextChild(MSRTTIClass *Child) {
- return Child + 1 + Child->NumBases;
- }
-
- const CXXRecordDecl *RD, *VirtualRoot;
- uint32_t Flags, NumBases, OffsetInVBase;
-};
-
-/// \brief Recursively initialize the base class array.
-uint32_t MSRTTIClass::initialize(const MSRTTIClass *Parent,
- const CXXBaseSpecifier *Specifier) {
- Flags = HasHierarchyDescriptor;
- if (!Parent) {
- VirtualRoot = 0;
- OffsetInVBase = 0;
- } else {
- if (Specifier->getAccessSpecifier() != AS_public)
- Flags |= IsPrivate | IsPrivateOnPath;
- if (Specifier->isVirtual()) {
- Flags |= IsVirtual;
- VirtualRoot = RD;
- OffsetInVBase = 0;
- } else {
- if (Parent->Flags & IsPrivateOnPath)
- Flags |= IsPrivateOnPath;
- VirtualRoot = Parent->VirtualRoot;
- OffsetInVBase = Parent->OffsetInVBase + RD->getASTContext()
- .getASTRecordLayout(Parent->RD).getBaseClassOffset(RD).getQuantity();
- }
- }
- NumBases = 0;
- MSRTTIClass *Child = getFirstChild();
- for (const CXXBaseSpecifier &Base : RD->bases()) {
- NumBases += Child->initialize(this, &Base) + 1;
- Child = getNextChild(Child);
- }
- return NumBases;
-}
-
-/// \brief An ephemeral helper class for building MS RTTI types. It caches some
-/// calls to the module and information about the most derived class in a
-/// hierarchy.
-struct MSRTTIBuilder {
- enum {
- HasBranchingHierarchy = 1,
- HasVirtualBranchingHierarchy = 2,
- HasAmbiguousBases = 4
- };
-
- MSRTTIBuilder(CodeGenModule &CGM, const CXXRecordDecl *RD)
- : CGM(CGM), Context(CGM.getContext()), VMContext(CGM.getLLVMContext()),
- Module(CGM.getModule()), RD(RD), Linkage(CGM.getVTableLinkage(RD)),
- Mangler(
- cast<MicrosoftMangleContext>(CGM.getCXXABI().getMangleContext())) {}
-
- llvm::GlobalVariable *getBaseClassDescriptor(const MSRTTIClass &Classes);
- llvm::GlobalVariable *
- getBaseClassArray(SmallVectorImpl<MSRTTIClass> &Classes);
- llvm::GlobalVariable *getClassHierarchyDescriptor();
- llvm::GlobalVariable *getCompleteObjectLocator(const VPtrInfo *Info);
-
- CodeGenModule &CGM;
- ASTContext &Context;
- llvm::LLVMContext &VMContext;
- llvm::Module &Module;
- const CXXRecordDecl *RD;
- llvm::GlobalVariable::LinkageTypes Linkage;
- MicrosoftMangleContext &Mangler;
-};
-
-} // namespace
-
-/// \brief Recursively serializes a class hierarchy in pre-order depth first
-/// order.
-static void serializeClassHierarchy(SmallVectorImpl<MSRTTIClass> &Classes,
- const CXXRecordDecl *RD) {
- Classes.push_back(MSRTTIClass(RD));
- for (const CXXBaseSpecifier &Base : RD->bases())
- serializeClassHierarchy(Classes, Base.getType()->getAsCXXRecordDecl());
-}
-
-/// \brief Find ambiguity among base classes.
-static void
-detectAmbiguousBases(SmallVectorImpl<MSRTTIClass> &Classes) {
- llvm::SmallPtrSet<const CXXRecordDecl *, 8> VirtualBases;
- llvm::SmallPtrSet<const CXXRecordDecl *, 8> UniqueBases;
- llvm::SmallPtrSet<const CXXRecordDecl *, 8> AmbiguousBases;
- for (MSRTTIClass *Class = &Classes.front(); Class <= &Classes.back();) {
- if ((Class->Flags & MSRTTIClass::IsVirtual) &&
- !VirtualBases.insert(Class->RD)) {
- Class = MSRTTIClass::getNextChild(Class);
- continue;
- }
- if (!UniqueBases.insert(Class->RD))
- AmbiguousBases.insert(Class->RD);
- Class++;
- }
- if (AmbiguousBases.empty())
- return;
- for (MSRTTIClass &Class : Classes)
- if (AmbiguousBases.count(Class.RD))
- Class.Flags |= MSRTTIClass::IsAmbiguous;
-}
-
-llvm::GlobalVariable *MSRTTIBuilder::getClassHierarchyDescriptor() {
- SmallString<256> MangledName;
- {
- llvm::raw_svector_ostream Out(MangledName);
- Mangler.mangleCXXRTTIClassHierarchyDescriptor(RD, Out);
- }
-
- // Check to see if we've already declared this ClassHierarchyDescriptor.
- if (auto CHD = Module.getNamedGlobal(MangledName))
- return CHD;
-
- // Serialize the class hierarchy and initalize the CHD Fields.
- SmallVector<MSRTTIClass, 8> Classes;
- serializeClassHierarchy(Classes, RD);
- Classes.front().initialize(/*Parent=*/0, /*Specifier=*/0);
- detectAmbiguousBases(Classes);
- int Flags = 0;
- for (auto Class : Classes) {
- if (Class.RD->getNumBases() > 1)
- Flags |= HasBranchingHierarchy;
- // Note: cl.exe does not calculate "HasAmbiguousBases" correctly. We
- // believe the field isn't actually used.
- if (Class.Flags & MSRTTIClass::IsAmbiguous)
- Flags |= HasAmbiguousBases;
- }
- if ((Flags & HasBranchingHierarchy) && RD->getNumVBases() != 0)
- Flags |= HasVirtualBranchingHierarchy;
- // These gep indices are used to get the address of the first element of the
- // base class array.
- llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.IntTy, 0),
- llvm::ConstantInt::get(CGM.IntTy, 0)};
-
- // Forward declare the class hierarchy descriptor
- auto Type = getClassHierarchyDescriptorType(CGM);
- auto CHD = new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage,
- /*Initializer=*/0, MangledName.c_str());
-
- // Initialize the base class ClassHierarchyDescriptor.
- llvm::Constant *Fields[] = {
- llvm::ConstantInt::get(CGM.IntTy, 0), // Unknown
- llvm::ConstantInt::get(CGM.IntTy, Flags),
- llvm::ConstantInt::get(CGM.IntTy, Classes.size()),
- llvm::ConstantExpr::getInBoundsGetElementPtr(
- getBaseClassArray(Classes),
- llvm::ArrayRef<llvm::Value *>(GEPIndices))};
- CHD->setInitializer(llvm::ConstantStruct::get(Type, Fields));
- return CHD;
-}
-
-llvm::GlobalVariable *
-MSRTTIBuilder::getBaseClassArray(SmallVectorImpl<MSRTTIClass> &Classes) {
- SmallString<256> MangledName;
- {
- llvm::raw_svector_ostream Out(MangledName);
- Mangler.mangleCXXRTTIBaseClassArray(RD, Out);
- }
-
- // Foward declare the base class array.
- // cl.exe pads the base class array with 1 (in 32 bit mode) or 4 (in 64 bit
- // mode) bytes of padding. We provide a pointer sized amount of padding by
- // adding +1 to Classes.size(). The sections have pointer alignment and are
- // marked pick-any so it shouldn't matter.
- auto PtrType = getBaseClassDescriptorType(CGM)->getPointerTo();
- auto ArrayType = llvm::ArrayType::get(PtrType, Classes.size() + 1);
- auto BCA = new llvm::GlobalVariable(Module, ArrayType,
- /*Constant=*/true, Linkage, /*Initializer=*/0, MangledName.c_str());
-
- // Initialize the BaseClassArray.
- SmallVector<llvm::Constant *, 8> BaseClassArrayData;
- for (MSRTTIClass &Class : Classes)
- BaseClassArrayData.push_back(getBaseClassDescriptor(Class));
- BaseClassArrayData.push_back(llvm::ConstantPointerNull::get(PtrType));
- BCA->setInitializer(llvm::ConstantArray::get(ArrayType, BaseClassArrayData));
- return BCA;
-}
-
-llvm::GlobalVariable *
-MSRTTIBuilder::getBaseClassDescriptor(const MSRTTIClass &Class) {
- // Compute the fields for the BaseClassDescriptor. They are computed up front
- // because they are mangled into the name of the object.
- uint32_t OffsetInVBTable = 0;
- int32_t VBPtrOffset = -1;
- if (Class.VirtualRoot) {
- auto &VTableContext = CGM.getMicrosoftVTableContext();
- OffsetInVBTable = VTableContext.getVBTableIndex(RD, Class.VirtualRoot) * 4;
- VBPtrOffset = Context.getASTRecordLayout(RD).getVBPtrOffset().getQuantity();
- }
-
- SmallString<256> MangledName;
- {
- llvm::raw_svector_ostream Out(MangledName);
- Mangler.mangleCXXRTTIBaseClassDescriptor(Class.RD, Class.OffsetInVBase,
- VBPtrOffset, OffsetInVBTable,
- Class.Flags, Out);
- }
-
- // Check to see if we've already declared declared this object.
- if (auto BCD = Module.getNamedGlobal(MangledName))
- return BCD;
-
- // Forward declare the base class descriptor.
- auto Type = getBaseClassDescriptorType(CGM);
- auto BCD = new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage,
- /*Initializer=*/0, MangledName.c_str());
-
- // Initialize the BaseClassDescriptor.
- llvm::Constant *Fields[] = {
- CGM.getMSTypeDescriptor(Context.getTypeDeclType(Class.RD)),
- llvm::ConstantInt::get(CGM.IntTy, Class.NumBases),
- llvm::ConstantInt::get(CGM.IntTy, Class.OffsetInVBase),
- llvm::ConstantInt::get(CGM.IntTy, VBPtrOffset),
- llvm::ConstantInt::get(CGM.IntTy, OffsetInVBTable),
- llvm::ConstantInt::get(CGM.IntTy, Class.Flags),
- MSRTTIBuilder(CGM, Class.RD).getClassHierarchyDescriptor()};
- BCD->setInitializer(llvm::ConstantStruct::get(Type, Fields));
- return BCD;
-}
-
-llvm::GlobalVariable *
-MSRTTIBuilder::getCompleteObjectLocator(const VPtrInfo *Info) {
- SmallString<256> MangledName;
- {
- llvm::raw_svector_ostream Out(MangledName);
- Mangler.mangleCXXRTTICompleteObjectLocator(RD, Info->MangledPath, Out);
- }
-
- // Check to see if we've already computed this complete object locator.
- if (auto COL = Module.getNamedGlobal(MangledName))
- return COL;
-
- // Compute the fields of the complete object locator.
- int OffsetToTop = Info->FullOffsetInMDC.getQuantity();
- int VFPtrOffset = 0;
- // The offset includes the vtordisp if one exists.
- if (const CXXRecordDecl *VBase = Info->getVBaseWithVPtr())
- if (Context.getASTRecordLayout(RD)
- .getVBaseOffsetsMap()
- .find(VBase)
- ->second.hasVtorDisp())
- VFPtrOffset = Info->NonVirtualOffset.getQuantity() + 4;
-
- // Forward declare the complete object locator.
- llvm::StructType *Type = getCompleteObjectLocatorType(CGM);
- auto COL = new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage,
- /*Initializer=*/0, MangledName.c_str());
-
- // Initialize the CompleteObjectLocator.
- llvm::Constant *Fields[] = {
- llvm::ConstantInt::get(CGM.IntTy, 0), // IsDeltaEncoded
- llvm::ConstantInt::get(CGM.IntTy, OffsetToTop),
- llvm::ConstantInt::get(CGM.IntTy, VFPtrOffset),
- CGM.getMSTypeDescriptor(Context.getTypeDeclType(RD)),
- getClassHierarchyDescriptor()};
- COL->setInitializer(llvm::ConstantStruct::get(Type, Fields));
- return COL;
-}
-
-
-/// \brief Gets a TypeDescriptor. Returns a llvm::Constant * rather than a
-/// llvm::GlobalVariable * because different type descriptors have different
-/// types, and need to be abstracted. They are abstracting by casting the
-/// address to an Int8PtrTy.
-llvm::Constant *CodeGenModule::getMSTypeDescriptor(QualType Type) {
- auto &Mangler(cast<MicrosoftMangleContext>(getCXXABI().getMangleContext()));
- SmallString<256> MangledName, TypeInfoString;
- {
- llvm::raw_svector_ostream Out(MangledName);
- Mangler.mangleCXXRTTI(Type, Out);
- }
-
- // Check to see if we've already declared this TypeDescriptor.
- if (auto TypeDescriptor = getModule().getNamedGlobal(MangledName))
- return llvm::ConstantExpr::getBitCast(TypeDescriptor, Int8PtrTy);
-
- // Compute the fields for the TypeDescriptor.
- {
- llvm::raw_svector_ostream Out(TypeInfoString);
- Mangler.mangleCXXRTTIName(Type, Out);
- }
-
- // Declare and initialize the TypeDescriptor.
- llvm::Constant *Fields[] = {
- getTypeInfoVTable(*this), // VFPtr
- llvm::ConstantPointerNull::get(Int8PtrTy), // Runtime data
- llvm::ConstantDataArray::getString(VMContext, TypeInfoString)};
- auto TypeDescriptorType = getTypeDescriptorType(*this, TypeInfoString);
- return llvm::ConstantExpr::getBitCast(
- new llvm::GlobalVariable(
- getModule(), TypeDescriptorType, /*Constant=*/false,
- getTypeInfoLinkage(Type),
- llvm::ConstantStruct::get(TypeDescriptorType, Fields),
- MangledName.c_str()),
- Int8PtrTy);
-}
-
-llvm::GlobalVariable *
-CodeGenModule::getMSCompleteObjectLocator(const CXXRecordDecl *RD,
- const VPtrInfo *Info) {
- return MSRTTIBuilder(*this, RD).getCompleteObjectLocator(Info);
-}
diff --git a/lib/CodeGen/ModuleBuilder.cpp b/lib/CodeGen/ModuleBuilder.cpp
index 78cb82d..c4a0e5c 100644
--- a/lib/CodeGen/ModuleBuilder.cpp
+++ b/lib/CodeGen/ModuleBuilder.cpp
@@ -49,6 +49,21 @@
return M.get();
}
+ const Decl *GetDeclForMangledName(StringRef MangledName) override {
+ GlobalDecl Result;
+ if (!Builder->lookupRepresentativeDecl(MangledName, Result))
+ return nullptr;
+ const Decl *D = Result.getCanonicalDecl().getDecl();
+ if (auto FD = dyn_cast<FunctionDecl>(D)) {
+ if (FD->hasBody(FD))
+ return FD;
+ } else if (auto TD = dyn_cast<TagDecl>(D)) {
+ if (auto Def = TD->getDefinition())
+ return Def;
+ }
+ return D;
+ }
+
llvm::Module *ReleaseModule() override { return M.release(); }
void Initialize(ASTContext &Context) override {
@@ -78,6 +93,12 @@
// Make sure to emit all elements of a Decl.
for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
Builder->EmitTopLevelDecl(*I);
+
+ // Emit any deferred inline method definitions.
+ for (CXXMethodDecl *MD : DeferredInlineMethodDefinitions)
+ Builder->EmitTopLevelDecl(MD);
+ DeferredInlineMethodDefinitions.clear();
+
return true;
}
@@ -87,12 +108,15 @@
assert(D->doesThisDeclarationHaveABody());
- // We may have member functions that need to be emitted at this point.
- if (!D->isDependentContext() &&
- (D->hasAttr<UsedAttr>() || D->hasAttr<ConstructorAttr>() ||
- D->hasAttr<DLLExportAttr>())) {
- Builder->EmitTopLevelDecl(D);
- }
+ // We may want to emit this definition. However, that decision might be
+ // based on computing the linkage, and we have to defer that in case we
+ // are inside of something that will change the method's final linkage,
+ // e.g.
+ // typedef struct {
+ // void bar();
+ // void foo() { bar(); }
+ // } A;
+ DeferredInlineMethodDefinitions.push_back(D);
}
/// HandleTagDeclDefinition - This callback is invoked each time a TagDecl
@@ -153,6 +177,9 @@
void HandleDependentLibrary(llvm::StringRef Lib) override {
Builder->AddDependentLib(Lib);
}
+
+ private:
+ std::vector<CXXMethodDecl *> DeferredInlineMethodDefinitions;
};
}
diff --git a/lib/CodeGen/SanitizerBlacklist.cpp b/lib/CodeGen/SanitizerBlacklist.cpp
new file mode 100644
index 0000000..60bdbe1
--- /dev/null
+++ b/lib/CodeGen/SanitizerBlacklist.cpp
@@ -0,0 +1,48 @@
+//===--- SanitizerBlacklist.cpp - Blacklist for sanitizers ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// User-provided blacklist used to disable/alter instrumentation done in
+// sanitizers.
+//
+//===----------------------------------------------------------------------===//
+#include "SanitizerBlacklist.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/GlobalValue.h"
+#include "llvm/IR/Module.h"
+
+using namespace clang;
+using namespace CodeGen;
+
+static StringRef GetGlobalTypeString(const llvm::GlobalValue &G) {
+ // Types of GlobalVariables are always pointer types.
+ llvm::Type *GType = G.getType()->getElementType();
+ // For now we support blacklisting struct types only.
+ if (llvm::StructType *SGType = dyn_cast<llvm::StructType>(GType)) {
+ if (!SGType->isLiteral())
+ return SGType->getName();
+ }
+ return "<unknown type>";
+}
+
+bool SanitizerBlacklist::isIn(const llvm::Module &M,
+ const StringRef Category) const {
+ return SCL->inSection("src", M.getModuleIdentifier(), Category);
+}
+
+bool SanitizerBlacklist::isIn(const llvm::Function &F) const {
+ return isIn(*F.getParent()) ||
+ SCL->inSection("fun", F.getName(), "");
+}
+
+bool SanitizerBlacklist::isIn(const llvm::GlobalVariable &G,
+ const StringRef Category) const {
+ return isIn(*G.getParent(), Category) ||
+ SCL->inSection("global", G.getName(), Category) ||
+ SCL->inSection("type", GetGlobalTypeString(G), Category);
+}
diff --git a/lib/CodeGen/SanitizerBlacklist.h b/lib/CodeGen/SanitizerBlacklist.h
new file mode 100644
index 0000000..b8c283c
--- /dev/null
+++ b/lib/CodeGen/SanitizerBlacklist.h
@@ -0,0 +1,45 @@
+//===--- SanitizerBlacklist.h - Blacklist for sanitizers --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// User-provided blacklist used to disable/alter instrumentation done in
+// sanitizers.
+//
+//===----------------------------------------------------------------------===//
+#ifndef CLANG_CODEGEN_SANITIZERBLACKLIST_H
+#define CLANG_CODEGEN_SANITIZERBLACKLIST_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/SpecialCaseList.h"
+#include <memory>
+
+namespace llvm {
+class GlobalVariable;
+class Function;
+class Module;
+}
+
+namespace clang {
+namespace CodeGen {
+
+class SanitizerBlacklist {
+ std::unique_ptr<llvm::SpecialCaseList> SCL;
+
+public:
+ SanitizerBlacklist(llvm::SpecialCaseList *SCL) : SCL(SCL) {}
+ bool isIn(const llvm::Module &M,
+ const StringRef Category = StringRef()) const;
+ bool isIn(const llvm::Function &F) const;
+ bool isIn(const llvm::GlobalVariable &G,
+ const StringRef Category = StringRef()) const;
+};
+} // end namespace CodeGen
+} // end namespace clang
+
+#endif
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index ab4c388..9cb93ac 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -957,8 +957,16 @@
else
State.FreeRegs = DefaultNumRegisterParameters;
- if (!getCXXABI().classifyReturnType(FI))
+ if (!getCXXABI().classifyReturnType(FI)) {
FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), State);
+ } else if (FI.getReturnInfo().isIndirect()) {
+ // The C++ ABI is not aware of register usage, so we have to check if the
+ // return value was sret and put it in a register ourselves if appropriate.
+ if (State.FreeRegs) {
+ --State.FreeRegs; // The sret parameter consumes a register.
+ FI.getReturnInfo().setInReg(true);
+ }
+ }
bool UsedInAlloca = false;
for (auto &I : FI.arguments()) {
@@ -1082,6 +1090,44 @@
return AddrTyped;
}
+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::AuroraUX:
+ case llvm::Triple::DragonFly:
+ case llvm::Triple::FreeBSD:
+ case llvm::Triple::OpenBSD:
+ case llvm::Triple::Bitrig:
+ return true;
+ case llvm::Triple::Win32:
+ switch (Triple.getEnvironment()) {
+ case llvm::Triple::UnknownEnvironment:
+ case llvm::Triple::Cygnus:
+ case llvm::Triple::GNU:
+ case llvm::Triple::MSVC:
+ return true;
+ default:
+ return false;
+ }
+ default:
+ return false;
+ }
+}
+
void X86_32TargetCodeGenInfo::SetTargetAttributes(const Decl *D,
llvm::GlobalValue *GV,
CodeGen::CodeGenModule &CGM) const {
@@ -2045,7 +2091,7 @@
/// the source type. IROffset is an offset in bytes into the LLVM IR type that
/// the 8-byte value references. PrefType may be null.
///
-/// SourceTy is the source level type for the entire argument. SourceOffset is
+/// SourceTy is the source-level type for the entire argument. SourceOffset is
/// an offset into this that we're processing (which is always either 0 or 8).
///
llvm::Type *X86_64ABIInfo::
@@ -2590,8 +2636,8 @@
llvm::Type *PTyHi = llvm::PointerType::getUnqual(TyHi);
llvm::Value *GPAddr = CGF.Builder.CreateGEP(RegAddr, gp_offset);
llvm::Value *FPAddr = CGF.Builder.CreateGEP(RegAddr, fp_offset);
- llvm::Value *RegLoAddr = TyLo->isFloatingPointTy() ? FPAddr : GPAddr;
- llvm::Value *RegHiAddr = TyLo->isFloatingPointTy() ? GPAddr : FPAddr;
+ llvm::Value *RegLoAddr = TyLo->isFPOrFPVectorTy() ? FPAddr : GPAddr;
+ llvm::Value *RegHiAddr = TyLo->isFPOrFPVectorTy() ? GPAddr : FPAddr;
llvm::Value *V =
CGF.Builder.CreateLoad(CGF.Builder.CreateBitCast(RegLoAddr, PTyLo));
CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 0));
@@ -2857,6 +2903,7 @@
PPC64_SVR4_ABIInfo(CodeGen::CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}
bool isPromotableTypeForABI(QualType Ty) const;
+ bool isAlignedParamType(QualType Ty) const;
ABIArgInfo classifyReturnType(QualType RetTy) const;
ABIArgInfo classifyArgumentType(QualType Ty) const;
@@ -2877,7 +2924,8 @@
const Type *T = isSingleElementStruct(I.type, getContext());
if (T) {
const BuiltinType *BT = T->getAs<BuiltinType>();
- if (T->isVectorType() || (BT && BT->isFloatingPoint())) {
+ if ((T->isVectorType() && getContext().getTypeSize(T) == 128) ||
+ (BT && BT->isFloatingPoint())) {
QualType QT(T, 0);
I.info = ABIArgInfo::getDirectInReg(CGT.ConvertType(QT));
continue;
@@ -2946,16 +2994,68 @@
return false;
}
+/// isAlignedParamType - Determine whether a type requires 16-byte
+/// alignment in the parameter area.
+bool
+PPC64_SVR4_ABIInfo::isAlignedParamType(QualType Ty) const {
+ // Complex types are passed just like their elements.
+ if (const ComplexType *CTy = Ty->getAs<ComplexType>())
+ Ty = CTy->getElementType();
+
+ // Only vector types of size 16 bytes need alignment (larger types are
+ // passed via reference, smaller types are not aligned).
+ if (Ty->isVectorType())
+ return getContext().getTypeSize(Ty) == 128;
+
+ // For single-element float/vector structs, we consider the whole type
+ // to have the same alignment requirements as its single element.
+ const Type *AlignAsType = nullptr;
+ const Type *EltType = isSingleElementStruct(Ty, getContext());
+ if (EltType) {
+ const BuiltinType *BT = EltType->getAs<BuiltinType>();
+ if ((EltType->isVectorType() &&
+ getContext().getTypeSize(EltType) == 128) ||
+ (BT && BT->isFloatingPoint()))
+ AlignAsType = EltType;
+ }
+
+ // With special case aggregates, only vector base types need alignment.
+ if (AlignAsType)
+ return AlignAsType->isVectorType();
+
+ // Otherwise, we only need alignment for any aggregate type that
+ // has an alignment requirement of >= 16 bytes.
+ if (isAggregateTypeForABI(Ty) && getContext().getTypeAlign(Ty) >= 128)
+ return true;
+
+ return false;
+}
+
ABIArgInfo
PPC64_SVR4_ABIInfo::classifyArgumentType(QualType Ty) const {
if (Ty->isAnyComplexType())
return ABIArgInfo::getDirect();
+ // Non-Altivec vector types are passed in GPRs (smaller than 16 bytes)
+ // or via reference (larger than 16 bytes).
+ if (Ty->isVectorType()) {
+ uint64_t Size = getContext().getTypeSize(Ty);
+ if (Size > 128)
+ return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+ else if (Size < 128) {
+ llvm::Type *CoerceTy = llvm::IntegerType::get(getVMContext(), Size);
+ return ABIArgInfo::getDirect(CoerceTy);
+ }
+ }
+
if (isAggregateTypeForABI(Ty)) {
if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
- return ABIArgInfo::getIndirect(0);
+ uint64_t ABIAlign = isAlignedParamType(Ty)? 16 : 8;
+ uint64_t TyAlign = getContext().getTypeAlign(Ty) / 8;
+ return ABIArgInfo::getIndirect(ABIAlign, /*ByVal=*/true,
+ /*Realign=*/TyAlign > ABIAlign);
}
return (isPromotableTypeForABI(Ty) ?
@@ -2970,6 +3070,18 @@
if (RetTy->isAnyComplexType())
return ABIArgInfo::getDirect();
+ // Non-Altivec vector types are returned in GPRs (smaller than 16 bytes)
+ // or via reference (larger than 16 bytes).
+ if (RetTy->isVectorType()) {
+ uint64_t Size = getContext().getTypeSize(RetTy);
+ if (Size > 128)
+ return ABIArgInfo::getIndirect(0);
+ else if (Size < 128) {
+ llvm::Type *CoerceTy = llvm::IntegerType::get(getVMContext(), Size);
+ return ABIArgInfo::getDirect(CoerceTy);
+ }
+ }
+
if (isAggregateTypeForABI(RetTy))
return ABIArgInfo::getIndirect(0);
@@ -2988,6 +3100,14 @@
llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP, "ap");
llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur");
+ // Handle types that require 16-byte alignment in the parameter save area.
+ if (isAlignedParamType(Ty)) {
+ llvm::Value *AddrAsInt = Builder.CreatePtrToInt(Addr, CGF.Int64Ty);
+ AddrAsInt = Builder.CreateAdd(AddrAsInt, Builder.getInt64(15));
+ AddrAsInt = Builder.CreateAnd(AddrAsInt, Builder.getInt64(-16));
+ Addr = Builder.CreateIntToPtr(AddrAsInt, BP, "ap.align");
+ }
+
// Update the va_list pointer. The pointer should be bumped by the
// size of the object. We can trust getTypeSize() except for a complex
// type whose base type is smaller than a doubleword. For these, the
@@ -3018,8 +3138,12 @@
if (CplxBaseSize && CplxBaseSize < 8) {
llvm::Value *RealAddr = Builder.CreatePtrToInt(Addr, CGF.Int64Ty);
llvm::Value *ImagAddr = RealAddr;
- RealAddr = Builder.CreateAdd(RealAddr, Builder.getInt64(8 - CplxBaseSize));
- ImagAddr = Builder.CreateAdd(ImagAddr, Builder.getInt64(16 - CplxBaseSize));
+ if (CGF.CGM.getDataLayout().isBigEndian()) {
+ RealAddr = Builder.CreateAdd(RealAddr, Builder.getInt64(8 - CplxBaseSize));
+ ImagAddr = Builder.CreateAdd(ImagAddr, Builder.getInt64(16 - CplxBaseSize));
+ } else {
+ ImagAddr = Builder.CreateAdd(ImagAddr, Builder.getInt64(8));
+ }
llvm::Type *PBaseTy = llvm::PointerType::getUnqual(CGF.ConvertType(BaseTy));
RealAddr = Builder.CreateIntToPtr(RealAddr, PBaseTy);
ImagAddr = Builder.CreateIntToPtr(ImagAddr, PBaseTy);
@@ -3037,7 +3161,7 @@
// If the argument is smaller than 8 bytes, it is right-adjusted in
// its doubleword slot. Adjust the pointer to pick it up from the
// correct offset.
- if (SizeInBytes < 8) {
+ if (SizeInBytes < 8 && CGF.CGM.getDataLayout().isBigEndian()) {
llvm::Value *AddrAsInt = Builder.CreatePtrToInt(Addr, CGF.Int64Ty);
AddrAsInt = Builder.CreateAdd(AddrAsInt, Builder.getInt64(8 - SizeInBytes));
Addr = Builder.CreateIntToPtr(AddrAsInt, BP);
@@ -4050,7 +4174,7 @@
/// which have been allocated. It is valid for AllocatedGPRs to go above 4,
/// this represents arguments being stored on the stack.
void ARMABIInfo::markAllocatedGPRs(unsigned Alignment,
- unsigned NumRequired) const {
+ unsigned NumRequired) const {
assert((Alignment == 1 || Alignment == 2) && "Alignment must be 4 or 8 bytes");
if (Alignment == 2 && AllocatedGPRs & 0x1)
@@ -4193,8 +4317,11 @@
getABIKind() == ARMABIInfo::AAPCS)
ABIAlign = std::min(std::max(TyAlign, (uint64_t)4), (uint64_t)8);
if (getContext().getTypeSizeInChars(Ty) > CharUnits::fromQuantity(64)) {
- // Update Allocated GPRs
- markAllocatedGPRs(1, 1);
+ // Update Allocated GPRs. Since this is only used when the size of the
+ // argument is greater than 64 bytes, this will always use up any available
+ // registers (of which there are 4). We also don't care about getting the
+ // alignment right, because general-purpose registers cannot be back-filled.
+ markAllocatedGPRs(1, 4);
return ABIArgInfo::getIndirect(TyAlign, /*ByVal=*/true,
/*Realign=*/TyAlign > ABIAlign);
}
@@ -4372,6 +4499,10 @@
// are returned indirectly.
uint64_t Size = getContext().getTypeSize(RetTy);
if (Size <= 32) {
+ if (getDataLayout().isBigEndian())
+ // Return in 32 bit integer integer type (as if loaded by LDR, AAPCS 5.4)
+ return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext()));
+
// Return in the smallest viable integer type.
if (Size <= 8)
return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext()));
@@ -4876,44 +5007,6 @@
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::AuroraUX:
- case llvm::Triple::DragonFly:
- case llvm::Triple::FreeBSD:
- case llvm::Triple::OpenBSD:
- case llvm::Triple::Bitrig:
- return true;
- case llvm::Triple::Win32:
- switch (Triple.getEnvironment()) {
- case llvm::Triple::UnknownEnvironment:
- case llvm::Triple::Cygnus:
- case llvm::Triple::GNU:
- case llvm::Triple::MSVC:
- return true;
- default:
- return false;
- }
- default:
- return false;
- }
-}
-
ABIArgInfo SystemZABIInfo::classifyReturnType(QualType RetTy) const {
if (RetTy->isVoidType())
return ABIArgInfo::getIgnore();
@@ -6332,7 +6425,8 @@
}
/// Appends array encoding to Enc before calling appendType for the element.
-static bool appendArrayType(SmallStringEnc &Enc, const ArrayType *AT,
+static bool appendArrayType(SmallStringEnc &Enc, QualType QT,
+ const ArrayType *AT,
const CodeGen::CodeGenModule &CGM,
TypeStringCache &TSC, StringRef NoSizeEnc) {
if (AT->getSizeModifier() != ArrayType::Normal)
@@ -6343,6 +6437,8 @@
else
Enc += NoSizeEnc; // Global arrays use "*", otherwise it is "".
Enc += ':';
+ // The Qualifiers should be attached to the type rather than the array.
+ appendQualifier(Enc, QT);
if (!appendType(Enc, AT->getElementType(), CGM, TSC))
return false;
Enc += ')';
@@ -6391,14 +6487,16 @@
QualType QT = QType.getCanonicalType();
+ if (const ArrayType *AT = QT->getAsArrayTypeUnsafe())
+ // The Qualifiers should be attached to the type rather than the array.
+ // Thus we don't call appendQualifier() here.
+ return appendArrayType(Enc, QT, AT, CGM, TSC, "");
+
appendQualifier(Enc, QT);
if (const BuiltinType *BT = QT->getAs<BuiltinType>())
return appendBuiltinType(Enc, BT);
- if (const ArrayType *AT = QT->getAsArrayTypeUnsafe())
- return appendArrayType(Enc, AT, CGM, TSC, "");
-
if (const PointerType *PT = QT->getAs<PointerType>())
return appendPointerType(Enc, PT, CGM, TSC);
@@ -6434,8 +6532,9 @@
QualType QT = VD->getType().getCanonicalType();
if (const ArrayType *AT = QT->getAsArrayTypeUnsafe()) {
// Global ArrayTypes are given a size of '*' if the size is unknown.
- appendQualifier(Enc, QT);
- return appendArrayType(Enc, AT, CGM, TSC, "*");
+ // The Qualifiers should be attached to the type rather than the array.
+ // Thus we don't call appendQualifier() here.
+ return appendArrayType(Enc, QT, AT, CGM, TSC, "*");
}
return appendType(Enc, QT, CGM, TSC);
}
@@ -6471,7 +6570,7 @@
case llvm::Triple::arm64:
case llvm::Triple::arm64_be: {
AArch64ABIInfo::ABIKind Kind = AArch64ABIInfo::AAPCS;
- if (strcmp(getTarget().getABI(), "darwinpcs") == 0)
+ if (getTarget().getABI() == "darwinpcs")
Kind = AArch64ABIInfo::DarwinPCS;
return *(TheTargetCodeGenInfo = new AArch64TargetCodeGenInfo(Types, Kind));
@@ -6483,7 +6582,7 @@
case llvm::Triple::thumbeb:
{
ARMABIInfo::ABIKind Kind = ARMABIInfo::AAPCS;
- if (strcmp(getTarget().getABI(), "apcs-gnu") == 0)
+ if (getTarget().getABI() == "apcs-gnu")
Kind = ARMABIInfo::APCS;
else if (CodeGenOpts.FloatABI == "hard" ||
(CodeGenOpts.FloatABI != "soft" &&
@@ -6546,7 +6645,7 @@
}
case llvm::Triple::x86_64: {
- bool HasAVX = strcmp(getTarget().getABI(), "avx") == 0;
+ bool HasAVX = getTarget().getABI() == "avx";
switch (Triple.getOS()) {
case llvm::Triple::Win32: