summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/CodeGenFunction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/CodeGenFunction.cpp')
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp136
1 files changed, 111 insertions, 25 deletions
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 2939062..1d02861 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -23,12 +23,12 @@
#include "clang/AST/StmtCXX.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/Intrinsics.h"
-#include "llvm/Support/MDBuilder.h"
+#include "llvm/MDBuilder.h"
#include "llvm/Target/TargetData.h"
using namespace clang;
using namespace CodeGen;
-CodeGenFunction::CodeGenFunction(CodeGenModule &cgm)
+CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
: CodeGenTypeCache(cgm), CGM(cgm),
Target(CGM.getContext().getTargetInfo()),
Builder(cgm.getModule().getContext()),
@@ -42,7 +42,8 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm)
TerminateHandler(0), TrapBB(0) {
CatchUndefined = getContext().getLangOpts().CatchUndefined;
- CGM.getCXXABI().getMangleContext().startNewFunction();
+ if (!suppressNewContext)
+ CGM.getCXXABI().getMangleContext().startNewFunction();
}
CodeGenFunction::~CodeGenFunction() {
@@ -251,6 +252,81 @@ void CodeGenFunction::EmitMCountInstrumentation() {
Builder.CreateCall(MCountFn);
}
+// 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,
+ llvm::SmallVector <llvm::Value*, 5> &kernelMDArgs) {
+
+ // Create MDNodes that represents 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 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);
+
+ // 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, argNames));
+}
+
+void CodeGenFunction::EmitOpenCLKernelMetadata(const FunctionDecl *FD,
+ llvm::Function *Fn)
+{
+ if (!FD->hasAttr<OpenCLKernelAttr>())
+ return;
+
+ llvm::LLVMContext &Context = getLLVMContext();
+
+ llvm::SmallVector <llvm::Value*, 5> kernelMDArgs;
+ kernelMDArgs.push_back(Fn);
+
+ if (CGM.getCodeGenOpts().EmitOpenCLArgMetadata)
+ GenOpenCLArgMetadata(FD, Fn, CGM, Context, kernelMDArgs);
+
+ if (FD->hasAttr<WorkGroupSizeHintAttr>()) {
+ llvm::SmallVector <llvm::Value*, 5> attrMDArgs;
+ attrMDArgs.push_back(llvm::MDString::get(Context, "work_group_size_hint"));
+ WorkGroupSizeHintAttr *attr = FD->getAttr<WorkGroupSizeHintAttr>();
+ llvm::Type *iTy = llvm::IntegerType::get(Context, 32);
+ attrMDArgs.push_back(llvm::ConstantInt::get(iTy,
+ llvm::APInt(32, (uint64_t)attr->getXDim())));
+ attrMDArgs.push_back(llvm::ConstantInt::get(iTy,
+ llvm::APInt(32, (uint64_t)attr->getYDim())));
+ attrMDArgs.push_back(llvm::ConstantInt::get(iTy,
+ llvm::APInt(32, (uint64_t)attr->getZDim())));
+ kernelMDArgs.push_back(llvm::MDNode::get(Context, attrMDArgs));
+ }
+
+ if (FD->hasAttr<ReqdWorkGroupSizeAttr>()) {
+ llvm::SmallVector <llvm::Value*, 5> attrMDArgs;
+ attrMDArgs.push_back(llvm::MDString::get(Context, "reqd_work_group_size"));
+ ReqdWorkGroupSizeAttr *attr = FD->getAttr<ReqdWorkGroupSizeAttr>();
+ llvm::Type *iTy = llvm::IntegerType::get(Context, 32);
+ attrMDArgs.push_back(llvm::ConstantInt::get(iTy,
+ llvm::APInt(32, (uint64_t)attr->getXDim())));
+ attrMDArgs.push_back(llvm::ConstantInt::get(iTy,
+ llvm::APInt(32, (uint64_t)attr->getYDim())));
+ attrMDArgs.push_back(llvm::ConstantInt::get(iTy,
+ llvm::APInt(32, (uint64_t)attr->getZDim())));
+ kernelMDArgs.push_back(llvm::MDNode::get(Context, attrMDArgs));
+ }
+
+ llvm::MDNode *kernelMDNode = llvm::MDNode::get(Context, kernelMDArgs);
+ llvm::NamedMDNode *OpenCLKernelMetadata =
+ CGM.getModule().getOrInsertNamedMetadata("opencl.kernels");
+ OpenCLKernelMetadata->addOperand(kernelMDNode);
+}
+
void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
llvm::Function *Fn,
const CGFunctionInfo &FnInfo,
@@ -279,14 +355,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
if (getContext().getLangOpts().OpenCL) {
// Add metadata for a kernel function.
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
- if (FD->hasAttr<OpenCLKernelAttr>()) {
- llvm::LLVMContext &Context = getLLVMContext();
- llvm::NamedMDNode *OpenCLMetadata =
- CGM.getModule().getOrInsertNamedMetadata("opencl.kernels");
-
- llvm::Value *Op = Fn;
- OpenCLMetadata->addOperand(llvm::MDNode::get(Context, Op));
- }
+ EmitOpenCLKernelMetadata(FD, Fn);
}
llvm::BasicBlock *EntryBB = createBasicBlock("entry", CurFn);
@@ -537,7 +606,7 @@ bool CodeGenFunction::containsBreak(const Stmt *S) {
/// constant folds return true and set the boolean result in Result.
bool CodeGenFunction::ConstantFoldsToSimpleInteger(const Expr *Cond,
bool &ResultBool) {
- llvm::APInt ResultInt;
+ llvm::APSInt ResultInt;
if (!ConstantFoldsToSimpleInteger(Cond, ResultInt))
return false;
@@ -549,7 +618,7 @@ bool CodeGenFunction::ConstantFoldsToSimpleInteger(const Expr *Cond,
/// to a constant, or if it does but contains a label, return false. If it
/// constant folds return true and set the folded value.
bool CodeGenFunction::
-ConstantFoldsToSimpleInteger(const Expr *Cond, llvm::APInt &ResultInt) {
+ConstantFoldsToSimpleInteger(const Expr *Cond, llvm::APSInt &ResultInt) {
// FIXME: Rename and handle conversion of other evaluatable things
// to bool.
llvm::APSInt Int;
@@ -687,10 +756,10 @@ void CodeGenFunction::ErrorUnsupported(const Stmt *S, const char *Type,
/// emitNonZeroVLAInit - Emit the "zero" initialization of a
/// variable-length array whose elements have a non-zero bit-pattern.
///
+/// \param baseType the inner-most element type of the array
/// \param src - a char* pointing to the bit-pattern for a single
/// base element of the array
/// \param sizeInChars - the total size of the VLA, in chars
-/// \param align - the total alignment of the VLA
static void emitNonZeroVLAInit(CodeGenFunction &CGF, QualType baseType,
llvm::Value *dest, llvm::Value *src,
llvm::Value *sizeInChars) {
@@ -881,33 +950,49 @@ llvm::Value *CodeGenFunction::emitArrayLength(const ArrayType *origArrayType,
llvm::ConstantInt *zero = Builder.getInt32(0);
gepIndices.push_back(zero);
- // It's more efficient to calculate the count from the LLVM
- // constant-length arrays than to re-evaluate the array bounds.
uint64_t countFromCLAs = 1;
+ QualType eltType;
llvm::ArrayType *llvmArrayType =
- cast<llvm::ArrayType>(
+ dyn_cast<llvm::ArrayType>(
cast<llvm::PointerType>(addr->getType())->getElementType());
- while (true) {
+ while (llvmArrayType) {
assert(isa<ConstantArrayType>(arrayType));
assert(cast<ConstantArrayType>(arrayType)->getSize().getZExtValue()
== llvmArrayType->getNumElements());
gepIndices.push_back(zero);
countFromCLAs *= llvmArrayType->getNumElements();
+ eltType = arrayType->getElementType();
llvmArrayType =
dyn_cast<llvm::ArrayType>(llvmArrayType->getElementType());
- if (!llvmArrayType) break;
-
arrayType = getContext().getAsArrayType(arrayType->getElementType());
- assert(arrayType && "LLVM and Clang types are out-of-synch");
+ assert((!llvmArrayType || arrayType) &&
+ "LLVM and Clang types are out-of-synch");
}
- baseType = arrayType->getElementType();
+ if (arrayType) {
+ // From this point onwards, the Clang array type has been emitted
+ // as some other type (probably a packed struct). Compute the array
+ // size, and just emit the 'begin' expression as a bitcast.
+ while (arrayType) {
+ countFromCLAs *=
+ cast<ConstantArrayType>(arrayType)->getSize().getZExtValue();
+ eltType = arrayType->getElementType();
+ arrayType = getContext().getAsArrayType(eltType);
+ }
+
+ unsigned AddressSpace =
+ cast<llvm::PointerType>(addr->getType())->getAddressSpace();
+ llvm::Type *BaseType = ConvertType(eltType)->getPointerTo(AddressSpace);
+ addr = Builder.CreateBitCast(addr, BaseType, "array.begin");
+ } else {
+ // Create the actual GEP.
+ addr = Builder.CreateInBoundsGEP(addr, gepIndices, "array.begin");
+ }
- // Create the actual GEP.
- addr = Builder.CreateInBoundsGEP(addr, gepIndices, "array.begin");
+ baseType = eltType;
llvm::Value *numElements
= llvm::ConstantInt::get(SizeTy, countFromCLAs);
@@ -1071,7 +1156,8 @@ void CodeGenFunction::EmitDeclRefExprDbgValue(const DeclRefExpr *E,
llvm::Constant *Init) {
assert (Init && "Invalid DeclRefExpr initializer!");
if (CGDebugInfo *Dbg = getDebugInfo())
- Dbg->EmitGlobalVariable(E->getDecl(), Init);
+ if (CGM.getCodeGenOpts().DebugInfo >= CodeGenOptions::LimitedDebugInfo)
+ Dbg->EmitGlobalVariable(E->getDecl(), Init);
}
CodeGenFunction::PeepholeProtection
OpenPOWER on IntegriCloud