diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/CodeGen')
33 files changed, 1343 insertions, 503 deletions
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp b/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp index f5edea7..0bccad0 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp @@ -536,7 +536,6 @@ TargetMachine *EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) { Options.NoZerosInBSS = CodeGenOpts.NoZeroInitializedInBSS; Options.UnsafeFPMath = CodeGenOpts.UnsafeFPMath; Options.StackAlignmentOverride = CodeGenOpts.StackAlignment; - Options.TrapFuncName = CodeGenOpts.TrapFuncName; Options.PositionIndependentExecutable = LangOpts.PIELevel != 0; Options.FunctionSections = CodeGenOpts.FunctionSections; Options.DataSections = CodeGenOpts.DataSections; @@ -604,7 +603,10 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action, if (!TM) TM.reset(CreateTargetMachine(UsesCodeGen)); - if (UsesCodeGen && !TM) return; + if (UsesCodeGen && !TM) + return; + if (TM) + TheModule->setDataLayout(*TM->getDataLayout()); CreatePasses(); switch (Action) { diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp index a14daac..2ec909b 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp @@ -82,9 +82,9 @@ static Value *EmitFromInt(CodeGenFunction &CGF, llvm::Value *V, /// Utility to insert an atomic instruction based on Instrinsic::ID /// and the expression node. -static RValue EmitBinaryAtomic(CodeGenFunction &CGF, - llvm::AtomicRMWInst::BinOp Kind, - const CallExpr *E) { +static Value *MakeBinaryAtomicValue(CodeGenFunction &CGF, + llvm::AtomicRMWInst::BinOp Kind, + const CallExpr *E) { QualType T = E->getType(); assert(E->getArg(0)->getType()->isPointerType()); assert(CGF.getContext().hasSameUnqualifiedType(T, @@ -108,8 +108,13 @@ static RValue EmitBinaryAtomic(CodeGenFunction &CGF, llvm::Value *Result = CGF.Builder.CreateAtomicRMW(Kind, Args[0], Args[1], llvm::SequentiallyConsistent); - Result = EmitFromInt(CGF, Result, T, ValueType); - return RValue::get(Result); + return EmitFromInt(CGF, Result, T, ValueType); +} + +static RValue EmitBinaryAtomic(CodeGenFunction &CGF, + llvm::AtomicRMWInst::BinOp Kind, + const CallExpr *E) { + return RValue::get(MakeBinaryAtomicValue(CGF, Kind, E)); } /// Utility to insert an atomic instruction based Instrinsic::ID and @@ -151,6 +156,47 @@ static RValue EmitBinaryAtomicPost(CodeGenFunction &CGF, return RValue::get(Result); } +/// @brief Utility to insert an atomic cmpxchg instruction. +/// +/// @param CGF The current codegen function. +/// @param E Builtin call expression to convert to cmpxchg. +/// arg0 - address to operate on +/// arg1 - value to compare with +/// arg2 - new value +/// @param ReturnBool Specifies whether to return success flag of +/// cmpxchg result or the old value. +/// +/// @returns result of cmpxchg, according to ReturnBool +static Value *MakeAtomicCmpXchgValue(CodeGenFunction &CGF, const CallExpr *E, + bool ReturnBool) { + QualType T = ReturnBool ? E->getArg(1)->getType() : E->getType(); + llvm::Value *DestPtr = CGF.EmitScalarExpr(E->getArg(0)); + unsigned AddrSpace = DestPtr->getType()->getPointerAddressSpace(); + + llvm::IntegerType *IntType = llvm::IntegerType::get( + CGF.getLLVMContext(), CGF.getContext().getTypeSize(T)); + llvm::Type *IntPtrType = IntType->getPointerTo(AddrSpace); + + Value *Args[3]; + Args[0] = CGF.Builder.CreateBitCast(DestPtr, IntPtrType); + Args[1] = CGF.EmitScalarExpr(E->getArg(1)); + llvm::Type *ValueType = Args[1]->getType(); + Args[1] = EmitToInt(CGF, Args[1], T, IntType); + Args[2] = EmitToInt(CGF, CGF.EmitScalarExpr(E->getArg(2)), T, IntType); + + Value *Pair = CGF.Builder.CreateAtomicCmpXchg(Args[0], Args[1], Args[2], + llvm::SequentiallyConsistent, + llvm::SequentiallyConsistent); + if (ReturnBool) + // Extract boolean success flag and zext it to int. + return CGF.Builder.CreateZExt(CGF.Builder.CreateExtractValue(Pair, 1), + CGF.ConvertType(E->getType())); + else + // Extract old value and emit it using the same type as compare value. + return EmitFromInt(CGF, CGF.Builder.CreateExtractValue(Pair, 0), T, + ValueType); +} + /// EmitFAbs - Emit a call to @llvm.fabs(). static Value *EmitFAbs(CodeGenFunction &CGF, Value *V) { Value *F = CGF.CGM.getIntrinsic(Intrinsic::fabs, V->getType()); @@ -497,14 +543,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Value *F = CGM.getIntrinsic(Intrinsic::clear_cache); return RValue::get(Builder.CreateCall(F, {Begin, End})); } - case Builtin::BI__builtin_trap: { - Value *F = CGM.getIntrinsic(Intrinsic::trap); - return RValue::get(Builder.CreateCall(F, {})); - } - case Builtin::BI__debugbreak: { - Value *F = CGM.getIntrinsic(Intrinsic::debugtrap); - return RValue::get(Builder.CreateCall(F, {})); - } + case Builtin::BI__builtin_trap: + return RValue::get(EmitTrapCall(Intrinsic::trap)); + case Builtin::BI__debugbreak: + return RValue::get(EmitTrapCall(Intrinsic::debugtrap)); case Builtin::BI__builtin_unreachable: { if (SanOpts.has(SanitizerKind::Unreachable)) { SanitizerScope SanScope(this); @@ -1057,58 +1099,15 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, case Builtin::BI__sync_val_compare_and_swap_2: case Builtin::BI__sync_val_compare_and_swap_4: case Builtin::BI__sync_val_compare_and_swap_8: - case Builtin::BI__sync_val_compare_and_swap_16: { - QualType T = E->getType(); - llvm::Value *DestPtr = EmitScalarExpr(E->getArg(0)); - unsigned AddrSpace = DestPtr->getType()->getPointerAddressSpace(); - - llvm::IntegerType *IntType = - llvm::IntegerType::get(getLLVMContext(), - getContext().getTypeSize(T)); - llvm::Type *IntPtrType = IntType->getPointerTo(AddrSpace); - - Value *Args[3]; - Args[0] = Builder.CreateBitCast(DestPtr, IntPtrType); - Args[1] = EmitScalarExpr(E->getArg(1)); - llvm::Type *ValueType = Args[1]->getType(); - Args[1] = EmitToInt(*this, Args[1], T, IntType); - Args[2] = EmitToInt(*this, EmitScalarExpr(E->getArg(2)), T, IntType); - - Value *Result = Builder.CreateAtomicCmpXchg(Args[0], Args[1], Args[2], - llvm::SequentiallyConsistent, - llvm::SequentiallyConsistent); - Result = Builder.CreateExtractValue(Result, 0); - Result = EmitFromInt(*this, Result, T, ValueType); - return RValue::get(Result); - } + case Builtin::BI__sync_val_compare_and_swap_16: + return RValue::get(MakeAtomicCmpXchgValue(*this, E, false)); case Builtin::BI__sync_bool_compare_and_swap_1: case Builtin::BI__sync_bool_compare_and_swap_2: case Builtin::BI__sync_bool_compare_and_swap_4: case Builtin::BI__sync_bool_compare_and_swap_8: - case Builtin::BI__sync_bool_compare_and_swap_16: { - QualType T = E->getArg(1)->getType(); - llvm::Value *DestPtr = EmitScalarExpr(E->getArg(0)); - unsigned AddrSpace = DestPtr->getType()->getPointerAddressSpace(); - - llvm::IntegerType *IntType = - llvm::IntegerType::get(getLLVMContext(), - getContext().getTypeSize(T)); - llvm::Type *IntPtrType = IntType->getPointerTo(AddrSpace); - - Value *Args[3]; - Args[0] = Builder.CreateBitCast(DestPtr, IntPtrType); - Args[1] = EmitToInt(*this, EmitScalarExpr(E->getArg(1)), T, IntType); - Args[2] = EmitToInt(*this, EmitScalarExpr(E->getArg(2)), T, IntType); - - Value *Pair = Builder.CreateAtomicCmpXchg(Args[0], Args[1], Args[2], - llvm::SequentiallyConsistent, - llvm::SequentiallyConsistent); - Value *Result = Builder.CreateExtractValue(Pair, 1); - // zext bool to int. - Result = Builder.CreateZExt(Result, ConvertType(E->getType())); - return RValue::get(Result); - } + case Builtin::BI__sync_bool_compare_and_swap_16: + return RValue::get(MakeAtomicCmpXchgValue(*this, E, true)); case Builtin::BI__sync_swap_1: case Builtin::BI__sync_swap_2: @@ -1880,6 +1879,9 @@ Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID, return EmitAMDGPUBuiltinExpr(BuiltinID, E); case llvm::Triple::systemz: return EmitSystemZBuiltinExpr(BuiltinID, E); + case llvm::Triple::nvptx: + case llvm::Triple::nvptx64: + return EmitNVPTXBuiltinExpr(BuiltinID, E); default: return nullptr; } @@ -3339,6 +3341,42 @@ static Value *EmitSpecialRegisterBuiltin(CodeGenFunction &CGF, return Builder.CreateCall(F, { Metadata, ArgValue }); } +/// Return true if BuiltinID is an overloaded Neon intrinsic with an extra +/// argument that specifies the vector type. +static bool HasExtraNeonArgument(unsigned BuiltinID) { + switch (BuiltinID) { + default: break; + case NEON::BI__builtin_neon_vget_lane_i8: + case NEON::BI__builtin_neon_vget_lane_i16: + case NEON::BI__builtin_neon_vget_lane_i32: + case NEON::BI__builtin_neon_vget_lane_i64: + case NEON::BI__builtin_neon_vget_lane_f32: + case NEON::BI__builtin_neon_vgetq_lane_i8: + case NEON::BI__builtin_neon_vgetq_lane_i16: + case NEON::BI__builtin_neon_vgetq_lane_i32: + case NEON::BI__builtin_neon_vgetq_lane_i64: + case NEON::BI__builtin_neon_vgetq_lane_f32: + case NEON::BI__builtin_neon_vset_lane_i8: + case NEON::BI__builtin_neon_vset_lane_i16: + case NEON::BI__builtin_neon_vset_lane_i32: + case NEON::BI__builtin_neon_vset_lane_i64: + case NEON::BI__builtin_neon_vset_lane_f32: + case NEON::BI__builtin_neon_vsetq_lane_i8: + case NEON::BI__builtin_neon_vsetq_lane_i16: + case NEON::BI__builtin_neon_vsetq_lane_i32: + case NEON::BI__builtin_neon_vsetq_lane_i64: + case NEON::BI__builtin_neon_vsetq_lane_f32: + case NEON::BI__builtin_neon_vsha1h_u32: + case NEON::BI__builtin_neon_vsha1cq_u32: + case NEON::BI__builtin_neon_vsha1pq_u32: + case NEON::BI__builtin_neon_vsha1mq_u32: + case ARM::BI_MoveToCoprocessor: + case ARM::BI_MoveToCoprocessor2: + return false; + } + return true; +} + Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { if (auto Hint = GetValueForARMHint(BuiltinID)) @@ -3591,7 +3629,9 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, SmallVector<Value*, 4> Ops; llvm::Value *Align = nullptr; - for (unsigned i = 0, e = E->getNumArgs() - 1; i != e; i++) { + bool HasExtraArg = HasExtraNeonArgument(BuiltinID); + unsigned NumArgs = E->getNumArgs() - (HasExtraArg ? 1 : 0); + for (unsigned i = 0, e = NumArgs; i != e; i++) { if (i == 0) { switch (BuiltinID) { case NEON::BI__builtin_neon_vld1_v: @@ -3666,8 +3706,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, switch (BuiltinID) { default: break; - // vget_lane and vset_lane are not overloaded and do not have an extra - // argument that specifies the vector type. + case NEON::BI__builtin_neon_vget_lane_i8: case NEON::BI__builtin_neon_vget_lane_i16: case NEON::BI__builtin_neon_vget_lane_i32: @@ -3678,8 +3717,8 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, case NEON::BI__builtin_neon_vgetq_lane_i32: case NEON::BI__builtin_neon_vgetq_lane_i64: case NEON::BI__builtin_neon_vgetq_lane_f32: - return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)), - "vget_lane"); + return Builder.CreateExtractElement(Ops[0], Ops[1], "vget_lane"); + case NEON::BI__builtin_neon_vset_lane_i8: case NEON::BI__builtin_neon_vset_lane_i16: case NEON::BI__builtin_neon_vset_lane_i32: @@ -3690,29 +3729,34 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, case NEON::BI__builtin_neon_vsetq_lane_i32: case NEON::BI__builtin_neon_vsetq_lane_i64: case NEON::BI__builtin_neon_vsetq_lane_f32: - Ops.push_back(EmitScalarExpr(E->getArg(2))); return Builder.CreateInsertElement(Ops[1], Ops[0], Ops[2], "vset_lane"); - // Non-polymorphic crypto instructions also not overloaded case NEON::BI__builtin_neon_vsha1h_u32: - Ops.push_back(EmitScalarExpr(E->getArg(0))); return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_sha1h), Ops, "vsha1h"); case NEON::BI__builtin_neon_vsha1cq_u32: - Ops.push_back(EmitScalarExpr(E->getArg(2))); return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_sha1c), Ops, "vsha1h"); case NEON::BI__builtin_neon_vsha1pq_u32: - Ops.push_back(EmitScalarExpr(E->getArg(2))); return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_sha1p), Ops, "vsha1h"); case NEON::BI__builtin_neon_vsha1mq_u32: - Ops.push_back(EmitScalarExpr(E->getArg(2))); return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_sha1m), Ops, "vsha1h"); + + // The ARM _MoveToCoprocessor builtins put the input register value as + // the first argument, but the LLVM intrinsic expects it as the third one. + case ARM::BI_MoveToCoprocessor: + case ARM::BI_MoveToCoprocessor2: { + Function *F = CGM.getIntrinsic(BuiltinID == ARM::BI_MoveToCoprocessor ? + Intrinsic::arm_mcr : Intrinsic::arm_mcr2); + return Builder.CreateCall(F, {Ops[1], Ops[2], Ops[0], + Ops[3], Ops[4], Ops[5]}); + } } // Get the last argument, which specifies the vector type. + assert(HasExtraArg); llvm::APSInt Result; const Expr *Arg = E->getArg(E->getNumArgs()-1); if (!Arg->isIntegerConstantExpr(Result, getContext())) @@ -6053,6 +6097,83 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, switch (BuiltinID) { default: return nullptr; + case X86::BI__builtin_cpu_supports: { + const Expr *FeatureExpr = E->getArg(0)->IgnoreParenCasts(); + StringRef FeatureStr = cast<StringLiteral>(FeatureExpr)->getString(); + + // TODO: When/if this becomes more than x86 specific then use a TargetInfo + // based mapping. + // Processor features and mapping to processor feature value. + enum X86Features { + CMOV = 0, + MMX, + POPCNT, + SSE, + SSE2, + SSE3, + SSSE3, + SSE4_1, + SSE4_2, + AVX, + AVX2, + SSE4_A, + FMA4, + XOP, + FMA, + AVX512F, + BMI, + BMI2, + MAX + }; + + X86Features Feature = StringSwitch<X86Features>(FeatureStr) + .Case("cmov", X86Features::CMOV) + .Case("mmx", X86Features::MMX) + .Case("popcnt", X86Features::POPCNT) + .Case("sse", X86Features::SSE) + .Case("sse2", X86Features::SSE2) + .Case("sse3", X86Features::SSE3) + .Case("sse4.1", X86Features::SSE4_1) + .Case("sse4.2", X86Features::SSE4_2) + .Case("avx", X86Features::AVX) + .Case("avx2", X86Features::AVX2) + .Case("sse4a", X86Features::SSE4_A) + .Case("fma4", X86Features::FMA4) + .Case("xop", X86Features::XOP) + .Case("fma", X86Features::FMA) + .Case("avx512f", X86Features::AVX512F) + .Case("bmi", X86Features::BMI) + .Case("bmi2", X86Features::BMI2) + .Default(X86Features::MAX); + assert(Feature != X86Features::MAX && "Invalid feature!"); + + // Matching the struct layout from the compiler-rt/libgcc structure that is + // filled in: + // unsigned int __cpu_vendor; + // unsigned int __cpu_type; + // unsigned int __cpu_subtype; + // unsigned int __cpu_features[1]; + llvm::Type *STy = llvm::StructType::get( + Int32Ty, Int32Ty, Int32Ty, llvm::ArrayType::get(Int32Ty, 1), nullptr); + + // Grab the global __cpu_model. + llvm::Constant *CpuModel = CGM.CreateRuntimeVariable(STy, "__cpu_model"); + + // Grab the first (0th) element from the field __cpu_features off of the + // global in the struct STy. + Value *Idxs[] = { + ConstantInt::get(Int32Ty, 0), + ConstantInt::get(Int32Ty, 3), + ConstantInt::get(Int32Ty, 0) + }; + Value *CpuFeatures = Builder.CreateGEP(STy, CpuModel, Idxs); + Value *Features = Builder.CreateLoad(CpuFeatures); + + // Check the value of the bit corresponding to the feature requested. + Value *Bitset = Builder.CreateAnd( + Features, llvm::ConstantInt::get(Int32Ty, 1 << Feature)); + return Builder.CreateICmpNE(Bitset, llvm::ConstantInt::get(Int32Ty, 0)); + } case X86::BI_mm_prefetch: { Value *Address = EmitScalarExpr(E->getArg(0)); Value *RW = ConstantInt::get(Int32Ty, 0); @@ -6512,6 +6633,13 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, llvm::Function *F = CGM.getIntrinsic(ID); return Builder.CreateCall(F, Ops, ""); } + case PPC::BI__builtin_vsx_xvrspip: + case PPC::BI__builtin_vsx_xvrdpip: + llvm::Type *ResultType = ConvertType(E->getType()); + Value *X = EmitScalarExpr(E->getArg(0)); + ID = Intrinsic::ceil; + llvm::Function *F = CGM.getIntrinsic(ID, ResultType); + return Builder.CreateCall(F, X); } } @@ -6859,3 +6987,72 @@ Value *CodeGenFunction::EmitSystemZBuiltinExpr(unsigned BuiltinID, return nullptr; } } + +Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, + const CallExpr *E) { + switch (BuiltinID) { + case NVPTX::BI__nvvm_atom_add_gen_i: + case NVPTX::BI__nvvm_atom_add_gen_l: + case NVPTX::BI__nvvm_atom_add_gen_ll: + return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::Add, E); + + case NVPTX::BI__nvvm_atom_sub_gen_i: + case NVPTX::BI__nvvm_atom_sub_gen_l: + case NVPTX::BI__nvvm_atom_sub_gen_ll: + return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::Sub, E); + + case NVPTX::BI__nvvm_atom_and_gen_i: + case NVPTX::BI__nvvm_atom_and_gen_l: + case NVPTX::BI__nvvm_atom_and_gen_ll: + return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::And, E); + + case NVPTX::BI__nvvm_atom_or_gen_i: + case NVPTX::BI__nvvm_atom_or_gen_l: + case NVPTX::BI__nvvm_atom_or_gen_ll: + return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::Or, E); + + case NVPTX::BI__nvvm_atom_xor_gen_i: + case NVPTX::BI__nvvm_atom_xor_gen_l: + case NVPTX::BI__nvvm_atom_xor_gen_ll: + return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::Xor, E); + + case NVPTX::BI__nvvm_atom_xchg_gen_i: + case NVPTX::BI__nvvm_atom_xchg_gen_l: + case NVPTX::BI__nvvm_atom_xchg_gen_ll: + return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::Xchg, E); + + case NVPTX::BI__nvvm_atom_max_gen_i: + case NVPTX::BI__nvvm_atom_max_gen_l: + case NVPTX::BI__nvvm_atom_max_gen_ll: + case NVPTX::BI__nvvm_atom_max_gen_ui: + case NVPTX::BI__nvvm_atom_max_gen_ul: + case NVPTX::BI__nvvm_atom_max_gen_ull: + return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::Max, E); + + case NVPTX::BI__nvvm_atom_min_gen_i: + case NVPTX::BI__nvvm_atom_min_gen_l: + case NVPTX::BI__nvvm_atom_min_gen_ll: + case NVPTX::BI__nvvm_atom_min_gen_ui: + case NVPTX::BI__nvvm_atom_min_gen_ul: + case NVPTX::BI__nvvm_atom_min_gen_ull: + return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::Min, E); + + case NVPTX::BI__nvvm_atom_cas_gen_i: + case NVPTX::BI__nvvm_atom_cas_gen_l: + case NVPTX::BI__nvvm_atom_cas_gen_ll: + return MakeAtomicCmpXchgValue(*this, E, true); + + case NVPTX::BI__nvvm_atom_add_gen_f: { + Value *Ptr = EmitScalarExpr(E->getArg(0)); + Value *Val = EmitScalarExpr(E->getArg(1)); + // atomicrmw only deals with integer arguments so we need to use + // LLVM's nvvm_atomic_load_add_f32 intrinsic for that. + Value *FnALAF32 = + CGM.getIntrinsic(Intrinsic::nvvm_atomic_load_add_f32, Ptr->getType()); + return Builder.CreateCall(FnALAF32, {Ptr, Val}); + } + + default: + return nullptr; + } +} diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp index cb7e6df..dc16616 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp @@ -130,10 +130,9 @@ CGCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) { return GetBogusMemberPointer(QualType(MPT, 0)); } -llvm::Constant *CGCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) { - return GetBogusMemberPointer( - CGM.getContext().getMemberPointerType(MD->getType(), - MD->getParent()->getTypeForDecl())); +llvm::Constant *CGCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) { + return GetBogusMemberPointer(CGM.getContext().getMemberPointerType( + MD->getType(), MD->getParent()->getTypeForDecl())); } llvm::Constant *CGCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT, diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.h b/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.h index b6b4ee6..436b96a 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.h +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.h @@ -172,7 +172,7 @@ public: virtual llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT); /// Create a member pointer for the given method. - virtual llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD); + virtual llvm::Constant *EmitMemberFunctionPointer(const CXXMethodDecl *MD); /// Create a member pointer for the given field. virtual llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT, diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp index 58ef171..0535c05 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp @@ -32,7 +32,6 @@ #include "llvm/IR/Intrinsics.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/Transforms/Utils/Local.h" -#include <sstream> using namespace clang; using namespace CodeGen; @@ -1453,6 +1452,8 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, // Attributes that should go on the call site only. if (!CodeGenOpts.SimplifyLibCalls) FuncAttrs.addAttribute(llvm::Attribute::NoBuiltin); + if (!CodeGenOpts.TrapFuncName.empty()) + FuncAttrs.addAttribute("trap-func-name", CodeGenOpts.TrapFuncName); } else { // Attributes that should go on the function, but not the call site. if (!CodeGenOpts.DisableFPElim) { @@ -1493,12 +1494,16 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, // avoid putting features in the target-features set if we know it'll be // one of the default features in the backend, e.g. corei7-avx and +avx or // figure out non-explicit dependencies. - std::vector<std::string> Features(getTarget().getTargetOpts().Features); + // Canonicalize the existing features in a new feature map. + // TODO: Migrate the existing backends to keep the map around rather than + // the vector. + llvm::StringMap<bool> FeatureMap; + for (auto F : getTarget().getTargetOpts().Features) { + const char *Name = F.c_str(); + bool Enabled = Name[0] == '+'; + getTarget().setFeatureEnabled(FeatureMap, Name + 1, Enabled); + } - // TODO: The target attribute complicates this further by allowing multiple - // additional features to be tacked on to the feature string for a - // particular function. For now we simply append to the set of features and - // let backend resolution fix them up. const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl); if (FD) { if (const TargetAttr *TD = FD->getAttr<TargetAttr>()) { @@ -1507,7 +1512,7 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, FeaturesStr.split(AttrFeatures, ","); // Grab the various features and prepend a "+" to turn on the feature to - // the backend and add them to our existing set of Features. + // the backend and add them to our existing set of features. for (auto &Feature : AttrFeatures) { // While we're here iterating check for a different target cpu. if (Feature.startswith("arch=")) @@ -1521,24 +1526,28 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, // attributes on the function. ; else if (Feature.startswith("mno-")) - Features.push_back("-" + Feature.split("-").second.str()); + getTarget().setFeatureEnabled(FeatureMap, Feature.split("-").second, + false); else - Features.push_back("+" + Feature.str()); - } + getTarget().setFeatureEnabled(FeatureMap, Feature, true); + } } } + // Produce the canonical string for this set of features. + std::vector<std::string> Features; + for (llvm::StringMap<bool>::const_iterator it = FeatureMap.begin(), + ie = FeatureMap.end(); + it != ie; ++it) + Features.push_back((it->second ? "+" : "-") + it->first().str()); + // Now add the target-cpu and target-features to the function. if (TargetCPU != "") FuncAttrs.addAttribute("target-cpu", TargetCPU); if (!Features.empty()) { - std::stringstream TargetFeatures; - std::copy(Features.begin(), Features.end(), - std::ostream_iterator<std::string>(TargetFeatures, ",")); - - // The drop_back gets rid of the trailing space. + std::sort(Features.begin(), Features.end()); FuncAttrs.addAttribute("target-features", - StringRef(TargetFeatures.str()).drop_back(1)); + llvm::join(Features.begin(), Features.end(), ",")); } } diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp index 1d2b787..62df982 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp @@ -29,13 +29,12 @@ using namespace clang; using namespace CodeGen; -static CharUnits -ComputeNonVirtualBaseClassOffset(ASTContext &Context, - const CXXRecordDecl *DerivedClass, - CastExpr::path_const_iterator Start, - CastExpr::path_const_iterator End) { +CharUnits CodeGenModule::computeNonVirtualBaseClassOffset( + const CXXRecordDecl *DerivedClass, CastExpr::path_const_iterator Start, + CastExpr::path_const_iterator End) { CharUnits Offset = CharUnits::Zero(); + const ASTContext &Context = getContext(); const CXXRecordDecl *RD = DerivedClass; for (CastExpr::path_const_iterator I = Start; I != End; ++I) { @@ -64,8 +63,7 @@ CodeGenModule::GetNonVirtualBaseClassOffset(const CXXRecordDecl *ClassDecl, assert(PathBegin != PathEnd && "Base path should not be empty!"); CharUnits Offset = - ComputeNonVirtualBaseClassOffset(getContext(), ClassDecl, - PathBegin, PathEnd); + computeNonVirtualBaseClassOffset(ClassDecl, PathBegin, PathEnd); if (Offset.isZero()) return nullptr; @@ -158,9 +156,8 @@ llvm::Value *CodeGenFunction::GetAddressOfBaseClass( // Compute the static offset of the ultimate destination within its // allocating subobject (the virtual base, if there is one, or else // the "complete" object that we see). - CharUnits NonVirtualOffset = - ComputeNonVirtualBaseClassOffset(getContext(), VBase ? VBase : Derived, - Start, PathEnd); + CharUnits NonVirtualOffset = CGM.computeNonVirtualBaseClassOffset( + VBase ? VBase : Derived, Start, PathEnd); // If there's a virtual step, we can sometimes "devirtualize" it. // For now, that's limited to when the derived type is final. @@ -1342,6 +1339,11 @@ FieldHasTrivialDestructorBody(ASTContext &Context, return true; CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); + + // The destructor for an implicit anonymous union member is never invoked. + if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion()) + return false; + return HasTrivialDestructorBody(Context, FieldClassDecl, FieldClassDecl); } diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp index a20e39f..8c4b4b3 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp @@ -27,6 +27,8 @@ #include "clang/Basic/SourceManager.h" #include "clang/Basic/Version.h" #include "clang/Frontend/CodeGenOptions.h" +#include "clang/Lex/HeaderSearchOptions.h" +#include "clang/Lex/PreprocessorOptions.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/IR/Constants.h" @@ -1179,12 +1181,13 @@ void CGDebugInfo::CollectCXXMemberFunctions( // the member being added to type units by LLVM, while still allowing it // to be emitted into the type declaration/reference inside the compile // unit. + // Ditto 'nodebug' methods, for consistency with CodeGenFunction.cpp. // FIXME: Handle Using(Shadow?)Decls here to create // DW_TAG_imported_declarations inside the class for base decls brought into // derived classes. GDB doesn't seem to notice/leverage these when I tried // it, so I'm not rushing to fix this. (GCC seems to produce them, if // referenced) - if (!Method || Method->isImplicit()) + if (!Method || Method->isImplicit() || Method->hasAttr<NoDebugAttr>()) continue; if (Method->getType()->getAs<FunctionProtoType>()->getContainedAutoType()) @@ -1279,7 +1282,7 @@ CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList, // Member function pointers have special support for building them, though // this is currently unsupported in LLVM CodeGen. else if ((MD = dyn_cast<CXXMethodDecl>(D)) && MD->isInstance()) - V = CGM.getCXXABI().EmitMemberPointer(MD); + V = CGM.getCXXABI().EmitMemberFunctionPointer(MD); else if (const auto *FD = dyn_cast<FunctionDecl>(D)) V = CGM.GetAddrOfFunction(FD); // Member data pointers have special handling too to compute the fixed @@ -1660,6 +1663,47 @@ llvm::DIType *CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, return CreateTypeDefinition(Ty, Unit); } +llvm::DIModule * +CGDebugInfo::getOrCreateModuleRef(ExternalASTSource::ASTSourceDescriptor Mod) { + auto it = ModuleRefCache.find(Mod.Signature); + if (it != ModuleRefCache.end()) + return it->second; + + // Macro definitions that were defined with "-D" on the command line. + SmallString<128> ConfigMacros; + { + llvm::raw_svector_ostream OS(ConfigMacros); + const auto &PPOpts = CGM.getPreprocessorOpts(); + unsigned I = 0; + // Translate the macro definitions back into a commmand line. + for (auto &M : PPOpts.Macros) { + if (++I > 1) + OS << " "; + const std::string &Macro = M.first; + bool Undef = M.second; + OS << "\"-" << (Undef ? 'U' : 'D'); + for (char c : Macro) + switch (c) { + case '\\' : OS << "\\\\"; break; + case '"' : OS << "\\\""; break; + default: OS << c; + } + OS << '\"'; + } + } + llvm::DIBuilder DIB(CGM.getModule()); + auto *CU = DIB.createCompileUnit( + TheCU->getSourceLanguage(), internString(Mod.ModuleName), + internString(Mod.Path), TheCU->getProducer(), true, StringRef(), 0, + internString(Mod.ASTFile), llvm::DIBuilder::FullDebug, Mod.Signature); + llvm::DIModule *ModuleRef = + DIB.createModule(CU, Mod.ModuleName, ConfigMacros, internString(Mod.Path), + internString(CGM.getHeaderSearchOpts().Sysroot)); + DIB.finalize(); + ModuleRefCache.insert(std::make_pair(Mod.Signature, ModuleRef)); + return ModuleRef; +} + llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty, llvm::DIFile *Unit) { ObjCInterfaceDecl *ID = Ty->getDecl(); @@ -3303,6 +3347,15 @@ void CGDebugInfo::EmitUsingDecl(const UsingDecl &UD) { getLineNumber(USD.getLocation())); } +void CGDebugInfo::EmitImportDecl(const ImportDecl &ID) { + auto *Reader = CGM.getContext().getExternalSource(); + auto Info = Reader->getSourceDescriptor(*ID.getImportedModule()); + DBuilder.createImportedDeclaration( + getCurrentContextDescriptor(cast<Decl>(ID.getDeclContext())), + getOrCreateModuleRef(Info), + getLineNumber(ID.getLocation())); +} + llvm::DIImportedEntity * CGDebugInfo::EmitNamespaceAlias(const NamespaceAliasDecl &NA) { if (CGM.getCodeGenOpts().getDebugInfo() < CodeGenOptions::LimitedDebugInfo) diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h index 8509e07..10d3b0d 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h @@ -83,6 +83,9 @@ class CGDebugInfo { /// which may change. llvm::SmallVector<ObjCInterfaceCacheEntry, 32> ObjCInterfaceCache; + /// \brief 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. std::vector<void *> RetainedTypes; @@ -289,6 +292,9 @@ public: /// \brief Emit C++ using declaration. void EmitUsingDecl(const UsingDecl &UD); + /// \brief Emit an @import declaration. + void EmitImportDecl(const ImportDecl &ID); + /// \brief Emit C++ namespace alias. llvm::DIImportedEntity *EmitNamespaceAlias(const NamespaceAliasDecl &NA); @@ -344,6 +350,10 @@ private: /// necessary. llvm::DIType *getOrCreateType(QualType Ty, llvm::DIFile *Fg); + /// \brief 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. llvm::DIType *getOrCreateLimitedType(const RecordType *Ty, llvm::DIFile *F); diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp index 07dbce4..839c2e4 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp @@ -579,9 +579,9 @@ static bool isAccessedBy(const VarDecl &var, const Stmt *s) { } } - for (Stmt::const_child_range children = s->children(); children; ++children) - // children might be null; as in missing decl or conditional of an if-stmt. - if ((*children) && isAccessedBy(var, *children)) + for (const Stmt *SubStmt : s->children()) + // SubStmt might be null; as in missing decl or conditional of an if-stmt. + if (SubStmt && isAccessedBy(var, SubStmt)) return true; return false; @@ -1074,8 +1074,8 @@ static bool isCapturedBy(const VarDecl &var, const Expr *e) { return false; } - for (Stmt::const_child_range children = e->children(); children; ++children) - if (isCapturedBy(var, cast<Expr>(*children))) + for (const Stmt *SubStmt : e->children()) + if (isCapturedBy(var, cast<Expr>(SubStmt))) return true; return false; diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp index 1a76afa..175763c 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp @@ -2403,8 +2403,7 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked) { TrapBB = createBasicBlock("trap"); Builder.CreateCondBr(Checked, Cont, TrapBB); EmitBlock(TrapBB); - llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::trap); - llvm::CallInst *TrapCall = Builder.CreateCall(F, {}); + llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap); TrapCall->setDoesNotReturn(); TrapCall->setDoesNotThrow(); Builder.CreateUnreachable(); @@ -2415,6 +2414,18 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked) { EmitBlock(Cont); } +llvm::CallInst *CodeGenFunction::EmitTrapCall(llvm::Intrinsic::ID IntrID) { + llvm::CallInst *TrapCall = + Builder.CreateCall(CGM.getIntrinsic(IntrID), {}); + + if (!CGM.getCodeGenOpts().TrapFuncName.empty()) + TrapCall->addAttribute(llvm::AttributeSet::FunctionIndex, + "trap-func-name", + CGM.getCodeGenOpts().TrapFuncName); + + return TrapCall; +} + /// isSimpleArrayDecayOperand - If the specified expr is a simple decay from an /// array to pointer, return the array subexpression. static const Expr *isSimpleArrayDecayOperand(const Expr *E) { diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp index f0f706d..c7adcca 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp @@ -1548,7 +1548,8 @@ namespace { // The size of an element, multiplied by the number of elements. llvm::Value *Size = llvm::ConstantInt::get(SizeTy, ElementTypeSize.getQuantity()); - Size = CGF.Builder.CreateMul(Size, NumElements); + if (NumElements) + Size = CGF.Builder.CreateMul(Size, NumElements); // Plus the size of the cookie if applicable. if (!CookieSize.isZero()) { diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp index acfb9b6..a15c151 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp @@ -1452,7 +1452,7 @@ CodeGenModule::getMemberPointerConstant(const UnaryOperator *uo) { // A member function pointer. if (const CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(decl)) - return getCXXABI().EmitMemberPointer(method); + return getCXXABI().EmitMemberFunctionPointer(method); // Otherwise, a member data pointer. uint64_t fieldOffset = getContext().getFieldOffset(decl); diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp index 330a0df..c73f118 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp @@ -16,6 +16,7 @@ #include "CGDebugInfo.h" #include "CGObjCRuntime.h" #include "CodeGenModule.h" +#include "TargetInfo.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/RecordLayout.h" @@ -2037,6 +2038,13 @@ ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr( return size; } + } else if (E->getKind() == UETT_OpenMPRequiredSimdAlign) { + auto Alignment = + CGF.getContext() + .toCharUnitsFromBits(CGF.getContext().getOpenMPDefaultSimdAlign( + E->getTypeOfArgument()->getPointeeType())) + .getQuantity(); + return llvm::ConstantInt::get(CGF.SizeTy, Alignment); } // If this isn't sizeof(vla), the result must be constant; use the constant diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp index 9981fcc..747326e 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp @@ -55,13 +55,15 @@ llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E) /// EmitObjCBoxedExpr - This routine generates code to call /// the appropriate expression boxing method. This will either be -/// one of +[NSNumber numberWith<Type>:], or +[NSString stringWithUTF8String:]. +/// one of +[NSNumber numberWith<Type>:], or +[NSString stringWithUTF8String:], +/// or [NSValue valueWithBytes:objCType:]. /// llvm::Value * CodeGenFunction::EmitObjCBoxedExpr(const ObjCBoxedExpr *E) { // Generate the correct selector for this literal's concrete type. // Get the method. const ObjCMethodDecl *BoxingMethod = E->getBoxingMethod(); + const Expr *SubExpr = E->getSubExpr(); assert(BoxingMethod && "BoxingMethod is null"); assert(BoxingMethod->isClassMethod() && "BoxingMethod must be a class method"); Selector Sel = BoxingMethod->getSelector(); @@ -74,7 +76,35 @@ CodeGenFunction::EmitObjCBoxedExpr(const ObjCBoxedExpr *E) { llvm::Value *Receiver = Runtime.GetClass(*this, ClassDecl); CallArgList Args; - EmitCallArgs(Args, BoxingMethod, E->arg_begin(), E->arg_end()); + const ParmVarDecl *ArgDecl = *BoxingMethod->param_begin(); + QualType ArgQT = ArgDecl->getType().getUnqualifiedType(); + + // ObjCBoxedExpr supports boxing of structs and unions + // via [NSValue valueWithBytes:objCType:] + const QualType ValueType(SubExpr->getType().getCanonicalType()); + if (ValueType->isObjCBoxableRecordType()) { + // Emit CodeGen for first parameter + // and cast value to correct type + llvm::Value *Temporary = CreateMemTemp(SubExpr->getType()); + EmitAnyExprToMem(SubExpr, Temporary, Qualifiers(), /*isInit*/ true); + llvm::Value *BitCast = Builder.CreateBitCast(Temporary, + ConvertType(ArgQT)); + Args.add(RValue::get(BitCast), ArgQT); + + // Create char array to store type encoding + std::string Str; + getContext().getObjCEncodingForType(ValueType, Str); + llvm::GlobalVariable *GV = CGM.GetAddrOfConstantCString(Str); + + // Cast type encoding to correct type + const ParmVarDecl *EncodingDecl = BoxingMethod->parameters()[1]; + QualType EncodingQT = EncodingDecl->getType().getUnqualifiedType(); + llvm::Value *Cast = Builder.CreateBitCast(GV, ConvertType(EncodingQT)); + + Args.add(RValue::get(Cast), EncodingQT); + } else { + Args.add(EmitAnyExpr(SubExpr), ArgQT); + } RValue result = Runtime.GenerateMessageSend( *this, ReturnValueSlot(), BoxingMethod->getReturnType(), Sel, Receiver, diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 3161af3..534d148 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -45,14 +45,14 @@ public: CGOpenMPRegionInfo(const CapturedStmt &CS, const CGOpenMPRegionKind RegionKind, - const RegionCodeGenTy &CodeGen) + const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind) : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind), - CodeGen(CodeGen) {} + CodeGen(CodeGen), Kind(Kind) {} CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind, - const RegionCodeGenTy &CodeGen) - : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), - CodeGen(CodeGen) {} + const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind) + : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen), + Kind(Kind) {} /// \brief Get a variable or parameter for storing global thread id /// inside OpenMP construct. @@ -67,6 +67,8 @@ public: CGOpenMPRegionKind getRegionKind() const { return RegionKind; } + OpenMPDirectiveKind getDirectiveKind() const { return Kind; } + static bool classof(const CGCapturedStmtInfo *Info) { return Info->getKind() == CR_OpenMP; } @@ -74,14 +76,16 @@ public: protected: CGOpenMPRegionKind RegionKind; const RegionCodeGenTy &CodeGen; + OpenMPDirectiveKind Kind; }; /// \brief API for captured statement code generation in OpenMP constructs. class CGOpenMPOutlinedRegionInfo : public CGOpenMPRegionInfo { public: CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar, - const RegionCodeGenTy &CodeGen) - : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen), + const RegionCodeGenTy &CodeGen, + OpenMPDirectiveKind Kind) + : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind), ThreadIDVar(ThreadIDVar) { assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); } @@ -109,8 +113,9 @@ class CGOpenMPTaskOutlinedRegionInfo : public CGOpenMPRegionInfo { public: CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar, - const RegionCodeGenTy &CodeGen) - : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen), + const RegionCodeGenTy &CodeGen, + OpenMPDirectiveKind Kind) + : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind), ThreadIDVar(ThreadIDVar) { assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); } @@ -141,8 +146,9 @@ private: class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo { public: CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI, - const RegionCodeGenTy &CodeGen) - : CGOpenMPRegionInfo(InlinedRegion, CodeGen), OldCSI(OldCSI), + const RegionCodeGenTy &CodeGen, + OpenMPDirectiveKind Kind) + : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind), OldCSI(OldCSI), OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {} // \brief Retrieve the value of the context parameter. llvm::Value *getContextValue() const override { @@ -207,11 +213,12 @@ public: /// \param CodeGen Code generation sequence for combined directives. Includes /// a list of functions used for code generation of implicitly inlined /// regions. - InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen) + InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen, + OpenMPDirectiveKind Kind) : CGF(CGF) { // Start emission for the construct. CGF.CapturedStmtInfo = - new CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, CodeGen); + new CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, CodeGen, Kind); } ~InlinedOpenMPRegionRAII() { // Restore original CapturedStmtInfo only if we're done with code emission. @@ -273,29 +280,28 @@ void CGOpenMPRuntime::clear() { InternalVars.clear(); } -llvm::Value * -CGOpenMPRuntime::emitParallelOutlinedFunction(const OMPExecutableDirective &D, - const VarDecl *ThreadIDVar, - const RegionCodeGenTy &CodeGen) { +llvm::Value *CGOpenMPRuntime::emitParallelOutlinedFunction( + const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, + OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { assert(ThreadIDVar->getType()->isPointerType() && "thread id variable must be of type kmp_int32 *"); const CapturedStmt *CS = cast<CapturedStmt>(D.getAssociatedStmt()); CodeGenFunction CGF(CGM, true); - CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen); - CGF.CapturedStmtInfo = &CGInfo; + CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind); + CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); return CGF.GenerateCapturedStmtFunction(*CS); } -llvm::Value * -CGOpenMPRuntime::emitTaskOutlinedFunction(const OMPExecutableDirective &D, - const VarDecl *ThreadIDVar, - const RegionCodeGenTy &CodeGen) { +llvm::Value *CGOpenMPRuntime::emitTaskOutlinedFunction( + const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, + OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { assert(!ThreadIDVar->getType()->isPointerType() && "thread id variable must be of type kmp_int32 for tasks"); auto *CS = cast<CapturedStmt>(D.getAssociatedStmt()); CodeGenFunction CGF(CGM, true); - CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen); - CGF.CapturedStmtInfo = &CGInfo; + CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, + InnermostKind); + CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); return CGF.GenerateCapturedStmtFunction(*CS); } @@ -530,6 +536,14 @@ CGOpenMPRuntime::createRuntimeFunction(OpenMPRTLFunction Function) { RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier"); break; } + case OMPRTL__kmpc_barrier: { + // Build void __kmpc_cancel_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); + RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier"); + break; + } case OMPRTL__kmpc_for_static_fini: { // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; @@ -781,6 +795,40 @@ CGOpenMPRuntime::createRuntimeFunction(OpenMPRTLFunction Function) { RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind"); break; } + case OMPRTL__kmpc_omp_task_with_deps: { + // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, + // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, + // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); + llvm::Type *TypeParams[] = { + getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty, + CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy}; + llvm::FunctionType *FnTy = + llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); + RTLFn = + CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps"); + break; + } + case OMPRTL__kmpc_omp_wait_deps: { + // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, + // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias, + // kmp_depend_info_t *noalias_dep_list); + llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, + CGM.Int32Ty, CGM.VoidPtrTy, + CGM.Int32Ty, CGM.VoidPtrTy}; + llvm::FunctionType *FnTy = + llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); + RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps"); + break; + } + case OMPRTL__kmpc_cancellationpoint: { + // Build kmp_int32 __kmpc_cancellationpoint(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_cancellationpoint"); + break; + } } return RTLFn; } @@ -1212,11 +1260,12 @@ void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF, CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>( NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_critical), llvm::makeArrayRef(Args)); - emitInlinedDirective(CGF, CriticalOpGen); + emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen); } } static void emitIfStmt(CodeGenFunction &CGF, llvm::Value *IfCond, + OpenMPDirectiveKind Kind, const RegionCodeGenTy &BodyOpGen) { llvm::Value *CallBool = CGF.EmitScalarConversion( IfCond, @@ -1228,7 +1277,7 @@ static void emitIfStmt(CodeGenFunction &CGF, llvm::Value *IfCond, // Generate the branch (If-stmt) CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); CGF.EmitBlock(ThenBlock); - CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, BodyOpGen); + CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, Kind, BodyOpGen); // Emit the rest of bblocks/branches CGF.EmitBranch(ContBlock); CGF.EmitBlock(ContBlock, true); @@ -1247,7 +1296,7 @@ void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF, CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_master), Args); typedef CallEndCleanup<std::extent<decltype(Args)>::value> MasterCallEndCleanup; - emitIfStmt(CGF, IsMaster, [&](CodeGenFunction &CGF) -> void { + emitIfStmt(CGF, IsMaster, OMPD_master, [&](CodeGenFunction &CGF) -> void { CodeGenFunction::RunCleanupsScope Scope(CGF); CGF.EHStack.pushCleanup<MasterCallEndCleanup>( NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_master), @@ -1280,7 +1329,7 @@ void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF, CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>( NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_taskgroup), llvm::makeArrayRef(Args)); - emitInlinedDirective(CGF, TaskgroupOpGen); + emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen); } } @@ -1376,7 +1425,7 @@ void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_single), Args); typedef CallEndCleanup<std::extent<decltype(Args)>::value> SingleCallEndCleanup; - emitIfStmt(CGF, IsSingle, [&](CodeGenFunction &CGF) -> void { + emitIfStmt(CGF, IsSingle, OMPD_single, [&](CodeGenFunction &CGF) -> void { CodeGenFunction::RunCleanupsScope Scope(CGF); CGF.EHStack.pushCleanup<SingleCallEndCleanup>( NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_single), @@ -1444,13 +1493,15 @@ void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF, CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>( NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_ordered), llvm::makeArrayRef(Args)); - emitInlinedDirective(CGF, OrderedOpGen); + emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); } } void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, - OpenMPDirectiveKind Kind) { + OpenMPDirectiveKind Kind, + bool CheckForCancel) { // Build call __kmpc_cancel_barrier(loc, thread_id); + // Build call __kmpc_barrier(loc, thread_id); OpenMPLocationFlags Flags = OMP_IDENT_KMPC; if (Kind == OMPD_for) { Flags = @@ -1466,15 +1517,34 @@ void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, } else { Flags = static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_IMPL); } - // Build call __kmpc_cancel_barrier(loc, thread_id); - // Replace __kmpc_barrier() function by __kmpc_cancel_barrier() because this - // one provides the same functionality and adds initial support for - // cancellation constructs introduced in OpenMP 4.0. __kmpc_cancel_barrier() - // is provided default by the runtime library so it safe to make such - // replacement. + // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc, + // thread_id); llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), getThreadID(CGF, Loc)}; - CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args); + if (auto *OMPRegionInfo = + dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { + auto CancelDestination = + CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); + if (CancelDestination.isValid()) { + auto *Result = CGF.EmitRuntimeCall( + createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args); + if (CheckForCancel) { + // if (__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); + // exit from construct; + CGF.EmitBranchThroughCleanup(CancelDestination); + CGF.EmitBlock(ContBB, /*IsFinished=*/true); + } + return; + } + } + CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args); } /// \brief Schedule types for 'omp for' loops (these enumerators are taken from @@ -2009,11 +2079,12 @@ void CGOpenMPRuntime::emitTaskCall( CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final, llvm::Value *TaskFunction, QualType SharedsTy, llvm::Value *Shareds, - const Expr *IfCond, const ArrayRef<const Expr *> PrivateVars, - const ArrayRef<const Expr *> PrivateCopies, - const ArrayRef<const Expr *> FirstprivateVars, - const ArrayRef<const Expr *> FirstprivateCopies, - const ArrayRef<const Expr *> FirstprivateInits) { + const Expr *IfCond, ArrayRef<const Expr *> PrivateVars, + ArrayRef<const Expr *> PrivateCopies, + ArrayRef<const Expr *> FirstprivateVars, + ArrayRef<const Expr *> FirstprivateCopies, + ArrayRef<const Expr *> FirstprivateInits, + ArrayRef<std::pair<OpenMPDependClauseKind, const Expr *>> Dependences) { auto &C = CGM.getContext(); llvm::SmallVector<PrivateDataTy, 8> Privates; // Aggregate privates and sort them by the alignment. @@ -2169,12 +2240,11 @@ void CGOpenMPRuntime::emitTaskCall( }); (void)InitScope.Privatize(); // Emit initialization for single element. - auto *OldCapturedStmtInfo = CGF.CapturedStmtInfo; - CGF.CapturedStmtInfo = &CapturesInfo; + CodeGenFunction::CGCapturedStmtRAII CapInfoRAII( + CGF, &CapturesInfo); CGF.EmitAnyExprToMem(Init, DestElement, Init->getType().getQualifiers(), /*IsInitializer=*/false); - CGF.CapturedStmtInfo = OldCapturedStmtInfo; }); } } else { @@ -2183,11 +2253,9 @@ void CGOpenMPRuntime::emitTaskCall( return SharedRefLValue.getAddress(); }); (void)InitScope.Privatize(); - auto *OldCapturedStmtInfo = CGF.CapturedStmtInfo; - CGF.CapturedStmtInfo = &CapturesInfo; + CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo); CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false); - CGF.CapturedStmtInfo = OldCapturedStmtInfo; } } else { CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false); @@ -2209,35 +2277,139 @@ void CGOpenMPRuntime::emitTaskCall( CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( DestructorFn, KmpRoutineEntryPtrTy), Destructor); + + // Process list of dependences. + llvm::Value *DependInfo = nullptr; + unsigned DependencesNumber = Dependences.size(); + if (!Dependences.empty()) { + // Dependence kind for RTL. + enum RTLDependenceKindTy { DepIn = 1, DepOut = 2, DepInOut = 3 }; + enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags }; + RecordDecl *KmpDependInfoRD; + QualType FlagsTy = C.getIntTypeForBitwidth( + C.toBits(C.getTypeSizeInChars(C.BoolTy)), /*Signed=*/false); + llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); + if (KmpDependInfoTy.isNull()) { + KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info"); + KmpDependInfoRD->startDefinition(); + addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType()); + addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType()); + addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); + KmpDependInfoRD->completeDefinition(); + KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); + } else { + KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); + } + // Define type kmp_depend_info[<Dependences.size()>]; + QualType KmpDependInfoArrayTy = C.getConstantArrayType( + KmpDependInfoTy, llvm::APInt(/*numBits=*/64, Dependences.size()), + ArrayType::Normal, /*IndexTypeQuals=*/0); + // kmp_depend_info[<Dependences.size()>] deps; + DependInfo = CGF.CreateMemTemp(KmpDependInfoArrayTy); + for (unsigned i = 0; i < DependencesNumber; ++i) { + auto Addr = CGF.EmitLValue(Dependences[i].second); + auto *Size = llvm::ConstantInt::get( + CGF.SizeTy, + C.getTypeSizeInChars(Dependences[i].second->getType()).getQuantity()); + auto Base = CGF.MakeNaturalAlignAddrLValue( + CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, DependInfo, i), + KmpDependInfoTy); + // deps[i].base_addr = &<Dependences[i].second>; + auto BaseAddrLVal = CGF.EmitLValueForField( + Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); + CGF.EmitStoreOfScalar( + CGF.Builder.CreatePtrToInt(Addr.getAddress(), CGF.IntPtrTy), + BaseAddrLVal); + // deps[i].len = sizeof(<Dependences[i].second>); + auto LenLVal = CGF.EmitLValueForField( + Base, *std::next(KmpDependInfoRD->field_begin(), Len)); + CGF.EmitStoreOfScalar(Size, LenLVal); + // deps[i].flags = <Dependences[i].first>; + RTLDependenceKindTy DepKind; + switch (Dependences[i].first) { + case OMPC_DEPEND_in: + DepKind = DepIn; + break; + case OMPC_DEPEND_out: + DepKind = DepOut; + break; + case OMPC_DEPEND_inout: + DepKind = DepInOut; + break; + case OMPC_DEPEND_unknown: + llvm_unreachable("Unknown task dependence type"); + } + auto FlagsLVal = CGF.EmitLValueForField( + Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); + CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), + FlagsLVal); + } + DependInfo = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( + CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, DependInfo, 0), + CGF.VoidPtrTy); + } + // NOTE: routine and part_id fields are intialized by __kmpc_omp_task_alloc() // libcall. // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t // *new_task); + // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, + // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, + // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence + // list is not empty auto *ThreadID = getThreadID(CGF, Loc); - llvm::Value *TaskArgs[] = {emitUpdateLocation(CGF, Loc), ThreadID, NewTask}; - auto &&ThenCodeGen = [this, &TaskArgs](CodeGenFunction &CGF) { + auto *UpLoc = emitUpdateLocation(CGF, Loc); + llvm::Value *TaskArgs[] = {UpLoc, ThreadID, NewTask}; + llvm::Value *DepTaskArgs[] = { + UpLoc, + ThreadID, + NewTask, + DependInfo ? CGF.Builder.getInt32(DependencesNumber) : nullptr, + DependInfo, + DependInfo ? CGF.Builder.getInt32(0) : nullptr, + DependInfo ? llvm::ConstantPointerNull::get(CGF.VoidPtrTy) : nullptr}; + auto &&ThenCodeGen = [this, DependInfo, &TaskArgs, + &DepTaskArgs](CodeGenFunction &CGF) { // TODO: add check for untied tasks. - CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs); + CGF.EmitRuntimeCall( + createRuntimeFunction(DependInfo ? OMPRTL__kmpc_omp_task_with_deps + : OMPRTL__kmpc_omp_task), + DependInfo ? makeArrayRef(DepTaskArgs) : makeArrayRef(TaskArgs)); }; typedef CallEndCleanup<std::extent<decltype(TaskArgs)>::value> IfCallEndCleanup; - auto &&ElseCodeGen = - [this, &TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry]( - CodeGenFunction &CGF) { - CodeGenFunction::RunCleanupsScope LocalScope(CGF); - CGF.EmitRuntimeCall( - createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs); - // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, - // kmp_task_t *new_task); - CGF.EHStack.pushCleanup<IfCallEndCleanup>( - NormalAndEHCleanup, - createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), - llvm::makeArrayRef(TaskArgs)); - - // Call proxy_task_entry(gtid, new_task); - llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy}; - CGF.EmitCallOrInvoke(TaskEntry, OutlinedFnArgs); - }; + llvm::Value *DepWaitTaskArgs[] = { + UpLoc, + ThreadID, + DependInfo ? CGF.Builder.getInt32(DependencesNumber) : nullptr, + DependInfo, + DependInfo ? CGF.Builder.getInt32(0) : nullptr, + DependInfo ? llvm::ConstantPointerNull::get(CGF.VoidPtrTy) : nullptr}; + auto &&ElseCodeGen = [this, &TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry, + DependInfo, &DepWaitTaskArgs](CodeGenFunction &CGF) { + CodeGenFunction::RunCleanupsScope LocalScope(CGF); + // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, + // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 + // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info + // is specified. + if (DependInfo) + CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps), + DepWaitTaskArgs); + // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, + // kmp_task_t *new_task); + CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), + TaskArgs); + // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, + // kmp_task_t *new_task); + CGF.EHStack.pushCleanup<IfCallEndCleanup>( + NormalAndEHCleanup, + createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), + llvm::makeArrayRef(TaskArgs)); + + // Call proxy_task_entry(gtid, new_task); + llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy}; + CGF.EmitCallOrInvoke(TaskEntry, OutlinedFnArgs); + }; if (IfCond) { emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen); } else { @@ -2545,8 +2717,60 @@ void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, } void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, + OpenMPDirectiveKind InnerKind, const RegionCodeGenTy &CodeGen) { - InlinedOpenMPRegionRAII Region(CGF, CodeGen); + InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind); 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; + if (CancelRegion == OMPD_parallel) + CancelKind = CancelParallel; + else if (CancelRegion == OMPD_for) + CancelKind = CancelLoop; + else if (CancelRegion == OMPD_sections) + CancelKind = CancelSections; + else { + assert(CancelRegion == OMPD_taskgroup); + CancelKind = CancelTaskgroup; + } + 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)}; + // Ignore return result until untied tasks are supported. + auto *Result = CGF.EmitRuntimeCall( + createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args); + // if (__kmpc_cancellationpoint()) { + // __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 d1efde2..76bb3ae 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h @@ -68,6 +68,8 @@ private: // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 // global_tid); OMPRTL__kmpc_cancel_barrier, + // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); + OMPRTL__kmpc_barrier, // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); OMPRTL__kmpc_for_static_fini, // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 @@ -138,6 +140,17 @@ private: // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, // int proc_bind); OMPRTL__kmpc_push_proc_bind, + // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32 + // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t + // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); + OMPRTL__kmpc_omp_task_with_deps, + // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32 + // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 + // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); + OMPRTL__kmpc_omp_wait_deps, + // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 + // global_tid, kmp_int32 cncl_kind); + OMPRTL__kmpc_cancellationpoint, }; /// \brief Values for bit flags used in the ident_t to describe the fields. @@ -249,6 +262,16 @@ private: /// deconstructors of firstprivate C++ objects */ /// } kmp_task_t; QualType KmpTaskTQTy; + /// \brief Type typedef struct kmp_depend_info { + /// kmp_intptr_t base_addr; + /// size_t len; + /// struct { + /// bool in:1; + /// bool out:1; + /// } flags; + /// } kmp_depend_info_t; + QualType KmpDependInfoTy; + /// \brief Build type kmp_routine_entry_t (if not built yet). void emitKmpRoutineEntryT(QualType KmpInt32Ty); @@ -341,22 +364,25 @@ public: /// kmp_int32 BoundID, struct context_vars*). /// \param D OpenMP directive. /// \param ThreadIDVar Variable for thread id in the current OpenMP region. + /// \param InnermostKind Kind of innermost directive (for simple directives it + /// is a directive itself, for combined - its innermost directive). /// \param CodeGen Code generation sequence for the \a D directive. - virtual llvm::Value * - emitParallelOutlinedFunction(const OMPExecutableDirective &D, - const VarDecl *ThreadIDVar, - const RegionCodeGenTy &CodeGen); + virtual llvm::Value *emitParallelOutlinedFunction( + const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, + OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen); /// \brief Emits outlined function for the OpenMP task directive \a D. This /// outlined function has type void(*)(kmp_int32 ThreadID, kmp_int32 /// PartID, struct context_vars*). /// \param D OpenMP directive. /// \param ThreadIDVar Variable for thread id in the current OpenMP region. + /// \param InnermostKind Kind of innermost directive (for simple directives it + /// is a directive itself, for combined - its innermost directive). /// \param CodeGen Code generation sequence for the \a D directive. /// - virtual llvm::Value *emitTaskOutlinedFunction(const OMPExecutableDirective &D, - const VarDecl *ThreadIDVar, - const RegionCodeGenTy &CodeGen); + virtual llvm::Value *emitTaskOutlinedFunction( + const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, + OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen); /// \brief Cleans up references to the objects in finished function. /// @@ -423,9 +449,12 @@ public: /// \brief Emit an implicit/explicit barrier for OpenMP threads. /// \param Kind Directive for which this implicit barrier call must be /// generated. Must be OMPD_barrier for explicit barrier generation. + /// \param CheckForCancel true if check for possible cancellation must be + /// performed, false otherwise. /// virtual void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, - OpenMPDirectiveKind Kind); + OpenMPDirectiveKind Kind, + bool CheckForCancel = true); /// \brief Check if the specified \a ScheduleKind is static non-chunked. /// This kind of worksharing directive is emitted without outer loop. @@ -580,7 +609,7 @@ public: /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32 /// /*part_id*/, captured_struct */*__context*/); /// \param SharedsTy A type which contains references the shared variables. - /// \param Shareds Context with the list of shared variables from the \a + /// \param Shareds Context with the list of shared variables from the \p /// TaskFunction. /// \param IfCond Not a nullptr if 'if' clause was specified, nullptr /// otherwise. @@ -595,21 +624,26 @@ public: /// \param FirstprivateInits List of references to auto generated variables /// used for initialization of a single array element. Used if firstprivate /// variable is of array type. - virtual void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, - const OMPExecutableDirective &D, bool Tied, - llvm::PointerIntPair<llvm::Value *, 1, bool> Final, - llvm::Value *TaskFunction, QualType SharedsTy, - llvm::Value *Shareds, const Expr *IfCond, - const ArrayRef<const Expr *> PrivateVars, - const ArrayRef<const Expr *> PrivateCopies, - const ArrayRef<const Expr *> FirstprivateVars, - const ArrayRef<const Expr *> FirstprivateCopies, - const ArrayRef<const Expr *> FirstprivateInits); + /// \param Dependences List of dependences for the 'task' construct, including + /// original expression and dependency type. + virtual void emitTaskCall( + CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, + bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final, + llvm::Value *TaskFunction, QualType SharedsTy, llvm::Value *Shareds, + const Expr *IfCond, ArrayRef<const Expr *> PrivateVars, + ArrayRef<const Expr *> PrivateCopies, + ArrayRef<const Expr *> FirstprivateVars, + ArrayRef<const Expr *> FirstprivateCopies, + ArrayRef<const Expr *> FirstprivateInits, + ArrayRef<std::pair<OpenMPDependClauseKind, const Expr *>> Dependences); /// \brief Emit code for the directive that does not require outlining. /// + /// \param InnermostKind Kind of innermost directive (for simple directives it + /// is a directive itself, for combined - its innermost directive). /// \param CodeGen Code generation sequence for the \a D directive. virtual void emitInlinedDirective(CodeGenFunction &CGF, + OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen); /// \brief Emit a code for reduction clause. Next code should be emitted for /// reduction: @@ -656,6 +690,14 @@ public: /// \brief Emit code for 'taskwait' directive. virtual void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc); + + /// \brief Emit code for 'cancellation point' construct. + /// \param CancelRegion Region kind for which the cancellation point must be + /// emitted. + /// + virtual void emitCancellationPointCall(CodeGenFunction &CGF, + SourceLocation Loc, + OpenMPDirectiveKind CancelRegion); }; } // namespace CodeGen diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp index 9286f03..a12f295 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp @@ -240,6 +240,12 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { case Stmt::OMPTeamsDirectiveClass: EmitOMPTeamsDirective(cast<OMPTeamsDirective>(*S)); break; + case Stmt::OMPCancellationPointDirectiveClass: + EmitOMPCancellationPointDirective(cast<OMPCancellationPointDirective>(*S)); + break; + case Stmt::OMPCancelDirectiveClass: + EmitOMPCancelDirective(cast<OMPCancelDirective>(*S)); + break; } } @@ -2149,7 +2155,7 @@ CodeGenFunction::EmitCapturedStmt(const CapturedStmt &S, CapturedRegionKind K) { // Emit the CapturedDecl CodeGenFunction CGF(CGM, true); - CGF.CapturedStmtInfo = new CGCapturedStmtInfo(S, K); + CGCapturedStmtRAII CapInfoRAII(CGF, new CGCapturedStmtInfo(S, K)); llvm::Function *F = CGF.GenerateCapturedStmtFunction(S); delete CGF.CapturedStmtInfo; diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp index 5e94d56..b021c12 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -451,11 +451,12 @@ void CodeGenFunction::EmitOMPReductionClauseFinal( static void emitCommonOMPParallelDirective(CodeGenFunction &CGF, const OMPExecutableDirective &S, + OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { auto CS = cast<CapturedStmt>(S.getAssociatedStmt()); auto CapturedStruct = CGF.GenerateCapturedStmtArgument(*CS); auto OutlinedFn = CGF.CGM.getOpenMPRuntime().emitParallelOutlinedFunction( - S, *CS->getCapturedDecl()->param_begin(), CodeGen); + S, *CS->getCapturedDecl()->param_begin(), InnermostKind, CodeGen); if (auto C = S.getSingleClause(OMPC_num_threads)) { CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); auto NumThreadsClause = cast<OMPNumThreadsClause>(C); @@ -502,10 +503,11 @@ void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) { CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(), OMPD_unknown); }; - emitCommonOMPParallelDirective(*this, S, CodeGen); + emitCommonOMPParallelDirective(*this, S, OMPD_parallel, CodeGen); } -void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &D) { +void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &D, + JumpDest LoopExit) { RunCleanupsScope BodyScope(*this); // Update counters values on current iteration. for (auto I : D.updates()) { @@ -521,7 +523,7 @@ void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &D) { // On a continue in the body, jump to the end. auto Continue = getJumpDestInCurrentScope("omp.body.continue"); - BreakContinueStack.push_back(BreakContinue(JumpDest(), Continue)); + BreakContinueStack.push_back(BreakContinue(LoopExit, Continue)); // Emit loop body. EmitStmt(D.getBody()); // The end (updates/cleanups). @@ -649,8 +651,10 @@ static void emitAlignedClause(CodeGenFunction &CGF, // If no optional parameter is specified, implementation-defined default // alignments for SIMD instructions on the target platforms are assumed. Alignment = - CGF.CGM.getTargetCodeGenInfo().getOpenMPSimdDefaultAlignment( - E->getType()); + CGF.getContext() + .toCharUnitsFromBits(CGF.getContext().getOpenMPDefaultSimdAlign( + E->getType()->getPointeeType())) + .getQuantity(); } assert((Alignment == 0 || llvm::isPowerOf2_32(Alignment)) && "alignment is not power of 2"); @@ -825,10 +829,10 @@ void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) { CGF.EmitOMPReductionClauseInit(S, LoopScope); HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope); (void)LoopScope.Privatize(); - CGF.EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), - S.getCond(), S.getInc(), + CGF.EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), S.getCond(), + S.getInc(), [&S](CodeGenFunction &CGF) { - CGF.EmitOMPLoopBody(S); + CGF.EmitOMPLoopBody(S, JumpDest()); CGF.EmitStopPoint(&S); }, [](CodeGenFunction &) {}); @@ -845,7 +849,7 @@ void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) { CGF.EmitBlock(ContBlock, true); } }; - CGM.getOpenMPRuntime().emitInlinedDirective(*this, CodeGen); + CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen); } void CodeGenFunction::EmitOMPForOuterLoop(OpenMPScheduleClauseKind ScheduleKind, @@ -977,19 +981,17 @@ void CodeGenFunction::EmitOMPForOuterLoop(OpenMPScheduleClauseKind ScheduleKind, } SourceLocation Loc = S.getLocStart(); - EmitOMPInnerLoop( - S, LoopScope.requiresCleanups(), S.getCond(), - S.getInc(), - [&S](CodeGenFunction &CGF) { - CGF.EmitOMPLoopBody(S); - CGF.EmitStopPoint(&S); - }, - [Ordered, IVSize, IVSigned, Loc](CodeGenFunction &CGF) { - if (Ordered) { - CGF.CGM.getOpenMPRuntime().emitForOrderedIterationEnd( - CGF, Loc, IVSize, IVSigned); - } - }); + EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), S.getCond(), S.getInc(), + [&S, LoopExit](CodeGenFunction &CGF) { + CGF.EmitOMPLoopBody(S, LoopExit); + CGF.EmitStopPoint(&S); + }, + [Ordered, IVSize, IVSigned, Loc](CodeGenFunction &CGF) { + if (Ordered) { + CGF.CGM.getOpenMPRuntime().emitForOrderedIterationEnd( + CGF, Loc, IVSize, IVSigned); + } + }); EmitBlock(Continue.getBlock()); BreakContinueStack.pop_back(); @@ -1138,6 +1140,7 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(const OMPLoopDirective &S) { RT.emitForInit(*this, S.getLocStart(), ScheduleKind, IVSize, IVSigned, Ordered, IL.getAddress(), LB.getAddress(), UB.getAddress(), ST.getAddress()); + auto LoopExit = getJumpDestInCurrentScope(createBasicBlock("omp.loop.exit")); // UB = min(UB, GlobalUB); EmitIgnoredExpr(S.getEnsureUpperBound()); // IV = LB; @@ -1145,11 +1148,12 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(const OMPLoopDirective &S) { // while (idx <= UB) { BODY; ++idx; } EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), S.getCond(), S.getInc(), - [&S](CodeGenFunction &CGF) { - CGF.EmitOMPLoopBody(S); + [&S, LoopExit](CodeGenFunction &CGF) { + CGF.EmitOMPLoopBody(S, LoopExit); CGF.EmitStopPoint(&S); }, [](CodeGenFunction &) {}); + EmitBlock(LoopExit.getBlock()); // Tell the runtime we are done. RT.emitForStaticFinish(*this, S.getLocStart()); } else { @@ -1183,7 +1187,7 @@ void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &S) { auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF) { HasLastprivates = CGF.EmitOMPWorksharingLoop(S); }; - CGM.getOpenMPRuntime().emitInlinedDirective(*this, CodeGen); + CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_for, CodeGen); // Emit an implicit barrier at the end. if (!S.getSingleClause(OMPC_nowait) || HasLastprivates) { @@ -1197,7 +1201,7 @@ void CodeGenFunction::EmitOMPForSimdDirective(const OMPForSimdDirective &S) { auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF) { HasLastprivates = CGF.EmitOMPWorksharingLoop(S); }; - CGM.getOpenMPRuntime().emitInlinedDirective(*this, CodeGen); + CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen); // Emit an implicit barrier at the end. if (!S.getSingleClause(OMPC_nowait) || HasLastprivates) { @@ -1214,8 +1218,8 @@ static LValue createSectionLVal(CodeGenFunction &CGF, QualType Ty, return LVal; } -static OpenMPDirectiveKind emitSections(CodeGenFunction &CGF, - const OMPExecutableDirective &S) { +OpenMPDirectiveKind +CodeGenFunction::EmitSections(const OMPExecutableDirective &S) { auto *Stmt = cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt(); auto *CS = dyn_cast<CompoundStmt>(Stmt); if (CS && CS->size() > 1) { @@ -1263,12 +1267,13 @@ static OpenMPDirectiveKind emitSections(CodeGenFunction &CGF, CGF.EmitLoadOfLValue(IV, S.getLocStart()).getScalarVal(), ExitBB, CS->size()); unsigned CaseNumber = 0; - for (auto C = CS->children(); C; ++C, ++CaseNumber) { + for (auto *SubStmt : CS->children()) { auto CaseBB = CGF.createBasicBlock(".omp.sections.case"); CGF.EmitBlock(CaseBB); SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB); - CGF.EmitStmt(*C); + CGF.EmitStmt(SubStmt); CGF.EmitBranch(ExitBB); + ++CaseNumber; } CGF.EmitBlock(ExitBB, /*IsFinished=*/true); }; @@ -1311,15 +1316,15 @@ static OpenMPDirectiveKind emitSections(CodeGenFunction &CGF, CGF.EmitLoadOfScalar(IL, S.getLocStart()))); }; - CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, CodeGen); + CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_sections, CodeGen); // Emit barrier for lastprivates only if 'sections' directive has 'nowait' // clause. Otherwise the barrier will be generated by the codegen for the // directive. if (HasLastprivates && S.getSingleClause(OMPC_nowait)) { // Emit implicit barrier to synchronize threads and avoid data races on // initialization of firstprivate variables. - CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(), - OMPD_unknown); + CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), + OMPD_unknown); } return OMPD_sections; } @@ -1340,11 +1345,10 @@ static OpenMPDirectiveKind emitSections(CodeGenFunction &CGF, (void)SingleScope.Privatize(); CGF.EmitStmt(Stmt); - CGF.EnsureInsertPoint(); }; - CGF.CGM.getOpenMPRuntime().emitSingleRegion(CGF, CodeGen, S.getLocStart(), - llvm::None, llvm::None, - llvm::None, llvm::None); + CGM.getOpenMPRuntime().emitSingleRegion(*this, CodeGen, S.getLocStart(), + llvm::None, llvm::None, llvm::None, + llvm::None); // Emit barrier for firstprivates, lastprivates or reductions only if // 'sections' directive has 'nowait' clause. Otherwise the barrier will be // generated by the codegen for the directive. @@ -1352,15 +1356,14 @@ static OpenMPDirectiveKind emitSections(CodeGenFunction &CGF, S.getSingleClause(OMPC_nowait)) { // Emit implicit barrier to synchronize threads and avoid data races on // initialization of firstprivate variables. - CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(), - OMPD_unknown); + CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_unknown); } return OMPD_single; } void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &S) { LexicalScope Scope(*this, S.getSourceRange()); - OpenMPDirectiveKind EmittedAs = emitSections(*this, S); + OpenMPDirectiveKind EmittedAs = EmitSections(S); // Emit an implicit barrier at the end. if (!S.getSingleClause(OMPC_nowait)) { CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), EmittedAs); @@ -1373,7 +1376,7 @@ void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &S) { CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); CGF.EnsureInsertPoint(); }; - CGM.getOpenMPRuntime().emitInlinedDirective(*this, CodeGen); + CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_section, CodeGen); } void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &S) { @@ -1453,7 +1456,7 @@ void CodeGenFunction::EmitOMPParallelForDirective( CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(), OMPD_parallel); }; - emitCommonOMPParallelDirective(*this, S, CodeGen); + emitCommonOMPParallelDirective(*this, S, OMPD_for, CodeGen); } void CodeGenFunction::EmitOMPParallelForSimdDirective( @@ -1470,7 +1473,7 @@ void CodeGenFunction::EmitOMPParallelForSimdDirective( CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(), OMPD_parallel); }; - emitCommonOMPParallelDirective(*this, S, CodeGen); + emitCommonOMPParallelDirective(*this, S, OMPD_simd, CodeGen); } void CodeGenFunction::EmitOMPParallelSectionsDirective( @@ -1479,12 +1482,12 @@ void CodeGenFunction::EmitOMPParallelSectionsDirective( // directives: 'parallel' with 'sections' directive. LexicalScope Scope(*this, S.getSourceRange()); auto &&CodeGen = [&S](CodeGenFunction &CGF) { - (void)emitSections(CGF, S); + (void)CGF.EmitSections(S); // Emit implicit barrier at the end of parallel region. CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(), OMPD_parallel); }; - emitCommonOMPParallelDirective(*this, S, CodeGen); + emitCommonOMPParallelDirective(*this, S, OMPD_sections, CodeGen); } void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) { @@ -1531,6 +1534,15 @@ void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) { ++IRef, ++IElemInitRef; } } + // Build list of dependences. + llvm::SmallVector<std::pair<OpenMPDependClauseKind, const Expr *>, 8> + Dependences; + for (auto &&I = S.getClausesOfKind(OMPC_depend); I; ++I) { + auto *C = cast<OMPDependClause>(*I); + for (auto *IRef : C->varlists()) { + Dependences.push_back(std::make_pair(C->getDependencyKind(), IRef)); + } + } auto &&CodeGen = [PartId, &S, &PrivateVars, &FirstprivateVars]( CodeGenFunction &CGF) { // Set proper addresses for generated private copies. @@ -1575,8 +1587,8 @@ void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) { } CGF.EmitStmt(CS->getCapturedStmt()); }; - auto OutlinedFn = - CGM.getOpenMPRuntime().emitTaskOutlinedFunction(S, *I, CodeGen); + auto OutlinedFn = CGM.getOpenMPRuntime().emitTaskOutlinedFunction( + S, *I, OMPD_task, CodeGen); // Check if we should emit tied or untied task. bool Tied = !S.getSingleClause(OMPC_untied); // Check if the task is final @@ -1602,7 +1614,7 @@ void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) { CGM.getOpenMPRuntime().emitTaskCall( *this, S.getLocStart(), S, Tied, Final, OutlinedFn, SharedsTy, CapturedStruct, IfCond, PrivateVars, PrivateCopies, FirstprivateVars, - FirstprivateCopies, FirstprivateInits); + FirstprivateCopies, FirstprivateInits, Dependences); } void CodeGenFunction::EmitOMPTaskyieldDirective( @@ -2041,6 +2053,7 @@ static void EmitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind, case OMPC_nowait: case OMPC_untied: case OMPC_threadprivate: + case OMPC_depend: case OMPC_mergeable: llvm_unreachable("Clause is not allowed in 'omp atomic'."); } @@ -2077,7 +2090,7 @@ void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) { S.getV(), S.getExpr(), S.getUpdateExpr(), S.isXLHSInRHSPart(), S.getLocStart()); }; - CGM.getOpenMPRuntime().emitInlinedDirective(*this, CodeGen); + CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_atomic, CodeGen); } void CodeGenFunction::EmitOMPTargetDirective(const OMPTargetDirective &) { @@ -2087,3 +2100,23 @@ void CodeGenFunction::EmitOMPTargetDirective(const OMPTargetDirective &) { void CodeGenFunction::EmitOMPTeamsDirective(const OMPTeamsDirective &) { llvm_unreachable("CodeGen for 'omp teams' is not supported yet."); } + +void CodeGenFunction::EmitOMPCancellationPointDirective( + const OMPCancellationPointDirective &S) { + CGM.getOpenMPRuntime().emitCancellationPointCall(*this, S.getLocStart(), + S.getCancelRegion()); +} + +void CodeGenFunction::EmitOMPCancelDirective(const OMPCancelDirective &S) { + llvm_unreachable("CodeGen for 'omp cancel' is not supported yet."); +} + +CodeGenFunction::JumpDest +CodeGenFunction::getOMPCancelDestination(OpenMPDirectiveKind Kind) { + if (Kind == OMPD_parallel || Kind == OMPD_task) + return ReturnBlock; + else if (Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections) + return BreakContinueStack.empty() ? JumpDest() + : BreakContinueStack.back().BreakBlock; + return JumpDest(); +} diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp index 17db401..969629f 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp @@ -123,8 +123,8 @@ static RValue PerformReturnAdjustment(CodeGenFunction &CGF, // no-op thunk for the regular definition) call va_start/va_end. // There's a bit of per-call overhead for this solution, but it's // better for codesize if the definition is long. -void CodeGenFunction::GenerateVarArgsThunk( - llvm::Function *Fn, +llvm::Function * +CodeGenFunction::GenerateVarArgsThunk(llvm::Function *Fn, const CGFunctionInfo &FnInfo, GlobalDecl GD, const ThunkInfo &Thunk) { const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); @@ -184,6 +184,8 @@ void CodeGenFunction::GenerateVarArgsThunk( } } } + + return Fn; } void CodeGenFunction::StartThunk(llvm::Function *Fn, GlobalDecl GD, @@ -378,9 +380,6 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, // Set the right linkage. CGM.setFunctionLinkage(GD, Fn); - if (CGM.supportsCOMDAT() && Fn->isWeakForLinker()) - Fn->setComdat(CGM.getModule().getOrInsertComdat(Fn->getName())); - // Set the right visibility. const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); setThunkVisibility(CGM, MD, Thunk, Fn); @@ -450,17 +449,19 @@ void CodeGenVTables::emitThunk(GlobalDecl GD, const ThunkInfo &Thunk, // expensive/sucky at the moment, so don't generate the thunk unless // we have to. // FIXME: Do something better here; GenerateVarArgsThunk is extremely ugly. - if (!UseAvailableExternallyLinkage) { - CodeGenFunction(CGM).GenerateVarArgsThunk(ThunkFn, FnInfo, GD, Thunk); - CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable, GD, - !Thunk.Return.isEmpty()); - } + if (UseAvailableExternallyLinkage) + return; + ThunkFn = + CodeGenFunction(CGM).GenerateVarArgsThunk(ThunkFn, FnInfo, GD, Thunk); } else { // Normal thunk body generation. CodeGenFunction(CGM).GenerateThunk(ThunkFn, FnInfo, GD, Thunk); - CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable, GD, - !Thunk.Return.isEmpty()); } + + CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable, GD, + !Thunk.Return.isEmpty()); + if (CGM.supportsCOMDAT() && ThunkFn->isWeakForLinker()) + ThunkFn->setComdat(CGM.getModule().getOrInsertComdat(ThunkFn->getName())); } void CodeGenVTables::maybeEmitThunkForVTable(GlobalDecl GD, @@ -702,7 +703,7 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) { llvm::Function::InternalLinkage; return llvm::GlobalVariable::ExternalLinkage; - + case TSK_ImplicitInstantiation: return !Context.getLangOpts().AppleKext ? llvm::GlobalVariable::LinkOnceODRLinkage : diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenABITypes.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenABITypes.cpp index 12189ae..755e8aa 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenABITypes.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenABITypes.cpp @@ -20,6 +20,8 @@ #include "CodeGenModule.h" #include "clang/CodeGen/CGFunctionInfo.h" #include "clang/Frontend/CodeGenOptions.h" +#include "clang/Lex/HeaderSearchOptions.h" +#include "clang/Lex/PreprocessorOptions.h" using namespace clang; using namespace CodeGen; @@ -29,7 +31,10 @@ CodeGenABITypes::CodeGenABITypes(ASTContext &C, const llvm::DataLayout &TD, CoverageSourceInfo *CoverageInfo) : CGO(new CodeGenOptions), - CGM(new CodeGen::CodeGenModule(C, *CGO, M, TD, C.getDiagnostics(), + HSO(new HeaderSearchOptions), + PPO(new PreprocessorOptions), + CGM(new CodeGen::CodeGenModule(C, *HSO, *PPO, *CGO, + M, TD, C.getDiagnostics(), CoverageInfo)) { } diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp index 54e6b73..0e7b6d8 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp @@ -57,6 +57,8 @@ namespace clang { public: BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags, + const HeaderSearchOptions &HeaderSearchOpts, + const PreprocessorOptions &PPOpts, const CodeGenOptions &CodeGenOpts, const TargetOptions &TargetOpts, const LangOptions &LangOpts, bool TimePasses, @@ -66,7 +68,8 @@ namespace clang { : Diags(Diags), Action(Action), CodeGenOpts(CodeGenOpts), TargetOpts(TargetOpts), LangOpts(LangOpts), AsmOutStream(OS), Context(nullptr), LLVMIRGeneration("LLVM IR Generation Time"), - Gen(CreateLLVMCodeGen(Diags, InFile, CodeGenOpts, C, CoverageInfo)), + Gen(CreateLLVMCodeGen(Diags, InFile, HeaderSearchOpts, PPOpts, + CodeGenOpts, C, CoverageInfo)), LinkModule(LinkModule) { llvm::TimePassesIsEnabled = TimePasses; } @@ -667,7 +670,8 @@ CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { std::unique_ptr<PPCallbacks>(CoverageInfo)); } std::unique_ptr<BackendConsumer> Result(new BackendConsumer( - BA, CI.getDiagnostics(), CI.getCodeGenOpts(), CI.getTargetOpts(), + BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(), + CI.getPreprocessorOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(), CI.getLangOpts(), CI.getFrontendOpts().ShowTimers, InFile, LinkModuleToUse, OS, *VMContext, CoverageInfo)); BEConsumer = Result.get(); diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp index bece41e..1fca466 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp @@ -930,8 +930,9 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, EmitCheck(std::make_pair(IsFalse, SanitizerKind::Return), "missing_return", EmitCheckSourceLocation(FD->getLocation()), None); - } else if (CGM.getCodeGenOpts().OptimizationLevel == 0) - Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::trap), {}); + } else if (CGM.getCodeGenOpts().OptimizationLevel == 0) { + EmitTrapCall(llvm::Intrinsic::trap); + } Builder.CreateUnreachable(); Builder.ClearInsertionPoint(); } @@ -970,8 +971,8 @@ bool CodeGenFunction::ContainsLabel(const Stmt *S, bool IgnoreCaseStmts) { IgnoreCaseStmts = true; // Scan subexpressions for verboten labels. - for (Stmt::const_child_range I = S->children(); I; ++I) - if (ContainsLabel(*I, IgnoreCaseStmts)) + for (const Stmt *SubStmt : S->children()) + if (ContainsLabel(SubStmt, IgnoreCaseStmts)) return true; return false; @@ -994,8 +995,8 @@ bool CodeGenFunction::containsBreak(const Stmt *S) { return true; // Scan subexpressions for verboten breaks. - for (Stmt::const_child_range I = S->children(); I; ++I) - if (containsBreak(*I)) + for (const Stmt *SubStmt : S->children()) + if (containsBreak(SubStmt)) return true; return false; diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h index 45475d1..a74c474 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h +++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h @@ -233,6 +233,20 @@ public: }; CGCapturedStmtInfo *CapturedStmtInfo; + /// \brief RAII for correct setting/restoring of CapturedStmtInfo. + class CGCapturedStmtRAII { + private: + CodeGenFunction &CGF; + CGCapturedStmtInfo *PrevCapturedStmtInfo; + public: + CGCapturedStmtRAII(CodeGenFunction &CGF, + CGCapturedStmtInfo *NewCapturedStmtInfo) + : CGF(CGF), PrevCapturedStmtInfo(CGF.CapturedStmtInfo) { + CGF.CapturedStmtInfo = NewCapturedStmtInfo; + } + ~CGCapturedStmtRAII() { CGF.CapturedStmtInfo = PrevCapturedStmtInfo; } + }; + /// BoundsChecking - Emit run-time bounds checks. Higher values mean /// potentially higher performance penalties. unsigned char BoundsChecking; @@ -283,12 +297,12 @@ public: /// Header for data within LifetimeExtendedCleanupStack. struct LifetimeExtendedCleanupHeader { /// The size of the following cleanup object. - unsigned Size : 29; + unsigned Size; /// The kind of cleanup to push: a value from the CleanupKind enumeration. - unsigned Kind : 3; + CleanupKind Kind; - size_t getSize() const { return size_t(Size); } - CleanupKind getKind() const { return static_cast<CleanupKind>(Kind); } + size_t getSize() const { return Size; } + CleanupKind getKind() const { return Kind; } }; /// i32s containing the indexes of the cleanup destinations. @@ -388,6 +402,8 @@ public: LifetimeExtendedCleanupStack.resize( LifetimeExtendedCleanupStack.size() + sizeof(Header) + Header.Size); + static_assert(sizeof(Header) % llvm::AlignOf<T>::Alignment == 0, + "Cleanup will be allocated on misaligned address"); char *Buffer = &LifetimeExtendedCleanupStack[OldSize]; new (Buffer) LifetimeExtendedCleanupHeader(Header); new (Buffer + sizeof(Header)) T(A...); @@ -1280,8 +1296,9 @@ public: void GenerateThunk(llvm::Function *Fn, const CGFunctionInfo &FnInfo, GlobalDecl GD, const ThunkInfo &Thunk); - void GenerateVarArgsThunk(llvm::Function *Fn, const CGFunctionInfo &FnInfo, - GlobalDecl GD, const ThunkInfo &Thunk); + llvm::Function *GenerateVarArgsThunk(llvm::Function *Fn, + const CGFunctionInfo &FnInfo, + GlobalDecl GD, const ThunkInfo &Thunk); void EmitCtorPrologue(const CXXConstructorDecl *CD, CXXCtorType Type, FunctionArgList &Args); @@ -2185,6 +2202,9 @@ public: void EmitOMPAtomicDirective(const OMPAtomicDirective &S); void EmitOMPTargetDirective(const OMPTargetDirective &S); void EmitOMPTeamsDirective(const OMPTeamsDirective &S); + void + EmitOMPCancellationPointDirective(const OMPCancellationPointDirective &S); + void EmitOMPCancelDirective(const OMPCancelDirective &S); /// \brief Emit inner loop of the worksharing/simd construct. /// @@ -2202,10 +2222,12 @@ public: const llvm::function_ref<void(CodeGenFunction &)> &BodyGen, const llvm::function_ref<void(CodeGenFunction &)> &PostIncGen); + JumpDest getOMPCancelDestination(OpenMPDirectiveKind Kind); + private: /// Helpers for the OpenMP loop directives. - void EmitOMPLoopBody(const OMPLoopDirective &D); + void EmitOMPLoopBody(const OMPLoopDirective &D, JumpDest LoopExit); void EmitOMPSimdInit(const OMPLoopDirective &D); void EmitOMPSimdFinal(const OMPLoopDirective &D); /// \brief Emit code for the worksharing loop-based directive. @@ -2217,6 +2239,8 @@ private: OMPPrivateScope &LoopScope, bool Ordered, llvm::Value *LB, llvm::Value *UB, llvm::Value *ST, llvm::Value *IL, llvm::Value *Chunk); + /// \brief Emit code for sections directive. + OpenMPDirectiveKind EmitSections(const OMPExecutableDirective &S); public: @@ -2586,6 +2610,7 @@ public: llvm::Value *EmitPPCBuiltinExpr(unsigned BuiltinID, const CallExpr *E); llvm::Value *EmitAMDGPUBuiltinExpr(unsigned BuiltinID, const CallExpr *E); llvm::Value *EmitSystemZBuiltinExpr(unsigned BuiltinID, const CallExpr *E); + llvm::Value *EmitNVPTXBuiltinExpr(unsigned BuiltinID, const CallExpr *E); llvm::Value *EmitObjCProtocolExpr(const ObjCProtocolExpr *E); llvm::Value *EmitObjCStringLiteral(const ObjCStringLiteral *E); @@ -2852,6 +2877,10 @@ public: /// conditional branch to it, for the -ftrapv checks. void EmitTrapCheck(llvm::Value *Checked); + /// \brief Emit a call to trap or debugtrap and attach function attribute + /// "trap-func-name" if specified. + llvm::CallInst *EmitTrapCall(llvm::Intrinsic::ID IntrID); + /// \brief Create a check for a function parameter that may potentially be /// declared as non-null. void EmitNonNullArgCheck(RValue RV, QualType ArgType, SourceLocation ArgLoc, diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp index 2dd5414..b905bd2 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp @@ -74,16 +74,19 @@ static CGCXXABI *createCXXABI(CodeGenModule &CGM) { llvm_unreachable("invalid C++ ABI kind"); } -CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO, - llvm::Module &M, const llvm::DataLayout &TD, +CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO, + const PreprocessorOptions &PPO, + const CodeGenOptions &CGO, llvm::Module &M, + const llvm::DataLayout &TD, DiagnosticsEngine &diags, CoverageSourceInfo *CoverageInfo) - : Context(C), LangOpts(C.getLangOpts()), CodeGenOpts(CGO), TheModule(M), - Diags(diags), TheDataLayout(TD), Target(C.getTargetInfo()), - ABI(createCXXABI(*this)), VMContext(M.getContext()), TBAA(nullptr), - TheTargetCodeGenInfo(nullptr), Types(*this), VTables(*this), - ObjCRuntime(nullptr), OpenCLRuntime(nullptr), OpenMPRuntime(nullptr), - CUDARuntime(nullptr), DebugInfo(nullptr), ARCData(nullptr), + : Context(C), LangOpts(C.getLangOpts()), HeaderSearchOpts(HSO), + PreprocessorOpts(PPO), CodeGenOpts(CGO), TheModule(M), Diags(diags), + TheDataLayout(TD), Target(C.getTargetInfo()), ABI(createCXXABI(*this)), + VMContext(M.getContext()), TBAA(nullptr), TheTargetCodeGenInfo(nullptr), + Types(*this), VTables(*this), ObjCRuntime(nullptr), + OpenCLRuntime(nullptr), OpenMPRuntime(nullptr), CUDARuntime(nullptr), + DebugInfo(nullptr), ARCData(nullptr), NoObjCARCExceptionsMetadata(nullptr), RRData(nullptr), PGOReader(nullptr), CFConstantStringClassRef(nullptr), ConstantStringClassRef(nullptr), NSConstantStringType(nullptr), NSConcreteGlobalBlock(nullptr), @@ -145,8 +148,9 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO, llvm::IndexedInstrProfReader::create(CodeGenOpts.InstrProfileInput); if (std::error_code EC = ReaderOrErr.getError()) { unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, - "Could not read profile: %0"); - getDiags().Report(DiagID) << EC.message(); + "Could not read profile %0: %1"); + getDiags().Report(DiagID) << CodeGenOpts.InstrProfileInput + << EC.message(); } else PGOReader = std::move(ReaderOrErr.get()); } @@ -1424,7 +1428,7 @@ namespace { return false; } unsigned BuiltinID = FD->getBuiltinID(); - if (!BuiltinID) + if (!BuiltinID || !BI.isLibFunction(BuiltinID)) return true; StringRef BuiltinName = BI.GetName(BuiltinID); if (BuiltinName.startswith("__builtin_") && @@ -3358,6 +3362,8 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { Owner->getTopLevelModule()->Name == getLangOpts().CurrentModule) break; } + if (CGDebugInfo *DI = getModuleDebugInfo()) + DI->EmitImportDecl(*Import); ImportedModules.insert(Import->getImportedModule()); break; diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h index 8e671fa..9a295fe 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h +++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h @@ -69,6 +69,8 @@ class ValueDecl; class VarDecl; class LangOptions; class CodeGenOptions; +class HeaderSearchOptions; +class PreprocessorOptions; class DiagnosticsEngine; class AnnotateAttr; class CXXDestructorDecl; @@ -278,6 +280,8 @@ public: private: ASTContext &Context; const LangOptions &LangOpts; + const HeaderSearchOptions &HeaderSearchOpts; // Only used for debug info. + const PreprocessorOptions &PreprocessorOpts; // Only used for debug info. const CodeGenOptions &CodeGenOpts; llvm::Module &TheModule; DiagnosticsEngine &Diags; @@ -488,7 +492,10 @@ private: std::unique_ptr<CoverageMappingModuleGen> CoverageMapping; public: - CodeGenModule(ASTContext &C, const CodeGenOptions &CodeGenOpts, + CodeGenModule(ASTContext &C, + const HeaderSearchOptions &headersearchopts, + const PreprocessorOptions &ppopts, + const CodeGenOptions &CodeGenOpts, llvm::Module &M, const llvm::DataLayout &TD, DiagnosticsEngine &Diags, CoverageSourceInfo *CoverageInfo = nullptr); @@ -600,6 +607,10 @@ public: ASTContext &getContext() const { return Context; } const LangOptions &getLangOpts() const { return LangOpts; } + const HeaderSearchOptions &getHeaderSearchOpts() + const { return HeaderSearchOpts; } + const PreprocessorOptions &getPreprocessorOpts() + const { return PreprocessorOpts; } const CodeGenOptions &getCodeGenOpts() const { return CodeGenOpts; } llvm::Module &getModule() const { return TheModule; } DiagnosticsEngine &getDiags() const { return Diags; } @@ -732,6 +743,11 @@ public: /// Get a reference to the target of VD. llvm::Constant *GetWeakRefReference(const ValueDecl *VD); + CharUnits + computeNonVirtualBaseClassOffset(const CXXRecordDecl *DerivedClass, + CastExpr::path_const_iterator Start, + CastExpr::path_const_iterator End); + /// Returns the offset from a derived class to a class. Returns null if the /// offset is 0. llvm::Constant * diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.cpp index f182a46..8dffefc 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.cpp @@ -275,10 +275,9 @@ struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> { void VisitStmt(const Stmt *S) { RecordStmtCount(S); - for (Stmt::const_child_range I = S->children(); I; ++I) { - if (*I) - this->Visit(*I); - } + for (const Stmt *Child : S->children()) + if (Child) + this->Visit(Child); } void VisitFunctionDecl(const FunctionDecl *D) { diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp index e0f926c..a4a8654 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp @@ -154,14 +154,16 @@ isSafeToConvert(const RecordDecl *RD, CodeGenTypes &CGT, static bool isSafeToConvert(QualType T, CodeGenTypes &CGT, llvm::SmallPtrSet<const RecordDecl*, 16> &AlreadyChecked) { - T = T.getCanonicalType(); - + // Strip off atomic type sugar. + if (const auto *AT = T->getAs<AtomicType>()) + T = AT->getValueType(); + // If this is a record, check it. - if (const RecordType *RT = dyn_cast<RecordType>(T)) + if (const auto *RT = T->getAs<RecordType>()) return isSafeToConvert(RT->getDecl(), CGT, AlreadyChecked); - + // If this is an array, check the elements, which are embedded inline. - if (const ArrayType *AT = dyn_cast<ArrayType>(T)) + if (const auto *AT = CGT.getContext().getAsArrayType(T)) return isSafeToConvert(AT->getElementType(), CGT, AlreadyChecked); // Otherwise, there is no concern about transforming this. We only care about diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.cpp index 9ad5d14..eca9159 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -475,7 +475,8 @@ struct CounterCoverageMappingBuilder /// files, this adjusts our current region stack and creates the file regions /// for the exited file. void handleFileExit(SourceLocation NewLoc) { - if (SM.isWrittenInSameFile(MostRecentLocation, NewLoc)) + if (NewLoc.isInvalid() || + SM.isWrittenInSameFile(MostRecentLocation, NewLoc)) return; // If NewLoc is not in a file that contains MostRecentLocation, walk up to @@ -581,10 +582,9 @@ struct CounterCoverageMappingBuilder void VisitStmt(const Stmt *S) { if (!S->getLocStart().isInvalid()) extendRegion(S); - for (Stmt::const_child_range I = S->children(); I; ++I) { - if (*I) - this->Visit(*I); - } + for (const Stmt *Child : S->children()) + if (Child) + this->Visit(Child); handleFileExit(getEnd(S)); } @@ -931,7 +931,8 @@ void CoverageMappingModuleGen::addFunctionMappingRecord( if (!FunctionRecordTy) { llvm::Type *FunctionRecordTypes[] = {Int8PtrTy, Int32Ty, Int32Ty, Int64Ty}; FunctionRecordTy = - llvm::StructType::get(Ctx, makeArrayRef(FunctionRecordTypes)); + llvm::StructType::get(Ctx, makeArrayRef(FunctionRecordTypes), + /*isPacked=*/true); } llvm::Constant *FunctionRecordVals[] = { diff --git a/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp b/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp index 3f5ad5d..fa86e52 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -94,7 +94,7 @@ public: llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT) override; - llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD) override; + llvm::Constant *EmitMemberFunctionPointer(const CXXMethodDecl *MD) override; llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT, CharUnits offset) override; llvm::Constant *EmitMemberPointer(const APValue &MP, QualType MPT) override; @@ -219,7 +219,7 @@ public: bool ReturnAdjustment) override { // Allow inlining of thunks by emitting them with available_externally // linkage together with vtables when needed. - if (ForVTable) + if (ForVTable && !Thunk->hasLocalLinkage()) Thunk->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage); } @@ -656,7 +656,8 @@ ItaniumCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT, return llvm::ConstantInt::get(CGM.PtrDiffTy, offset.getQuantity()); } -llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) { +llvm::Constant * +ItaniumCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) { return BuildMemberPointer(MD, CharUnits::Zero()); } diff --git a/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 679516b..d149df6 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -247,6 +247,50 @@ public: getAddrOfVBTable(const VPtrInfo &VBT, const CXXRecordDecl *RD, llvm::GlobalVariable::LinkageTypes Linkage); + llvm::GlobalVariable * + getAddrOfVirtualDisplacementMap(const CXXRecordDecl *SrcRD, + const CXXRecordDecl *DstRD) { + SmallString<256> OutName; + llvm::raw_svector_ostream Out(OutName); + getMangleContext().mangleCXXVirtualDisplacementMap(SrcRD, DstRD, Out); + Out.flush(); + StringRef MangledName = OutName.str(); + + if (auto *VDispMap = CGM.getModule().getNamedGlobal(MangledName)) + return VDispMap; + + MicrosoftVTableContext &VTContext = CGM.getMicrosoftVTableContext(); + unsigned NumEntries = 1 + SrcRD->getNumVBases(); + SmallVector<llvm::Constant *, 4> Map(NumEntries, + llvm::UndefValue::get(CGM.IntTy)); + Map[0] = llvm::ConstantInt::get(CGM.IntTy, 0); + bool AnyDifferent = false; + for (const auto &I : SrcRD->vbases()) { + const CXXRecordDecl *VBase = I.getType()->getAsCXXRecordDecl(); + if (!DstRD->isVirtuallyDerivedFrom(VBase)) + continue; + + unsigned SrcVBIndex = VTContext.getVBTableIndex(SrcRD, VBase); + unsigned DstVBIndex = VTContext.getVBTableIndex(DstRD, VBase); + Map[SrcVBIndex] = llvm::ConstantInt::get(CGM.IntTy, DstVBIndex * 4); + AnyDifferent |= SrcVBIndex != DstVBIndex; + } + // This map would be useless, don't use it. + if (!AnyDifferent) + return nullptr; + + llvm::ArrayType *VDispMapTy = llvm::ArrayType::get(CGM.IntTy, Map.size()); + llvm::Constant *Init = llvm::ConstantArray::get(VDispMapTy, Map); + llvm::GlobalValue::LinkageTypes Linkage = + SrcRD->isExternallyVisible() && DstRD->isExternallyVisible() + ? llvm::GlobalValue::LinkOnceODRLinkage + : llvm::GlobalValue::InternalLinkage; + auto *VDispMap = new llvm::GlobalVariable( + CGM.getModule(), VDispMapTy, /*Constant=*/true, Linkage, + /*Initializer=*/Init, MangledName); + return VDispMap; + } + void emitVBTableDefinition(const VPtrInfo &VBT, const CXXRecordDecl *RD, llvm::GlobalVariable *GV) const; @@ -502,10 +546,6 @@ private: CharUnits NonVirtualBaseAdjustment, unsigned VBTableIndex); - llvm::Constant *BuildMemberPointer(const CXXRecordDecl *RD, - const CXXMethodDecl *MD, - CharUnits NonVirtualBaseAdjustment); - bool MemberPointerConstantIsNull(const MemberPointerType *MPT, llvm::Constant *MP); @@ -545,7 +585,7 @@ public: llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT, CharUnits offset) override; - llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD) override; + llvm::Constant *EmitMemberFunctionPointer(const CXXMethodDecl *MD) override; llvm::Constant *EmitMemberPointer(const APValue &MP, QualType MPT) override; llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF, @@ -563,6 +603,12 @@ public: llvm::Value *Base, llvm::Value *MemPtr, const MemberPointerType *MPT) override; + llvm::Value *EmitNonNullMemberPointerConversion( + const MemberPointerType *SrcTy, const MemberPointerType *DstTy, + CastKind CK, CastExpr::path_const_iterator PathBegin, + CastExpr::path_const_iterator PathEnd, llvm::Value *Src, + CGBuilderTy &Builder); + llvm::Value *EmitMemberPointerConversion(CodeGenFunction &CGF, const CastExpr *E, llvm::Value *Src) override; @@ -570,6 +616,11 @@ public: llvm::Constant *EmitMemberPointerConversion(const CastExpr *E, llvm::Constant *Src) override; + llvm::Constant *EmitMemberPointerConversion( + const MemberPointerType *SrcTy, const MemberPointerType *DstTy, + CastKind CK, CastExpr::path_const_iterator PathBegin, + CastExpr::path_const_iterator PathEnd, llvm::Constant *Src); + llvm::Value * EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, const Expr *E, llvm::Value *&This, llvm::Value *MemPtr, @@ -2457,7 +2508,7 @@ MicrosoftCXXABI::EmitFullMemberPointer(llvm::Constant *FirstField, if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance)) { CharUnits Offs = CharUnits::Zero(); - if (VBTableIndex && RD->getNumVBases()) + if (VBTableIndex) Offs = getContext().getASTRecordLayout(RD).getVBPtrOffset(); fields.push_back(llvm::ConstantInt::get(CGM.IntTy, Offs.getQuantity())); } @@ -2473,43 +2524,76 @@ llvm::Constant * MicrosoftCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT, CharUnits offset) { const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); + if (RD->getMSInheritanceModel() == + MSInheritanceAttr::Keyword_virtual_inheritance) + offset -= getContext().getOffsetOfBaseWithVBPtr(RD); llvm::Constant *FirstField = llvm::ConstantInt::get(CGM.IntTy, offset.getQuantity()); return EmitFullMemberPointer(FirstField, /*IsMemberFunction=*/false, RD, CharUnits::Zero(), /*VBTableIndex=*/0); } -llvm::Constant *MicrosoftCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) { - return BuildMemberPointer(MD->getParent(), MD, CharUnits::Zero()); -} - llvm::Constant *MicrosoftCXXABI::EmitMemberPointer(const APValue &MP, QualType MPType) { - const MemberPointerType *MPT = MPType->castAs<MemberPointerType>(); + const MemberPointerType *DstTy = MPType->castAs<MemberPointerType>(); const ValueDecl *MPD = MP.getMemberPointerDecl(); if (!MPD) - return EmitNullMemberPointer(MPT); + return EmitNullMemberPointer(DstTy); - CharUnits ThisAdjustment = getMemberPointerPathAdjustment(MP); + ASTContext &Ctx = getContext(); + ArrayRef<const CXXRecordDecl *> MemberPointerPath = MP.getMemberPointerPath(); - // FIXME PR15713: Support virtual inheritance paths. + llvm::Constant *C; + if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD)) { + C = EmitMemberFunctionPointer(MD); + } else { + CharUnits FieldOffset = Ctx.toCharUnitsFromBits(Ctx.getFieldOffset(MPD)); + C = EmitMemberDataPointer(DstTy, FieldOffset); + } - if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD)) - return BuildMemberPointer(MPT->getMostRecentCXXRecordDecl(), MD, - ThisAdjustment); + if (!MemberPointerPath.empty()) { + const CXXRecordDecl *SrcRD = cast<CXXRecordDecl>(MPD->getDeclContext()); + const Type *SrcRecTy = Ctx.getTypeDeclType(SrcRD).getTypePtr(); + const MemberPointerType *SrcTy = + Ctx.getMemberPointerType(DstTy->getPointeeType(), SrcRecTy) + ->castAs<MemberPointerType>(); + + bool DerivedMember = MP.isMemberPointerToDerivedMember(); + SmallVector<const CXXBaseSpecifier *, 4> DerivedToBasePath; + const CXXRecordDecl *PrevRD = SrcRD; + for (const CXXRecordDecl *PathElem : MemberPointerPath) { + const CXXRecordDecl *Base = nullptr; + const CXXRecordDecl *Derived = nullptr; + if (DerivedMember) { + Base = PathElem; + Derived = PrevRD; + } else { + Base = PrevRD; + Derived = PathElem; + } + for (const CXXBaseSpecifier &BS : Derived->bases()) + if (BS.getType()->getAsCXXRecordDecl()->getCanonicalDecl() == + Base->getCanonicalDecl()) + DerivedToBasePath.push_back(&BS); + PrevRD = PathElem; + } + assert(DerivedToBasePath.size() == MemberPointerPath.size()); - CharUnits FieldOffset = - getContext().toCharUnitsFromBits(getContext().getFieldOffset(MPD)); - return EmitMemberDataPointer(MPT, ThisAdjustment + FieldOffset); + CastKind CK = DerivedMember ? CK_DerivedToBaseMemberPointer + : CK_BaseToDerivedMemberPointer; + C = EmitMemberPointerConversion(SrcTy, DstTy, CK, DerivedToBasePath.begin(), + DerivedToBasePath.end(), C); + } + return C; } llvm::Constant * -MicrosoftCXXABI::BuildMemberPointer(const CXXRecordDecl *RD, - const CXXMethodDecl *MD, - CharUnits NonVirtualBaseAdjustment) { +MicrosoftCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) { assert(MD->isInstance() && "Member function must not be static!"); + MD = MD->getCanonicalDecl(); - RD = RD->getMostRecentDecl(); + CharUnits NonVirtualBaseAdjustment = CharUnits::Zero(); + const CXXRecordDecl *RD = MD->getParent()->getMostRecentDecl(); CodeGenTypes &Types = CGM.getTypes(); unsigned VBTableIndex = 0; @@ -2527,20 +2611,24 @@ MicrosoftCXXABI::BuildMemberPointer(const CXXRecordDecl *RD, Ty = CGM.PtrDiffTy; } FirstField = CGM.GetAddrOfFunction(MD, Ty); - FirstField = llvm::ConstantExpr::getBitCast(FirstField, CGM.VoidPtrTy); } else { auto &VTableContext = CGM.getMicrosoftVTableContext(); MicrosoftVTableContext::MethodVFTableLocation ML = VTableContext.getMethodVFTableLocation(MD); - llvm::Function *Thunk = EmitVirtualMemPtrThunk(MD, ML); - FirstField = llvm::ConstantExpr::getBitCast(Thunk, CGM.VoidPtrTy); + FirstField = EmitVirtualMemPtrThunk(MD, ML); // Include the vfptr adjustment if the method is in a non-primary vftable. NonVirtualBaseAdjustment += ML.VFPtrOffset; if (ML.VBase) VBTableIndex = VTableContext.getVBTableIndex(RD, ML.VBase) * 4; } + if (VBTableIndex == 0 && + RD->getMSInheritanceModel() == + MSInheritanceAttr::Keyword_virtual_inheritance) + NonVirtualBaseAdjustment -= getContext().getOffsetOfBaseWithVBPtr(RD); + // The rest of the fields are common with data member pointers. + FirstField = llvm::ConstantExpr::getBitCast(FirstField, CGM.VoidPtrTy); return EmitFullMemberPointer(FirstField, /*IsMemberFunction=*/true, RD, NonVirtualBaseAdjustment, VBTableIndex); } @@ -2798,11 +2886,6 @@ llvm::Value *MicrosoftCXXABI::EmitMemberDataPointerAddress( return Builder.CreateBitCast(Addr, PType); } -static MSInheritanceAttr::Spelling -getInheritanceFromMemptr(const MemberPointerType *MPT) { - return MPT->getMostRecentCXXRecordDecl()->getMSInheritanceModel(); -} - llvm::Value * MicrosoftCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF, const CastExpr *E, @@ -2854,12 +2937,37 @@ MicrosoftCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF, Builder.CreateCondBr(IsNotNull, ConvertBB, ContinueBB); CGF.EmitBlock(ConvertBB); + llvm::Value *Dst = EmitNonNullMemberPointerConversion( + SrcTy, DstTy, E->getCastKind(), E->path_begin(), E->path_end(), Src, + Builder); + + Builder.CreateBr(ContinueBB); + + // In the continuation, choose between DstNull and Dst. + CGF.EmitBlock(ContinueBB); + llvm::PHINode *Phi = Builder.CreatePHI(DstNull->getType(), 2, "memptr.converted"); + Phi->addIncoming(DstNull, OriginalBB); + Phi->addIncoming(Dst, ConvertBB); + return Phi; +} + +llvm::Value *MicrosoftCXXABI::EmitNonNullMemberPointerConversion( + const MemberPointerType *SrcTy, const MemberPointerType *DstTy, CastKind CK, + CastExpr::path_const_iterator PathBegin, + CastExpr::path_const_iterator PathEnd, llvm::Value *Src, + CGBuilderTy &Builder) { + const CXXRecordDecl *SrcRD = SrcTy->getMostRecentCXXRecordDecl(); + const CXXRecordDecl *DstRD = DstTy->getMostRecentCXXRecordDecl(); + MSInheritanceAttr::Spelling SrcInheritance = SrcRD->getMSInheritanceModel(); + MSInheritanceAttr::Spelling DstInheritance = DstRD->getMSInheritanceModel(); + bool IsFunc = SrcTy->isMemberFunctionPointer(); + bool IsConstant = isa<llvm::Constant>(Src); + // Decompose src. llvm::Value *FirstField = Src; - llvm::Value *NonVirtualBaseAdjustment = nullptr; - llvm::Value *VirtualBaseAdjustmentOffset = nullptr; - llvm::Value *VBPtrOffset = nullptr; - MSInheritanceAttr::Spelling SrcInheritance = SrcRD->getMSInheritanceModel(); + llvm::Value *NonVirtualBaseAdjustment = getZeroInt(); + llvm::Value *VirtualBaseAdjustmentOffset = getZeroInt(); + llvm::Value *VBPtrOffset = getZeroInt(); if (!MSInheritanceAttr::hasOnlyOneField(IsFunc, SrcInheritance)) { // We need to extract values. unsigned I = 0; @@ -2872,59 +2980,138 @@ MicrosoftCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF, VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(Src, I++); } + bool IsDerivedToBase = (CK == CK_DerivedToBaseMemberPointer); + const MemberPointerType *DerivedTy = IsDerivedToBase ? SrcTy : DstTy; + const CXXRecordDecl *DerivedClass = DerivedTy->getMostRecentCXXRecordDecl(); + // For data pointers, we adjust the field offset directly. For functions, we // have a separate field. - llvm::Constant *Adj = getMemberPointerAdjustment(E); - if (Adj) { - Adj = llvm::ConstantExpr::getTruncOrBitCast(Adj, CGM.IntTy); - llvm::Value *&NVAdjustField = IsFunc ? NonVirtualBaseAdjustment : FirstField; - bool isDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer); - if (!NVAdjustField) // If this field didn't exist in src, it's zero. - NVAdjustField = getZeroInt(); - if (isDerivedToBase) - NVAdjustField = Builder.CreateNSWSub(NVAdjustField, Adj, "adj"); - else - NVAdjustField = Builder.CreateNSWAdd(NVAdjustField, Adj, "adj"); + llvm::Value *&NVAdjustField = IsFunc ? NonVirtualBaseAdjustment : FirstField; + + // The virtual inheritance model has a quirk: the virtual base table is always + // referenced when dereferencing a member pointer even if the member pointer + // is non-virtual. This is accounted for by adjusting the non-virtual offset + // to point backwards to the top of the MDC from the first VBase. Undo this + // adjustment to normalize the member pointer. + llvm::Value *SrcVBIndexEqZero = + Builder.CreateICmpEQ(VirtualBaseAdjustmentOffset, getZeroInt()); + if (SrcInheritance == MSInheritanceAttr::Keyword_virtual_inheritance) { + if (int64_t SrcOffsetToFirstVBase = + getContext().getOffsetOfBaseWithVBPtr(SrcRD).getQuantity()) { + llvm::Value *UndoSrcAdjustment = Builder.CreateSelect( + SrcVBIndexEqZero, + llvm::ConstantInt::get(CGM.IntTy, SrcOffsetToFirstVBase), + getZeroInt()); + NVAdjustField = Builder.CreateNSWAdd(NVAdjustField, UndoSrcAdjustment); + } } - // FIXME PR15713: Support conversions through virtually derived classes. + // A non-zero vbindex implies that we are dealing with a source member in a + // floating virtual base in addition to some non-virtual offset. If the + // vbindex is zero, we are dealing with a source that exists in a non-virtual, + // fixed, base. The difference between these two cases is that the vbindex + + // nvoffset *always* point to the member regardless of what context they are + // evaluated in so long as the vbindex is adjusted. A member inside a fixed + // base requires explicit nv adjustment. + llvm::Constant *BaseClassOffset = llvm::ConstantInt::get( + CGM.IntTy, + CGM.computeNonVirtualBaseClassOffset(DerivedClass, PathBegin, PathEnd) + .getQuantity()); + + llvm::Value *NVDisp; + if (IsDerivedToBase) + NVDisp = Builder.CreateNSWSub(NVAdjustField, BaseClassOffset, "adj"); + else + NVDisp = Builder.CreateNSWAdd(NVAdjustField, BaseClassOffset, "adj"); + + NVAdjustField = Builder.CreateSelect(SrcVBIndexEqZero, NVDisp, getZeroInt()); + + // Update the vbindex to an appropriate value in the destination because + // SrcRD's vbtable might not be a strict prefix of the one in DstRD. + llvm::Value *DstVBIndexEqZero = SrcVBIndexEqZero; + if (MSInheritanceAttr::hasVBTableOffsetField(DstInheritance) && + MSInheritanceAttr::hasVBTableOffsetField(SrcInheritance)) { + if (llvm::GlobalVariable *VDispMap = + getAddrOfVirtualDisplacementMap(SrcRD, DstRD)) { + llvm::Value *VBIndex = Builder.CreateExactUDiv( + VirtualBaseAdjustmentOffset, llvm::ConstantInt::get(CGM.IntTy, 4)); + if (IsConstant) { + llvm::Constant *Mapping = VDispMap->getInitializer(); + VirtualBaseAdjustmentOffset = + Mapping->getAggregateElement(cast<llvm::Constant>(VBIndex)); + } else { + llvm::Value *Idxs[] = {getZeroInt(), VBIndex}; + VirtualBaseAdjustmentOffset = + Builder.CreateLoad(Builder.CreateInBoundsGEP(VDispMap, Idxs)); + } + + DstVBIndexEqZero = + Builder.CreateICmpEQ(VirtualBaseAdjustmentOffset, getZeroInt()); + } + } + + // Set the VBPtrOffset to zero if the vbindex is zero. Otherwise, initialize + // it to the offset of the vbptr. + if (MSInheritanceAttr::hasVBPtrOffsetField(DstInheritance)) { + llvm::Value *DstVBPtrOffset = llvm::ConstantInt::get( + CGM.IntTy, + getContext().getASTRecordLayout(DstRD).getVBPtrOffset().getQuantity()); + VBPtrOffset = + Builder.CreateSelect(DstVBIndexEqZero, getZeroInt(), DstVBPtrOffset); + } + + // Likewise, apply a similar adjustment so that dereferencing the member + // pointer correctly accounts for the distance between the start of the first + // virtual base and the top of the MDC. + if (DstInheritance == MSInheritanceAttr::Keyword_virtual_inheritance) { + if (int64_t DstOffsetToFirstVBase = + getContext().getOffsetOfBaseWithVBPtr(DstRD).getQuantity()) { + llvm::Value *DoDstAdjustment = Builder.CreateSelect( + DstVBIndexEqZero, + llvm::ConstantInt::get(CGM.IntTy, DstOffsetToFirstVBase), + getZeroInt()); + NVAdjustField = Builder.CreateNSWSub(NVAdjustField, DoDstAdjustment); + } + } // Recompose dst from the null struct and the adjusted fields from src. - MSInheritanceAttr::Spelling DstInheritance = DstRD->getMSInheritanceModel(); llvm::Value *Dst; if (MSInheritanceAttr::hasOnlyOneField(IsFunc, DstInheritance)) { Dst = FirstField; } else { - Dst = llvm::UndefValue::get(DstNull->getType()); + Dst = llvm::UndefValue::get(ConvertMemberPointerType(DstTy)); unsigned Idx = 0; Dst = Builder.CreateInsertValue(Dst, FirstField, Idx++); if (MSInheritanceAttr::hasNVOffsetField(IsFunc, DstInheritance)) - Dst = Builder.CreateInsertValue( - Dst, getValueOrZeroInt(NonVirtualBaseAdjustment), Idx++); + Dst = Builder.CreateInsertValue(Dst, NonVirtualBaseAdjustment, Idx++); if (MSInheritanceAttr::hasVBPtrOffsetField(DstInheritance)) - Dst = Builder.CreateInsertValue( - Dst, getValueOrZeroInt(VBPtrOffset), Idx++); + Dst = Builder.CreateInsertValue(Dst, VBPtrOffset, Idx++); if (MSInheritanceAttr::hasVBTableOffsetField(DstInheritance)) - Dst = Builder.CreateInsertValue( - Dst, getValueOrZeroInt(VirtualBaseAdjustmentOffset), Idx++); + Dst = Builder.CreateInsertValue(Dst, VirtualBaseAdjustmentOffset, Idx++); } - Builder.CreateBr(ContinueBB); - - // In the continuation, choose between DstNull and Dst. - CGF.EmitBlock(ContinueBB); - llvm::PHINode *Phi = Builder.CreatePHI(DstNull->getType(), 2, "memptr.converted"); - Phi->addIncoming(DstNull, OriginalBB); - Phi->addIncoming(Dst, ConvertBB); - return Phi; + return Dst; } llvm::Constant * MicrosoftCXXABI::EmitMemberPointerConversion(const CastExpr *E, llvm::Constant *Src) { const MemberPointerType *SrcTy = - E->getSubExpr()->getType()->castAs<MemberPointerType>(); + E->getSubExpr()->getType()->castAs<MemberPointerType>(); const MemberPointerType *DstTy = E->getType()->castAs<MemberPointerType>(); + CastKind CK = E->getCastKind(); + + return EmitMemberPointerConversion(SrcTy, DstTy, CK, E->path_begin(), + E->path_end(), Src); +} + +llvm::Constant *MicrosoftCXXABI::EmitMemberPointerConversion( + const MemberPointerType *SrcTy, const MemberPointerType *DstTy, CastKind CK, + CastExpr::path_const_iterator PathBegin, + CastExpr::path_const_iterator PathEnd, llvm::Constant *Src) { + assert(CK == CK_DerivedToBaseMemberPointer || + CK == CK_BaseToDerivedMemberPointer || + CK == CK_ReinterpretMemberPointer); // If src is null, emit a new null for dst. We can't return src because dst // might have a new representation. if (MemberPointerConstantIsNull(SrcTy, Src)) @@ -2933,61 +3120,14 @@ MicrosoftCXXABI::EmitMemberPointerConversion(const CastExpr *E, // We don't need to do anything for reinterpret_casts of non-null member // pointers. We should only get here when the two type representations have // the same size. - if (E->getCastKind() == CK_ReinterpretMemberPointer) + if (CK == CK_ReinterpretMemberPointer) return Src; - MSInheritanceAttr::Spelling SrcInheritance = getInheritanceFromMemptr(SrcTy); - MSInheritanceAttr::Spelling DstInheritance = getInheritanceFromMemptr(DstTy); - - // Decompose src. - llvm::Constant *FirstField = Src; - llvm::Constant *NonVirtualBaseAdjustment = nullptr; - llvm::Constant *VirtualBaseAdjustmentOffset = nullptr; - llvm::Constant *VBPtrOffset = nullptr; - bool IsFunc = SrcTy->isMemberFunctionPointer(); - if (!MSInheritanceAttr::hasOnlyOneField(IsFunc, SrcInheritance)) { - // We need to extract values. - unsigned I = 0; - FirstField = Src->getAggregateElement(I++); - if (MSInheritanceAttr::hasNVOffsetField(IsFunc, SrcInheritance)) - NonVirtualBaseAdjustment = Src->getAggregateElement(I++); - if (MSInheritanceAttr::hasVBPtrOffsetField(SrcInheritance)) - VBPtrOffset = Src->getAggregateElement(I++); - if (MSInheritanceAttr::hasVBTableOffsetField(SrcInheritance)) - VirtualBaseAdjustmentOffset = Src->getAggregateElement(I++); - } - - // For data pointers, we adjust the field offset directly. For functions, we - // have a separate field. - llvm::Constant *Adj = getMemberPointerAdjustment(E); - if (Adj) { - Adj = llvm::ConstantExpr::getTruncOrBitCast(Adj, CGM.IntTy); - llvm::Constant *&NVAdjustField = - IsFunc ? NonVirtualBaseAdjustment : FirstField; - bool IsDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer); - if (!NVAdjustField) // If this field didn't exist in src, it's zero. - NVAdjustField = getZeroInt(); - if (IsDerivedToBase) - NVAdjustField = llvm::ConstantExpr::getNSWSub(NVAdjustField, Adj); - else - NVAdjustField = llvm::ConstantExpr::getNSWAdd(NVAdjustField, Adj); - } - - // FIXME PR15713: Support conversions through virtually derived classes. + CGBuilderTy Builder(CGM.getLLVMContext()); + auto *Dst = cast<llvm::Constant>(EmitNonNullMemberPointerConversion( + SrcTy, DstTy, CK, PathBegin, PathEnd, Src, Builder)); - // Recompose dst from the null struct and the adjusted fields from src. - if (MSInheritanceAttr::hasOnlyOneField(IsFunc, DstInheritance)) - return FirstField; - - llvm::SmallVector<llvm::Constant *, 4> Fields; - Fields.push_back(FirstField); - if (MSInheritanceAttr::hasNVOffsetField(IsFunc, DstInheritance)) - Fields.push_back(getConstantOrZeroInt(NonVirtualBaseAdjustment)); - if (MSInheritanceAttr::hasVBPtrOffsetField(DstInheritance)) - Fields.push_back(getConstantOrZeroInt(VBPtrOffset)); - if (MSInheritanceAttr::hasVBTableOffsetField(DstInheritance)) - Fields.push_back(getConstantOrZeroInt(VirtualBaseAdjustmentOffset)); - return llvm::ConstantStruct::getAnon(Fields); + return Dst; } llvm::Value *MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer( @@ -3592,6 +3732,8 @@ MicrosoftCXXABI::getAddrOfCXXCtorClosure(const CXXConstructorDecl *CD, ThunkTy, getLinkageForRTTI(RecordTy), ThunkName.str(), &CGM.getModule()); ThunkFn->setCallingConv(static_cast<llvm::CallingConv::ID>( FnInfo.getEffectiveCallingConvention())); + if (ThunkFn->isWeakForLinker()) + ThunkFn->setComdat(CGM.getModule().getOrInsertComdat(ThunkFn->getName())); bool IsCopy = CT == Ctor_CopyingClosure; // Start codegen. diff --git a/contrib/llvm/tools/clang/lib/CodeGen/ModuleBuilder.cpp b/contrib/llvm/tools/clang/lib/CodeGen/ModuleBuilder.cpp index 25e5740..def56a9 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/ModuleBuilder.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/ModuleBuilder.cpp @@ -32,6 +32,8 @@ namespace { DiagnosticsEngine &Diags; std::unique_ptr<const llvm::DataLayout> TD; ASTContext *Ctx; + const HeaderSearchOptions &HeaderSearchOpts; // Only used for debug info. + const PreprocessorOptions &PreprocessorOpts; // Only used for debug info. const CodeGenOptions CodeGenOpts; // Intentionally copied in. unsigned HandlingTopLevelDecls; @@ -56,12 +58,15 @@ namespace { SmallVector<CXXMethodDecl *, 8> DeferredInlineMethodDefinitions; public: - CodeGeneratorImpl(DiagnosticsEngine &diags, const std::string& ModuleName, - const CodeGenOptions &CGO, llvm::LLVMContext& C, + CodeGeneratorImpl(DiagnosticsEngine &diags, const std::string &ModuleName, + const HeaderSearchOptions &HSO, + const PreprocessorOptions &PPO, const CodeGenOptions &CGO, + llvm::LLVMContext &C, CoverageSourceInfo *CoverageInfo = nullptr) - : Diags(diags), Ctx(nullptr), CodeGenOpts(CGO), HandlingTopLevelDecls(0), - CoverageInfo(CoverageInfo), - M(new llvm::Module(ModuleName, C)) {} + : Diags(diags), Ctx(nullptr), HeaderSearchOpts(HSO), + PreprocessorOpts(PPO), CodeGenOpts(CGO), HandlingTopLevelDecls(0), + CoverageInfo(CoverageInfo), + M(new llvm::Module(ModuleName, C)) {} ~CodeGeneratorImpl() override { // There should normally not be any leftover inline method definitions. @@ -97,7 +102,10 @@ namespace { M->setDataLayout(Ctx->getTargetInfo().getTargetDescription()); TD.reset( new llvm::DataLayout(Ctx->getTargetInfo().getTargetDescription())); - Builder.reset(new CodeGen::CodeGenModule(Context, CodeGenOpts, *M, *TD, + Builder.reset(new CodeGen::CodeGenModule(Context, + HeaderSearchOpts, + PreprocessorOpts, + CodeGenOpts, *M, *TD, Diags, CoverageInfo)); for (size_t i = 0, e = CodeGenOpts.DependentLibraries.size(); i < e; ++i) @@ -236,10 +244,11 @@ namespace { void CodeGenerator::anchor() { } -CodeGenerator *clang::CreateLLVMCodeGen(DiagnosticsEngine &Diags, - const std::string& ModuleName, - const CodeGenOptions &CGO, - llvm::LLVMContext& C, - CoverageSourceInfo *CoverageInfo) { - return new CodeGeneratorImpl(Diags, ModuleName, CGO, C, CoverageInfo); +CodeGenerator *clang::CreateLLVMCodeGen( + DiagnosticsEngine &Diags, const std::string &ModuleName, + const HeaderSearchOptions &HeaderSearchOpts, + const PreprocessorOptions &PreprocessorOpts, const CodeGenOptions &CGO, + llvm::LLVMContext &C, CoverageSourceInfo *CoverageInfo) { + return new CodeGeneratorImpl(Diags, ModuleName, HeaderSearchOpts, + PreprocessorOpts, CGO, C, CoverageInfo); } diff --git a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp index e77c124..e5ba200 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp @@ -1391,6 +1391,26 @@ bool X86_32TargetCodeGenInfo::initDwarfEHRegSizeTable( namespace { +/// The AVX ABI level for X86 targets. +enum class X86AVXABILevel { + None, + AVX, + AVX512 +}; + +/// \p returns the size in bits of the largest (native) vector for \p AVXLevel. +static unsigned getNativeVectorSizeForAVXABI(X86AVXABILevel AVXLevel) { + switch (AVXLevel) { + case X86AVXABILevel::AVX512: + return 512; + case X86AVXABILevel::AVX: + return 256; + case X86AVXABILevel::None: + return 128; + } + llvm_unreachable("Unknown AVXLevel"); +} + /// X86_64ABIInfo - The X86_64 ABI information. class X86_64ABIInfo : public ABIInfo { enum Class { @@ -1496,13 +1516,14 @@ class X86_64ABIInfo : public ABIInfo { return !getTarget().getTriple().isOSDarwin(); } + X86AVXABILevel AVXLevel; // Some ABIs (e.g. X32 ABI and Native Client OS) use 32 bit pointers on // 64-bit hardware. bool Has64BitPointers; public: - X86_64ABIInfo(CodeGen::CodeGenTypes &CGT) : - ABIInfo(CGT), + X86_64ABIInfo(CodeGen::CodeGenTypes &CGT, X86AVXABILevel AVXLevel) : + ABIInfo(CGT), AVXLevel(AVXLevel), Has64BitPointers(CGT.getDataLayout().getPointerSize(0) == 8) { } @@ -1527,10 +1548,6 @@ public: bool has64BitPointers() const { return Has64BitPointers; } - - bool hasAVX() const { - return getTarget().getABI() == "avx"; - } }; /// WinX86_64ABIInfo - The Windows X86_64 ABI information. @@ -1561,8 +1578,8 @@ public: class X86_64TargetCodeGenInfo : public TargetCodeGenInfo { public: - X86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT) - : TargetCodeGenInfo(new X86_64ABIInfo(CGT)) {} + X86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, X86AVXABILevel AVXLevel) + : TargetCodeGenInfo(new X86_64ABIInfo(CGT, AVXLevel)) {} const X86_64ABIInfo &getABIInfo() const { return static_cast<const X86_64ABIInfo&>(TargetCodeGenInfo::getABIInfo()); @@ -1628,16 +1645,12 @@ public: ('T' << 24); return llvm::ConstantInt::get(CGM.Int32Ty, Sig); } - - unsigned getOpenMPSimdDefaultAlignment(QualType) const override { - return getABIInfo().hasAVX() ? 32 : 16; - } }; class PS4TargetCodeGenInfo : public X86_64TargetCodeGenInfo { public: - PS4TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT) - : X86_64TargetCodeGenInfo(CGT) {} + PS4TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, X86AVXABILevel AVXLevel) + : X86_64TargetCodeGenInfo(CGT, AVXLevel) {} void getDependentLibraryOption(llvm::StringRef Lib, llvm::SmallString<24> &Opt) const override { @@ -1703,11 +1716,10 @@ void WinX86_32TargetCodeGenInfo::setTargetAttributes(const Decl *D, } class WinX86_64TargetCodeGenInfo : public TargetCodeGenInfo { - bool hasAVX() const { return getABIInfo().getTarget().getABI() == "avx"; } - public: - WinX86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT) - : TargetCodeGenInfo(new WinX86_64ABIInfo(CGT)) {} + WinX86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, + X86AVXABILevel AVXLevel) + : TargetCodeGenInfo(new WinX86_64ABIInfo(CGT)) {} void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const override; @@ -1737,10 +1749,6 @@ public: llvm::SmallString<32> &Opt) const override { Opt = "/FAILIFMISMATCH:\"" + Name.str() + "=" + Value.str() + "\""; } - - unsigned getOpenMPSimdDefaultAlignment(QualType) const override { - return hasAVX() ? 32 : 16; - } }; void WinX86_64TargetCodeGenInfo::setTargetAttributes(const Decl *D, @@ -1928,7 +1936,8 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, // split. if (OffsetBase && OffsetBase != 64) Hi = Lo; - } else if (Size == 128 || (hasAVX() && isNamedArg && Size == 256)) { + } else if (Size == 128 || + (isNamedArg && Size <= getNativeVectorSizeForAVXABI(AVXLevel))) { // Arguments of 256-bits are split into four eightbyte chunks. The // least significant one belongs to class SSE and all the others to class // SSEUP. The original Lo and Hi design considers that types can't be @@ -1940,6 +1949,9 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, // Note that per 3.5.7 of AMD64-ABI, 256-bit args are only passed in // registers if they are "named", i.e. not part of the "..." of a // variadic function. + // + // Similarly, per 3.2.3. of the AVX512 draft, 512-bits ("named") args are + // split into eight eightbyte chunks, one SSE and seven SSEUP. Lo = SSE; Hi = SSEUp; } @@ -2150,7 +2162,7 @@ ABIArgInfo X86_64ABIInfo::getIndirectReturnResult(QualType Ty) const { bool X86_64ABIInfo::IsIllegalVectorType(QualType Ty) const { if (const VectorType *VecTy = Ty->getAs<VectorType>()) { uint64_t Size = getContext().getTypeSize(VecTy); - unsigned LargestVector = hasAVX() ? 256 : 128; + unsigned LargestVector = getNativeVectorSizeForAVXABI(AVXLevel); if (Size <= 64 || Size > LargestVector) return true; } @@ -2475,13 +2487,16 @@ GetX86_64ByValArgumentPair(llvm::Type *Lo, llvm::Type *Hi, // of the second element because it might make us access off the end of the // struct. if (HiStart != 8) { - // There are only two sorts of types the ABI generation code can produce for - // the low part of a pair that aren't 8 bytes in size: float or i8/i16/i32. + // There are usually two sorts of types the ABI generation code can produce + // for the low part of a pair that aren't 8 bytes in size: float or + // i8/i16/i32. This can also include pointers when they are 32-bit (X32 and + // NaCl). // Promote these to a larger type. if (Lo->isFloatTy()) Lo = llvm::Type::getDoubleTy(Lo->getContext()); else { - assert(Lo->isIntegerTy() && "Invalid/unknown lo type"); + assert((Lo->isIntegerTy() || Lo->isPointerTy()) + && "Invalid/unknown lo type"); Lo = llvm::Type::getInt64Ty(Lo->getContext()); } } @@ -3145,10 +3160,6 @@ public: bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, llvm::Value *Address) const override; - - unsigned getOpenMPSimdDefaultAlignment(QualType) const override { - return 16; // Natural alignment for Altivec vectors. - } }; } @@ -3388,13 +3399,11 @@ public: }; class PPC64_SVR4_TargetCodeGenInfo : public TargetCodeGenInfo { - bool HasQPX; public: PPC64_SVR4_TargetCodeGenInfo(CodeGenTypes &CGT, PPC64_SVR4_ABIInfo::ABIKind Kind, bool HasQPX) - : TargetCodeGenInfo(new PPC64_SVR4_ABIInfo(CGT, Kind, HasQPX)), - HasQPX(HasQPX) {} + : TargetCodeGenInfo(new PPC64_SVR4_ABIInfo(CGT, Kind, HasQPX)) {} int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override { // This is recovered from gcc output. @@ -3403,15 +3412,6 @@ public: bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, llvm::Value *Address) const override; - - unsigned getOpenMPSimdDefaultAlignment(QualType QT) const override { - if (HasQPX) - if (const PointerType *PT = QT->getAs<PointerType>()) - if (PT->getPointeeType()->isSpecificBuiltinType(BuiltinType::Double)) - return 32; // Natural alignment for QPX doubles. - - return 16; // Natural alignment for Altivec and VSX vectors. - } }; class PPC64TargetCodeGenInfo : public DefaultTargetCodeGenInfo { @@ -3425,10 +3425,6 @@ public: bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, llvm::Value *Address) const override; - - unsigned getOpenMPSimdDefaultAlignment(QualType) const override { - return 16; // Natural alignment for Altivec vectors. - } }; } @@ -7194,13 +7190,21 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() { } case llvm::Triple::x86_64: { + StringRef ABI = getTarget().getABI(); + X86AVXABILevel AVXLevel = (ABI == "avx512" ? X86AVXABILevel::AVX512 : + ABI == "avx" ? X86AVXABILevel::AVX : + X86AVXABILevel::None); + switch (Triple.getOS()) { case llvm::Triple::Win32: - return *(TheTargetCodeGenInfo = new WinX86_64TargetCodeGenInfo(Types)); + return *(TheTargetCodeGenInfo = + new WinX86_64TargetCodeGenInfo(Types, AVXLevel)); case llvm::Triple::PS4: - return *(TheTargetCodeGenInfo = new PS4TargetCodeGenInfo(Types)); + return *(TheTargetCodeGenInfo = + new PS4TargetCodeGenInfo(Types, AVXLevel)); default: - return *(TheTargetCodeGenInfo = new X86_64TargetCodeGenInfo(Types)); + return *(TheTargetCodeGenInfo = + new X86_64TargetCodeGenInfo(Types, AVXLevel)); } } case llvm::Triple::hexagon: diff --git a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.h b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.h index bf63265..95275d5 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.h +++ b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.h @@ -218,13 +218,6 @@ public: virtual void getDetectMismatchOption(llvm::StringRef Name, llvm::StringRef Value, llvm::SmallString<32> &Opt) const {} - - /// Gets the target-specific default alignment used when an 'aligned' clause - /// is used with a 'simd' OpenMP directive without specifying a specific - /// alignment. - virtual unsigned getOpenMPSimdDefaultAlignment(QualType Type) const { - return 0; - } }; } |