diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp index 684fda7440731..35ce3cf1bc81a 100644 --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -2841,7 +2841,10 @@ llvm::FunctionCallee CodeGenModule::getBlockObjectDispose() { llvm::Type *args[] = { Int8PtrTy, Int32Ty }; llvm::FunctionType *fty = llvm::FunctionType::get(VoidTy, args, false); - BlockObjectDispose = CreateRuntimeFunction(fty, "_Block_object_dispose"); + llvm::AttributeList AL = + getTargetExtAttrs({AttrKind::None, AttrKind::None, AttrKind::SExt}); + BlockObjectDispose = CreateRuntimeFunction(fty, "_Block_object_dispose", AL); + // FIXME: Correct signedness of extension?? configureBlocksRuntimeObject( *this, cast(BlockObjectDispose.getCallee())); return BlockObjectDispose; @@ -2854,7 +2857,9 @@ llvm::FunctionCallee CodeGenModule::getBlockObjectAssign() { llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, Int32Ty }; llvm::FunctionType *fty = llvm::FunctionType::get(VoidTy, args, false); - BlockObjectAssign = CreateRuntimeFunction(fty, "_Block_object_assign"); + llvm::AttributeList AL = getTargetExtAttrs( + {AttrKind::None, AttrKind::None, AttrKind::None, AttrKind::SExt}); + BlockObjectAssign = CreateRuntimeFunction(fty, "_Block_object_assign", AL); configureBlocksRuntimeObject( *this, cast(BlockObjectAssign.getCallee())); return BlockObjectAssign; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 25c1c496a4f27..a7e4ce3ba4f7d 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -4755,6 +4755,15 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction( llvm::AttrBuilder B(F->getContext(), ExtraAttrs.getFnAttrs()); F->addFnAttrs(B); } + if (ExtraAttrs.hasRetAttrs()) { + llvm::AttrBuilder B(F->getContext(), ExtraAttrs.getRetAttrs()); + F->addRetAttrs(B); + } + for (unsigned i = 0; i < F->arg_size(); ++i) + if (ExtraAttrs.hasParamAttrs(i)) { + llvm::AttrBuilder B(F->getContext(), ExtraAttrs.getParamAttrs(i)); + F->addParamAttrs(i, B); + } if (!DontDefer) { // All MSVC dtors other than the base dtor are linkonce_odr and delegate to @@ -4938,6 +4947,40 @@ CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy, StringRef Name, return {FTy, C}; } +llvm::AttributeList +CodeGenModule::getTargetExtAttrs(ArrayRef Extensions) { + using AttrIndex = llvm::AttributeList::AttrIndex; + assert(Extensions.size() && "Empty array not expected."); + const auto &T = getTarget().getTriple(); + llvm::AttributeList AL; + + bool IsSigned; + auto isExtension = [&IsSigned](AttrKind AK) -> bool { + assert((AK == AttrKind::None || AK == AttrKind::SExt || + AK == AttrKind::ZExt) && + "Unhandled extension attribute."); + if (AK != AttrKind::SExt && AK != AttrKind::ZExt) + return false; + IsSigned = (AK == AttrKind::SExt); + return true; + }; + + if (isExtension(Extensions[0])) { // Returned value at index 0. + AttrKind AK = llvm::TargetLibraryInfo::getExtAttrForI32Return(T, IsSigned); + if (AK != AttrKind::None) + AL = AL.addAttributeAtIndex(getLLVMContext(), AttrIndex::ReturnIndex, AK); + } + for (unsigned i = 1; i < Extensions.size(); ++i) + if (isExtension(Extensions[i])) { + AttrKind AK = llvm::TargetLibraryInfo::getExtAttrForI32Param(T, IsSigned); + if (AK != AttrKind::None) + AL = AL.addAttributeAtIndex(getLLVMContext(), + AttrIndex::FirstArgIndex + i - 1, AK); + } + + return AL; +} + /// GetOrCreateLLVMGlobal - If the specified mangled name is not in the module, /// create and return an llvm GlobalVariable with the specified type and address /// space. If there is something in the module with the specified name, return diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index c58bb88035ca8..4f0f0c4546e1a 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -1252,6 +1252,12 @@ class CodeGenModule : public CodeGenTypeCache { llvm::AttributeList ExtraAttrs = llvm::AttributeList(), bool Local = false, bool AssumeConvergent = false); + /// Return the extension attributes as an AttributeList after any needed + /// adjustments for target. The \Param Extensions list begins with the + /// return value and then continues with the arguments. + using AttrKind = llvm::Attribute::AttrKind; + llvm::AttributeList getTargetExtAttrs(ArrayRef Extensions); + /// Create a new runtime global variable with the specified type and name. llvm::Constant *CreateRuntimeVariable(llvm::Type *Ty, StringRef Name);