Support generic ldc.attributes.llvmAttr UDAs for function parameters

This commit is contained in:
Martin Kinkelin 2019-03-31 19:25:20 +02:00
parent 1fdf330346
commit cc336d6df1
5 changed files with 96 additions and 51 deletions

View file

@ -603,6 +603,11 @@ void DtoDeclareFunction(FuncDeclaration *fdecl) {
// add func to IRFunc
irFunc->setLLVMFunc(func);
// First apply the TargetMachine attributes, such that they can be overridden
// by UDAs.
applyTargetMachineAttributes(*func, *gTargetMachine);
applyFuncDeclUDAs(fdecl, irFunc);
// parameter attributes
if (!DtoIsIntrinsic(fdecl)) {
applyParamAttrsToLLFunc(f, getIrFunc(fdecl)->irFty, func);
@ -611,11 +616,6 @@ void DtoDeclareFunction(FuncDeclaration *fdecl) {
}
}
// First apply the TargetMachine attributes, such that they can be overridden
// by UDAs.
applyTargetMachineAttributes(*func, *gTargetMachine);
applyFuncDeclUDAs(fdecl, irFunc);
if(irFunc->isDynamicCompiled()) {
declareDynamicCompiledFunction(gIR, irFunc);
}

View file

@ -121,7 +121,7 @@ static void addExplicitArguments(std::vector<LLValue *> &args, AttrSet &attrs,
const size_t formalLLArgCount = irFty.args.size();
// Number of formal arguments in the D call expression (excluding varargs).
const int formalDArgCount = Parameter::dim(formalParams);
const size_t formalDArgCount = Parameter::dim(formalParams);
// The number of explicit arguments in the D call expression (including
// varargs), not all of which necessarily generate a LLVM argument.
@ -167,9 +167,11 @@ static void addExplicitArguments(std::vector<LLValue *> &args, AttrSet &attrs,
// Make sure to evaluate argument expressions for which there's no LL
// parameter (e.g., empty structs for some ABIs).
if (irArg->parametersIdx < formalDArgCount) {
for (; dArgIndex < irArg->parametersIdx; ++dArgIndex) {
toElem(argexps[dArgIndex]);
}
}
Expression *const argexp = argexps[dArgIndex];
Parameter *const formalParam =

View file

@ -207,19 +207,19 @@ void applyAttrAllocSize(StructLiteralExp *sle, IrFunction *irFunc) {
// @llvmAttr("key", "value")
// @llvmAttr("key")
void applyAttrLLVMAttr(StructLiteralExp *sle, llvm::Function *func) {
void applyAttrLLVMAttr(StructLiteralExp *sle, llvm::AttrBuilder &attrs) {
checkStructElems(sle, {Type::tstring, Type::tstring});
llvm::StringRef key = getStringElem(sle, 0);
llvm::StringRef value = getStringElem(sle, 1);
if (value.empty()) {
const auto kind = llvm::getAttrKindFromName(key);
if (kind != llvm::Attribute::None) {
func->addFnAttr(kind);
attrs.addAttribute(kind);
} else {
func->addFnAttr(key);
attrs.addAttribute(key);
}
} else {
func->addFnAttr(key, value);
attrs.addAttribute(key, value);
}
}
@ -407,9 +407,8 @@ void applyVarDeclUDAs(VarDeclaration *decl, llvm::GlobalVariable *gvar) {
}
void applyFuncDeclUDAs(FuncDeclaration *decl, IrFunction *irFunc) {
if (!decl->userAttribDecl)
return;
// function UDAs
if (decl->userAttribDecl) {
llvm::Function *func = irFunc->getLLVMFunc();
assert(func);
@ -424,7 +423,15 @@ void applyFuncDeclUDAs(FuncDeclaration *decl, IrFunction *irFunc) {
if (ident == Id::udaAllocSize) {
applyAttrAllocSize(sle, irFunc);
} else if (ident == Id::udaLLVMAttr) {
applyAttrLLVMAttr(sle, func);
llvm::AttrBuilder attrs;
applyAttrLLVMAttr(sle, attrs);
#if LDC_LLVM_VER >= 500
func->addAttributes(LLAttributeSet::FunctionIndex, attrs);
#else
AttrSet attrSet;
attrSet.addToFunction(attrs);
func->addAttributes(LLAttributeSet::FunctionIndex, attrSet);
#endif
} else if (ident == Id::udaLLVMFastMathFlag) {
applyAttrLLVMFastMathFlag(sle, irFunc);
} else if (ident == Id::udaOptStrategy) {
@ -453,6 +460,36 @@ void applyFuncDeclUDAs(FuncDeclaration *decl, IrFunction *irFunc) {
}
}
// parameter UDAs
auto parameterList = irFunc->type->parameterList;
for (auto arg : irFunc->irFty.args) {
if (arg->parametersIdx >= parameterList.length())
continue;
auto param =
Parameter::getNth(parameterList.parameters, arg->parametersIdx);
if (!param->userAttribDecl)
continue;
Expressions *attrs = param->userAttribDecl->getAttributes();
expandTuples(attrs);
for (auto &attr : *attrs) {
auto sle = getLdcAttributesStruct(attr);
if (!sle)
continue;
auto ident = sle->sd->ident;
if (ident == Id::udaLLVMAttr) {
applyAttrLLVMAttr(sle, arg->attrs);
} else {
sle->warning("Ignoring unrecognized special parameter attribute "
"`ldc.attributes.%s`",
ident->toChars());
}
}
}
}
/// Checks whether 'sym' has the @ldc.attributes._weak() UDA applied.
bool hasWeakUDA(Dsymbol *sym) {
auto sle = getMagicAttribute(sym, Id::udaWeak, Id::attributes);

View file

@ -46,7 +46,7 @@ struct IrFuncTyArg {
/// The index of the declaration in the FuncDeclaration::parameters array
/// corresponding to this argument.
size_t parametersIdx = 0;
size_t parametersIdx = -1;
/// This is the final LLVM Type used for the parameter/return value type
llvm::Type *ltype = nullptr;

View file

@ -0,0 +1,6 @@
// RUN: %ldc -output-ll -of=%t.ll %s && FileCheck %s < %t.ll
import ldc.attributes;
// CHECK: define{{.*}} @{{.*}}3foo{{.*}}(i8* noalias %p_arg)
void foo(@llvmAttr("noalias") void* p) {}