From a7aa1ac1cf90739cdfbd1cdd0208f63b40a8207b Mon Sep 17 00:00:00 2001 From: Evghenii Date: Mon, 28 Oct 2013 12:57:09 +0100 Subject: [PATCH] now nvptx allows extern "C" task void, which is emits a kernel that should (?) be callable by driver API from external code --- decl.cpp | 4 +++- func.cpp | 57 ++++++++++++++++++++++++++++++++++++++---------------- module.cpp | 4 +++- type.cpp | 12 ++++++++++-- 4 files changed, 56 insertions(+), 21 deletions(-) diff --git a/decl.cpp b/decl.cpp index 8a10543b..40d7eb72 100644 --- a/decl.cpp +++ b/decl.cpp @@ -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"); diff --git a/func.cpp b/func.cpp index 609e2554..7c041bc8 100644 --- a/func.cpp +++ b/func.cpp @@ -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(structArgType)); const llvm::PointerType *pt = llvm::dyn_cast(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 av; diff --git a/module.cpp b/module.cpp index 41861a2d..bb081656 100644 --- a/module.cpp +++ b/module.cpp @@ -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 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); diff --git a/type.cpp b/type.cpp index 956a0ddd..d1588c99 100644 --- a/type.cpp +++ b/type.cpp @@ -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 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