diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/CodeGen')
27 files changed, 1089 insertions, 577 deletions
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp b/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp index 0bccad0..afcb9e5 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp @@ -292,6 +292,7 @@ void EmitAssemblyHelper::CreatePasses() { PMBuilder.DisableUnitAtATime = !CodeGenOpts.UnitAtATime; PMBuilder.DisableUnrollLoops = !CodeGenOpts.UnrollLoops; PMBuilder.MergeFunctions = CodeGenOpts.MergeFunctions; + PMBuilder.PrepareForLTO = CodeGenOpts.PrepareForLTO; PMBuilder.RerollLoops = CodeGenOpts.RerollLoops; PMBuilder.addExtension(PassManagerBuilder::EP_EarlyAsPossible, @@ -454,8 +455,6 @@ TargetMachine *EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) { BackendArgs.push_back("-limit-float-precision"); BackendArgs.push_back(CodeGenOpts.LimitFloatPrecision.c_str()); } - if (llvm::TimePassesIsEnabled) - BackendArgs.push_back("-time-passes"); for (unsigned i = 0, e = CodeGenOpts.BackendOptions.size(); i != e; ++i) BackendArgs.push_back(CodeGenOpts.BackendOptions[i].c_str()); BackendArgs.push_back(nullptr); diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGAtomic.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGAtomic.cpp index da82249..9839617 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGAtomic.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGAtomic.cpp @@ -93,6 +93,7 @@ namespace { BFI = OrigBFI; BFI.Offset = Offset; BFI.StorageSize = AtomicSizeInBits; + BFI.StorageOffset += OffsetInChars; LVal = LValue::MakeBitfield(Addr, BFI, lvalue.getType(), lvalue.getAlignment()); LVal.setTBAAInfo(lvalue.getTBAAInfo()); diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp index 2ec909b..9e53870 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp @@ -535,7 +535,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, } case Builtin::BI__builtin_readcyclecounter: { Value *F = CGM.getIntrinsic(Intrinsic::readcyclecounter); - return RValue::get(Builder.CreateCall(F, {})); + return RValue::get(Builder.CreateCall(F)); } case Builtin::BI__builtin___clear_cache: { Value *Begin = EmitScalarExpr(E->getArg(0)); @@ -923,7 +923,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, } case Builtin::BI__builtin_unwind_init: { Value *F = CGM.getIntrinsic(Intrinsic::eh_unwind_init); - return RValue::get(Builder.CreateCall(F, {})); + return RValue::get(Builder.CreateCall(F)); } case Builtin::BI__builtin_extend_pointer: { // Extends a pointer to the size of an _Unwind_Word, which is @@ -962,7 +962,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, // Store the stack pointer to the setjmp buffer. Value *StackAddr = - Builder.CreateCall(CGM.getIntrinsic(Intrinsic::stacksave), {}); + Builder.CreateCall(CGM.getIntrinsic(Intrinsic::stacksave)); Value *StackSaveSlot = Builder.CreateGEP(Buf, ConstantInt::get(Int32Ty, 2)); Builder.CreateStore(StackAddr, StackSaveSlot); @@ -3399,7 +3399,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, : InlineAsm::get(FTy, ".inst 0x" + utohexstr(ZExtValue), "", /*SideEffects=*/true); - return Builder.CreateCall(Emit, {}); + return Builder.CreateCall(Emit); } if (BuiltinID == ARM::BI__builtin_arm_dbg) { @@ -3543,7 +3543,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, if (BuiltinID == ARM::BI__builtin_arm_clrex) { Function *F = CGM.getIntrinsic(Intrinsic::arm_clrex); - return Builder.CreateCall(F, {}); + return Builder.CreateCall(F); } // CRC32 @@ -4339,7 +4339,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, if (BuiltinID == AArch64::BI__builtin_arm_clrex) { Function *F = CGM.getIntrinsic(Intrinsic::aarch64_clrex); - return Builder.CreateCall(F, {}); + return Builder.CreateCall(F); } // CRC32 @@ -6375,7 +6375,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, break; } - Value *Call = Builder.CreateCall(CGM.getIntrinsic(ID), {}); + Value *Call = Builder.CreateCall(CGM.getIntrinsic(ID)); Builder.CreateStore(Builder.CreateExtractValue(Call, 0), Ops[0]); return Builder.CreateExtractValue(Call, 1); } @@ -6633,14 +6633,104 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, llvm::Function *F = CGM.getIntrinsic(ID); return Builder.CreateCall(F, Ops, ""); } + // Square root + case PPC::BI__builtin_vsx_xvsqrtsp: + case PPC::BI__builtin_vsx_xvsqrtdp: { + llvm::Type *ResultType = ConvertType(E->getType()); + Value *X = EmitScalarExpr(E->getArg(0)); + ID = Intrinsic::sqrt; + llvm::Function *F = CGM.getIntrinsic(ID, ResultType); + return Builder.CreateCall(F, X); + } + // Count leading zeros + case PPC::BI__builtin_altivec_vclzb: + case PPC::BI__builtin_altivec_vclzh: + case PPC::BI__builtin_altivec_vclzw: + case PPC::BI__builtin_altivec_vclzd: { + llvm::Type *ResultType = ConvertType(E->getType()); + Value *X = EmitScalarExpr(E->getArg(0)); + Value *Undef = ConstantInt::get(Builder.getInt1Ty(), false); + Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ResultType); + return Builder.CreateCall(F, {X, Undef}); + } + // Copy sign + case PPC::BI__builtin_vsx_xvcpsgnsp: + case PPC::BI__builtin_vsx_xvcpsgndp: { + llvm::Type *ResultType = ConvertType(E->getType()); + Value *X = EmitScalarExpr(E->getArg(0)); + Value *Y = EmitScalarExpr(E->getArg(1)); + ID = Intrinsic::copysign; + llvm::Function *F = CGM.getIntrinsic(ID, ResultType); + return Builder.CreateCall(F, {X, Y}); + } + // Rounding/truncation case PPC::BI__builtin_vsx_xvrspip: case PPC::BI__builtin_vsx_xvrdpip: + case PPC::BI__builtin_vsx_xvrdpim: + case PPC::BI__builtin_vsx_xvrspim: + case PPC::BI__builtin_vsx_xvrdpi: + case PPC::BI__builtin_vsx_xvrspi: + case PPC::BI__builtin_vsx_xvrdpic: + case PPC::BI__builtin_vsx_xvrspic: + case PPC::BI__builtin_vsx_xvrdpiz: + case PPC::BI__builtin_vsx_xvrspiz: { llvm::Type *ResultType = ConvertType(E->getType()); Value *X = EmitScalarExpr(E->getArg(0)); - ID = Intrinsic::ceil; + if (BuiltinID == PPC::BI__builtin_vsx_xvrdpim || + BuiltinID == PPC::BI__builtin_vsx_xvrspim) + ID = Intrinsic::floor; + else if (BuiltinID == PPC::BI__builtin_vsx_xvrdpi || + BuiltinID == PPC::BI__builtin_vsx_xvrspi) + ID = Intrinsic::round; + else if (BuiltinID == PPC::BI__builtin_vsx_xvrdpic || + BuiltinID == PPC::BI__builtin_vsx_xvrspic) + ID = Intrinsic::nearbyint; + else if (BuiltinID == PPC::BI__builtin_vsx_xvrdpip || + BuiltinID == PPC::BI__builtin_vsx_xvrspip) + ID = Intrinsic::ceil; + else if (BuiltinID == PPC::BI__builtin_vsx_xvrdpiz || + BuiltinID == PPC::BI__builtin_vsx_xvrspiz) + ID = Intrinsic::trunc; llvm::Function *F = CGM.getIntrinsic(ID, ResultType); return Builder.CreateCall(F, X); } + // FMA variations + case PPC::BI__builtin_vsx_xvmaddadp: + case PPC::BI__builtin_vsx_xvmaddasp: + case PPC::BI__builtin_vsx_xvnmaddadp: + case PPC::BI__builtin_vsx_xvnmaddasp: + case PPC::BI__builtin_vsx_xvmsubadp: + case PPC::BI__builtin_vsx_xvmsubasp: + case PPC::BI__builtin_vsx_xvnmsubadp: + case PPC::BI__builtin_vsx_xvnmsubasp: { + llvm::Type *ResultType = ConvertType(E->getType()); + Value *X = EmitScalarExpr(E->getArg(0)); + Value *Y = EmitScalarExpr(E->getArg(1)); + Value *Z = EmitScalarExpr(E->getArg(2)); + Value *Zero = llvm::ConstantFP::getZeroValueForNegation(ResultType); + llvm::Function *F = CGM.getIntrinsic(Intrinsic::fma, ResultType); + switch (BuiltinID) { + case PPC::BI__builtin_vsx_xvmaddadp: + case PPC::BI__builtin_vsx_xvmaddasp: + return Builder.CreateCall(F, {X, Y, Z}); + case PPC::BI__builtin_vsx_xvnmaddadp: + case PPC::BI__builtin_vsx_xvnmaddasp: + return Builder.CreateFSub(Zero, + Builder.CreateCall(F, {X, Y, Z}), "sub"); + case PPC::BI__builtin_vsx_xvmsubadp: + case PPC::BI__builtin_vsx_xvmsubasp: + return Builder.CreateCall(F, + {X, Y, Builder.CreateFSub(Zero, Z, "sub")}); + case PPC::BI__builtin_vsx_xvnmsubadp: + case PPC::BI__builtin_vsx_xvnmsubasp: + Value *FsubRes = + Builder.CreateCall(F, {X, Y, Builder.CreateFSub(Zero, Z, "sub")}); + return Builder.CreateFSub(Zero, FsubRes, "sub"); + } + llvm_unreachable("Unknown FMA operation"); + return nullptr; // Suppress no-return warning + } + } } // Emit an intrinsic that has 1 float or double. diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp index 0535c05..3e4d7f3 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp @@ -912,20 +912,21 @@ static llvm::Value *CoerceIntOrPtrToIntOrPtr(llvm::Value *Val, /// CreateCoercedLoad - Create a load from \arg SrcPtr interpreted as -/// a pointer to an object of type \arg Ty. +/// a pointer to an object of type \arg Ty, known to be aligned to +/// \arg SrcAlign bytes. /// /// This safely handles the case when the src type is smaller than the /// destination type; in this situation the values of bits which not /// present in the src are undefined. static llvm::Value *CreateCoercedLoad(llvm::Value *SrcPtr, - llvm::Type *Ty, + llvm::Type *Ty, CharUnits SrcAlign, CodeGenFunction &CGF) { llvm::Type *SrcTy = cast<llvm::PointerType>(SrcPtr->getType())->getElementType(); // If SrcTy and Ty are the same, just do a load. if (SrcTy == Ty) - return CGF.Builder.CreateLoad(SrcPtr); + return CGF.Builder.CreateAlignedLoad(SrcPtr, SrcAlign.getQuantity()); uint64_t DstSize = CGF.CGM.getDataLayout().getTypeAllocSize(Ty); @@ -940,7 +941,8 @@ static llvm::Value *CreateCoercedLoad(llvm::Value *SrcPtr, // extension or truncation to the desired type. if ((isa<llvm::IntegerType>(Ty) || isa<llvm::PointerType>(Ty)) && (isa<llvm::IntegerType>(SrcTy) || isa<llvm::PointerType>(SrcTy))) { - llvm::LoadInst *Load = CGF.Builder.CreateLoad(SrcPtr); + llvm::LoadInst *Load = + CGF.Builder.CreateAlignedLoad(SrcPtr, SrcAlign.getQuantity()); return CoerceIntOrPtrToIntOrPtr(Load, Ty, CGF); } @@ -954,23 +956,20 @@ static llvm::Value *CreateCoercedLoad(llvm::Value *SrcPtr, // to that information. llvm::Value *Casted = CGF.Builder.CreateBitCast(SrcPtr, llvm::PointerType::getUnqual(Ty)); - llvm::LoadInst *Load = CGF.Builder.CreateLoad(Casted); - // FIXME: Use better alignment / avoid requiring aligned load. - Load->setAlignment(1); - return Load; + return CGF.Builder.CreateAlignedLoad(Casted, SrcAlign.getQuantity()); } // Otherwise do coercion through memory. This is stupid, but // simple. - llvm::Value *Tmp = CGF.CreateTempAlloca(Ty); + llvm::AllocaInst *Tmp = CGF.CreateTempAlloca(Ty); + Tmp->setAlignment(SrcAlign.getQuantity()); llvm::Type *I8PtrTy = CGF.Builder.getInt8PtrTy(); llvm::Value *Casted = CGF.Builder.CreateBitCast(Tmp, I8PtrTy); llvm::Value *SrcCasted = CGF.Builder.CreateBitCast(SrcPtr, I8PtrTy); - // FIXME: Use better alignment. CGF.Builder.CreateMemCpy(Casted, SrcCasted, llvm::ConstantInt::get(CGF.IntPtrTy, SrcSize), - 1, false); - return CGF.Builder.CreateLoad(Tmp); + SrcAlign.getQuantity(), false); + return CGF.Builder.CreateAlignedLoad(Tmp, SrcAlign.getQuantity()); } // Function to store a first-class aggregate into memory. We prefer to @@ -979,39 +978,45 @@ static llvm::Value *CreateCoercedLoad(llvm::Value *SrcPtr, // FIXME: Do we need to recurse here? static void BuildAggStore(CodeGenFunction &CGF, llvm::Value *Val, llvm::Value *DestPtr, bool DestIsVolatile, - bool LowAlignment) { + CharUnits DestAlign) { // Prefer scalar stores to first-class aggregate stores. if (llvm::StructType *STy = dyn_cast<llvm::StructType>(Val->getType())) { + const llvm::StructLayout *Layout = + CGF.CGM.getDataLayout().getStructLayout(STy); + for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { llvm::Value *EltPtr = CGF.Builder.CreateConstGEP2_32(STy, DestPtr, 0, i); llvm::Value *Elt = CGF.Builder.CreateExtractValue(Val, i); - llvm::StoreInst *SI = CGF.Builder.CreateStore(Elt, EltPtr, - DestIsVolatile); - if (LowAlignment) - SI->setAlignment(1); + uint64_t EltOffset = Layout->getElementOffset(i); + CharUnits EltAlign = + DestAlign.alignmentAtOffset(CharUnits::fromQuantity(EltOffset)); + CGF.Builder.CreateAlignedStore(Elt, EltPtr, EltAlign.getQuantity(), + DestIsVolatile); } } else { - llvm::StoreInst *SI = CGF.Builder.CreateStore(Val, DestPtr, DestIsVolatile); - if (LowAlignment) - SI->setAlignment(1); + CGF.Builder.CreateAlignedStore(Val, DestPtr, DestAlign.getQuantity(), + DestIsVolatile); } } /// CreateCoercedStore - Create a store to \arg DstPtr from \arg Src, -/// where the source and destination may have different types. +/// where the source and destination may have different types. The +/// destination is known to be aligned to \arg DstAlign bytes. /// /// This safely handles the case when the src type is larger than the /// destination type; the upper bits of the src will be lost. static void CreateCoercedStore(llvm::Value *Src, llvm::Value *DstPtr, bool DstIsVolatile, + CharUnits DstAlign, CodeGenFunction &CGF) { llvm::Type *SrcTy = Src->getType(); llvm::Type *DstTy = cast<llvm::PointerType>(DstPtr->getType())->getElementType(); if (SrcTy == DstTy) { - CGF.Builder.CreateStore(Src, DstPtr, DstIsVolatile); + CGF.Builder.CreateAlignedStore(Src, DstPtr, DstAlign.getQuantity(), + DstIsVolatile); return; } @@ -1027,7 +1032,8 @@ static void CreateCoercedStore(llvm::Value *Src, if ((isa<llvm::IntegerType>(SrcTy) || isa<llvm::PointerType>(SrcTy)) && (isa<llvm::IntegerType>(DstTy) || isa<llvm::PointerType>(DstTy))) { Src = CoerceIntOrPtrToIntOrPtr(Src, DstTy, CGF); - CGF.Builder.CreateStore(Src, DstPtr, DstIsVolatile); + CGF.Builder.CreateAlignedStore(Src, DstPtr, DstAlign.getQuantity(), + DstIsVolatile); return; } @@ -1037,8 +1043,7 @@ static void CreateCoercedStore(llvm::Value *Src, if (SrcSize <= DstSize) { llvm::Value *Casted = CGF.Builder.CreateBitCast(DstPtr, llvm::PointerType::getUnqual(SrcTy)); - // FIXME: Use better alignment / avoid requiring aligned store. - BuildAggStore(CGF, Src, Casted, DstIsVolatile, true); + BuildAggStore(CGF, Src, Casted, DstIsVolatile, DstAlign); } else { // Otherwise do coercion through memory. This is stupid, but // simple. @@ -1049,15 +1054,15 @@ static void CreateCoercedStore(llvm::Value *Src, // // FIXME: Assert that we aren't truncating non-padding bits when have access // to that information. - llvm::Value *Tmp = CGF.CreateTempAlloca(SrcTy); - CGF.Builder.CreateStore(Src, Tmp); + llvm::AllocaInst *Tmp = CGF.CreateTempAlloca(SrcTy); + Tmp->setAlignment(DstAlign.getQuantity()); + CGF.Builder.CreateAlignedStore(Src, Tmp, DstAlign.getQuantity()); llvm::Type *I8PtrTy = CGF.Builder.getInt8PtrTy(); llvm::Value *Casted = CGF.Builder.CreateBitCast(Tmp, I8PtrTy); llvm::Value *DstCasted = CGF.Builder.CreateBitCast(DstPtr, I8PtrTy); - // FIXME: Use better alignment. CGF.Builder.CreateMemCpy(DstCasted, Casted, llvm::ConstantInt::get(CGF.IntPtrTy, DstSize), - 1, false); + DstAlign.getQuantity(), false); } } @@ -1506,7 +1511,7 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl); if (FD) { - if (const TargetAttr *TD = FD->getAttr<TargetAttr>()) { + if (const auto *TD = FD->getAttr<TargetAttr>()) { StringRef FeaturesStr = TD->getFeatures(); SmallVector<StringRef, 1> AttrFeatures; FeaturesStr.split(AttrFeatures, ","); @@ -1514,9 +1519,13 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, // Grab the various features and prepend a "+" to turn on the feature to // the backend and add them to our existing set of features. for (auto &Feature : AttrFeatures) { + // Go ahead and trim whitespace rather than either erroring or + // accepting it weirdly. + Feature = Feature.trim(); + // While we're here iterating check for a different target cpu. if (Feature.startswith("arch=")) - TargetCPU = Feature.split("=").second; + TargetCPU = Feature.split("=").second.trim(); else if (Feature.startswith("tune=")) // We don't support cpu tuning this way currently. ; @@ -1992,6 +2001,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, Alloca->setAlignment(AlignmentToUse); llvm::Value *V = Alloca; llvm::Value *Ptr = V; // Pointer to store into. + CharUnits PtrAlign = CharUnits::fromQuantity(AlignmentToUse); // If the value is offset in memory, apply the offset now. if (unsigned Offs = ArgI.getDirectOffset()) { @@ -1999,6 +2009,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, Ptr = Builder.CreateConstGEP1_32(Builder.getInt8Ty(), Ptr, Offs); Ptr = Builder.CreateBitCast(Ptr, llvm::PointerType::getUnqual(ArgI.getCoerceToType())); + PtrAlign = PtrAlign.alignmentAtOffset(CharUnits::fromQuantity(Offs)); } // Fast-isel and the optimizer generally like scalar values better than @@ -2043,7 +2054,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, assert(NumIRArgs == 1); auto AI = FnArgs[FirstIRArg]; AI->setName(Arg->getName() + ".coerce"); - CreateCoercedStore(AI, Ptr, /*DestIsVolatile=*/false, *this); + CreateCoercedStore(AI, Ptr, /*DestIsVolatile=*/false, PtrAlign, *this); } @@ -2411,15 +2422,17 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI, } } else { llvm::Value *V = ReturnValue; + CharUnits Align = getContext().getTypeAlignInChars(RetTy); // If the value is offset in memory, apply the offset now. if (unsigned Offs = RetAI.getDirectOffset()) { V = Builder.CreateBitCast(V, Builder.getInt8PtrTy()); V = Builder.CreateConstGEP1_32(Builder.getInt8Ty(), V, Offs); V = Builder.CreateBitCast(V, llvm::PointerType::getUnqual(RetAI.getCoerceToType())); + Align = Align.alignmentAtOffset(CharUnits::fromQuantity(Offs)); } - RV = CreateCoercedLoad(V, RetAI.getCoerceToType(), *this); + RV = CreateCoercedLoad(V, RetAI.getCoerceToType(), Align, *this); } // In ARC, end functions that return a retainable type with a call @@ -3282,12 +3295,17 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // FIXME: Avoid the conversion through memory if possible. llvm::Value *SrcPtr; + CharUnits SrcAlign; if (RV.isScalar() || RV.isComplex()) { SrcPtr = CreateMemTemp(I->Ty, "coerce"); + SrcAlign = TypeAlign; LValue SrcLV = MakeAddrLValue(SrcPtr, I->Ty, TypeAlign); EmitInitStoreOfNonAggregate(*this, RV, SrcLV); - } else + } else { SrcPtr = RV.getAggregateAddr(); + // This alignment is guaranteed by EmitCallArg. + SrcAlign = TypeAlign; + } // If the value is offset in memory, apply the offset now. if (unsigned Offs = ArgInfo.getDirectOffset()) { @@ -3295,7 +3313,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, SrcPtr = Builder.CreateConstGEP1_32(Builder.getInt8Ty(), SrcPtr, Offs); SrcPtr = Builder.CreateBitCast(SrcPtr, llvm::PointerType::getUnqual(ArgInfo.getCoerceToType())); - + SrcAlign = SrcAlign.alignmentAtOffset(CharUnits::fromQuantity(Offs)); } // Fast-isel and the optimizer generally like scalar values better than @@ -3334,7 +3352,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // In the simple case, just pass the coerced loaded value. assert(NumIRArgs == 1); IRCallArgs[FirstIRArg] = - CreateCoercedLoad(SrcPtr, ArgInfo.getCoerceToType(), *this); + CreateCoercedLoad(SrcPtr, ArgInfo.getCoerceToType(), + SrcAlign, *this); } break; @@ -3531,12 +3550,13 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, case TEK_Aggregate: { llvm::Value *DestPtr = ReturnValue.getValue(); bool DestIsVolatile = ReturnValue.isVolatile(); + CharUnits DestAlign = getContext().getTypeAlignInChars(RetTy); if (!DestPtr) { DestPtr = CreateMemTemp(RetTy, "agg.tmp"); DestIsVolatile = false; } - BuildAggStore(*this, CI, DestPtr, DestIsVolatile, false); + BuildAggStore(*this, CI, DestPtr, DestIsVolatile, DestAlign); return RValue::getAggregate(DestPtr); } case TEK_Scalar: { @@ -3553,6 +3573,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, llvm::Value *DestPtr = ReturnValue.getValue(); bool DestIsVolatile = ReturnValue.isVolatile(); + CharUnits DestAlign = getContext().getTypeAlignInChars(RetTy); if (!DestPtr) { DestPtr = CreateMemTemp(RetTy, "coerce"); @@ -3561,14 +3582,17 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // If the value is offset in memory, apply the offset now. llvm::Value *StorePtr = DestPtr; + CharUnits StoreAlign = DestAlign; if (unsigned Offs = RetAI.getDirectOffset()) { StorePtr = Builder.CreateBitCast(StorePtr, Builder.getInt8PtrTy()); StorePtr = Builder.CreateConstGEP1_32(Builder.getInt8Ty(), StorePtr, Offs); StorePtr = Builder.CreateBitCast(StorePtr, llvm::PointerType::getUnqual(RetAI.getCoerceToType())); + StoreAlign = + StoreAlign.alignmentAtOffset(CharUnits::fromQuantity(Offs)); } - CreateCoercedStore(CI, StorePtr, DestIsVolatile, *this); + CreateCoercedStore(CI, StorePtr, DestIsVolatile, StoreAlign, *this); return convertTempToRValue(DestPtr, RetTy, SourceLocation()); } diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp index 62df982..c49f182 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp @@ -554,6 +554,20 @@ static bool isMemcpyEquivalentSpecialMember(const CXXMethodDecl *D) { return false; } +static void EmitLValueForAnyFieldInitialization(CodeGenFunction &CGF, + CXXCtorInitializer *MemberInit, + LValue &LHS) { + FieldDecl *Field = MemberInit->getAnyMember(); + if (MemberInit->isIndirectMemberInitializer()) { + // If we are initializing an anonymous union field, drill down to the field. + IndirectFieldDecl *IndirectField = MemberInit->getIndirectMember(); + for (const auto *I : IndirectField->chain()) + LHS = CGF.EmitLValueForFieldInitialization(LHS, cast<FieldDecl>(I)); + } else { + LHS = CGF.EmitLValueForFieldInitialization(LHS, Field); + } +} + static void EmitMemberInitializer(CodeGenFunction &CGF, const CXXRecordDecl *ClassDecl, CXXCtorInitializer *MemberInit, @@ -572,16 +586,7 @@ static void EmitMemberInitializer(CodeGenFunction &CGF, QualType RecordTy = CGF.getContext().getTypeDeclType(ClassDecl); LValue LHS = CGF.MakeNaturalAlignAddrLValue(ThisPtr, RecordTy); - if (MemberInit->isIndirectMemberInitializer()) { - // If we are initializing an anonymous union field, drill down to - // the field. - IndirectFieldDecl *IndirectField = MemberInit->getIndirectMember(); - for (const auto *I : IndirectField->chain()) - LHS = CGF.EmitLValueForFieldInitialization(LHS, cast<FieldDecl>(I)); - FieldType = MemberInit->getIndirectMember()->getAnonField()->getType(); - } else { - LHS = CGF.EmitLValueForFieldInitialization(LHS, Field); - } + EmitLValueForAnyFieldInitialization(CGF, MemberInit, LHS); // Special case: if we are in a copy or move constructor, and we are copying // an array of PODs or classes with trivial copy constructors, ignore the @@ -606,6 +611,11 @@ static void EmitMemberInitializer(CodeGenFunction &CGF, // Copy the aggregate. CGF.EmitAggregateCopy(LHS.getAddress(), Src.getAddress(), FieldType, LHS.isVolatileQualified()); + // Ensure that we destroy the objects if an exception is thrown later in + // the constructor. + QualType::DestructionKind dtorKind = FieldType.isDestructedType(); + if (CGF.needsEHCleanup(dtorKind)) + CGF.pushEHDestroy(dtorKind, LHS.getAddress(), FieldType); return; } } @@ -906,32 +916,18 @@ namespace { return; } - CharUnits Alignment; - uint64_t FirstByteOffset; if (FirstField->isBitField()) { const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(FirstField->getParent()); const CGBitFieldInfo &BFInfo = RL.getBitFieldInfo(FirstField); - Alignment = CharUnits::fromQuantity(BFInfo.StorageAlignment); // FirstFieldOffset is not appropriate for bitfields, - // it won't tell us what the storage offset should be and thus might not - // be properly aligned. - // - // Instead calculate the storage offset using the offset of the field in - // the struct type. - const llvm::DataLayout &DL = CGF.CGM.getDataLayout(); - FirstByteOffset = - DL.getStructLayout(RL.getLLVMType()) - ->getElementOffsetInBits(RL.getLLVMFieldNo(FirstField)); + // we need to use the storage offset instead. + FirstByteOffset = CGF.getContext().toBits(BFInfo.StorageOffset); } else { - Alignment = CGF.getContext().getDeclAlign(FirstField); FirstByteOffset = FirstFieldOffset; } - assert((CGF.getContext().toCharUnitsFromBits(FirstByteOffset) % - Alignment) == 0 && "Bad field alignment."); - CharUnits MemcpySize = getMemcpySize(FirstByteOffset); QualType RecordTy = CGF.getContext().getTypeDeclType(ClassDecl); llvm::Value *ThisPtr = CGF.LoadCXXThis(); @@ -941,6 +937,9 @@ namespace { LValue SrcLV = CGF.MakeNaturalAlignAddrLValue(SrcPtr, RecordTy); LValue Src = CGF.EmitLValueForFieldInitialization(SrcLV, FirstField); + CharUnits Offset = CGF.getContext().toCharUnitsFromBits(FirstByteOffset); + CharUnits Alignment = DestLV.getAlignment().alignmentAtOffset(Offset); + emitMemcpyIR(Dest.isBitField() ? Dest.getBitFieldAddr() : Dest.getAddress(), Src.isBitField() ? Src.getBitFieldAddr() : Src.getAddress(), MemcpySize, Alignment); @@ -1078,6 +1077,7 @@ namespace { CopyingValueRepresentation CVR(CGF); EmitMemberInitializer(CGF, ConstructorDecl->getParent(), AggregatedInits[0], ConstructorDecl, Args); + AggregatedInits.clear(); } reset(); return; @@ -1094,10 +1094,14 @@ namespace { LValue LHS = CGF.MakeNaturalAlignAddrLValue(ThisPtr, RecordTy); for (unsigned i = 0; i < AggregatedInits.size(); ++i) { - QualType FieldType = AggregatedInits[i]->getMember()->getType(); + CXXCtorInitializer *MemberInit = AggregatedInits[i]; + QualType FieldType = MemberInit->getAnyMember()->getType(); QualType::DestructionKind dtorKind = FieldType.isDestructedType(); - if (CGF.needsEHCleanup(dtorKind)) - CGF.pushEHDestroy(dtorKind, LHS.getAddress(), FieldType); + if (!CGF.needsEHCleanup(dtorKind)) + continue; + LValue FieldLHS = LHS; + EmitLValueForAnyFieldInitialization(CGF, MemberInit, FieldLHS); + CGF.pushEHDestroy(dtorKind, FieldLHS.getAddress(), FieldType); } } @@ -1363,6 +1367,25 @@ static bool CanSkipVTablePointerInitialization(ASTContext &Context, return true; } +// Generates function call for handling object poisoning, passing in +// references to 'this' and its size as arguments. +static void EmitDtorSanitizerCallback(CodeGenFunction &CGF, + const CXXDestructorDecl *Dtor) { + const ASTRecordLayout &Layout = + CGF.getContext().getASTRecordLayout(Dtor->getParent()); + + llvm::Value *Args[] = { + CGF.Builder.CreateBitCast(CGF.LoadCXXThis(), CGF.VoidPtrTy), + llvm::ConstantInt::get(CGF.SizeTy, Layout.getSize().getQuantity())}; + llvm::Type *ArgTypes[] = {CGF.VoidPtrTy, CGF.SizeTy}; + + llvm::FunctionType *FnType = + llvm::FunctionType::get(CGF.VoidTy, ArgTypes, false); + llvm::Value *Fn = + CGF.CGM.CreateRuntimeFunction(FnType, "__sanitizer_dtor_callback"); + CGF.EmitNounwindRuntimeCall(Fn, Args); +} + /// EmitDestructorBody - Emits the body of the current destructor. void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) { const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CurGD.getDecl()); @@ -1450,6 +1473,10 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) { // Exit the try if applicable. if (isTryBody) ExitCXXTryStmt(*cast<CXXTryStmt>(Body), true); + + // Insert memory-poisoning instrumentation. + if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor) + EmitDtorSanitizerCallback(*this, Dtor); } void CodeGenFunction::emitImplicitAssignmentOperatorBody(FunctionArgList &Args) { @@ -2202,8 +2229,7 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD, llvm::Value *VTable, CFITypeCheckKind TCK, SourceLocation Loc) { - // FIXME: Add blacklisting scheme. - if (RD->isInStdNamespace()) + if (CGM.IsCFIBlacklistedRecord(RD)) return; SanitizerScope SanScope(this); diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp index 8c4b4b3..93a2287 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp @@ -106,8 +106,6 @@ ApplyDebugLocation::~ApplyDebugLocation() { CGF.Builder.SetCurrentDebugLocation(std::move(OriginalLocation)); } -/// ArtificialLocation - An RAII object that temporarily switches to -/// an artificial debug location that has a valid scope, but no line void CGDebugInfo::setLocation(SourceLocation Loc) { // If the new location isn't valid return. if (Loc.isInvalid()) @@ -140,7 +138,6 @@ void CGDebugInfo::setLocation(SourceLocation Loc) { } } -/// getContextDescriptor - Get context info for the decl. llvm::DIScope *CGDebugInfo::getContextDescriptor(const Decl *Context) { if (!Context) return TheCU; @@ -162,9 +159,6 @@ llvm::DIScope *CGDebugInfo::getContextDescriptor(const Decl *Context) { return TheCU; } -/// getFunctionName - Get function name for the given FunctionDecl. If the -/// name is constructed on demand (e.g. C++ destructor) then the name -/// is stored on the side. StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) { assert(FD && "Invalid FunctionDecl!"); IdentifierInfo *FII = FD->getIdentifier(); @@ -220,13 +214,10 @@ StringRef CGDebugInfo::getObjCMethodName(const ObjCMethodDecl *OMD) { return internString(OS.str()); } -/// getSelectorName - Return selector name. This is used for debugging -/// info. StringRef CGDebugInfo::getSelectorName(Selector S) { return internString(S.getAsString()); } -/// getClassName - Get class name including template argument list. StringRef CGDebugInfo::getClassName(const RecordDecl *RD) { // quick optimization to avoid having to intern strings that are already // stored reliably elsewhere @@ -244,7 +235,6 @@ StringRef CGDebugInfo::getClassName(const RecordDecl *RD) { return internString(Name); } -/// getOrCreateFile - Get the file debug info descriptor for the input location. llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) { if (!Loc.isValid()) // If Location is not valid then use main input file. @@ -274,13 +264,10 @@ llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) { return F; } -/// getOrCreateMainFile - Get the file info for main compile unit. llvm::DIFile *CGDebugInfo::getOrCreateMainFile() { return DBuilder.createFile(TheCU->getFilename(), TheCU->getDirectory()); } -/// getLineNumber - Get line number for the location. If location is invalid -/// then use current location. unsigned CGDebugInfo::getLineNumber(SourceLocation Loc) { if (Loc.isInvalid() && CurLoc.isInvalid()) return 0; @@ -289,7 +276,6 @@ unsigned CGDebugInfo::getLineNumber(SourceLocation Loc) { return PLoc.isValid() ? PLoc.getLine() : 0; } -/// getColumnNumber - Get column number for the location. unsigned CGDebugInfo::getColumnNumber(SourceLocation Loc, bool Force) { // We may not want column information at all. if (!Force && !CGM.getCodeGenOpts().DebugColumnInfo) @@ -314,7 +300,6 @@ StringRef CGDebugInfo::getCurrentDirname() { return CWDName = internString(CWD); } -/// CreateCompileUnit - Create new compile unit. void CGDebugInfo::CreateCompileUnit() { // Should we be asking the SourceManager for the main file name, instead of @@ -385,8 +370,6 @@ void CGDebugInfo::CreateCompileUnit() { DebugKind != CodeGenOptions::LocTrackingOnly); } -/// CreateType - Get the Basic type from the cache or create a new -/// one if necessary. llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) { llvm::dwarf::TypeKind Encoding; StringRef BTName; @@ -537,8 +520,6 @@ llvm::DIType *CGDebugInfo::CreateType(const ComplexType *Ty) { return DBuilder.createBasicType("complex", Size, Align, Encoding); } -/// CreateCVRType - Get the qualified type from the cache or create -/// a new one if necessary. llvm::DIType *CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile *Unit) { QualifierCollector Qc; @@ -627,6 +608,7 @@ static SmallString<256> getUniqueTagTypeName(const TagType *Ty, return FullName; } +/// \return the approproate DWARF tag for a composite type. static llvm::dwarf::Tag getTagForRecord(const RecordDecl *RD) { llvm::dwarf::Tag Tag; if (RD->isStruct() || RD->isInterface()) @@ -642,7 +624,6 @@ static llvm::dwarf::Tag getTagForRecord(const RecordDecl *RD) { return Tag; } -// Creates a forward declaration for a RecordDecl in the given context. llvm::DICompositeType * CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty, llvm::DIScope *Ctx) { @@ -705,9 +686,6 @@ llvm::DIType *CGDebugInfo::getOrCreateStructPtrType(StringRef Name, llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty, llvm::DIFile *Unit) { - if (BlockLiteralGeneric) - return BlockLiteralGeneric; - SmallVector<llvm::Metadata *, 8> EltTys; QualType FType; uint64_t FieldSize, FieldOffset; @@ -723,10 +701,10 @@ llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty, EltTys.clear(); unsigned Flags = llvm::DINode::FlagAppleBlock; - unsigned LineNo = getLineNumber(CurLoc); + unsigned LineNo = 0; auto *EltTy = - DBuilder.createStructType(Unit, "__block_descriptor", Unit, LineNo, + DBuilder.createStructType(Unit, "__block_descriptor", nullptr, LineNo, FieldOffset, 0, Flags, nullptr, Elements); // Bit size, align and offset of the type. @@ -746,19 +724,22 @@ llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty, FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy); FieldSize = CGM.getContext().getTypeSize(Ty); FieldAlign = CGM.getContext().getTypeAlign(Ty); - EltTys.push_back(DBuilder.createMemberType(Unit, "__descriptor", Unit, LineNo, + EltTys.push_back(DBuilder.createMemberType(Unit, "__descriptor", nullptr, LineNo, FieldSize, FieldAlign, FieldOffset, 0, DescTy)); FieldOffset += FieldSize; Elements = DBuilder.getOrCreateArray(EltTys); + // The __block_literal_generic structs are marked with a special + // DW_AT_APPLE_BLOCK attribute and are an implementation detail only + // the debugger needs to know about. To allow type uniquing, emit + // them without a name or a location. EltTy = - DBuilder.createStructType(Unit, "__block_literal_generic", Unit, LineNo, + DBuilder.createStructType(Unit, "", nullptr, LineNo, FieldOffset, 0, Flags, nullptr, Elements); - BlockLiteralGeneric = DBuilder.createPointerType(EltTy, Size); - return BlockLiteralGeneric; + return DBuilder.createPointerType(EltTy, Size); } llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty, @@ -871,7 +852,6 @@ llvm::DIType *CGDebugInfo::createFieldType( AlignInBits, offsetInBits, flags, debugType); } -/// CollectRecordLambdaFields - Helper for CollectRecordFields. void CGDebugInfo::CollectRecordLambdaFields( const CXXRecordDecl *CXXDecl, SmallVectorImpl<llvm::Metadata *> &elements, llvm::DIType *RecordTy) { @@ -916,7 +896,6 @@ void CGDebugInfo::CollectRecordLambdaFields( } } -/// Helper for CollectRecordFields. llvm::DIDerivedType * CGDebugInfo::CreateRecordStaticField(const VarDecl *Var, llvm::DIType *RecordTy, const RecordDecl *RD) { @@ -946,7 +925,6 @@ CGDebugInfo::CreateRecordStaticField(const VarDecl *Var, llvm::DIType *RecordTy, return GV; } -/// CollectRecordNormalField - Helper for CollectRecordFields. void CGDebugInfo::CollectRecordNormalField( const FieldDecl *field, uint64_t OffsetInBits, llvm::DIFile *tunit, SmallVectorImpl<llvm::Metadata *> &elements, llvm::DIType *RecordTy, @@ -971,8 +949,6 @@ void CGDebugInfo::CollectRecordNormalField( elements.push_back(fieldType); } -/// CollectRecordFields - A helper function to collect debug info for -/// record fields. This is used while creating debug info entry for a Record. void CGDebugInfo::CollectRecordFields( const RecordDecl *record, llvm::DIFile *tunit, SmallVectorImpl<llvm::Metadata *> &elements, @@ -1011,9 +987,6 @@ void CGDebugInfo::CollectRecordFields( } } -/// getOrCreateMethodType - CXXMethodDecl's type is a FunctionType. This -/// function type is not updated to include implicit "this" pointer. Use this -/// routine to get a method type which includes "this" pointer. llvm::DISubroutineType * CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method, llvm::DIFile *Unit) { @@ -1088,8 +1061,6 @@ static bool isFunctionLocalClass(const CXXRecordDecl *RD) { return false; } -/// CreateCXXMemberFunction - A helper function to create a subprogram for -/// a single member function GlobalDecl. llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction( const CXXMethodDecl *Method, llvm::DIFile *Unit, llvm::DIType *RecordTy) { bool IsCtorOrDtor = @@ -1165,9 +1136,6 @@ llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction( return SP; } -/// CollectCXXMemberFunctions - A helper function to collect debug info for -/// C++ member functions. This is used while creating debug info entry for -/// a Record. void CGDebugInfo::CollectCXXMemberFunctions( const CXXRecordDecl *RD, llvm::DIFile *Unit, SmallVectorImpl<llvm::Metadata *> &EltTys, llvm::DIType *RecordTy) { @@ -1206,9 +1174,6 @@ void CGDebugInfo::CollectCXXMemberFunctions( } } -/// CollectCXXBases - A helper function to collect debug info for -/// C++ base classes. This is used while creating debug info entry for -/// a Record. void CGDebugInfo::CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile *Unit, SmallVectorImpl<llvm::Metadata *> &EltTys, llvm::DIType *RecordTy) { @@ -1246,7 +1211,6 @@ void CGDebugInfo::CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile *Unit, } } -/// CollectTemplateParams - A helper function to collect template parameters. llvm::DINodeArray CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList, ArrayRef<TemplateArgument> TAList, @@ -1351,8 +1315,6 @@ CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList, return DBuilder.getOrCreateArray(TemplateParams); } -/// CollectFunctionTemplateParams - A helper function to collect debug -/// info for function template parameters. llvm::DINodeArray CGDebugInfo::CollectFunctionTemplateParams(const FunctionDecl *FD, llvm::DIFile *Unit) { @@ -1367,8 +1329,6 @@ CGDebugInfo::CollectFunctionTemplateParams(const FunctionDecl *FD, return llvm::DINodeArray(); } -/// CollectCXXTemplateParams - A helper function to collect debug info for -/// template parameters. llvm::DINodeArray CGDebugInfo::CollectCXXTemplateParams( const ClassTemplateSpecializationDecl *TSpecial, llvm::DIFile *Unit) { // Always get the full list of parameters, not just the ones from @@ -1379,7 +1339,6 @@ llvm::DINodeArray CGDebugInfo::CollectCXXTemplateParams( return CollectTemplateParams(TPList, TAList.asArray(), Unit); } -/// getOrCreateVTablePtrType - Return debug info descriptor for vtable. llvm::DIType *CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile *Unit) { if (VTablePtrType) return VTablePtrType; @@ -1397,14 +1356,11 @@ llvm::DIType *CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile *Unit) { return VTablePtrType; } -/// getVTableName - Get vtable name for the given Class. StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) { // Copy the gdb compatible name on the side and use its reference. return internString("_vptr$", RD->getNameAsString()); } -/// CollectVTableInfo - If the C++ class has vtable info then insert appropriate -/// debug info entry in EltTys vector. void CGDebugInfo::CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile *Unit, SmallVectorImpl<llvm::Metadata *> &EltTys) { const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); @@ -1424,7 +1380,6 @@ void CGDebugInfo::CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile *Unit, EltTys.push_back(VPTR); } -/// getOrCreateRecordType - Emit record type's standalone debug info. llvm::DIType *CGDebugInfo::getOrCreateRecordType(QualType RTy, SourceLocation Loc) { assert(DebugKind >= CodeGenOptions::LimitedDebugInfo); @@ -1432,8 +1387,6 @@ llvm::DIType *CGDebugInfo::getOrCreateRecordType(QualType RTy, return T; } -/// getOrCreateInterfaceType - Emit an objective c interface type standalone -/// debug info. llvm::DIType *CGDebugInfo::getOrCreateInterfaceType(QualType D, SourceLocation Loc) { assert(DebugKind >= CodeGenOptions::LimitedDebugInfo); @@ -1531,7 +1484,6 @@ static bool shouldOmitDefinition(CodeGenOptions::DebugInfoKind DebugKind, return false; } -/// CreateType - get structure or union type. llvm::DIType *CGDebugInfo::CreateType(const RecordType *Ty) { RecordDecl *RD = Ty->getDecl(); llvm::DIType *T = cast_or_null<llvm::DIType>(getTypeOrNull(QualType(Ty, 0))); @@ -1605,7 +1557,6 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) { return FwdDecl; } -/// CreateType - get objective-c object type. llvm::DIType *CGDebugInfo::CreateType(const ObjCObjectType *Ty, llvm::DIFile *Unit) { // Ignore protocols. @@ -1636,7 +1587,6 @@ static bool hasDefaultSetterName(const ObjCPropertyDecl *PD, Setter->getDeclName().getObjCSelector().getNameForSlot(0); } -/// CreateType - get objective-c interface type. llvm::DIType *CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, llvm::DIFile *Unit) { ObjCInterfaceDecl *ID = Ty->getDecl(); @@ -1956,7 +1906,6 @@ llvm::DIType *CGDebugInfo::CreateType(const AtomicType *Ty, llvm::DIFile *U) { return getOrCreateType(Ty->getValueType(), U); } -/// CreateEnumType - get enumeration type. llvm::DIType *CGDebugInfo::CreateEnumType(const EnumType *Ty) { const EnumDecl *ED = Ty->getDecl(); uint64_t Size = 0; @@ -2076,8 +2025,6 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) { } while (true); } -/// getType - Get the type from the cache or return null type if it doesn't -/// exist. llvm::DIType *CGDebugInfo::getTypeOrNull(QualType Ty) { // Unwrap the type as needed for debug information. @@ -2104,8 +2051,6 @@ void CGDebugInfo::completeTemplateDefinition( RetainedTypes.push_back(CGM.getContext().getRecordType(&SD).getAsOpaquePtr()); } -/// getOrCreateType - Get the type from the cache or create a new -/// one if necessary. llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit) { if (Ty.isNull()) return nullptr; @@ -2126,8 +2071,6 @@ llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit) { return Res; } -/// Currently the checksum of an interface includes the number of -/// ivars and property accessors. unsigned CGDebugInfo::Checksum(const ObjCInterfaceDecl *ID) { // The assumption is that the number of ivars can only increase // monotonically, so it is safe to just use their current number as @@ -2152,7 +2095,6 @@ ObjCInterfaceDecl *CGDebugInfo::getObjCInterfaceDecl(QualType Ty) { } } -/// CreateTypeNode - Create a new debug type node. llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) { // Handle qualifiers, which recursively handles what they refer to. if (Ty.hasLocalQualifiers()) @@ -2233,8 +2175,6 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) { llvm_unreachable("type should have been unwrapped!"); } -/// getOrCreateLimitedType - Get the type from the cache or create a new -/// limited type if necessary. llvm::DIType *CGDebugInfo::getOrCreateLimitedType(const RecordType *Ty, llvm::DIFile *Unit) { QualType QTy(Ty, 0); @@ -2328,7 +2268,6 @@ void CGDebugInfo::CollectContainingType(const CXXRecordDecl *RD, DBuilder.replaceVTableHolder(RealDecl, ContainingType); } -/// CreateMemberType - Create new member and increase Offset by FType's size. llvm::DIType *CGDebugInfo::CreateMemberType(llvm::DIFile *Unit, QualType FType, StringRef Name, uint64_t *Offset) { llvm::DIType *FieldTy = CGDebugInfo::getOrCreateType(FType, Unit); @@ -2493,8 +2432,6 @@ llvm::DINode *CGDebugInfo::getDeclarationOrDefinition(const Decl *D) { return nullptr; } -/// getFunctionDeclaration - Return debug info descriptor to describe method -/// declaration for the given method definition. llvm::DISubprogram *CGDebugInfo::getFunctionDeclaration(const Decl *D) { if (!D || DebugKind <= CodeGenOptions::DebugLineTablesOnly) return nullptr; @@ -2591,7 +2528,6 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateFunctionType(const Decl *D, return cast<llvm::DISubroutineType>(getOrCreateType(FnType, F)); } -/// EmitFunctionStart - Constructs the debug code for entering a function. void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc, SourceLocation ScopeLoc, QualType FnType, llvm::Function *Fn, CGBuilderTy &Builder) { @@ -2667,9 +2603,6 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc, RegionMap[D].reset(SP); } -/// EmitLocation - Emit metadata to indicate a change in line/column -/// information in the source file. If the location is invalid, the -/// previous location will be reused. void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc) { // Update our current location setLocation(Loc); @@ -2682,8 +2615,6 @@ void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc) { getLineNumber(CurLoc), getColumnNumber(CurLoc), Scope)); } -/// CreateLexicalBlock - Creates a new lexical block node and pushes it on -/// the stack. void CGDebugInfo::CreateLexicalBlock(SourceLocation Loc) { llvm::MDNode *Back = nullptr; if (!LexicalBlockStack.empty()) @@ -2693,8 +2624,6 @@ void CGDebugInfo::CreateLexicalBlock(SourceLocation Loc) { getColumnNumber(CurLoc))); } -/// EmitLexicalBlockStart - Constructs the debug code for entering a declarative -/// region - beginning of a DW_TAG_lexical_block. void CGDebugInfo::EmitLexicalBlockStart(CGBuilderTy &Builder, SourceLocation Loc) { // Set our current location. @@ -2711,8 +2640,6 @@ void CGDebugInfo::EmitLexicalBlockStart(CGBuilderTy &Builder, CreateLexicalBlock(Loc); } -/// EmitLexicalBlockEnd - Constructs the debug code for exiting a declarative -/// region - end of a DW_TAG_lexical_block. void CGDebugInfo::EmitLexicalBlockEnd(CGBuilderTy &Builder, SourceLocation Loc) { assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!"); @@ -2726,7 +2653,6 @@ void CGDebugInfo::EmitLexicalBlockEnd(CGBuilderTy &Builder, LexicalBlockStack.pop_back(); } -/// EmitFunctionEnd - Constructs the debug code for exiting a function. void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder) { assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!"); unsigned RCount = FnBeginRegionCount.back(); @@ -2741,8 +2667,6 @@ void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder) { FnBeginRegionCount.pop_back(); } -// EmitTypeForVarWithBlocksAttr - Build up structure info for the byref. -// See BuildByRefType. llvm::DIType *CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD, uint64_t *XOffset) { @@ -2816,7 +2740,6 @@ llvm::DIType *CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD, nullptr, Elements); } -/// EmitDeclare - Emit local variable declaration debug info. void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::dwarf::Tag Tag, llvm::Value *Storage, unsigned ArgNo, CGBuilderTy &Builder) { @@ -2944,12 +2867,6 @@ void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD, EmitDeclare(VD, llvm::dwarf::DW_TAG_auto_variable, Storage, 0, Builder); } -/// Look up the completed type for a self pointer in the TypeCache and -/// create a copy of it with the ObjectPointer and Artificial flags -/// set. If the type is not cached, a new one is created. This should -/// never happen though, since creating a type for the implicit self -/// argument implies that we already parsed the interface definition -/// and the ivar declarations in the implementation. llvm::DIType *CGDebugInfo::CreateSelfType(const QualType &QualTy, llvm::DIType *Ty) { llvm::DIType *CachedTy = getTypeOrNull(QualTy); @@ -3027,8 +2944,6 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable( Builder.GetInsertBlock()); } -/// EmitDeclareOfArgVariable - Emit call to llvm.dbg.declare for an argument -/// variable declaration. void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *VD, llvm::Value *AI, unsigned ArgNo, CGBuilderTy &Builder) { @@ -3192,8 +3107,6 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block, Builder.GetInsertBlock()); } -/// If D is an out-of-class definition of a static data member of a class, find -/// its corresponding in-class declaration. llvm::DIDerivedType * CGDebugInfo::getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D) { if (!D->isStaticDataMember()) @@ -3213,9 +3126,6 @@ CGDebugInfo::getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D) { return CreateRecordStaticField(D, Ctxt, cast<RecordDecl>(DC)); } -/// Recursively collect all of the member fields of a global anonymous decl and -/// create static variables for them. The first time this is called it needs -/// to be on a union and then from there we can have additional unnamed fields. llvm::DIGlobalVariable *CGDebugInfo::CollectAnonRecordDecls( const RecordDecl *RD, llvm::DIFile *Unit, unsigned LineNo, StringRef LinkageName, llvm::GlobalVariable *Var, llvm::DIScope *DContext) { @@ -3241,7 +3151,6 @@ llvm::DIGlobalVariable *CGDebugInfo::CollectAnonRecordDecls( return GV; } -/// EmitGlobalVariable - Emit information about a global variable. void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, const VarDecl *D) { assert(DebugKind >= CodeGenOptions::LimitedDebugInfo); @@ -3274,7 +3183,6 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, DeclCache[D->getCanonicalDecl()].reset(static_cast<llvm::Metadata *>(GV)); } -/// EmitGlobalVariable - Emit global variable's debug info. void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, llvm::Constant *Init) { assert(DebugKind >= CodeGenOptions::LimitedDebugInfo); @@ -3380,8 +3288,6 @@ CGDebugInfo::EmitNamespaceAlias(const NamespaceAliasDecl &NA) { return R; } -/// getOrCreateNamesSpace - Return namespace descriptor for the given -/// namespace decl. llvm::DINamespace * CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl) { NSDecl = NSDecl->getCanonicalDecl(); diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h index 10d3b0d..4c77a8d 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h @@ -26,26 +26,26 @@ #include "llvm/Support/Allocator.h" namespace llvm { - class MDNode; +class MDNode; } namespace clang { - class CXXMethodDecl; - class VarDecl; - class ObjCInterfaceDecl; - class ObjCIvarDecl; - class ClassTemplateSpecializationDecl; - class GlobalDecl; - class UsingDecl; +class CXXMethodDecl; +class VarDecl; +class ObjCInterfaceDecl; +class ObjCIvarDecl; +class ClassTemplateSpecializationDecl; +class GlobalDecl; +class UsingDecl; namespace CodeGen { - class CodeGenModule; - class CodeGenFunction; - class CGBlockInfo; +class CodeGenModule; +class CodeGenFunction; +class CGBlockInfo; -/// \brief This class gathers all debug information during compilation -/// and is responsible for emitting to llvm globals or pass directly to -/// the backend. +/// This class gathers all debug information during compilation and is +/// responsible for emitting to llvm globals or pass directly to the +/// backend. class CGDebugInfo { friend class ApplyDebugLocation; friend class SaveAndRestoreLocation; @@ -65,9 +65,8 @@ class CGDebugInfo { llvm::DIType *OCLImage2dArrayDITy = nullptr; llvm::DIType *OCLImage3dDITy = nullptr; llvm::DIType *OCLEventDITy = nullptr; - llvm::DIType *BlockLiteralGeneric = nullptr; - /// \brief Cache of previously constructed Types. + /// Cache of previously constructed Types. llvm::DenseMap<const void *, llvm::TrackingMDRef> TypeCache; struct ObjCInterfaceCacheEntry { @@ -79,41 +78,40 @@ class CGDebugInfo { : Type(Type), Decl(Decl), Unit(Unit) {} }; - /// \brief Cache of previously constructed interfaces - /// which may change. + /// Cache of previously constructed interfaces which may change. llvm::SmallVector<ObjCInterfaceCacheEntry, 32> ObjCInterfaceCache; - /// \brief Cache of references to AST files such as PCHs or modules. + /// Cache of references to AST files such as PCHs or modules. llvm::DenseMap<uint64_t, llvm::DIModule *> ModuleRefCache; - /// \brief list of interfaces we want to keep even if orphaned. + /// List of interfaces we want to keep even if orphaned. std::vector<void *> RetainedTypes; - /// \brief Cache of forward declared types to RAUW at the end of + /// Cache of forward declared types to RAUW at the end of /// compilation. std::vector<std::pair<const TagType *, llvm::TrackingMDRef>> ReplaceMap; - /// \brief Cache of replaceable forward declarartions (functions and + /// Cache of replaceable forward declarartions (functions and /// variables) to RAUW at the end of compilation. std::vector<std::pair<const DeclaratorDecl *, llvm::TrackingMDRef>> FwdDeclReplaceMap; - // LexicalBlockStack - Keep track of our current nested lexical block. + /// Keep track of our current nested lexical block. std::vector<llvm::TypedTrackingMDRef<llvm::DIScope>> LexicalBlockStack; llvm::DenseMap<const Decl *, llvm::TrackingMDRef> RegionMap; - // FnBeginRegionCount - Keep track of LexicalBlockStack counter at the - // beginning of a function. This is used to pop unbalanced regions at - // the end of a function. + /// Keep track of LexicalBlockStack counter at the beginning of a + /// function. This is used to pop unbalanced regions at the end of a + /// function. std::vector<unsigned> FnBeginRegionCount; - /// \brief This is a storage for names that are - /// constructed on demand. For example, C++ destructors, C++ operators etc.. + /// This is a storage for names that are constructed on demand. For + /// example, C++ destructors, C++ operators etc.. llvm::BumpPtrAllocator DebugInfoNames; StringRef CWDName; llvm::DenseMap<const char *, llvm::TrackingMDRef> DIFileCache; llvm::DenseMap<const FunctionDecl *, llvm::TrackingMDRef> SPCache; - /// \brief Cache declarations relevant to DW_TAG_imported_declarations (C++ + /// Cache declarations relevant to DW_TAG_imported_declarations (C++ /// using declarations) that aren't covered by other more specific caches. llvm::DenseMap<const Decl *, llvm::TrackingMDRef> DeclCache; llvm::DenseMap<const NamespaceDecl *, llvm::TrackingMDRef> NameSpaceCache; @@ -122,6 +120,9 @@ class CGDebugInfo { llvm::DenseMap<const Decl *, llvm::TrackingMDRef> StaticDataMemberCache; /// Helper functions for getOrCreateType. + /// @{ + /// Currently the checksum of an interface includes the number of + /// ivars and property accessors. unsigned Checksum(const ObjCInterfaceDecl *InterfaceDecl); llvm::DIType *CreateType(const BuiltinType *Ty); llvm::DIType *CreateType(const ComplexType *Ty); @@ -133,14 +134,17 @@ class CGDebugInfo { llvm::DIType *CreateType(const PointerType *Ty, llvm::DIFile *F); llvm::DIType *CreateType(const BlockPointerType *Ty, llvm::DIFile *F); llvm::DIType *CreateType(const FunctionType *Ty, llvm::DIFile *F); + /// Get structure or union type. llvm::DIType *CreateType(const RecordType *Tyg); llvm::DIType *CreateTypeDefinition(const RecordType *Ty); llvm::DICompositeType *CreateLimitedType(const RecordType *Ty); void CollectContainingType(const CXXRecordDecl *RD, llvm::DICompositeType *CT); + /// Get Objective-C interface type. llvm::DIType *CreateType(const ObjCInterfaceType *Ty, llvm::DIFile *F); llvm::DIType *CreateTypeDefinition(const ObjCInterfaceType *Ty, llvm::DIFile *F); + /// Get Objective-C object type. llvm::DIType *CreateType(const ObjCObjectType *Ty, llvm::DIFile *F); llvm::DIType *CreateType(const VectorType *Ty, llvm::DIFile *F); llvm::DIType *CreateType(const ArrayType *Ty, llvm::DIFile *F); @@ -148,10 +152,25 @@ class CGDebugInfo { llvm::DIType *CreateType(const RValueReferenceType *Ty, llvm::DIFile *Unit); llvm::DIType *CreateType(const MemberPointerType *Ty, llvm::DIFile *F); llvm::DIType *CreateType(const AtomicType *Ty, llvm::DIFile *F); + /// Get enumeration type. llvm::DIType *CreateEnumType(const EnumType *Ty); llvm::DIType *CreateTypeDefinition(const EnumType *Ty); + /// Look up the completed type for a self pointer in the TypeCache and + /// create a copy of it with the ObjectPointer and Artificial flags + /// set. If the type is not cached, a new one is created. This should + /// never happen though, since creating a type for the implicit self + /// argument implies that we already parsed the interface definition + /// and the ivar declarations in the implementation. llvm::DIType *CreateSelfType(const QualType &QualTy, llvm::DIType *Ty); + /// @} + + /// Get the type from the cache or return null type if it doesn't + /// exist. llvm::DIType *getTypeOrNull(const QualType); + /// Return the debug type for a C++ method. + /// \arg CXXMethodDecl is of FunctionType. This function type is + /// not updated to include implicit \c this pointer. Use this routine + /// to get a method type which includes \c this pointer. llvm::DISubroutineType *getOrCreateMethodType(const CXXMethodDecl *Method, llvm::DIFile *F); llvm::DISubroutineType * @@ -159,7 +178,9 @@ class CGDebugInfo { llvm::DIFile *Unit); llvm::DISubroutineType * getOrCreateFunctionType(const Decl *D, QualType FnType, llvm::DIFile *F); + /// \return debug info descriptor for vtable. llvm::DIType *getOrCreateVTablePtrType(llvm::DIFile *F); + /// \return namespace descriptor for the given namespace decl. llvm::DINamespace *getOrCreateNameSpace(const NamespaceDecl *N); llvm::DIType *getOrCreateTypeDeclaration(QualType PointeeTy, llvm::DIFile *F); llvm::DIType *CreatePointerLikeType(llvm::dwarf::Tag Tag, const Type *Ty, @@ -168,23 +189,37 @@ class CGDebugInfo { llvm::Value *getCachedInterfaceTypeOrNull(const QualType Ty); llvm::DIType *getOrCreateStructPtrType(StringRef Name, llvm::DIType *&Cache); + /// A helper function to create a subprogram for a single member + /// function GlobalDecl. llvm::DISubprogram *CreateCXXMemberFunction(const CXXMethodDecl *Method, llvm::DIFile *F, llvm::DIType *RecordTy); + /// A helper function to collect debug info for C++ member + /// functions. This is used while creating debug info entry for a + /// Record. void CollectCXXMemberFunctions(const CXXRecordDecl *Decl, llvm::DIFile *F, SmallVectorImpl<llvm::Metadata *> &E, llvm::DIType *T); + /// A helper function to collect debug info for C++ base + /// classes. This is used while creating debug info entry for a + /// Record. void CollectCXXBases(const CXXRecordDecl *Decl, llvm::DIFile *F, SmallVectorImpl<llvm::Metadata *> &EltTys, llvm::DIType *RecordTy); + /// A helper function to collect template parameters. llvm::DINodeArray CollectTemplateParams(const TemplateParameterList *TPList, ArrayRef<TemplateArgument> TAList, llvm::DIFile *Unit); + /// A helper function to collect debug info for function template + /// parameters. llvm::DINodeArray CollectFunctionTemplateParams(const FunctionDecl *FD, llvm::DIFile *Unit); + + /// A helper function to collect debug info for template + /// parameters. llvm::DINodeArray CollectCXXTemplateParams(const ClassTemplateSpecializationDecl *TS, llvm::DIFile *F); @@ -195,7 +230,8 @@ class CGDebugInfo { llvm::DIFile *tunit, llvm::DIScope *scope, const RecordDecl *RD = nullptr); - // Helpers for collecting fields of a record. + /// Helpers for collecting fields of a record. + /// @{ void CollectRecordLambdaFields(const CXXRecordDecl *CXXDecl, SmallVectorImpl<llvm::Metadata *> &E, llvm::DIType *RecordTy); @@ -210,11 +246,13 @@ class CGDebugInfo { SmallVectorImpl<llvm::Metadata *> &E, llvm::DICompositeType *RecordTy); + /// If the C++ class has vtable info then insert appropriate debug + /// info entry in EltTys vector. void CollectVTableInfo(const CXXRecordDecl *Decl, llvm::DIFile *F, SmallVectorImpl<llvm::Metadata *> &EltTys); + /// @} - // CreateLexicalBlock - Create a new lexical block node and push it on - // the stack. + /// Create a new lexical block node and push it on the stack. void CreateLexicalBlock(SourceLocation Loc); public: @@ -223,86 +261,84 @@ public: void finalize(); - /// \brief Update the current source location. If \arg loc is - /// invalid it is ignored. + /// Update the current source location. If \arg loc is invalid it is + /// ignored. void setLocation(SourceLocation Loc); - /// \brief Emit metadata to indicate a change in line/column - /// information in the source file. + /// Emit metadata to indicate a change in line/column information in + /// the source file. If the location is invalid, the previous + /// location will be reused. void EmitLocation(CGBuilderTy &Builder, SourceLocation Loc); - /// \brief Emit a call to llvm.dbg.function.start to indicate + /// Emit a call to llvm.dbg.function.start to indicate /// start of a new function. /// \param Loc The location of the function header. /// \param ScopeLoc The location of the function body. - void EmitFunctionStart(GlobalDecl GD, - SourceLocation Loc, SourceLocation ScopeLoc, - QualType FnType, llvm::Function *Fn, - CGBuilderTy &Builder); + void EmitFunctionStart(GlobalDecl GD, SourceLocation Loc, + SourceLocation ScopeLoc, QualType FnType, + llvm::Function *Fn, CGBuilderTy &Builder); - /// \brief Constructs the debug code for exiting a function. + /// Constructs the debug code for exiting a function. void EmitFunctionEnd(CGBuilderTy &Builder); - /// \brief Emit metadata to indicate the beginning of a - /// new lexical block and push the block onto the stack. + /// Emit metadata to indicate the beginning of a new lexical block + /// and push the block onto the stack. void EmitLexicalBlockStart(CGBuilderTy &Builder, SourceLocation Loc); - /// \brief Emit metadata to indicate the end of a new lexical - /// block and pop the current block. + /// Emit metadata to indicate the end of a new lexical block and pop + /// the current block. void EmitLexicalBlockEnd(CGBuilderTy &Builder, SourceLocation Loc); - /// \brief Emit call to llvm.dbg.declare for an automatic - /// variable declaration. + /// Emit call to \c llvm.dbg.declare for an automatic variable + /// declaration. void EmitDeclareOfAutoVariable(const VarDecl *Decl, llvm::Value *AI, CGBuilderTy &Builder); - /// \brief Emit call to llvm.dbg.declare for an - /// imported variable declaration in a block. + /// Emit call to \c llvm.dbg.declare for an imported variable + /// declaration in a block. void EmitDeclareOfBlockDeclRefVariable(const VarDecl *variable, llvm::Value *storage, CGBuilderTy &Builder, const CGBlockInfo &blockInfo, llvm::Instruction *InsertPoint = 0); - /// \brief Emit call to llvm.dbg.declare for an argument - /// variable declaration. + /// Emit call to \c llvm.dbg.declare for an argument variable + /// declaration. void EmitDeclareOfArgVariable(const VarDecl *Decl, llvm::Value *AI, unsigned ArgNo, CGBuilderTy &Builder); - /// \brief Emit call to - /// llvm.dbg.declare for the block-literal argument to a block - /// invocation function. + /// Emit call to \c llvm.dbg.declare for the block-literal argument + /// to a block invocation function. void EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block, llvm::Value *Arg, unsigned ArgNo, llvm::Value *LocalAddr, CGBuilderTy &Builder); - /// \brief Emit information about a global variable. + /// Emit information about a global variable. void EmitGlobalVariable(llvm::GlobalVariable *GV, const VarDecl *Decl); - /// \brief Emit global variable's debug info. + /// Emit global variable's debug info. void EmitGlobalVariable(const ValueDecl *VD, llvm::Constant *Init); - /// \brief Emit C++ using directive. + /// Emit C++ using directive. void EmitUsingDirective(const UsingDirectiveDecl &UD); - /// \brief Emit the type explicitly casted to. + /// Emit the type explicitly casted to. void EmitExplicitCastType(QualType Ty); - /// \brief Emit C++ using declaration. + /// Emit C++ using declaration. void EmitUsingDecl(const UsingDecl &UD); - /// \brief Emit an @import declaration. + /// Emit an @import declaration. void EmitImportDecl(const ImportDecl &ID); - /// \brief Emit C++ namespace alias. + /// Emit C++ namespace alias. llvm::DIImportedEntity *EmitNamespaceAlias(const NamespaceAliasDecl &NA); - /// \brief Emit record type's standalone debug info. + /// Emit record type's standalone debug info. llvm::DIType *getOrCreateRecordType(QualType Ty, SourceLocation L); - /// \brief Emit an objective c interface type standalone - /// debug info. + /// Emit an Objective-C interface type standalone debug info. llvm::DIType *getOrCreateInterfaceType(QualType Ty, SourceLocation Loc); void completeType(const EnumDecl *ED); @@ -313,120 +349,124 @@ public: void completeTemplateDefinition(const ClassTemplateSpecializationDecl &SD); private: - /// \brief Emit call to llvm.dbg.declare for a variable declaration. + /// Emit call to llvm.dbg.declare for a variable declaration. /// Tag accepts custom types DW_TAG_arg_variable and DW_TAG_auto_variable, /// otherwise would be of type llvm::dwarf::Tag. void EmitDeclare(const VarDecl *decl, llvm::dwarf::Tag Tag, llvm::Value *AI, unsigned ArgNo, CGBuilderTy &Builder); - // EmitTypeForVarWithBlocksAttr - Build up structure info for the byref. - // See BuildByRefType. + /// Build up structure info for the byref. See \a BuildByRefType. llvm::DIType *EmitTypeForVarWithBlocksAttr(const VarDecl *VD, uint64_t *OffSet); - /// \brief Get context info for the decl. + /// Get context info for the decl. llvm::DIScope *getContextDescriptor(const Decl *Decl); llvm::DIScope *getCurrentContextDescriptor(const Decl *Decl); - /// \brief Create a forward decl for a RecordType in a given context. + /// Create a forward decl for a RecordType in a given context. llvm::DICompositeType *getOrCreateRecordFwdDecl(const RecordType *, llvm::DIScope *); - /// \brief Return current directory name. + /// Return current directory name. StringRef getCurrentDirname(); - /// \brief Create new compile unit. + /// Create new compile unit. void CreateCompileUnit(); - /// \brief Get the file debug info descriptor for the input - /// location. + /// Get the file debug info descriptor for the input location. llvm::DIFile *getOrCreateFile(SourceLocation Loc); - /// \brief Get the file info for main compile unit. + /// Get the file info for main compile unit. llvm::DIFile *getOrCreateMainFile(); - /// \brief Get the type from the cache or create a new type if - /// necessary. + /// Get the type from the cache or create a new type if necessary. llvm::DIType *getOrCreateType(QualType Ty, llvm::DIFile *Fg); - /// \brief Get a reference to a clang module. + /// Get a reference to a clang module. llvm::DIModule * getOrCreateModuleRef(ExternalASTSource::ASTSourceDescriptor Mod); - /// \brief Get the type from the cache or create a new - /// partial type if necessary. + /// Get the type from the cache or create a new partial type if + /// necessary. llvm::DIType *getOrCreateLimitedType(const RecordType *Ty, llvm::DIFile *F); - /// \brief Create type metadata for a source language type. + /// Create type metadata for a source language type. llvm::DIType *CreateTypeNode(QualType Ty, llvm::DIFile *Fg); - /// \brief return the underlying ObjCInterfaceDecl - /// if Ty is an ObjCInterface or a pointer to one. - ObjCInterfaceDecl* getObjCInterfaceDecl(QualType Ty); + /// Return the underlying ObjCInterfaceDecl if \arg Ty is an + /// ObjCInterface or a pointer to one. + ObjCInterfaceDecl *getObjCInterfaceDecl(QualType Ty); - /// \brief Create new member and increase Offset by FType's size. + /// Create new member and increase Offset by FType's size. llvm::DIType *CreateMemberType(llvm::DIFile *Unit, QualType FType, StringRef Name, uint64_t *Offset); - /// \brief Retrieve the DIDescriptor, if any, for the canonical form of this + /// Retrieve the DIDescriptor, if any, for the canonical form of this /// declaration. llvm::DINode *getDeclarationOrDefinition(const Decl *D); - /// \brief Return debug info descriptor to describe method + /// \return debug info descriptor to describe method /// declaration for the given method definition. llvm::DISubprogram *getFunctionDeclaration(const Decl *D); - /// Return debug info descriptor to describe in-class static data member - /// declaration for the given out-of-class definition. + /// \return debug info descriptor to describe in-class static data + /// member declaration for the given out-of-class definition. If D + /// is an out-of-class definition of a static data member of a + /// class, find its corresponding in-class declaration. llvm::DIDerivedType * getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D); - /// \brief Create a subprogram describing the forward - /// decalration represented in the given FunctionDecl. + /// Create a subprogram describing the forward declaration + /// represented in the given FunctionDecl. llvm::DISubprogram *getFunctionForwardDeclaration(const FunctionDecl *FD); - /// \brief Create a global variable describing the forward decalration + /// Create a global variable describing the forward decalration /// represented in the given VarDecl. llvm::DIGlobalVariable * getGlobalVariableForwardDeclaration(const VarDecl *VD); - /// Return a global variable that represents one of the collection of - /// global variables created for an anonmyous union. + /// \brief Return a global variable that represents one of the + /// collection of global variables created for an anonmyous union. + /// + /// Recursively collect all of the member fields of a global + /// anonymous decl and create static variables for them. The first + /// time this is called it needs to be on a union and then from + /// there we can have additional unnamed fields. llvm::DIGlobalVariable * CollectAnonRecordDecls(const RecordDecl *RD, llvm::DIFile *Unit, unsigned LineNo, StringRef LinkageName, llvm::GlobalVariable *Var, llvm::DIScope *DContext); - /// \brief Get function name for the given FunctionDecl. If the - /// name is constructed on demand (e.g. C++ destructor) then the name - /// is stored on the side. + /// Get function name for the given FunctionDecl. If the name is + /// constructed on demand (e.g., C++ destructor) then the name is + /// stored on the side. StringRef getFunctionName(const FunctionDecl *FD); - /// \brief Returns the unmangled name of an Objective-C method. + /// Returns the unmangled name of an Objective-C method. /// This is the display name for the debugging info. StringRef getObjCMethodName(const ObjCMethodDecl *FD); - /// \brief Return selector name. This is used for debugging + /// Return selector name. This is used for debugging /// info. StringRef getSelectorName(Selector S); - /// \brief Get class name including template argument list. + /// Get class name including template argument list. StringRef getClassName(const RecordDecl *RD); - /// \brief Get vtable name for the given Class. + /// Get the vtable name for the given class. StringRef getVTableName(const CXXRecordDecl *Decl); - /// \brief Get line number for the location. If location is invalid + /// Get line number for the location. If location is invalid /// then use current location. unsigned getLineNumber(SourceLocation Loc); - /// \brief Get column number for the location. If location is + /// Get column number for the location. If location is /// invalid then use current location. /// \param Force Assume DebugColumnInfo option is true. - unsigned getColumnNumber(SourceLocation Loc, bool Force=false); + unsigned getColumnNumber(SourceLocation Loc, bool Force = false); - /// \brief Collect various properties of a FunctionDecl. + /// Collect various properties of a FunctionDecl. /// \param GD A GlobalDecl whose getDecl() must return a FunctionDecl. void collectFunctionDeclProps(GlobalDecl GD, llvm::DIFile *Unit, StringRef &Name, StringRef &LinkageName, @@ -434,12 +474,12 @@ private: llvm::DINodeArray &TParamsArray, unsigned &Flags); - /// \brief Collect various properties of a VarDecl. + /// Collect various properties of a VarDecl. void collectVarDeclProps(const VarDecl *VD, llvm::DIFile *&Unit, unsigned &LineNo, QualType &T, StringRef &Name, StringRef &LinkageName, llvm::DIScope *&VDContext); - /// \brief Allocate a copy of \p A using the DebugInfoNames allocator + /// Allocate a copy of \p A using the DebugInfoNames allocator /// and return a reference to it. If multiple arguments are given the strings /// are concatenated. StringRef internString(StringRef A, StringRef B = StringRef()) { @@ -450,7 +490,7 @@ private: } }; -/// \brief A scoped helper to set the current debug location to the specified +/// A scoped helper to set the current debug location to the specified /// location or preferred location of the specified Expr. class ApplyDebugLocation { private: @@ -460,55 +500,56 @@ private: llvm::DebugLoc OriginalLocation; CodeGenFunction &CGF; -public: - /// \brief Set the location to the (valid) TemporaryLocation. +public: + /// Set the location to the (valid) TemporaryLocation. ApplyDebugLocation(CodeGenFunction &CGF, SourceLocation TemporaryLocation); ApplyDebugLocation(CodeGenFunction &CGF, const Expr *E); ApplyDebugLocation(CodeGenFunction &CGF, llvm::DebugLoc Loc); ~ApplyDebugLocation(); - /// \brief Apply TemporaryLocation if it is valid. Otherwise switch to an - /// artificial debug location that has a valid scope, but no line information. + /// \brief Apply TemporaryLocation if it is valid. Otherwise switch + /// to an artificial debug location that has a valid scope, but no + /// line information. /// - /// Artificial locations are useful when emitting compiler-generated helper - /// functions that have no source location associated with them. The DWARF - /// specification allows the compiler to use the special line number 0 to - /// indicate code that can not be attributed to any source location. Note that - /// passing an empty SourceLocation to CGDebugInfo::setLocation() will result - /// in the last valid location being reused. + /// Artificial locations are useful when emitting compiler-generated + /// helper functions that have no source location associated with + /// them. The DWARF specification allows the compiler to use the + /// special line number 0 to indicate code that can not be + /// attributed to any source location. Note that passing an empty + /// SourceLocation to CGDebugInfo::setLocation() will result in the + /// last valid location being reused. static ApplyDebugLocation CreateArtificial(CodeGenFunction &CGF) { return ApplyDebugLocation(CGF, false, SourceLocation()); } - /// \brief Apply TemporaryLocation if it is valid. Otherwise switch to an - /// artificial debug location that has a valid scope, but no line information. - static ApplyDebugLocation CreateDefaultArtificial(CodeGenFunction &CGF, - SourceLocation TemporaryLocation) { + /// \brief Apply TemporaryLocation if it is valid. Otherwise switch + /// to an artificial debug location that has a valid scope, but no + /// line information. + static ApplyDebugLocation + CreateDefaultArtificial(CodeGenFunction &CGF, + SourceLocation TemporaryLocation) { return ApplyDebugLocation(CGF, false, TemporaryLocation); } - /// \brief Set the IRBuilder to not attach debug locations. Note that passing - /// an empty SourceLocation to CGDebugInfo::setLocation() will result in the - /// last valid location being reused. Note that all instructions that do not - /// have a location at the beginning of a function are counted towards to - /// funciton prologue. + /// Set the IRBuilder to not attach debug locations. Note that + /// passing an empty SourceLocation to \a CGDebugInfo::setLocation() + /// will result in the last valid location being reused. Note that + /// all instructions that do not have a location at the beginning of + /// a function are counted towards to funciton prologue. static ApplyDebugLocation CreateEmpty(CodeGenFunction &CGF) { return ApplyDebugLocation(CGF, true, SourceLocation()); } /// \brief Apply TemporaryLocation if it is valid. Otherwise set the IRBuilder /// to not attach debug locations. - static ApplyDebugLocation CreateDefaultEmpty(CodeGenFunction &CGF, - SourceLocation TemporaryLocation) { + static ApplyDebugLocation + CreateDefaultEmpty(CodeGenFunction &CGF, SourceLocation TemporaryLocation) { return ApplyDebugLocation(CGF, true, TemporaryLocation); } - }; - } // namespace CodeGen } // namespace clang - #endif diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp index 839c2e4..96aa8c68 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp @@ -79,6 +79,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) { case Decl::Captured: case Decl::ClassScopeFunctionSpecialization: case Decl::UsingShadow: + case Decl::ObjCTypeParam: llvm_unreachable("Declaration should not be in declstmts!"); case Decl::Function: // void X(); case Decl::Record: // struct/union/class X; @@ -987,7 +988,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { llvm::Value *Stack = CreateTempAlloca(Int8PtrTy, "saved_stack"); llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::stacksave); - llvm::Value *V = Builder.CreateCall(F, {}); + llvm::Value *V = Builder.CreateCall(F); Builder.CreateStore(V, Stack); diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp index 4c85017..7b8368e 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp @@ -20,6 +20,7 @@ #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" #include "clang/AST/StmtVisitor.h" +#include "clang/Basic/TargetBuiltins.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/IntrinsicInst.h" @@ -1279,14 +1280,6 @@ llvm::BasicBlock *CodeGenFunction::getEHResumeBlock(bool isCleanup) { } void CodeGenFunction::EmitSEHTryStmt(const SEHTryStmt &S) { - // FIXME: Implement SEH on other architectures. - const llvm::Triple &T = CGM.getTarget().getTriple(); - if (T.getArch() != llvm::Triple::x86_64 || - !T.isKnownWindowsMSVCEnvironment()) { - ErrorUnsupported(&S, "__try statement"); - return; - } - EnterSEHTryStmt(S); { JumpDest TryExit = getJumpDestInCurrentScope("__try.__leave"); @@ -1311,24 +1304,27 @@ struct PerformSEHFinally : EHScopeStack::Cleanup { void Emit(CodeGenFunction &CGF, Flags F) override { ASTContext &Context = CGF.getContext(); - QualType ArgTys[2] = {Context.UnsignedCharTy, Context.VoidPtrTy}; - FunctionProtoType::ExtProtoInfo EPI; - const auto *FTP = cast<FunctionType>( - Context.getFunctionType(Context.VoidTy, ArgTys, EPI)); + CodeGenModule &CGM = CGF.CGM; CallArgList Args; + + // Compute the two argument values. + QualType ArgTys[2] = {Context.UnsignedCharTy, Context.VoidPtrTy}; + llvm::Value *LocalAddrFn = CGM.getIntrinsic(llvm::Intrinsic::localaddress); + llvm::Value *FP = CGF.Builder.CreateCall(LocalAddrFn); llvm::Value *IsForEH = llvm::ConstantInt::get(CGF.ConvertType(ArgTys[0]), F.isForEHCleanup()); Args.add(RValue::get(IsForEH), ArgTys[0]); - - CodeGenModule &CGM = CGF.CGM; - llvm::Value *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0); - llvm::Value *FrameAddr = CGM.getIntrinsic(llvm::Intrinsic::frameaddress); - llvm::Value *FP = CGF.Builder.CreateCall(FrameAddr, Zero); Args.add(RValue::get(FP), ArgTys[1]); + // Arrange a two-arg function info and type. + FunctionProtoType::ExtProtoInfo EPI; + const auto *FPT = cast<FunctionProtoType>( + Context.getFunctionType(Context.VoidTy, ArgTys, EPI)); const CGFunctionInfo &FnInfo = - CGM.getTypes().arrangeFreeFunctionCall(Args, FTP, /*chainCall=*/false); + CGM.getTypes().arrangeFreeFunctionCall(Args, FPT, + /*chainCall=*/false); + CGF.EmitCall(FnInfo, OutlinedFinally, ReturnValueSlot(), Args); } }; @@ -1340,9 +1336,15 @@ struct CaptureFinder : ConstStmtVisitor<CaptureFinder> { CodeGenFunction &ParentCGF; const VarDecl *ParentThis; SmallVector<const VarDecl *, 4> Captures; + llvm::Value *SEHCodeSlot = nullptr; CaptureFinder(CodeGenFunction &ParentCGF, const VarDecl *ParentThis) : ParentCGF(ParentCGF), ParentThis(ParentThis) {} + // Return true if we need to do any capturing work. + bool foundCaptures() { + return !Captures.empty() || SEHCodeSlot; + } + void Visit(const Stmt *S) { // See if this is a capture, then recurse. ConstStmtVisitor<CaptureFinder>::Visit(S); @@ -1366,27 +1368,106 @@ struct CaptureFinder : ConstStmtVisitor<CaptureFinder> { void VisitCXXThisExpr(const CXXThisExpr *E) { Captures.push_back(ParentThis); } + + void VisitCallExpr(const CallExpr *E) { + // We only need to add parent frame allocations for these builtins in x86. + if (ParentCGF.getTarget().getTriple().getArch() != llvm::Triple::x86) + return; + + unsigned ID = E->getBuiltinCallee(); + switch (ID) { + case Builtin::BI__exception_code: + case Builtin::BI_exception_code: + // This is the simple case where we are the outermost finally. All we + // have to do here is make sure we escape this and recover it in the + // outlined handler. + if (!SEHCodeSlot) + SEHCodeSlot = ParentCGF.SEHCodeSlotStack.back(); + break; + } + } }; } +llvm::Value *CodeGenFunction::recoverAddrOfEscapedLocal( + CodeGenFunction &ParentCGF, llvm::Value *ParentVar, llvm::Value *ParentFP) { + llvm::CallInst *RecoverCall = nullptr; + CGBuilderTy Builder(AllocaInsertPt); + if (auto *ParentAlloca = dyn_cast<llvm::AllocaInst>(ParentVar)) { + // Mark the variable escaped if nobody else referenced it and compute the + // localescape index. + auto InsertPair = ParentCGF.EscapedLocals.insert( + std::make_pair(ParentAlloca, ParentCGF.EscapedLocals.size())); + int FrameEscapeIdx = InsertPair.first->second; + // call i8* @llvm.localrecover(i8* bitcast(@parentFn), i8* %fp, i32 N) + llvm::Function *FrameRecoverFn = llvm::Intrinsic::getDeclaration( + &CGM.getModule(), llvm::Intrinsic::localrecover); + llvm::Constant *ParentI8Fn = + llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy); + RecoverCall = Builder.CreateCall( + FrameRecoverFn, {ParentI8Fn, ParentFP, + llvm::ConstantInt::get(Int32Ty, FrameEscapeIdx)}); + + } else { + // If the parent didn't have an alloca, we're doing some nested outlining. + // Just clone the existing localrecover call, but tweak the FP argument to + // use our FP value. All other arguments are constants. + auto *ParentRecover = + cast<llvm::IntrinsicInst>(ParentVar->stripPointerCasts()); + assert(ParentRecover->getIntrinsicID() == llvm::Intrinsic::localrecover && + "expected alloca or localrecover in parent LocalDeclMap"); + RecoverCall = cast<llvm::CallInst>(ParentRecover->clone()); + RecoverCall->setArgOperand(1, ParentFP); + RecoverCall->insertBefore(AllocaInsertPt); + } + + // Bitcast the variable, rename it, and insert it in the local decl map. + llvm::Value *ChildVar = + Builder.CreateBitCast(RecoverCall, ParentVar->getType()); + ChildVar->setName(ParentVar->getName()); + return ChildVar; +} + void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF, const Stmt *OutlinedStmt, - llvm::Value *ParentFP) { + bool IsFilter) { // Find all captures in the Stmt. CaptureFinder Finder(ParentCGF, ParentCGF.CXXABIThisDecl); Finder.Visit(OutlinedStmt); - // Typically there are no captures and we can exit early. - if (Finder.Captures.empty()) + // We can exit early on x86_64 when there are no captures. We just have to + // save the exception code in filters so that __exception_code() works. + if (!Finder.foundCaptures() && + CGM.getTarget().getTriple().getArch() != llvm::Triple::x86) { + if (IsFilter) + EmitSEHExceptionCodeSave(ParentCGF, nullptr, nullptr); return; + } - // Prepare the first two arguments to llvm.framerecover. - llvm::Function *FrameRecoverFn = llvm::Intrinsic::getDeclaration( - &CGM.getModule(), llvm::Intrinsic::framerecover); - llvm::Constant *ParentI8Fn = - llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy); + llvm::Value *EntryEBP = nullptr; + llvm::Value *ParentFP; + if (IsFilter && CGM.getTarget().getTriple().getArch() == llvm::Triple::x86) { + // 32-bit SEH filters need to be careful about FP recovery. The end of the + // EH registration is passed in as the EBP physical register. We can + // recover that with llvm.frameaddress(1), and adjust that to recover the + // parent's true frame pointer. + CGBuilderTy Builder(AllocaInsertPt); + EntryEBP = Builder.CreateCall( + CGM.getIntrinsic(llvm::Intrinsic::frameaddress), {Builder.getInt32(1)}); + llvm::Function *RecoverFPIntrin = + CGM.getIntrinsic(llvm::Intrinsic::x86_seh_recoverfp); + llvm::Constant *ParentI8Fn = + llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy); + ParentFP = Builder.CreateCall(RecoverFPIntrin, {ParentI8Fn, EntryEBP}); + } else { + // Otherwise, for x64 and 32-bit finally functions, the parent FP is the + // second parameter. + auto AI = CurFn->arg_begin(); + ++AI; + ParentFP = AI; + } - // Create llvm.framerecover calls for all captures. + // Create llvm.localrecover calls for all captures. for (const VarDecl *VD : Finder.Captures) { if (isa<ImplicitParamDecl>(VD)) { CGM.ErrorUnsupported(VD, "'this' captured by SEH"); @@ -1407,49 +1488,63 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF, continue; llvm::Value *ParentVar = I->second; - llvm::CallInst *RecoverCall = nullptr; - CGBuilderTy Builder(AllocaInsertPt); - if (auto *ParentAlloca = dyn_cast<llvm::AllocaInst>(ParentVar)) { - // Mark the variable escaped if nobody else referenced it and compute the - // frameescape index. - auto InsertPair = - ParentCGF.EscapedLocals.insert(std::make_pair(ParentAlloca, -1)); - if (InsertPair.second) - InsertPair.first->second = ParentCGF.EscapedLocals.size() - 1; - int FrameEscapeIdx = InsertPair.first->second; - // call i8* @llvm.framerecover(i8* bitcast(@parentFn), i8* %fp, i32 N) - RecoverCall = Builder.CreateCall( - FrameRecoverFn, {ParentI8Fn, ParentFP, - llvm::ConstantInt::get(Int32Ty, FrameEscapeIdx)}); - - } else { - // If the parent didn't have an alloca, we're doing some nested outlining. - // Just clone the existing framerecover call, but tweak the FP argument to - // use our FP value. All other arguments are constants. - auto *ParentRecover = - cast<llvm::IntrinsicInst>(ParentVar->stripPointerCasts()); - assert(ParentRecover->getIntrinsicID() == llvm::Intrinsic::framerecover && - "expected alloca or framerecover in parent LocalDeclMap"); - RecoverCall = cast<llvm::CallInst>(ParentRecover->clone()); - RecoverCall->setArgOperand(1, ParentFP); - RecoverCall->insertBefore(AllocaInsertPt); - } + LocalDeclMap[VD] = + recoverAddrOfEscapedLocal(ParentCGF, ParentVar, ParentFP); + } - // Bitcast the variable, rename it, and insert it in the local decl map. - llvm::Value *ChildVar = - Builder.CreateBitCast(RecoverCall, ParentVar->getType()); - ChildVar->setName(ParentVar->getName()); - LocalDeclMap[VD] = ChildVar; + if (Finder.SEHCodeSlot) { + SEHCodeSlotStack.push_back( + recoverAddrOfEscapedLocal(ParentCGF, Finder.SEHCodeSlot, ParentFP)); } + + if (IsFilter) + EmitSEHExceptionCodeSave(ParentCGF, ParentFP, EntryEBP); } /// Arrange a function prototype that can be called by Windows exception /// handling personalities. On Win64, the prototype looks like: /// RetTy func(void *EHPtrs, void *ParentFP); void CodeGenFunction::startOutlinedSEHHelper(CodeGenFunction &ParentCGF, - StringRef Name, QualType RetTy, - FunctionArgList &Args, + bool IsFilter, const Stmt *OutlinedStmt) { + SourceLocation StartLoc = OutlinedStmt->getLocStart(); + + // Get the mangled function name. + SmallString<128> Name; + { + llvm::raw_svector_ostream OS(Name); + const Decl *ParentCodeDecl = ParentCGF.CurCodeDecl; + const NamedDecl *Parent = dyn_cast_or_null<NamedDecl>(ParentCodeDecl); + assert(Parent && "FIXME: handle unnamed decls (lambdas, blocks) with SEH"); + MangleContext &Mangler = CGM.getCXXABI().getMangleContext(); + if (IsFilter) + Mangler.mangleSEHFilterExpression(Parent, OS); + else + Mangler.mangleSEHFinallyBlock(Parent, OS); + } + + FunctionArgList Args; + if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86 || !IsFilter) { + // All SEH finally functions take two parameters. Win64 filters take two + // parameters. Win32 filters take no parameters. + if (IsFilter) { + Args.push_back(ImplicitParamDecl::Create( + getContext(), nullptr, StartLoc, + &getContext().Idents.get("exception_pointers"), + getContext().VoidPtrTy)); + } else { + Args.push_back(ImplicitParamDecl::Create( + getContext(), nullptr, StartLoc, + &getContext().Idents.get("abnormal_termination"), + getContext().UnsignedCharTy)); + } + Args.push_back(ImplicitParamDecl::Create( + getContext(), nullptr, StartLoc, + &getContext().Idents.get("frame_pointer"), getContext().VoidPtrTy)); + } + + QualType RetTy = IsFilter ? getContext().LongTy : getContext().VoidTy; + llvm::Function *ParentFn = ParentCGF.CurFn; const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeFreeFunctionDeclaration( RetTy, Args, FunctionType::ExtInfo(), /*isVariadic=*/false); @@ -1474,10 +1569,7 @@ void CodeGenFunction::startOutlinedSEHHelper(CodeGenFunction &ParentCGF, OutlinedStmt->getLocStart(), OutlinedStmt->getLocStart()); CGM.SetLLVMFunctionAttributes(nullptr, FnInfo, CurFn); - - auto AI = Fn->arg_begin(); - ++AI; - EmitCapturedLocals(ParentCGF, OutlinedStmt, &*AI); + EmitCapturedLocals(ParentCGF, OutlinedStmt, IsFilter); } /// Create a stub filter function that will ultimately hold the code of the @@ -1487,37 +1579,7 @@ llvm::Function * CodeGenFunction::GenerateSEHFilterFunction(CodeGenFunction &ParentCGF, const SEHExceptStmt &Except) { const Expr *FilterExpr = Except.getFilterExpr(); - SourceLocation StartLoc = FilterExpr->getLocStart(); - - SEHPointersDecl = ImplicitParamDecl::Create( - getContext(), nullptr, StartLoc, - &getContext().Idents.get("exception_pointers"), getContext().VoidPtrTy); - FunctionArgList Args; - Args.push_back(SEHPointersDecl); - Args.push_back(ImplicitParamDecl::Create( - getContext(), nullptr, StartLoc, - &getContext().Idents.get("frame_pointer"), getContext().VoidPtrTy)); - - // Get the mangled function name. - SmallString<128> Name; - { - llvm::raw_svector_ostream OS(Name); - const Decl *ParentCodeDecl = ParentCGF.CurCodeDecl; - const NamedDecl *Parent = dyn_cast_or_null<NamedDecl>(ParentCodeDecl); - assert(Parent && "FIXME: handle unnamed decls (lambdas, blocks) with SEH"); - CGM.getCXXABI().getMangleContext().mangleSEHFilterExpression(Parent, OS); - } - - startOutlinedSEHHelper(ParentCGF, Name, getContext().LongTy, Args, - FilterExpr); - - // Mark finally block calls as nounwind and noinline to make LLVM's job a - // little easier. - // FIXME: Remove these restrictions in the future. - CurFn->addFnAttr(llvm::Attribute::NoUnwind); - CurFn->addFnAttr(llvm::Attribute::NoInline); - - EmitSEHExceptionCodeSave(); + startOutlinedSEHHelper(ParentCGF, true, FilterExpr); // Emit the original filter expression, convert to i32, and return. llvm::Value *R = EmitScalarExpr(FilterExpr); @@ -1534,29 +1596,13 @@ llvm::Function * CodeGenFunction::GenerateSEHFinallyFunction(CodeGenFunction &ParentCGF, const SEHFinallyStmt &Finally) { const Stmt *FinallyBlock = Finally.getBlock(); - SourceLocation StartLoc = FinallyBlock->getLocStart(); + startOutlinedSEHHelper(ParentCGF, false, FinallyBlock); - FunctionArgList Args; - Args.push_back(ImplicitParamDecl::Create( - getContext(), nullptr, StartLoc, - &getContext().Idents.get("abnormal_termination"), - getContext().UnsignedCharTy)); - Args.push_back(ImplicitParamDecl::Create( - getContext(), nullptr, StartLoc, - &getContext().Idents.get("frame_pointer"), getContext().VoidPtrTy)); - - // Get the mangled function name. - SmallString<128> Name; - { - llvm::raw_svector_ostream OS(Name); - const Decl *ParentCodeDecl = ParentCGF.CurCodeDecl; - const NamedDecl *Parent = dyn_cast_or_null<NamedDecl>(ParentCodeDecl); - assert(Parent && "FIXME: handle unnamed decls (lambdas, blocks) with SEH"); - CGM.getCXXABI().getMangleContext().mangleSEHFinallyBlock(Parent, OS); - } - - startOutlinedSEHHelper(ParentCGF, Name, getContext().VoidTy, Args, - FinallyBlock); + // Mark finally block calls as nounwind and noinline to make LLVM's job a + // little easier. + // FIXME: Remove these restrictions in the future. + CurFn->addFnAttr(llvm::Attribute::NoUnwind); + CurFn->addFnAttr(llvm::Attribute::NoInline); // Emit the original filter expression, convert to i32, and return. EmitStmt(FinallyBlock); @@ -1566,44 +1612,58 @@ CodeGenFunction::GenerateSEHFinallyFunction(CodeGenFunction &ParentCGF, return CurFn; } -void CodeGenFunction::EmitSEHExceptionCodeSave() { +void CodeGenFunction::EmitSEHExceptionCodeSave(CodeGenFunction &ParentCGF, + llvm::Value *ParentFP, + llvm::Value *EntryEBP) { + // Get the pointer to the EXCEPTION_POINTERS struct. This is returned by the + // __exception_info intrinsic. + if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86) { + // On Win64, the info is passed as the first parameter to the filter. + auto AI = CurFn->arg_begin(); + SEHInfo = AI; + SEHCodeSlotStack.push_back( + CreateMemTemp(getContext().IntTy, "__exception_code")); + } else { + // On Win32, the EBP on entry to the filter points to the end of an + // exception registration object. It contains 6 32-bit fields, and the info + // pointer is stored in the second field. So, GEP 20 bytes backwards and + // load the pointer. + SEHInfo = Builder.CreateConstInBoundsGEP1_32(Int8Ty, EntryEBP, -20); + SEHInfo = Builder.CreateBitCast(SEHInfo, Int8PtrTy->getPointerTo()); + SEHInfo = Builder.CreateLoad(Int8PtrTy, SEHInfo); + SEHCodeSlotStack.push_back(recoverAddrOfEscapedLocal( + ParentCGF, ParentCGF.SEHCodeSlotStack.back(), ParentFP)); + } + // Save the exception code in the exception slot to unify exception access in // the filter function and the landing pad. // struct EXCEPTION_POINTERS { // EXCEPTION_RECORD *ExceptionRecord; // CONTEXT *ContextRecord; // }; - // void *exn.slot = - // (void *)(uintptr_t)exception_pointers->ExceptionRecord->ExceptionCode; - llvm::Value *Ptrs = Builder.CreateLoad(GetAddrOfLocalVar(SEHPointersDecl)); + // int exceptioncode = exception_pointers->ExceptionRecord->ExceptionCode; llvm::Type *RecordTy = CGM.Int32Ty->getPointerTo(); llvm::Type *PtrsTy = llvm::StructType::get(RecordTy, CGM.VoidPtrTy, nullptr); - Ptrs = Builder.CreateBitCast(Ptrs, PtrsTy->getPointerTo()); + llvm::Value *Ptrs = Builder.CreateBitCast(SEHInfo, PtrsTy->getPointerTo()); llvm::Value *Rec = Builder.CreateStructGEP(PtrsTy, Ptrs, 0); Rec = Builder.CreateLoad(Rec); llvm::Value *Code = Builder.CreateLoad(Rec); - Code = Builder.CreateZExt(Code, CGM.IntPtrTy); - // FIXME: Change landing pads to produce {i32, i32} and make the exception - // slot an i32. - Code = Builder.CreateIntToPtr(Code, CGM.VoidPtrTy); - Builder.CreateStore(Code, getExceptionSlot()); + assert(!SEHCodeSlotStack.empty() && "emitting EH code outside of __except"); + Builder.CreateStore(Code, SEHCodeSlotStack.back()); } llvm::Value *CodeGenFunction::EmitSEHExceptionInfo() { // Sema should diagnose calling this builtin outside of a filter context, but // don't crash if we screw up. - if (!SEHPointersDecl) + if (!SEHInfo) return llvm::UndefValue::get(Int8PtrTy); - return Builder.CreateLoad(GetAddrOfLocalVar(SEHPointersDecl)); + assert(SEHInfo->getType() == Int8PtrTy); + return SEHInfo; } llvm::Value *CodeGenFunction::EmitSEHExceptionCode() { - // If we're in a landing pad or filter function, the exception slot contains - // the code. - assert(ExceptionSlot); - llvm::Value *Code = - Builder.CreatePtrToInt(getExceptionFromSlot(), CGM.IntPtrTy); - return Builder.CreateTrunc(Code, CGM.Int32Ty); + assert(!SEHCodeSlotStack.empty() && "emitting EH code outside of __except"); + return Builder.CreateLoad(Int32Ty, SEHCodeSlotStack.back()); } llvm::Value *CodeGenFunction::EmitSEHAbnormalTermination() { @@ -1616,9 +1676,11 @@ llvm::Value *CodeGenFunction::EmitSEHAbnormalTermination() { void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S) { CodeGenFunction HelperCGF(CGM, /*suppressNewContext=*/true); if (const SEHFinallyStmt *Finally = S.getFinallyHandler()) { - // Push a cleanup for __finally blocks. + // Outline the finally block. llvm::Function *FinallyFunc = HelperCGF.GenerateSEHFinallyFunction(*this, *Finally); + + // Push a cleanup for __finally blocks. EHStack.pushCleanup<PerformSEHFinally>(NormalAndEHCleanup, FinallyFunc); return; } @@ -1627,12 +1689,16 @@ void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S) { const SEHExceptStmt *Except = S.getExceptHandler(); assert(Except); EHCatchScope *CatchScope = EHStack.pushCatch(1); + SEHCodeSlotStack.push_back( + CreateMemTemp(getContext().IntTy, "__exception_code")); - // If the filter is known to evaluate to 1, then we can use the clause "catch - // i8* null". + // If the filter is known to evaluate to 1, then we can use the clause + // "catch i8* null". We can't do this on x86 because the filter has to save + // the exception code. llvm::Constant *C = CGM.EmitConstantExpr(Except->getFilterExpr(), getContext().IntTy, this); - if (C && C->isOneValue()) { + if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86 && C && + C->isOneValue()) { CatchScope->setCatchAllHandler(0, createBasicBlock("__except")); return; } @@ -1664,6 +1730,7 @@ void CodeGenFunction::ExitSEHTryStmt(const SEHTryStmt &S) { if (!CatchScope.hasEHBranches()) { CatchScope.clearHandlerBlocks(); EHStack.popCatch(); + SEHCodeSlotStack.pop_back(); return; } @@ -1683,9 +1750,20 @@ void CodeGenFunction::ExitSEHTryStmt(const SEHTryStmt &S) { EmitBlockAfterUses(ExceptBB); + // On Win64, the exception pointer is the exception code. Copy it to the slot. + if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86) { + llvm::Value *Code = + Builder.CreatePtrToInt(getExceptionFromSlot(), IntPtrTy); + Code = Builder.CreateTrunc(Code, Int32Ty); + Builder.CreateStore(Code, SEHCodeSlotStack.back()); + } + // Emit the __except body. EmitStmt(Except->getBlock()); + // End the lifetime of the exception code. + SEHCodeSlotStack.pop_back(); + if (HaveInsertPoint()) Builder.CreateBr(ContBB); diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp index 175763c..9c3dfe5 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp @@ -1356,14 +1356,15 @@ RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, SourceLocation Loc) { RValue CodeGenFunction::EmitLoadOfBitfieldLValue(LValue LV) { const CGBitFieldInfo &Info = LV.getBitFieldInfo(); + CharUnits Align = LV.getAlignment().alignmentAtOffset(Info.StorageOffset); // Get the output type. llvm::Type *ResLTy = ConvertType(LV.getType()); llvm::Value *Ptr = LV.getBitFieldAddr(); - llvm::Value *Val = Builder.CreateLoad(Ptr, LV.isVolatileQualified(), - "bf.load"); - cast<llvm::LoadInst>(Val)->setAlignment(Info.StorageAlignment); + llvm::Value *Val = Builder.CreateAlignedLoad(Ptr, Align.getQuantity(), + LV.isVolatileQualified(), + "bf.load"); if (Info.IsSigned) { assert(static_cast<unsigned>(Info.Offset + Info.Size) <= Info.StorageSize); @@ -1559,6 +1560,7 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst, void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst, llvm::Value **Result) { const CGBitFieldInfo &Info = Dst.getBitFieldInfo(); + CharUnits Align = Dst.getAlignment().alignmentAtOffset(Info.StorageOffset); llvm::Type *ResLTy = ConvertTypeForMem(Dst.getType()); llvm::Value *Ptr = Dst.getBitFieldAddr(); @@ -1575,9 +1577,9 @@ void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst, // and mask together with source before storing. if (Info.StorageSize != Info.Size) { assert(Info.StorageSize > Info.Size && "Invalid bitfield size."); - llvm::Value *Val = Builder.CreateLoad(Ptr, Dst.isVolatileQualified(), - "bf.load"); - cast<llvm::LoadInst>(Val)->setAlignment(Info.StorageAlignment); + llvm::Value *Val = Builder.CreateAlignedLoad(Ptr, Align.getQuantity(), + Dst.isVolatileQualified(), + "bf.load"); // Mask the source value as needed. if (!hasBooleanRepresentation(Dst.getType())) @@ -1603,9 +1605,8 @@ void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst, } // Write the new value back out. - llvm::StoreInst *Store = Builder.CreateStore(SrcVal, Ptr, - Dst.isVolatileQualified()); - Store->setAlignment(Info.StorageAlignment); + Builder.CreateAlignedStore(SrcVal, Ptr, Align.getQuantity(), + Dst.isVolatileQualified()); // Return the new value of the bit-field, if requested. if (Result) { @@ -2415,8 +2416,7 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked) { } llvm::CallInst *CodeGenFunction::EmitTrapCall(llvm::Intrinsic::ID IntrID) { - llvm::CallInst *TrapCall = - Builder.CreateCall(CGM.getIntrinsic(IntrID), {}); + llvm::CallInst *TrapCall = Builder.CreateCall(CGM.getIntrinsic(IntrID)); if (!CGM.getCodeGenOpts().TrapFuncName.empty()) TrapCall->addAttribute(llvm::AttributeSet::FunctionIndex, diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp index 747326e..eb76ad1 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp @@ -31,10 +31,9 @@ using namespace CodeGen; typedef llvm::PointerIntPair<llvm::Value*,1,bool> TryEmitResult; static TryEmitResult tryEmitARCRetainScalarExpr(CodeGenFunction &CGF, const Expr *e); -static RValue AdjustRelatedResultType(CodeGenFunction &CGF, - QualType ET, - const ObjCMethodDecl *Method, - RValue Result); +static RValue AdjustObjCObjectType(CodeGenFunction &CGF, + QualType ET, + RValue Result); /// Given the address of a variable of pointer type, find the correct /// null to store into it. @@ -248,23 +247,22 @@ llvm::Value *CodeGenFunction::EmitObjCProtocolExpr(const ObjCProtocolExpr *E) { return CGM.getObjCRuntime().GenerateProtocolRef(*this, E->getProtocol()); } -/// \brief Adjust the type of the result of an Objective-C message send -/// expression when the method has a related result type. -static RValue AdjustRelatedResultType(CodeGenFunction &CGF, - QualType ExpT, - const ObjCMethodDecl *Method, - RValue Result) { - if (!Method) +/// \brief Adjust the type of an Objective-C object that doesn't match up due +/// to type erasure at various points, e.g., related result types or the use +/// of parameterized classes. +static RValue AdjustObjCObjectType(CodeGenFunction &CGF, QualType ExpT, + RValue Result) { + if (!ExpT->isObjCRetainableType()) return Result; - if (!Method->hasRelatedResultType() || - CGF.getContext().hasSameType(ExpT, Method->getReturnType()) || - !Result.isScalar()) + // If the converted types are the same, we're done. + llvm::Type *ExpLLVMTy = CGF.ConvertType(ExpT); + if (ExpLLVMTy == Result.getScalarVal()->getType()) return Result; - - // We have applied a related result type. Cast the rvalue appropriately. + + // We have applied a substitution. Cast the rvalue appropriately. return RValue::get(CGF.Builder.CreateBitCast(Result.getScalarVal(), - CGF.ConvertType(ExpT))); + ExpLLVMTy)); } /// Decide whether to extend the lifetime of the receiver of a @@ -449,7 +447,7 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E, Builder.CreateStore(newSelf, selfAddr); } - return AdjustRelatedResultType(*this, E->getType(), method, result); + return AdjustObjCObjectType(*this, E->getType(), result); } namespace { @@ -2011,7 +2009,7 @@ CodeGenFunction::EmitARCRetainAutoreleasedReturnValue(llvm::Value *value) { // Call the marker asm if we made one, which we do only at -O0. if (marker) - Builder.CreateCall(marker, {}); + Builder.CreateCall(marker); return emitARCValueOperation(*this, value, CGM.getARCEntrypoints().objc_retainAutoreleasedReturnValue, diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.cpp index 5290a87..2ac6bb2 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.cpp @@ -134,7 +134,7 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, CGBitFieldInfo *Info = new (CGF.CGM.getContext()) CGBitFieldInfo( CGBitFieldInfo::MakeInfo(CGF.CGM.getTypes(), Ivar, BitOffset, BitFieldSize, CGF.CGM.getContext().toBits(StorageSize), - Alignment.getQuantity())); + CharUnits::fromQuantity(0))); V = CGF.Builder.CreateBitCast(V, llvm::Type::getIntNPtrTy(CGF.getLLVMContext(), @@ -160,7 +160,7 @@ namespace { void Emit(CodeGenFunction &CGF, Flags flags) override { if (!MightThrow) { - CGF.Builder.CreateCall(Fn, {})->setDoesNotThrow(); + CGF.Builder.CreateCall(Fn)->setDoesNotThrow(); return; } diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 534d148..8148839 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -537,7 +537,7 @@ CGOpenMPRuntime::createRuntimeFunction(OpenMPRTLFunction Function) { break; } case OMPRTL__kmpc_barrier: { - // Build void __kmpc_cancel_barrier(ident_t *loc, kmp_int32 global_tid); + // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; llvm::FunctionType *FnTy = llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); @@ -829,6 +829,15 @@ CGOpenMPRuntime::createRuntimeFunction(OpenMPRTLFunction Function) { RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint"); break; } + case OMPRTL__kmpc_cancel: { + // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, + // kmp_int32 cncl_kind) + llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; + llvm::FunctionType *FnTy = + llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); + RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel"); + break; + } } return RTLFn; } @@ -923,6 +932,8 @@ llvm::Constant *CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, llvm::Constant * CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) { + assert(!CGM.getLangOpts().OpenMPUseTLS || + !CGM.getContext().getTargetInfo().isTLSSupported()); // Lookup the entry, lazily creating it if necessary. return getOrCreateInternalVariable(CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)) + ".cache."); @@ -932,6 +943,10 @@ llvm::Value *CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, llvm::Value *VDAddr, SourceLocation Loc) { + if (CGM.getLangOpts().OpenMPUseTLS && + CGM.getContext().getTargetInfo().isTLSSupported()) + return VDAddr; + auto VarTy = VDAddr->getType()->getPointerElementType(); llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), CGF.Builder.CreatePointerCast(VDAddr, CGM.Int8PtrTy), @@ -961,6 +976,10 @@ void CGOpenMPRuntime::emitThreadPrivateVarInit( llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( const VarDecl *VD, llvm::Value *VDAddr, SourceLocation Loc, bool PerformInit, CodeGenFunction *CGF) { + if (CGM.getLangOpts().OpenMPUseTLS && + CGM.getContext().getTargetInfo().isTLSSupported()) + return nullptr; + VD = VD->getDefinition(CGM.getContext()); if (VD && ThreadPrivateWithDefinition.count(VD) == 0) { ThreadPrivateWithDefinition.insert(VD); @@ -2723,18 +2742,18 @@ void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); } -void CGOpenMPRuntime::emitCancellationPointCall( - CodeGenFunction &CGF, SourceLocation Loc, - OpenMPDirectiveKind CancelRegion) { - // Build call kmp_int32 OMPRTL__kmpc_cancellationpoint(ident_t *loc, kmp_int32 - // global_tid, kmp_int32 cncl_kind); - enum { - CancelNoreq = 0, - CancelParallel = 1, - CancelLoop = 2, - CancelSections = 3, - CancelTaskgroup = 4 - } CancelKind = CancelNoreq; +namespace { +enum RTCancelKind { + CancelNoreq = 0, + CancelParallel = 1, + CancelLoop = 2, + CancelSections = 3, + CancelTaskgroup = 4 +}; +} + +static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) { + RTCancelKind CancelKind = CancelNoreq; if (CancelRegion == OMPD_parallel) CancelKind = CancelParallel; else if (CancelRegion == OMPD_for) @@ -2745,14 +2764,22 @@ void CGOpenMPRuntime::emitCancellationPointCall( assert(CancelRegion == OMPD_taskgroup); CancelKind = CancelTaskgroup; } + return CancelKind; +} + +void CGOpenMPRuntime::emitCancellationPointCall( + CodeGenFunction &CGF, SourceLocation Loc, + OpenMPDirectiveKind CancelRegion) { + // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 + // global_tid, kmp_int32 cncl_kind); if (auto *OMPRegionInfo = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { auto CancelDest = CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); if (CancelDest.isValid()) { - llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), - getThreadID(CGF, Loc), - CGF.Builder.getInt32(CancelKind)}; + llvm::Value *Args[] = { + emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), + CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; // Ignore return result until untied tasks are supported. auto *Result = CGF.EmitRuntimeCall( createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args); @@ -2774,3 +2801,36 @@ void CGOpenMPRuntime::emitCancellationPointCall( } } +void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, + OpenMPDirectiveKind CancelRegion) { + // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, + // kmp_int32 cncl_kind); + if (auto *OMPRegionInfo = + dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { + auto CancelDest = + CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); + if (CancelDest.isValid()) { + llvm::Value *Args[] = { + emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), + CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; + // Ignore return result until untied tasks are supported. + auto *Result = + CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_cancel), Args); + // if (__kmpc_cancel()) { + // __kmpc_cancel_barrier(); + // exit from construct; + // } + auto *ExitBB = CGF.createBasicBlock(".cancel.exit"); + auto *ContBB = CGF.createBasicBlock(".cancel.continue"); + auto *Cmp = CGF.Builder.CreateIsNotNull(Result); + CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); + CGF.EmitBlock(ExitBB); + // __kmpc_cancel_barrier(); + emitBarrierCall(CGF, Loc, OMPD_unknown, /*CheckForCancel=*/false); + // exit from construct; + CGF.EmitBranchThroughCleanup(CancelDest); + CGF.EmitBlock(ContBB, /*IsFinished=*/true); + } + } +} + diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h index 76bb3ae..44bc8a1 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h @@ -151,6 +151,9 @@ private: // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 // global_tid, kmp_int32 cncl_kind); OMPRTL__kmpc_cancellationpoint, + // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, + // kmp_int32 cncl_kind); + OMPRTL__kmpc_cancel, }; /// \brief Values for bit flags used in the ident_t to describe the fields. @@ -698,6 +701,12 @@ public: virtual void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind CancelRegion); + + /// \brief Emit code for 'cancel' construct. + /// \param CancelRegion Region kind for which the cancel must be emitted. + /// + virtual void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, + OpenMPDirectiveKind CancelRegion); }; } // namespace CodeGen diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayout.h b/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayout.h index c15f9fd..d4ad33e 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayout.h +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayout.h @@ -78,16 +78,16 @@ struct CGBitFieldInfo { /// bitfield. unsigned StorageSize; - /// The alignment which should be used when accessing the bitfield. - unsigned StorageAlignment; + /// The offset of the bitfield storage from the start of the struct. + CharUnits StorageOffset; CGBitFieldInfo() - : Offset(), Size(), IsSigned(), StorageSize(), StorageAlignment() {} + : Offset(), Size(), IsSigned(), StorageSize(), StorageOffset() {} CGBitFieldInfo(unsigned Offset, unsigned Size, bool IsSigned, - unsigned StorageSize, unsigned StorageAlignment) + unsigned StorageSize, CharUnits StorageOffset) : Offset(Offset), Size(Size), IsSigned(IsSigned), - StorageSize(StorageSize), StorageAlignment(StorageAlignment) {} + StorageSize(StorageSize), StorageOffset(StorageOffset) {} void print(raw_ostream &OS) const; void dump() const; @@ -99,7 +99,7 @@ struct CGBitFieldInfo { const FieldDecl *FD, uint64_t Offset, uint64_t Size, uint64_t StorageSize, - uint64_t StorageAlignment); + CharUnits StorageOffset); }; /// CGRecordLayout - This class handles struct and union layout info while diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp index c89d5cc..f91eceb 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -228,11 +228,7 @@ void CGRecordLowering::setBitFieldInfo( Info.Offset = (unsigned)(getFieldBitOffset(FD) - Context.toBits(StartOffset)); Info.Size = FD->getBitWidthValue(Context); Info.StorageSize = (unsigned)DataLayout.getTypeAllocSizeInBits(StorageType); - // Here we calculate the actual storage alignment of the bits. E.g if we've - // got an alignment >= 2 and the bitfield starts at offset 6 we've got an - // alignment of 2. - Info.StorageAlignment = - Layout.getAlignment().alignmentAtOffset(StartOffset).getQuantity(); + Info.StorageOffset = StartOffset; if (Info.Size > Info.StorageSize) Info.Size = Info.StorageSize; // Reverse the bit offsets for big endian machines. Because we represent @@ -651,7 +647,7 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types, const FieldDecl *FD, uint64_t Offset, uint64_t Size, uint64_t StorageSize, - uint64_t StorageAlignment) { + CharUnits StorageOffset) { // This function is vestigial from CGRecordLayoutBuilder days but is still // used in GCObjCRuntime.cpp. That usage has a "fixme" attached to it that // when addressed will allow for the removal of this function. @@ -683,7 +679,7 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types, Offset = StorageSize - (Offset + Size); } - return CGBitFieldInfo(Offset, Size, IsSigned, StorageSize, StorageAlignment); + return CGBitFieldInfo(Offset, Size, IsSigned, StorageSize, StorageOffset); } CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D, @@ -856,7 +852,7 @@ void CGBitFieldInfo::print(raw_ostream &OS) const { << " Size:" << Size << " IsSigned:" << IsSigned << " StorageSize:" << StorageSize - << " StorageAlignment:" << StorageAlignment << ">"; + << " StorageOffset:" << StorageOffset.getQuantity() << ">"; } void CGBitFieldInfo::dump() const { diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp index a12f295..7a0b8a3 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp @@ -1852,6 +1852,14 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { std::vector<llvm::Value*> InOutArgs; std::vector<llvm::Type*> InOutArgTypes; + // An inline asm can be marked readonly if it meets the following conditions: + // - it doesn't have any sideeffects + // - it doesn't clobber memory + // - it doesn't return a value by-reference + // It can be marked readnone if it doesn't have any input memory constraints + // in addition to meeting the conditions listed above. + bool ReadOnly = true, ReadNone = true; + for (unsigned i = 0, e = S.getNumOutputs(); i != e; i++) { TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[i]; @@ -1915,6 +1923,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { Args.push_back(Dest.getAddress()); Constraints += "=*"; Constraints += OutputConstraint; + ReadOnly = ReadNone = false; } if (Info.isReadWrite()) { @@ -1959,6 +1968,9 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i]; + if (Info.allowsMemory()) + ReadNone = false; + if (!Constraints.empty()) Constraints += ','; @@ -2023,7 +2035,9 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { for (unsigned i = 0, e = S.getNumClobbers(); i != e; i++) { StringRef Clobber = S.getClobber(i); - if (Clobber != "memory" && Clobber != "cc") + if (Clobber == "memory") + ReadOnly = ReadNone = false; + else if (Clobber != "cc") Clobber = getTarget().getNormalizedGCCRegisterName(Clobber); if (!Constraints.empty()) @@ -2063,6 +2077,16 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { Result->addAttribute(llvm::AttributeSet::FunctionIndex, llvm::Attribute::NoUnwind); + // Attach readnone and readonly attributes. + if (!HasSideEffect) { + if (ReadNone) + Result->addAttribute(llvm::AttributeSet::FunctionIndex, + llvm::Attribute::ReadNone); + else if (ReadOnly) + Result->addAttribute(llvm::AttributeSet::FunctionIndex, + llvm::Attribute::ReadOnly); + } + // Slap the source location of the inline asm into a !srcloc metadata on the // call. if (const GCCAsmStmt *gccAsmStmt = dyn_cast<GCCAsmStmt>(&S)) { diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp index b021c12..a1f093a 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -2108,7 +2108,8 @@ void CodeGenFunction::EmitOMPCancellationPointDirective( } void CodeGenFunction::EmitOMPCancelDirective(const OMPCancelDirective &S) { - llvm_unreachable("CodeGen for 'omp cancel' is not supported yet."); + CGM.getOpenMPRuntime().emitCancelCall(*this, S.getLocStart(), + S.getCancelRegion()); } CodeGenFunction::JumpDest diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp index 969629f..e36051c 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp @@ -364,7 +364,7 @@ void CodeGenFunction::EmitMustTailThunk(const CXXMethodDecl *MD, FinishFunction(); } -void CodeGenFunction::GenerateThunk(llvm::Function *Fn, +void CodeGenFunction::generateThunk(llvm::Function *Fn, const CGFunctionInfo &FnInfo, GlobalDecl GD, const ThunkInfo &Thunk) { StartThunk(Fn, GD, FnInfo); @@ -376,13 +376,6 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, // Make the call and return the result. EmitCallAndReturnForThunk(Callee, &Thunk); - - // Set the right linkage. - CGM.setFunctionLinkage(GD, Fn); - - // Set the right visibility. - const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); - setThunkVisibility(CGM, MD, Thunk, Fn); } void CodeGenVTables::emitThunk(GlobalDecl GD, const ThunkInfo &Thunk, @@ -455,11 +448,17 @@ void CodeGenVTables::emitThunk(GlobalDecl GD, const ThunkInfo &Thunk, CodeGenFunction(CGM).GenerateVarArgsThunk(ThunkFn, FnInfo, GD, Thunk); } else { // Normal thunk body generation. - CodeGenFunction(CGM).GenerateThunk(ThunkFn, FnInfo, GD, Thunk); + CodeGenFunction(CGM).generateThunk(ThunkFn, FnInfo, GD, Thunk); } + CGM.setFunctionLinkage(GD, ThunkFn); CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable, GD, !Thunk.Return.isEmpty()); + + // Set the right visibility. + const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); + setThunkVisibility(CGM, MD, Thunk, ThunkFn); + if (CGM.supportsCOMDAT() && ThunkFn->isWeakForLinker()) ThunkFn->setComdat(CGM.getModule().getOrInsertComdat(ThunkFn->getName())); } @@ -841,6 +840,11 @@ void CodeGenModule::EmitDeferredVTables() { DeferredVTables.clear(); } +bool CodeGenModule::IsCFIBlacklistedRecord(const CXXRecordDecl *RD) { + // FIXME: Make this user configurable. + return RD->isInStdNamespace(); +} + void CodeGenModule::EmitVTableBitSetEntries(llvm::GlobalVariable *VTable, const VTableLayout &VTLayout) { if (!LangOpts.Sanitize.has(SanitizerKind::CFIVCall) && @@ -855,8 +859,7 @@ void CodeGenModule::EmitVTableBitSetEntries(llvm::GlobalVariable *VTable, std::vector<llvm::MDTuple *> BitsetEntries; // Create a bit set entry for each address point. for (auto &&AP : VTLayout.getAddressPoints()) { - // FIXME: Add blacklisting scheme. - if (AP.first.getBase()->isInStdNamespace()) + if (IsCFIBlacklistedRecord(AP.first.getBase())) continue; BitsetEntries.push_back(CreateVTableBitSetEntry( diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp index 1fca466..ec3c75c 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp @@ -45,12 +45,12 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext) LambdaThisCaptureField(nullptr), NormalCleanupDest(nullptr), NextCleanupDestIndex(1), FirstBlockInfo(nullptr), EHResumeBlock(nullptr), ExceptionSlot(nullptr), EHSelectorSlot(nullptr), - AbnormalTerminationSlot(nullptr), SEHPointersDecl(nullptr), - DebugInfo(CGM.getModuleDebugInfo()), DisableDebugInfo(false), - DidCallStackSave(false), IndirectBranch(nullptr), PGO(cgm), - SwitchInsn(nullptr), SwitchWeights(nullptr), CaseRangeBlock(nullptr), - UnreachableBlock(nullptr), NumReturnExprs(0), NumSimpleReturnExprs(0), - CXXABIThisDecl(nullptr), CXXABIThisValue(nullptr), CXXThisValue(nullptr), + DebugInfo(CGM.getModuleDebugInfo()), + DisableDebugInfo(false), DidCallStackSave(false), IndirectBranch(nullptr), + PGO(cgm), SwitchInsn(nullptr), SwitchWeights(nullptr), + CaseRangeBlock(nullptr), UnreachableBlock(nullptr), NumReturnExprs(0), + NumSimpleReturnExprs(0), CXXABIThisDecl(nullptr), + CXXABIThisValue(nullptr), CXXThisValue(nullptr), CXXDefaultInitExprThis(nullptr), CXXStructorImplicitParamDecl(nullptr), CXXStructorImplicitParamValue(nullptr), OutermostConditional(nullptr), CurLexicalScope(nullptr), TerminateLandingPad(nullptr), @@ -284,7 +284,7 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { Builder.ClearInsertionPoint(); } - // If some of our locals escaped, insert a call to llvm.frameescape in the + // If some of our locals escaped, insert a call to llvm.localescape in the // entry block. if (!EscapedLocals.empty()) { // Invert the map from local to index into a simple vector. There should be @@ -294,7 +294,7 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { for (auto &Pair : EscapedLocals) EscapeArgs[Pair.second] = Pair.first; llvm::Function *FrameEscapeFn = llvm::Intrinsic::getDeclaration( - &CGM.getModule(), llvm::Intrinsic::frameescape); + &CGM.getModule(), llvm::Intrinsic::localescape); CGBuilderTy(AllocaInsertPt).CreateCall(FrameEscapeFn, EscapeArgs); } diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h index a74c474..f2bc402 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h +++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h @@ -324,11 +324,13 @@ public: /// write the current selector value into this alloca. llvm::AllocaInst *EHSelectorSlot; - llvm::AllocaInst *AbnormalTerminationSlot; + /// A stack of exception code slots. Entering an __except block pushes a slot + /// on the stack and leaving pops one. The __exception_code() intrinsic loads + /// a value from the top of the stack. + SmallVector<llvm::Value *, 1> SEHCodeSlotStack; - /// The implicit parameter to SEH filter functions of type - /// 'EXCEPTION_POINTERS*'. - ImplicitParamDecl *SEHPointersDecl; + /// Value returned by __exception_info intrinsic. + llvm::Value *SEHInfo = nullptr; /// Emits a landing pad for the current EH stack. llvm::BasicBlock *EmitLandingPad(); @@ -886,7 +888,7 @@ private: DeclMapTy LocalDeclMap; /// Track escaped local variables with auto storage. Used during SEH - /// outlining to produce a call to llvm.frameescape. + /// outlining to produce a call to llvm.localescape. llvm::DenseMap<llvm::AllocaInst *, int> EscapedLocals; /// LabelMap - This keeps track of the LLVM basic block for each C label. @@ -1292,8 +1294,8 @@ public: void EmitMustTailThunk(const CXXMethodDecl *MD, llvm::Value *AdjustedThisPtr, llvm::Value *Callee); - /// GenerateThunk - Generate a thunk for the given method. - void GenerateThunk(llvm::Function *Fn, const CGFunctionInfo &FnInfo, + /// Generate a thunk for the given method. + void generateThunk(llvm::Function *Fn, const CGFunctionInfo &FnInfo, GlobalDecl GD, const ThunkInfo &Thunk); llvm::Function *GenerateVarArgsThunk(llvm::Function *Fn, @@ -2048,8 +2050,7 @@ public: void EnterSEHTryStmt(const SEHTryStmt &S); void ExitSEHTryStmt(const SEHTryStmt &S); - void startOutlinedSEHHelper(CodeGenFunction &ParentCGF, StringRef Name, - QualType RetTy, FunctionArgList &Args, + void startOutlinedSEHHelper(CodeGenFunction &ParentCGF, bool IsFilter, const Stmt *OutlinedStmt); llvm::Function *GenerateSEHFilterFunction(CodeGenFunction &ParentCGF, @@ -2058,16 +2059,27 @@ public: llvm::Function *GenerateSEHFinallyFunction(CodeGenFunction &ParentCGF, const SEHFinallyStmt &Finally); - void EmitSEHExceptionCodeSave(); + void EmitSEHExceptionCodeSave(CodeGenFunction &ParentCGF, + llvm::Value *ParentFP, + llvm::Value *EntryEBP); llvm::Value *EmitSEHExceptionCode(); llvm::Value *EmitSEHExceptionInfo(); llvm::Value *EmitSEHAbnormalTermination(); /// Scan the outlined statement for captures from the parent function. For /// each capture, mark the capture as escaped and emit a call to - /// llvm.framerecover. Insert the framerecover result into the LocalDeclMap. + /// llvm.localrecover. Insert the localrecover result into the LocalDeclMap. void EmitCapturedLocals(CodeGenFunction &ParentCGF, const Stmt *OutlinedStmt, - llvm::Value *ParentFP); + bool IsFilter); + + /// Recovers the address of a local in a parent function. ParentVar is the + /// address of the variable used in the immediate parent function. It can + /// either be an alloca or a call to llvm.localrecover if there are nested + /// outlined functions. ParentFP is the frame pointer of the outermost parent + /// frame. + llvm::Value *recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF, + llvm::Value *ParentVar, + llvm::Value *ParentFP); void EmitCXXForRangeStmt(const CXXForRangeStmt &S, ArrayRef<const Attr *> Attrs = None); @@ -2931,6 +2943,26 @@ private: SourceLocation Loc); public: +#ifndef NDEBUG + // Determine whether the given argument is an Objective-C method + // that may have type parameters in its signature. + static bool isObjCMethodWithTypeParams(const ObjCMethodDecl *method) { + const DeclContext *dc = method->getDeclContext(); + if (const ObjCInterfaceDecl *classDecl= dyn_cast<ObjCInterfaceDecl>(dc)) { + return classDecl->getTypeParamListAsWritten(); + } + + if (const ObjCCategoryDecl *catDecl = dyn_cast<ObjCCategoryDecl>(dc)) { + return catDecl->getTypeParamList(); + } + + return false; + } + + template<typename T> + static bool isObjCMethodWithTypeParams(const T *) { return false; } +#endif + /// EmitCallArgs - Emit call arguments for a function. template <typename T> void EmitCallArgs(CallArgList &Args, const T *CallArgTypeInfo, @@ -2944,18 +2976,25 @@ public: assert((ParamsToSkip == 0 || CallArgTypeInfo) && "Can't skip parameters if type info is not provided"); if (CallArgTypeInfo) { +#ifndef NDEBUG + bool isGenericMethod = isObjCMethodWithTypeParams(CallArgTypeInfo); +#endif + // First, use the argument types that the type info knows about for (auto I = CallArgTypeInfo->param_type_begin() + ParamsToSkip, E = CallArgTypeInfo->param_type_end(); I != E; ++I, ++Arg) { assert(Arg != ArgEnd && "Running over edge of argument list!"); - assert( - ((*I)->isVariablyModifiedType() || - getContext() - .getCanonicalType((*I).getNonReferenceType()) - .getTypePtr() == - getContext().getCanonicalType(Arg->getType()).getTypePtr()) && - "type mismatch in call argument!"); + assert((isGenericMethod || + ((*I)->isVariablyModifiedType() || + (*I).getNonReferenceType()->isObjCRetainableType() || + getContext() + .getCanonicalType((*I).getNonReferenceType()) + .getTypePtr() == + getContext() + .getCanonicalType(Arg->getType()) + .getTypePtr())) && + "type mismatch in call argument!"); ArgTypes.push_back(*I); } } diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp index b905bd2..a179ad4 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp @@ -1262,6 +1262,11 @@ bool CodeGenModule::MayBeEmittedEagerly(const ValueDecl *Global) { // Implicit template instantiations may change linkage if they are later // explicitly instantiated, so they should not be emitted eagerly. return false; + // If OpenMP is enabled and threadprivates must be generated like TLS, delay + // codegen for global variables, because they may be marked as threadprivate. + if (LangOpts.OpenMP && LangOpts.OpenMPUseTLS && + getContext().getTargetInfo().isTLSSupported() && isa<VarDecl>(Global)) + return false; return true; } diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h index 9a295fe..dd167a2 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h +++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h @@ -1126,6 +1126,10 @@ public: /// \param D Threadprivate declaration. void EmitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D); + /// Returns whether the given record is blacklisted from control flow + /// integrity checks. + bool IsCFIBlacklistedRecord(const CXXRecordDecl *RD); + /// Emit bit set entries for the given vtable using the given layout if /// vptr CFI is enabled. void EmitVTableBitSetEntries(llvm::GlobalVariable *VTable, diff --git a/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp b/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp index fa86e52..70af69b 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -2095,7 +2095,7 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs( CGBuilderTy Builder(Entry); if (InitIsInitFunc) { if (Init) - Builder.CreateCall(Init, {}); + Builder.CreateCall(Init); } else { // Don't know whether we have an init function. Call it if it exists. llvm::Value *Have = Builder.CreateIsNotNull(Init); @@ -2104,7 +2104,7 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs( Builder.CreateCondBr(Have, InitBB, ExitBB); Builder.SetInsertPoint(InitBB); - Builder.CreateCall(Init, {}); + Builder.CreateCall(Init); Builder.CreateBr(ExitBB); Builder.SetInsertPoint(ExitBB); @@ -2133,7 +2133,7 @@ LValue ItaniumCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, llvm::Value *Val = CGF.CGM.GetAddrOfGlobalVar(VD, Ty); llvm::Function *Wrapper = getOrCreateThreadLocalWrapper(VD, Val); - Val = CGF.Builder.CreateCall(Wrapper, {}); + Val = CGF.Builder.CreateCall(Wrapper); LValue LV; if (VD->getType()->isReferenceType()) @@ -3620,7 +3620,7 @@ static llvm::Constant *getClangCallTerminateFn(CodeGenModule &CGM) { catchCall->setCallingConv(CGM.getRuntimeCC()); // Call std::terminate(). - llvm::CallInst *termCall = builder.CreateCall(CGM.getTerminateFn(), {}); + llvm::CallInst *termCall = builder.CreateCall(CGM.getTerminateFn()); termCall->setDoesNotThrow(); termCall->setDoesNotReturn(); termCall->setCallingConv(CGM.getRuntimeCC()); diff --git a/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp index d149df6..3433990 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -1466,20 +1466,27 @@ void MicrosoftCXXABI::emitVTableBitSetEntries(VPtrInfo *Info, llvm::NamedMDNode *BitsetsMD = CGM.getModule().getOrInsertNamedMetadata("llvm.bitsets"); - CharUnits PointerWidth = getContext().toCharUnitsFromBits( - getContext().getTargetInfo().getPointerWidth(0)); - // FIXME: Add blacklisting scheme. + // The location of the first virtual function pointer in the virtual table, + // aka the "address point" on Itanium. This is at offset 0 if RTTI is + // disabled, or sizeof(void*) if RTTI is enabled. + CharUnits AddressPoint = + getContext().getLangOpts().RTTIData + ? getContext().toCharUnitsFromBits( + getContext().getTargetInfo().getPointerWidth(0)) + : CharUnits::Zero(); if (Info->PathToBaseWithVPtr.empty()) { - BitsetsMD->addOperand( - CGM.CreateVTableBitSetEntry(VTable, PointerWidth, RD)); + if (!CGM.IsCFIBlacklistedRecord(RD)) + BitsetsMD->addOperand( + CGM.CreateVTableBitSetEntry(VTable, AddressPoint, RD)); return; } // Add a bitset entry for the least derived base belonging to this vftable. - BitsetsMD->addOperand(CGM.CreateVTableBitSetEntry( - VTable, PointerWidth, Info->PathToBaseWithVPtr.back())); + if (!CGM.IsCFIBlacklistedRecord(Info->PathToBaseWithVPtr.back())) + BitsetsMD->addOperand(CGM.CreateVTableBitSetEntry( + VTable, AddressPoint, Info->PathToBaseWithVPtr.back())); // Add a bitset entry for each derived class that is laid out at the same // offset as the least derived base. @@ -1497,14 +1504,15 @@ void MicrosoftCXXABI::emitVTableBitSetEntries(VPtrInfo *Info, Offset = VBI->second.VBaseOffset; if (!Offset.isZero()) return; - BitsetsMD->addOperand( - CGM.CreateVTableBitSetEntry(VTable, PointerWidth, DerivedRD)); + if (!CGM.IsCFIBlacklistedRecord(DerivedRD)) + BitsetsMD->addOperand( + CGM.CreateVTableBitSetEntry(VTable, AddressPoint, DerivedRD)); } // Finally do the same for the most derived class. - if (Info->FullOffsetInMDC.isZero()) + if (Info->FullOffsetInMDC.isZero() && !CGM.IsCFIBlacklistedRecord(RD)) BitsetsMD->addOperand( - CGM.CreateVTableBitSetEntry(VTable, PointerWidth, RD)); + CGM.CreateVTableBitSetEntry(VTable, AddressPoint, RD)); } void MicrosoftCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT, @@ -1707,7 +1715,7 @@ static const CXXRecordDecl *getClassAtVTableLocation(ASTContext &Ctx, for (auto &&B : RD->bases()) { const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl(); CharUnits BaseOffset = Layout.getBaseClassOffset(Base); - if (BaseOffset <= Offset && BaseOffset > MaxBaseOffset) { + if (BaseOffset <= Offset && BaseOffset >= MaxBaseOffset) { MaxBase = Base; MaxBaseOffset = BaseOffset; } @@ -1715,7 +1723,7 @@ static const CXXRecordDecl *getClassAtVTableLocation(ASTContext &Ctx, for (auto &&B : RD->vbases()) { const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl(); CharUnits BaseOffset = Layout.getVBaseClassOffset(Base); - if (BaseOffset <= Offset && BaseOffset > MaxBaseOffset) { + if (BaseOffset <= Offset && BaseOffset >= MaxBaseOffset) { MaxBase = Base; MaxBaseOffset = BaseOffset; } diff --git a/contrib/llvm/tools/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp b/contrib/llvm/tools/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp new file mode 100644 index 0000000..8f04e06 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp @@ -0,0 +1,193 @@ +//===--- ObjectFilePCHContainerOperations.cpp -----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "clang/CodeGen/ObjectFilePCHContainerOperations.h" +#include "CGDebugInfo.h" +#include "CodeGenModule.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/Expr.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/CodeGen/BackendUtil.h" +#include "clang/Frontend/CodeGenOptions.h" +#include "clang/Serialization/ASTWriter.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Bitcode/BitstreamReader.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/Object/COFF.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/TargetRegistry.h" +#include <memory> +using namespace clang; + +#define DEBUG_TYPE "pchcontainer" + +namespace { +class PCHContainerGenerator : public ASTConsumer { + DiagnosticsEngine &Diags; + const std::string MainFileName; + ASTContext *Ctx; + const HeaderSearchOptions &HeaderSearchOpts; + const PreprocessorOptions &PreprocessorOpts; + CodeGenOptions CodeGenOpts; + const TargetOptions TargetOpts; + const LangOptions LangOpts; + std::unique_ptr<llvm::LLVMContext> VMContext; + std::unique_ptr<llvm::Module> M; + std::unique_ptr<CodeGen::CodeGenModule> Builder; + raw_pwrite_stream *OS; + std::shared_ptr<PCHBuffer> Buffer; + +public: + PCHContainerGenerator(DiagnosticsEngine &diags, + const HeaderSearchOptions &HSO, + const PreprocessorOptions &PPO, const TargetOptions &TO, + const LangOptions &LO, const std::string &MainFileName, + const std::string &OutputFileName, + raw_pwrite_stream *OS, + std::shared_ptr<PCHBuffer> Buffer) + : Diags(diags), HeaderSearchOpts(HSO), PreprocessorOpts(PPO), + TargetOpts(TO), LangOpts(LO), OS(OS), Buffer(Buffer) { + // The debug info output isn't affected by CodeModel and + // ThreadModel, but the backend expects them to be nonempty. + CodeGenOpts.CodeModel = "default"; + CodeGenOpts.ThreadModel = "single"; + CodeGenOpts.setDebugInfo(CodeGenOptions::FullDebugInfo); + CodeGenOpts.SplitDwarfFile = OutputFileName; + } + + virtual ~PCHContainerGenerator() {} + + void Initialize(ASTContext &Context) override { + Ctx = &Context; + VMContext.reset(new llvm::LLVMContext()); + M.reset(new llvm::Module(MainFileName, *VMContext)); + M->setDataLayout(Ctx->getTargetInfo().getTargetDescription()); + Builder.reset(new CodeGen::CodeGenModule(*Ctx, HeaderSearchOpts, + PreprocessorOpts, CodeGenOpts, *M, + M->getDataLayout(), Diags)); + } + + /// Emit a container holding the serialized AST. + void HandleTranslationUnit(ASTContext &Ctx) override { + assert(M && VMContext && Builder); + // Delete these on function exit. + std::unique_ptr<llvm::LLVMContext> VMContext = std::move(this->VMContext); + std::unique_ptr<llvm::Module> M = std::move(this->M); + std::unique_ptr<CodeGen::CodeGenModule> Builder = std::move(this->Builder); + + if (Diags.hasErrorOccurred()) + return; + + M->setTargetTriple(Ctx.getTargetInfo().getTriple().getTriple()); + M->setDataLayout(Ctx.getTargetInfo().getTargetDescription()); + + // Finalize the Builder. + if (Builder) + Builder->Release(); + + // Ensure the target exists. + std::string Error; + auto Triple = Ctx.getTargetInfo().getTriple(); + if (!llvm::TargetRegistry::lookupTarget(Triple.getTriple(), Error)) + llvm::report_fatal_error(Error); + + // Emit the serialized Clang AST into its own section. + assert(Buffer->IsComplete && "serialization did not complete"); + auto &SerializedAST = Buffer->Data; + auto Size = SerializedAST.size(); + auto Int8Ty = llvm::Type::getInt8Ty(*VMContext); + auto *Ty = llvm::ArrayType::get(Int8Ty, Size); + auto *Data = llvm::ConstantDataArray::getString( + *VMContext, StringRef(SerializedAST.data(), Size), + /*AddNull=*/false); + auto *ASTSym = new llvm::GlobalVariable( + *M, Ty, /*constant*/ true, llvm::GlobalVariable::InternalLinkage, Data, + "__clang_ast"); + // The on-disk hashtable needs to be aligned. + ASTSym->setAlignment(8); + + // Mach-O also needs a segment name. + if (Triple.isOSBinFormatMachO()) + ASTSym->setSection("__CLANG,__clangast"); + // COFF has an eight character length limit. + else if (Triple.isOSBinFormatCOFF()) + ASTSym->setSection("clangast"); + else + ASTSym->setSection("__clangast"); + + DEBUG({ + // Print the IR for the PCH container to the debug output. + llvm::SmallString<0> Buffer; + llvm::raw_svector_ostream OS(Buffer); + clang::EmitBackendOutput(Diags, CodeGenOpts, TargetOpts, LangOpts, + Ctx.getTargetInfo().getTargetDescription(), + M.get(), BackendAction::Backend_EmitLL, &OS); + OS.flush(); + llvm::dbgs() << Buffer; + }); + + // Use the LLVM backend to emit the pch container. + clang::EmitBackendOutput(Diags, CodeGenOpts, TargetOpts, LangOpts, + Ctx.getTargetInfo().getTargetDescription(), + M.get(), BackendAction::Backend_EmitObj, OS); + + // Make sure the pch container hits disk. + OS->flush(); + + // Free the memory for the temporary buffer. + llvm::SmallVector<char, 0> Empty; + SerializedAST = std::move(Empty); + } +}; + +} // namespace + +std::unique_ptr<ASTConsumer> +ObjectFilePCHContainerOperations::CreatePCHContainerGenerator( + DiagnosticsEngine &Diags, const HeaderSearchOptions &HSO, + const PreprocessorOptions &PPO, const TargetOptions &TO, + const LangOptions &LO, const std::string &MainFileName, + const std::string &OutputFileName, llvm::raw_pwrite_stream *OS, + std::shared_ptr<PCHBuffer> Buffer) const { + return llvm::make_unique<PCHContainerGenerator>( + Diags, HSO, PPO, TO, LO, MainFileName, OutputFileName, OS, Buffer); +} + +void ObjectFilePCHContainerOperations::ExtractPCH( + llvm::MemoryBufferRef Buffer, llvm::BitstreamReader &StreamFile) const { + if (auto OF = llvm::object::ObjectFile::createObjectFile(Buffer)) { + auto *Obj = OF.get().get(); + bool IsCOFF = isa<llvm::object::COFFObjectFile>(Obj); + // Find the clang AST section in the container. + for (auto &Section : OF->get()->sections()) { + StringRef Name; + Section.getName(Name); + if ((!IsCOFF && Name == "__clangast") || + ( IsCOFF && Name == "clangast")) { + StringRef Buf; + Section.getContents(Buf); + StreamFile.init((const unsigned char *)Buf.begin(), + (const unsigned char *)Buf.end()); + return; + } + } + } + + // As a fallback, treat the buffer as a raw AST. + StreamFile.init((const unsigned char *)Buffer.getBufferStart(), + (const unsigned char *)Buffer.getBufferEnd()); + return; +} diff --git a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp index e5ba200..6226d21 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp @@ -2073,8 +2073,10 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, classify(I.getType(), Offset, FieldLo, FieldHi, isNamedArg); Lo = merge(Lo, FieldLo); Hi = merge(Hi, FieldHi); - if (Lo == Memory || Hi == Memory) - break; + if (Lo == Memory || Hi == Memory) { + postMerge(Size, Lo, Hi); + return; + } } } @@ -2094,11 +2096,13 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, // if (Size > 128 && getContext().getTypeSize(i->getType()) != 256) { Lo = Memory; + postMerge(Size, Lo, Hi); return; } // Note, skip this test for bit-fields, see below. if (!BitField && Offset % getContext().getTypeAlign(i->getType())) { Lo = Memory; + postMerge(Size, Lo, Hi); return; } @@ -7095,6 +7099,8 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() { return *(TheTargetCodeGenInfo = new PNaClTargetCodeGenInfo(Types)); case llvm::Triple::mips: case llvm::Triple::mipsel: + if (Triple.getOS() == llvm::Triple::NaCl) + return *(TheTargetCodeGenInfo = new PNaClTargetCodeGenInfo(Types)); return *(TheTargetCodeGenInfo = new MIPSTargetCodeGenInfo(Types, true)); case llvm::Triple::mips64: |