Generate metadata to implement the -cl-kernel-arg-info option.

OpenCL 1.2 spec. 5.7.3.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@177839 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Guy Benyei 2013-03-24 13:58:12 +00:00
Родитель e8b87f9086
Коммит 1db7040604
4 изменённых файлов: 134 добавлений и 12 удалений

Просмотреть файл

@ -333,7 +333,6 @@ def OpenCLKernel : Attr {
def OpenCLImageAccess : Attr {
let Spellings = [GNU<"opencl_image_access">];
let Args = [IntArgument<"Access">];
let ASTNode = 0;
}
def Deprecated : InheritableAttr {

Просмотреть файл

@ -20,6 +20,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/StmtCXX.h"
#include "clang/Basic/OpenCL.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/IR/DataLayout.h"
@ -285,27 +286,117 @@ void CodeGenFunction::EmitMCountInstrumentation() {
// OpenCL v1.2 s5.6.4.6 allows the compiler to store kernel argument
// information in the program executable. The argument information stored
// includes the argument name, its type, the address and access qualifiers used.
// FIXME: Add type, address, and access qualifiers.
static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn,
CodeGenModule &CGM,llvm::LLVMContext &Context,
SmallVector <llvm::Value*, 5> &kernelMDArgs) {
// Create MDNodes that represents the kernel arg metadata.
SmallVector <llvm::Value*, 5> &kernelMDArgs,
CGBuilderTy& Builder, ASTContext &ASTCtx) {
// Create MDNodes that represent the kernel arg metadata.
// Each MDNode is a list in the form of "key", N number of values which is
// the same number of values as their are kernel arguments.
// MDNode for the kernel argument address space qualifiers.
SmallVector<llvm::Value*, 8> addressQuals;
addressQuals.push_back(llvm::MDString::get(Context, "kernel_arg_addr_space"));
// MDNode for the kernel argument access qualifiers (images only).
SmallVector<llvm::Value*, 8> accessQuals;
accessQuals.push_back(llvm::MDString::get(Context, "kernel_arg_access_qual"));
// MDNode for the kernel argument type names.
SmallVector<llvm::Value*, 8> argTypeNames;
argTypeNames.push_back(llvm::MDString::get(Context, "kernel_arg_type"));
// MDNode for the kernel argument type qualifiers.
SmallVector<llvm::Value*, 8> argTypeQuals;
argTypeQuals.push_back(llvm::MDString::get(Context, "kernel_arg_type_qual"));
// MDNode for the kernel argument names.
SmallVector<llvm::Value*, 8> argNames;
argNames.push_back(llvm::MDString::get(Context, "kernel_arg_name"));
for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
const ParmVarDecl *parm = FD->getParamDecl(i);
QualType ty = parm->getType();
std::string typeQuals;
if (ty->isPointerType()) {
QualType pointeeTy = ty->getPointeeType();
// Get address qualifier.
addressQuals.push_back(Builder.getInt32(ASTCtx.getTargetAddressSpace(
pointeeTy.getAddressSpace())));
// Get argument type name.
std::string typeName = pointeeTy.getUnqualifiedType().getAsString() + "*";
// Turn "unsigned type" to "utype"
std::string::size_type pos = typeName.find("unsigned");
if(pos != std::string::npos) {
typeName = typeName.substr(0, pos+1) +
typeName.substr(pos+9, typeName.size());
}
argTypeNames.push_back(llvm::MDString::get(Context, typeName));
// Get argument type qualifiers:
if (ty.isRestrictQualified())
typeQuals = "restrict";
if (pointeeTy.isConstQualified() ||
(pointeeTy.getAddressSpace() == LangAS::opencl_constant))
if (typeQuals != "")
typeQuals += " const";
else
typeQuals += "const";
if (pointeeTy.isVolatileQualified())
if (typeQuals != "")
typeQuals += " volatile";
else
typeQuals += "volatile";
} else {
addressQuals.push_back(Builder.getInt32(0));
// Get argument type name.
std::string typeName = ty.getUnqualifiedType().getAsString();
// Turn "unsigned type" to "utype"
std::string::size_type pos = typeName.find("unsigned");
if(pos != std::string::npos) {
typeName = typeName.substr(0, pos+1) +
typeName.substr(pos+9, typeName.size());
}
argTypeNames.push_back(llvm::MDString::get(Context, typeName));
// Get argument type qualifiers:
if (ty.isConstQualified())
typeQuals = "const";
if (ty.isVolatileQualified())
if (typeQuals != "")
typeQuals += " volatile";
else
typeQuals += "volatile";
}
argTypeQuals.push_back(llvm::MDString::get(Context, typeQuals));
// Get image access qualifier:
if (ty->isImageType()) {
if (parm->hasAttr<OpenCLImageAccessAttr>() &&
parm->getAttr<OpenCLImageAccessAttr>()->getAccess() == CLIA_write_only)
accessQuals.push_back(llvm::MDString::get(Context, "write_only"));
else
accessQuals.push_back(llvm::MDString::get(Context, "read_only"));
} else
accessQuals.push_back(llvm::MDString::get(Context, "none"));
// Get argument name.
argNames.push_back(llvm::MDString::get(Context, parm->getName()));
}
// Add MDNode to the list of all metadata.
kernelMDArgs.push_back(llvm::MDNode::get(Context, addressQuals));
kernelMDArgs.push_back(llvm::MDNode::get(Context, accessQuals));
kernelMDArgs.push_back(llvm::MDNode::get(Context, argTypeNames));
kernelMDArgs.push_back(llvm::MDNode::get(Context, argTypeQuals));
kernelMDArgs.push_back(llvm::MDNode::get(Context, argNames));
}
@ -321,7 +412,8 @@ void CodeGenFunction::EmitOpenCLKernelMetadata(const FunctionDecl *FD,
kernelMDArgs.push_back(Fn);
if (CGM.getCodeGenOpts().EmitOpenCLArgMetadata)
GenOpenCLArgMetadata(FD, Fn, CGM, Context, kernelMDArgs);
GenOpenCLArgMetadata(FD, Fn, CGM, Context, kernelMDArgs,
Builder, getContext());
if (FD->hasAttr<VecTypeHintAttr>()) {
VecTypeHintAttr *attr = FD->getAttr<VecTypeHintAttr>();

Просмотреть файл

@ -3997,6 +3997,22 @@ static void handleOpenCLKernelAttr(Sema &S, Decl *D, const AttributeList &Attr){
D->addAttr(::new (S.Context) OpenCLKernelAttr(Attr.getRange(), S.Context));
}
static void handleOpenCLImageAccessAttr(Sema &S, Decl *D, const AttributeList &Attr){
assert(!Attr.isInvalid());
Expr *E = Attr.getArg(0);
llvm::APSInt ArgNum(32);
if (E->isTypeDependent() || E->isValueDependent() ||
!E->isIntegerConstantExpr(ArgNum, S.Context)) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
<< Attr.getName()->getName() << E->getSourceRange();
return;
}
D->addAttr(::new (S.Context) OpenCLImageAccessAttr(
Attr.getRange(), S.Context, ArgNum.getZExtValue()));
}
bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,
const FunctionDecl *FD) {
if (attr.isInvalid())
@ -4687,7 +4703,6 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_IBOutletCollection:
handleIBOutletCollection(S, D, Attr); break;
case AttributeList::AT_AddressSpace:
case AttributeList::AT_OpenCLImageAccess:
case AttributeList::AT_ObjCGC:
case AttributeList::AT_VectorSize:
case AttributeList::AT_NeonVectorType:
@ -4866,6 +4881,9 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_OpenCLKernel:
handleOpenCLKernelAttr(S, D, Attr);
break;
case AttributeList::AT_OpenCLImageAccess:
handleOpenCLImageAccessAttr(S, D, Attr);
break;
// Microsoft attributes:
case AttributeList::AT_MsStruct:

Просмотреть файл

@ -1,7 +1,20 @@
// RUN: %clang_cc1 %s -cl-kernel-arg-info -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 %s -cl-kernel-arg-info -emit-llvm -o - -triple spir-unknown-unknown | FileCheck %s
kernel void foo(global int *X, int Y, int anotherArg) {
kernel void foo(__global int * restrict X, const int Y,
volatile int anotherArg, __constant float * restrict Z) {
*X = Y + anotherArg;
}
// CHECK: metadata !{metadata !"kernel_arg_name", metadata !"X", metadata !"Y", metadata !"anotherArg"}
// CHECK: metadata !{metadata !"kernel_arg_addr_space", i32 1, i32 0, i32 0, i32 2}
// CHECK: metadata !{metadata !"kernel_arg_access_qual", metadata !"none", metadata !"none", metadata !"none", metadata !"none"}
// CHECK: metadata !{metadata !"kernel_arg_type", metadata !"int*", metadata !"int", metadata !"int", metadata !"float*"}
// CHECK: metadata !{metadata !"kernel_arg_type_qual", metadata !"restrict", metadata !"const", metadata !"volatile", metadata !"restrict const"}
// CHECK: metadata !{metadata !"kernel_arg_name", metadata !"X", metadata !"Y", metadata !"anotherArg", metadata !"Z"}
kernel void foo2(read_only image1d_t img1, image2d_t img2, write_only image2d_array_t img3) {
}
// CHECK: metadata !{metadata !"kernel_arg_addr_space", i32 0, i32 0, i32 0}
// CHECK: metadata !{metadata !"kernel_arg_access_qual", metadata !"read_only", metadata !"read_only", metadata !"write_only"}
// CHECK: metadata !{metadata !"kernel_arg_type", metadata !"image1d_t", metadata !"image2d_t", metadata !"image2d_array_t"}
// CHECK: metadata !{metadata !"kernel_arg_type_qual", metadata !"", metadata !"", metadata !""}
// CHECK: metadata !{metadata !"kernel_arg_name", metadata !"img1", metadata !"img2", metadata !"img3"}