Add @ldc.attributes.llvmAttr.

Partly resolves #1438
This commit is contained in:
Johan Engelen 2016-04-17 18:08:40 +02:00
parent 7657e5f7d8
commit 4b108025ef
3 changed files with 58 additions and 10 deletions

View file

@ -1,6 +1,7 @@
#include "gen/uda.h"
#include "gen/llvm.h"
#include "gen/llvmhelpers.h"
#include "aggregate.h"
#include "attrib.h"
#include "declaration.h"
@ -13,6 +14,7 @@ namespace {
/// Names of the attribute structs we recognize.
namespace attr {
const std::string llvmAttr = "llvmAttr";
const std::string section = "section";
const std::string target = "target";
const std::string weak = "_weak";
@ -62,7 +64,7 @@ StructLiteralExp *getLdcAttributesStruct(Expression *attr) {
return nullptr;
}
void checkStructElems(StructLiteralExp *sle, llvm::ArrayRef<Type *> elemTypes) {
void checkStructElems(StructLiteralExp *sle, ArrayParam<Type *> elemTypes) {
if (sle->elements->dim != elemTypes.size()) {
sle->error(
"unexpected field count in 'ldc.attributes.%s'; does druntime not "
@ -81,12 +83,33 @@ void checkStructElems(StructLiteralExp *sle, llvm::ArrayRef<Type *> elemTypes) {
}
}
const char *getFirstElemString(StructLiteralExp *sle) {
auto arg = (*sle->elements)[0];
assert(arg->op == TOKstring);
const char *getStringElem(StructLiteralExp *sle, size_t idx) {
auto arg = (*sle->elements)[idx];
if (arg && arg->op == TOKstring) {
auto strexp = static_cast<StringExp *>(arg);
assert(strexp->sz == 1);
return strexp->toStringz();
} else {
// Default initialized element (arg->op == TOKnull)
return "";
}
}
const char *getFirstElemString(StructLiteralExp *sle) {
return getStringElem(sle, 0);
}
// @llvmAttr("key", "value")
// @llvmAttr("key")
void applyAttrLLVMAttr(StructLiteralExp *sle, llvm::Function *func) {
checkStructElems(sle, {Type::tstring, Type::tstring});
llvm::StringRef key = getStringElem(sle, 0);
llvm::StringRef value = getStringElem(sle, 1);
if (value.empty()) {
func->addFnAttr(key);
} else {
func->addFnAttr(key, value);
}
}
void applyAttrSection(StructLiteralExp *sle, llvm::GlobalObject *globj) {
@ -200,7 +223,9 @@ void applyFuncDeclUDAs(FuncDeclaration *decl, llvm::Function *func) {
continue;
auto name = sle->sd->ident->string;
if (name == attr::section) {
if (name == attr::llvmAttr) {
applyAttrLLVMAttr(sle, func);
} else if (name == attr::section) {
applyAttrSection(sle, func);
} else if (name == attr::target) {
applyAttrTarget(sle, func);

@ -1 +1 @@
Subproject commit 68d026b0e0968134db632d0aa5975e3e6afbca4f
Subproject commit a785ec2fdd2f597698980700fa3febbdba5f89b2

View file

@ -0,0 +1,23 @@
// Tests @llvmAttr attribute
// RUN: %ldc -c -output-ll -of=%t.ll %s && FileCheck %s < %t.ll
import ldc.attributes;
extern (C): // For easier name mangling
// CHECK: define{{.*}} @keyvalue{{.*}} #[[KEYVALUE:[0-9]+]]
@(llvmAttr("key", "value"))
void keyvalue()
{
}
// CHECK: define{{.*}} @keyonly{{.*}} #[[KEYONLY:[0-9]+]]
@(llvmAttr("keyonly"))
void keyonly()
{
}
// CHECK-DAG: attributes #[[KEYVALUE]] = {{.*}} "key"="value"
// CHECK-NOT: attributes #[[KEYONLY]] = {{.*}} "keyonly"=
// CHECK-DAG: attributes #[[KEYONLY]] = {{.*}} "keyonly"