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:
4
decl.cpp
4
decl.cpp
@@ -539,12 +539,14 @@ Declarator::InitFromType(const Type *baseType, DeclSpecs *ds) {
|
|||||||
Error(pos, "Function can't have both \"task\" and \"export\" "
|
Error(pos, "Function can't have both \"task\" and \"export\" "
|
||||||
"qualifiers");
|
"qualifiers");
|
||||||
return;
|
return;
|
||||||
}
|
}j
|
||||||
|
#if 0 /* NVPTX64::task_and_externC */
|
||||||
if (isExternC && isTask) {
|
if (isExternC && isTask) {
|
||||||
Error(pos, "Function can't have both \"extern \"C\"\" and \"task\" "
|
Error(pos, "Function can't have both \"extern \"C\"\" and \"task\" "
|
||||||
"qualifiers");
|
"qualifiers");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if (isExternC && isExported) {
|
if (isExternC && isExported) {
|
||||||
Error(pos, "Function can't have both \"extern \"C\"\" and \"export\" "
|
Error(pos, "Function can't have both \"extern \"C\"\" and \"export\" "
|
||||||
"qualifiers");
|
"qualifiers");
|
||||||
|
|||||||
57
func.cpp
57
func.cpp
@@ -186,6 +186,7 @@ lCopyInTaskParameter(int i, llvm::Value *structArgPtr, const
|
|||||||
FunctionEmitContext *ctx) {
|
FunctionEmitContext *ctx) {
|
||||||
// We expect the argument structure to come in as a poitner to a
|
// We expect the argument structure to come in as a poitner to a
|
||||||
// structure. Confirm and figure out its type here.
|
// structure. Confirm and figure out its type here.
|
||||||
|
|
||||||
const llvm::Type *structArgType = structArgPtr->getType();
|
const llvm::Type *structArgType = structArgPtr->getType();
|
||||||
Assert(llvm::isa<llvm::PointerType>(structArgType));
|
Assert(llvm::isa<llvm::PointerType>(structArgType));
|
||||||
const llvm::PointerType *pt = llvm::dyn_cast<const 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
|
// For tasks, we there should always be three parmeters: the
|
||||||
// pointer to the structure that holds all of the arguments, the
|
// pointer to the structure that holds all of the arguments, the
|
||||||
// thread index, and the thread count variables.
|
// 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)
|
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 *threadIndex = argIter++;
|
||||||
llvm::Value *threadCount = argIter++;
|
llvm::Value *threadCount = argIter++;
|
||||||
llvm::Value *taskIndex = argIter++;
|
llvm::Value *taskIndex = argIter++;
|
||||||
@@ -320,6 +321,28 @@ Function::emitCode(FunctionEmitContext *ctx, llvm::Function *function,
|
|||||||
}
|
}
|
||||||
else
|
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 =
|
llvm::NamedMDNode* annotations =
|
||||||
m->module->getOrInsertNamedMetadata("nvvm.annotations");
|
m->module->getOrInsertNamedMetadata("nvvm.annotations");
|
||||||
llvm::SmallVector<llvm::Value*, 3> av;
|
llvm::SmallVector<llvm::Value*, 3> av;
|
||||||
|
|||||||
@@ -733,11 +733,13 @@ Module::AddFunctionDeclaration(const std::string &name,
|
|||||||
if (storageClass == SC_EXTERN_C) {
|
if (storageClass == SC_EXTERN_C) {
|
||||||
// Make sure the user hasn't supplied both an 'extern "C"' and a
|
// Make sure the user hasn't supplied both an 'extern "C"' and a
|
||||||
// 'task' qualifier with the function
|
// 'task' qualifier with the function
|
||||||
|
#if 0 /* NVPTX64::task_and_externC */
|
||||||
if (functionType->isTask) {
|
if (functionType->isTask) {
|
||||||
Error(pos, "\"task\" qualifier is illegal with C-linkage extern "
|
Error(pos, "\"task\" qualifier is illegal with C-linkage extern "
|
||||||
"function \"%s\". Ignoring this function.", name.c_str());
|
"function \"%s\". Ignoring this function.", name.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
std::vector<Symbol *> funcs;
|
std::vector<Symbol *> funcs;
|
||||||
symbolTable->LookupFunction(name.c_str(), &funcs);
|
symbolTable->LookupFunction(name.c_str(), &funcs);
|
||||||
@@ -795,7 +797,7 @@ Module::AddFunctionDeclaration(const std::string &name,
|
|||||||
#else // LLVM 3.1 and 3.3+
|
#else // LLVM 3.1 and 3.3+
|
||||||
function->addFnAttr(llvm::Attribute::AlwaysInline);
|
function->addFnAttr(llvm::Attribute::AlwaysInline);
|
||||||
#endif
|
#endif
|
||||||
if (functionType->isTask)
|
if (functionType->isTask && g->target->getISA() != Target::NVPTX64)
|
||||||
// This also applies transitively to members I think?
|
// This also applies transitively to members I think?
|
||||||
#if defined(LLVM_3_1)
|
#if defined(LLVM_3_1)
|
||||||
function->setDoesNotAlias(1, true);
|
function->setDoesNotAlias(1, true);
|
||||||
|
|||||||
12
type.cpp
12
type.cpp
@@ -2924,8 +2924,11 @@ FunctionType::GetReturnTypeString() const {
|
|||||||
|
|
||||||
llvm::FunctionType *
|
llvm::FunctionType *
|
||||||
FunctionType::LLVMFunctionType(llvm::LLVMContext *ctx, bool removeMask) const {
|
FunctionType::LLVMFunctionType(llvm::LLVMContext *ctx, bool removeMask) const {
|
||||||
|
|
||||||
|
#if 0 /* NVPTX64::task_and_externC */
|
||||||
if (isTask == true)
|
if (isTask == true)
|
||||||
Assert(removeMask == false);
|
Assert(removeMask == false);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Get the LLVM Type *s for the function arguments
|
// Get the LLVM Type *s for the function arguments
|
||||||
std::vector<llvm::Type *> llvmArgTypes;
|
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
|
// threads the tasks system has running. (Task arguments are
|
||||||
// marshalled in a struct so that it's easy to allocate space to
|
// marshalled in a struct so that it's easy to allocate space to
|
||||||
// hold them until the task actually runs.)
|
// 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)
|
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); // threadIndex
|
||||||
callTypes.push_back(LLVMTypes::Int32Type); // threadCount
|
callTypes.push_back(LLVMTypes::Int32Type); // threadCount
|
||||||
callTypes.push_back(LLVMTypes::Int32Type); // taskIndex
|
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); // taskCount1
|
||||||
callTypes.push_back(LLVMTypes::Int32Type); // taskCount2
|
callTypes.push_back(LLVMTypes::Int32Type); // taskCount2
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
callTypes = llvmArgTypes;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
// Otherwise we already have the types of the arguments
|
// Otherwise we already have the types of the arguments
|
||||||
|
|||||||
Reference in New Issue
Block a user