now nvptx allows extern "C" task void, which is emits a kernel that should (?) be callable by driver API from external code

This commit is contained in:
Evghenii
2013-10-28 12:57:09 +01:00
parent ae23320417
commit a7aa1ac1cf
4 changed files with 56 additions and 21 deletions

View File

@@ -539,12 +539,14 @@ Declarator::InitFromType(const Type *baseType, DeclSpecs *ds) {
Error(pos, "Function can't have both \"task\" and \"export\" "
"qualifiers");
return;
}
}j
#if 0 /* NVPTX64::task_and_externC */
if (isExternC && isTask) {
Error(pos, "Function can't have both \"extern \"C\"\" and \"task\" "
"qualifiers");
return;
}
#endif
if (isExternC && isExported) {
Error(pos, "Function can't have both \"extern \"C\"\" and \"export\" "
"qualifiers");

View File

@@ -186,6 +186,7 @@ lCopyInTaskParameter(int i, llvm::Value *structArgPtr, const
FunctionEmitContext *ctx) {
// We expect the argument structure to come in as a poitner to a
// structure. Confirm and figure out its type here.
const llvm::Type *structArgType = structArgPtr->getType();
Assert(llvm::isa<llvm::PointerType>(structArgType));
const llvm::PointerType *pt = llvm::dyn_cast<const llvm::PointerType>(structArgType);
@@ -240,26 +241,26 @@ Function::emitCode(FunctionEmitContext *ctx, llvm::Function *function,
// For tasks, we there should always be three parmeters: the
// pointer to the structure that holds all of the arguments, the
// thread index, and the thread count variables.
llvm::Function::arg_iterator argIter = function->arg_begin();
llvm::Value *structParamPtr = argIter++;
// Copy the function parameter values from the structure into local
// storage
for (unsigned int i = 0; i < args.size(); ++i)
lCopyInTaskParameter(i, structParamPtr, args, ctx);
if (type->isUnmasked == false) {
// Copy in the mask as well.
int nArgs = (int)args.size();
// The mask is the last parameter in the argument structure
llvm::Value *ptr = ctx->AddElementOffset(structParamPtr, nArgs, NULL,
"task_struct_mask");
llvm::Value *ptrval = ctx->LoadInst(ptr, "mask");
ctx->SetFunctionMask(ptrval);
}
if (g->target->getISA() != Target::NVPTX64)
{
llvm::Function::arg_iterator argIter = function->arg_begin();
llvm::Value *structParamPtr = argIter++;
// Copy the function parameter values from the structure into local
// storage
for (unsigned int i = 0; i < args.size(); ++i)
lCopyInTaskParameter(i, structParamPtr, args, ctx);
if (type->isUnmasked == false) {
// Copy in the mask as well.
int nArgs = (int)args.size();
// The mask is the last parameter in the argument structure
llvm::Value *ptr = ctx->AddElementOffset(structParamPtr, nArgs, NULL,
"task_struct_mask");
llvm::Value *ptrval = ctx->LoadInst(ptr, "mask");
ctx->SetFunctionMask(ptrval);
}
llvm::Value *threadIndex = argIter++;
llvm::Value *threadCount = argIter++;
llvm::Value *taskIndex = argIter++;
@@ -320,6 +321,28 @@ Function::emitCode(FunctionEmitContext *ctx, llvm::Function *function,
}
else
{
llvm::Function::arg_iterator argIter = function->arg_begin();
for (unsigned int i = 0; i < args.size(); ++i, ++argIter) {
Symbol *sym = args[i];
if (sym == NULL)
// anonymous function parameter
continue;
argIter->setName(sym->name.c_str());
// Allocate stack storage for the parameter and emit code
// to store the its value there.
sym->storagePtr = ctx->AllocaInst(argIter->getType(), sym->name.c_str());
ctx->StoreInst(argIter, sym->storagePtr);
ctx->EmitFunctionParameterDebugInfo(sym, i);
}
if (argIter == function->arg_end()) {
Assert(type->isUnmasked || type->isExported);
ctx->SetFunctionMask(LLVMMaskAllOn);
}
else
assert(0);
llvm::NamedMDNode* annotations =
m->module->getOrInsertNamedMetadata("nvvm.annotations");
llvm::SmallVector<llvm::Value*, 3> av;

View File

@@ -733,11 +733,13 @@ Module::AddFunctionDeclaration(const std::string &name,
if (storageClass == SC_EXTERN_C) {
// Make sure the user hasn't supplied both an 'extern "C"' and a
// 'task' qualifier with the function
#if 0 /* NVPTX64::task_and_externC */
if (functionType->isTask) {
Error(pos, "\"task\" qualifier is illegal with C-linkage extern "
"function \"%s\". Ignoring this function.", name.c_str());
return;
}
#endif
std::vector<Symbol *> funcs;
symbolTable->LookupFunction(name.c_str(), &funcs);
@@ -795,7 +797,7 @@ Module::AddFunctionDeclaration(const std::string &name,
#else // LLVM 3.1 and 3.3+
function->addFnAttr(llvm::Attribute::AlwaysInline);
#endif
if (functionType->isTask)
if (functionType->isTask && g->target->getISA() != Target::NVPTX64)
// This also applies transitively to members I think?
#if defined(LLVM_3_1)
function->setDoesNotAlias(1, true);

View File

@@ -2924,8 +2924,11 @@ FunctionType::GetReturnTypeString() const {
llvm::FunctionType *
FunctionType::LLVMFunctionType(llvm::LLVMContext *ctx, bool removeMask) const {
#if 0 /* NVPTX64::task_and_externC */
if (isTask == true)
Assert(removeMask == false);
#endif
// Get the LLVM Type *s for the function arguments
std::vector<llvm::Type *> llvmArgTypes;
@@ -2955,10 +2958,10 @@ FunctionType::LLVMFunctionType(llvm::LLVMContext *ctx, bool removeMask) const {
// threads the tasks system has running. (Task arguments are
// marshalled in a struct so that it's easy to allocate space to
// hold them until the task actually runs.)
llvm::Type *st = llvm::StructType::get(*ctx, llvmArgTypes);
callTypes.push_back(llvm::PointerType::getUnqual(st));
if (g->target->getISA() != Target::NVPTX64)
{
llvm::Type *st = llvm::StructType::get(*ctx, llvmArgTypes);
callTypes.push_back(llvm::PointerType::getUnqual(st));
callTypes.push_back(LLVMTypes::Int32Type); // threadIndex
callTypes.push_back(LLVMTypes::Int32Type); // threadCount
callTypes.push_back(LLVMTypes::Int32Type); // taskIndex
@@ -2970,6 +2973,11 @@ FunctionType::LLVMFunctionType(llvm::LLVMContext *ctx, bool removeMask) const {
callTypes.push_back(LLVMTypes::Int32Type); // taskCount1
callTypes.push_back(LLVMTypes::Int32Type); // taskCount2
}
else
{
callTypes = llvmArgTypes;
}
}
else
// Otherwise we already have the types of the arguments