Commit cc336d6d authored by Martin Kinkelin's avatar Martin Kinkelin

Support generic ldc.attributes.llvmAttr UDAs for function parameters

parent 1fdf3303
......@@ -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);
}
......
......@@ -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,8 +167,10 @@ 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).
for (; dArgIndex < irArg->parametersIdx; ++dArgIndex) {
toElem(argexps[dArgIndex]);
if (irArg->parametersIdx < formalDArgCount) {
for (; dArgIndex < irArg->parametersIdx; ++dArgIndex) {
toElem(argexps[dArgIndex]);
}
}
Expression *const argexp = argexps[dArgIndex];
......
......@@ -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,48 +407,85 @@ 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);
Expressions *attrs = decl->userAttribDecl->getAttributes();
expandTuples(attrs);
for (auto &attr : *attrs) {
auto sle = getLdcAttributesStruct(attr);
if (!sle)
continue;
auto ident = sle->sd->ident;
if (ident == Id::udaAllocSize) {
applyAttrAllocSize(sle, irFunc);
} else if (ident == Id::udaLLVMAttr) {
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) {
applyAttrOptStrategy(sle, irFunc);
} else if (ident == Id::udaSection) {
applyAttrSection(sle, func);
} else if (ident == Id::udaTarget) {
applyAttrTarget(sle, func, irFunc);
} else if (ident == Id::udaAssumeUsed) {
applyAttrAssumeUsed(*gIR, sle, func);
} else if (ident == Id::udaWeak || ident == Id::udaKernel) {
// @weak and @kernel are applied elsewhere
} else if (ident == Id::udaDynamicCompile) {
irFunc->dynamicCompile = true;
} else if (ident == Id::udaDynamicCompileEmit) {
irFunc->dynamicCompileEmit = true;
} else if (ident == Id::udaDynamicCompileConst) {
sle->error(
"Special attribute `ldc.attributes.%s` is only valid for variables",
ident->toChars());
} else {
sle->warning(
"Ignoring unrecognized special attribute `ldc.attributes.%s`",
ident->toChars());
}
}
}
llvm::Function *func = irFunc->getLLVMFunc();
assert(func);
// parameter UDAs
auto parameterList = irFunc->type->parameterList;
for (auto arg : irFunc->irFty.args) {
if (arg->parametersIdx >= parameterList.length())
continue;
Expressions *attrs = decl->userAttribDecl->getAttributes();
expandTuples(attrs);
for (auto &attr : *attrs) {
auto sle = getLdcAttributesStruct(attr);
if (!sle)
auto param =
Parameter::getNth(parameterList.parameters, arg->parametersIdx);
if (!param->userAttribDecl)
continue;
auto ident = sle->sd->ident;
if (ident == Id::udaAllocSize) {
applyAttrAllocSize(sle, irFunc);
} else if (ident == Id::udaLLVMAttr) {
applyAttrLLVMAttr(sle, func);
} else if (ident == Id::udaLLVMFastMathFlag) {
applyAttrLLVMFastMathFlag(sle, irFunc);
} else if (ident == Id::udaOptStrategy) {
applyAttrOptStrategy(sle, irFunc);
} else if (ident == Id::udaSection) {
applyAttrSection(sle, func);
} else if (ident == Id::udaTarget) {
applyAttrTarget(sle, func, irFunc);
} else if (ident == Id::udaAssumeUsed) {
applyAttrAssumeUsed(*gIR, sle, func);
} else if (ident == Id::udaWeak || ident == Id::udaKernel) {
// @weak and @kernel are applied elsewhere
} else if (ident == Id::udaDynamicCompile) {
irFunc->dynamicCompile = true;
} else if (ident == Id::udaDynamicCompileEmit) {
irFunc->dynamicCompileEmit = true;
} else if (ident == Id::udaDynamicCompileConst) {
sle->error(
"Special attribute `ldc.attributes.%s` is only valid for variables",
ident->toChars());
} else {
sle->warning(
"Ignoring unrecognized special attribute `ldc.attributes.%s`",
ident->toChars());
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());
}
}
}
}
......
......@@ -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;
......
// 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) {}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment