Add support for 'unmasked' function qualifier.

This commit is contained in:
Matt Pharr
2012-06-20 15:36:00 -07:00
parent 46716aada3
commit 007a734595
9 changed files with 91 additions and 53 deletions

21
ctx.cpp
View File

@@ -3235,11 +3235,9 @@ FunctionEmitContext::CallInst(llvm::Value *func, const FunctionType *funcType,
SetInternalMask(callMask); SetInternalMask(callMask);
// bitcast the i32/64 function pointer to the actual function // bitcast the i32/64 function pointer to the actual function
// pointer type (the variant that includes a mask). // pointer type.
llvm::Type *llvmFuncType = llvm::Type *llvmFuncType = funcType->LLVMFunctionType(g->ctx);
funcType->LLVMFunctionType(g->ctx, true); llvm::Type *llvmFPtrType = llvm::PointerType::get(llvmFuncType, 0);
llvm::Type *llvmFPtrType =
llvm::PointerType::get(llvmFuncType, 0);
llvm::Value *fptrCast = IntToPtrInst(fptr, llvmFPtrType); llvm::Value *fptrCast = IntToPtrInst(fptr, llvmFPtrType);
// Call the function: callResult = call ftpr(args, args, call mask) // Call the function: callResult = call ftpr(args, args, call mask)
@@ -3344,7 +3342,6 @@ FunctionEmitContext::LaunchInst(llvm::Value *callee,
AssertPos(currentPos, llvm::StructType::classof(pt->getElementType())); AssertPos(currentPos, llvm::StructType::classof(pt->getElementType()));
llvm::StructType *argStructType = llvm::StructType *argStructType =
static_cast<llvm::StructType *>(pt->getElementType()); static_cast<llvm::StructType *>(pt->getElementType());
AssertPos(currentPos, argStructType->getNumElements() == argVals.size() + 1);
llvm::Function *falloc = m->module->getFunction("ISPCAlloc"); llvm::Function *falloc = m->module->getFunction("ISPCAlloc");
AssertPos(currentPos, falloc != NULL); AssertPos(currentPos, falloc != NULL);
@@ -3371,11 +3368,13 @@ FunctionEmitContext::LaunchInst(llvm::Value *callee,
StoreInst(argVals[i], ptr); StoreInst(argVals[i], ptr);
} }
// copy in the mask if (argStructType->getNumElements() == argVals.size() + 1) {
llvm::Value *mask = GetFullMask(); // copy in the mask
llvm::Value *ptr = AddElementOffset(argmem, argVals.size(), NULL, llvm::Value *mask = GetFullMask();
"funarg_mask"); llvm::Value *ptr = AddElementOffset(argmem, argVals.size(), NULL,
StoreInst(mask, ptr); "funarg_mask");
StoreInst(mask, ptr);
}
// And emit the call to the user-supplied task launch function, passing // And emit the call to the user-supplied task launch function, passing
// a pointer to the task function being called and a pointer to the // a pointer to the task function being called and a pointer to the

View File

@@ -57,6 +57,7 @@ lPrintTypeQualifiers(int typeQualifiers) {
if (typeQualifiers & TYPEQUAL_SIGNED) printf("signed "); if (typeQualifiers & TYPEQUAL_SIGNED) printf("signed ");
if (typeQualifiers & TYPEQUAL_UNSIGNED) printf("unsigned "); if (typeQualifiers & TYPEQUAL_UNSIGNED) printf("unsigned ");
if (typeQualifiers & TYPEQUAL_EXPORT) printf("export "); if (typeQualifiers & TYPEQUAL_EXPORT) printf("export ");
if (typeQualifiers & TYPEQUAL_UNMASKED) printf("unmasked ");
} }
@@ -296,6 +297,7 @@ Declarator::InitFromType(const Type *baseType, DeclSpecs *ds) {
bool isTask = ((typeQualifiers & TYPEQUAL_TASK) != 0); bool isTask = ((typeQualifiers & TYPEQUAL_TASK) != 0);
bool isExported = ((typeQualifiers & TYPEQUAL_EXPORT) != 0); bool isExported = ((typeQualifiers & TYPEQUAL_EXPORT) != 0);
bool isConst = ((typeQualifiers & TYPEQUAL_CONST) != 0); bool isConst = ((typeQualifiers & TYPEQUAL_CONST) != 0);
bool isUnmasked = ((typeQualifiers & TYPEQUAL_UNMASKED) != 0);
if (hasUniformQual && hasVaryingQual) { if (hasUniformQual && hasVaryingQual) {
Error(pos, "Can't provide both \"uniform\" and \"varying\" qualifiers."); Error(pos, "Can't provide both \"uniform\" and \"varying\" qualifiers.");
@@ -305,6 +307,10 @@ Declarator::InitFromType(const Type *baseType, DeclSpecs *ds) {
Error(pos, "\"task\" qualifier illegal in variable declaration."); Error(pos, "\"task\" qualifier illegal in variable declaration.");
return; return;
} }
if (kind != DK_FUNCTION && isUnmasked) {
Error(pos, "\"unmasked\" qualifier illegal in variable declaration.");
return;
}
if (kind != DK_FUNCTION && isExported) { if (kind != DK_FUNCTION && isExported) {
Error(pos, "\"export\" qualifier illegal in variable declaration."); Error(pos, "\"export\" qualifier illegal in variable declaration.");
return; return;
@@ -507,6 +513,7 @@ Declarator::InitFromType(const Type *baseType, DeclSpecs *ds) {
bool isExternC = ds && (ds->storageClass == SC_EXTERN_C); bool isExternC = ds && (ds->storageClass == SC_EXTERN_C);
bool isExported = ds && ((ds->typeQualifiers & TYPEQUAL_EXPORT) != 0); bool isExported = ds && ((ds->typeQualifiers & TYPEQUAL_EXPORT) != 0);
bool isTask = ds && ((ds->typeQualifiers & TYPEQUAL_TASK) != 0); bool isTask = ds && ((ds->typeQualifiers & TYPEQUAL_TASK) != 0);
bool isUnmasked = ds && ((ds->typeQualifiers & TYPEQUAL_UNMASKED) != 0);
if (isExported && isTask) { if (isExported && isTask) {
Error(pos, "Function can't have both \"task\" and \"export\" " Error(pos, "Function can't have both \"task\" and \"export\" "
@@ -523,6 +530,9 @@ Declarator::InitFromType(const Type *baseType, DeclSpecs *ds) {
"qualifiers"); "qualifiers");
return; return;
} }
if (isUnmasked && isExported)
Warning(pos, "\"unmasked\" qualifier is redundant for exported "
"functions.");
if (child == NULL) { if (child == NULL) {
AssertPos(pos, m->errorCount > 0); AssertPos(pos, m->errorCount > 0);
@@ -531,7 +541,7 @@ Declarator::InitFromType(const Type *baseType, DeclSpecs *ds) {
const FunctionType *functionType = const FunctionType *functionType =
new FunctionType(returnType, args, argNames, argDefaults, new FunctionType(returnType, args, argNames, argDefaults,
argPos, isTask, isExported, isExternC); argPos, isTask, isExported, isExternC, isUnmasked);
// handle any explicit __declspecs on the function // handle any explicit __declspecs on the function
if (ds != NULL) { if (ds != NULL) {

1
decl.h
View File

@@ -74,6 +74,7 @@ class Declarator;
#define TYPEQUAL_UNSIGNED (1<<5) #define TYPEQUAL_UNSIGNED (1<<5)
#define TYPEQUAL_INLINE (1<<6) #define TYPEQUAL_INLINE (1<<6)
#define TYPEQUAL_EXPORT (1<<7) #define TYPEQUAL_EXPORT (1<<7)
#define TYPEQUAL_UNMASKED (1<<8)
/** @brief Representation of the declaration specifiers in a declaration. /** @brief Representation of the declaration specifiers in a declaration.

View File

@@ -223,13 +223,15 @@ Function::emitCode(FunctionEmitContext *ctx, llvm::Function *function,
for (unsigned int i = 0; i < args.size(); ++i) for (unsigned int i = 0; i < args.size(); ++i)
lCopyInTaskParameter(i, structParamPtr, args, ctx); lCopyInTaskParameter(i, structParamPtr, args, ctx);
// Copy in the mask as well. if (type->isUnmasked == false) {
int nArgs = (int)args.size(); // Copy in the mask as well.
// The mask is the last parameter in the argument structure int nArgs = (int)args.size();
llvm::Value *ptr = ctx->AddElementOffset(structParamPtr, nArgs, NULL, // The mask is the last parameter in the argument structure
"task_struct_mask"); llvm::Value *ptr = ctx->AddElementOffset(structParamPtr, nArgs, NULL,
llvm::Value *ptrval = ctx->LoadInst(ptr, "mask"); "task_struct_mask");
ctx->SetFunctionMask(ptrval); llvm::Value *ptrval = ctx->LoadInst(ptr, "mask");
ctx->SetFunctionMask(ptrval);
}
// Copy threadIndex and threadCount into stack-allocated storage so // Copy threadIndex and threadCount into stack-allocated storage so
// that their symbols point to something reasonable. // that their symbols point to something reasonable.
@@ -270,9 +272,13 @@ Function::emitCode(FunctionEmitContext *ctx, llvm::Function *function,
// don't have a mask parameter, so set it to be all on. This // don't have a mask parameter, so set it to be all on. This
// happens for exmaple with 'export'ed functions that the app // happens for exmaple with 'export'ed functions that the app
// calls. // calls.
if (argIter == function->arg_end()) if (argIter == function->arg_end()) {
Assert(type->isUnmasked || type->isExported);
ctx->SetFunctionMask(LLVMMaskAllOn); ctx->SetFunctionMask(LLVMMaskAllOn);
}
else { else {
Assert(type->isUnmasked == false);
// Otherwise use the mask to set the entry mask value // Otherwise use the mask to set the entry mask value
argIter->setName("__mask"); argIter->setName("__mask");
Assert(argIter->getType() == LLVMTypes::MaskType); Assert(argIter->getType() == LLVMTypes::MaskType);
@@ -297,6 +303,7 @@ Function::emitCode(FunctionEmitContext *ctx, llvm::Function *function,
bool checkMask = (type->isTask == true) || bool checkMask = (type->isTask == true) ||
((function->hasFnAttr(llvm::Attribute::AlwaysInline) == false) && ((function->hasFnAttr(llvm::Attribute::AlwaysInline) == false) &&
costEstimate > CHECK_MASK_AT_FUNCTION_START_COST); costEstimate > CHECK_MASK_AT_FUNCTION_START_COST);
checkMask &= (type->isUnmasked == false);
checkMask &= (g->target.maskingIsFree == false); checkMask &= (g->target.maskingIsFree == false);
checkMask &= (g->opt.disableCoherentControlFlow == false); checkMask &= (g->opt.disableCoherentControlFlow == false);
@@ -423,8 +430,7 @@ Function::GenerateIR() {
Assert(type != NULL); Assert(type != NULL);
if (type->isExported) { if (type->isExported) {
if (!type->isTask) { if (!type->isTask) {
llvm::FunctionType *ftype = llvm::FunctionType *ftype = type->LLVMFunctionType(g->ctx, true);
type->LLVMFunctionType(g->ctx);
llvm::GlobalValue::LinkageTypes linkage = llvm::GlobalValue::ExternalLinkage; llvm::GlobalValue::LinkageTypes linkage = llvm::GlobalValue::ExternalLinkage;
std::string functionName = sym->name; std::string functionName = sym->name;
if (g->mangleFunctionsWithTarget) if (g->mangleFunctionsWithTarget)

9
lex.ll
View File

@@ -71,9 +71,9 @@ static int allTokens[] = {
TOKEN_INT, TOKEN_INT8, TOKEN_INT16, TOKEN_INT, TOKEN_INT64, TOKEN_LAUNCH, TOKEN_INT, TOKEN_INT8, TOKEN_INT16, TOKEN_INT, TOKEN_INT64, TOKEN_LAUNCH,
TOKEN_NEW, TOKEN_NULL, TOKEN_PRINT, TOKEN_RETURN, TOKEN_SOA, TOKEN_SIGNED, TOKEN_NEW, TOKEN_NULL, TOKEN_PRINT, TOKEN_RETURN, TOKEN_SOA, TOKEN_SIGNED,
TOKEN_SIZEOF, TOKEN_STATIC, TOKEN_STRUCT, TOKEN_SWITCH, TOKEN_SYNC, TOKEN_SIZEOF, TOKEN_STATIC, TOKEN_STRUCT, TOKEN_SWITCH, TOKEN_SYNC,
TOKEN_TASK, TOKEN_TRUE, TOKEN_TYPEDEF, TOKEN_UNIFORM, TOKEN_UNSIGNED, TOKEN_TASK, TOKEN_TRUE, TOKEN_TYPEDEF, TOKEN_UNIFORM, TOKEN_UNMASKED,
TOKEN_VARYING, TOKEN_VOID, TOKEN_WHILE, TOKEN_STRING_C_LITERAL, TOKEN_UNSIGNED, TOKEN_VARYING, TOKEN_VOID, TOKEN_WHILE,
TOKEN_DOTDOTDOT, TOKEN_STRING_C_LITERAL, TOKEN_DOTDOTDOT,
TOKEN_FLOAT_CONSTANT, TOKEN_FLOAT_CONSTANT,
TOKEN_INT32_CONSTANT, TOKEN_UINT32_CONSTANT, TOKEN_INT32_CONSTANT, TOKEN_UINT32_CONSTANT,
TOKEN_INT64_CONSTANT, TOKEN_UINT64_CONSTANT, TOKEN_INT64_CONSTANT, TOKEN_UINT64_CONSTANT,
@@ -142,6 +142,7 @@ void ParserInit() {
tokenToName[TOKEN_TRUE] = "true"; tokenToName[TOKEN_TRUE] = "true";
tokenToName[TOKEN_TYPEDEF] = "typedef"; tokenToName[TOKEN_TYPEDEF] = "typedef";
tokenToName[TOKEN_UNIFORM] = "uniform"; tokenToName[TOKEN_UNIFORM] = "uniform";
tokenToName[TOKEN_UNMASKED] = "unmasked";
tokenToName[TOKEN_UNSIGNED] = "unsigned"; tokenToName[TOKEN_UNSIGNED] = "unsigned";
tokenToName[TOKEN_VARYING] = "varying"; tokenToName[TOKEN_VARYING] = "varying";
tokenToName[TOKEN_VOID] = "void"; tokenToName[TOKEN_VOID] = "void";
@@ -253,6 +254,7 @@ void ParserInit() {
tokenNameRemap["TOKEN_TRUE"] = "\'true\'"; tokenNameRemap["TOKEN_TRUE"] = "\'true\'";
tokenNameRemap["TOKEN_TYPEDEF"] = "\'typedef\'"; tokenNameRemap["TOKEN_TYPEDEF"] = "\'typedef\'";
tokenNameRemap["TOKEN_UNIFORM"] = "\'uniform\'"; tokenNameRemap["TOKEN_UNIFORM"] = "\'uniform\'";
tokenNameRemap["TOKEN_UNMASKED"] = "\'unmasked\'";
tokenNameRemap["TOKEN_UNSIGNED"] = "\'unsigned\'"; tokenNameRemap["TOKEN_UNSIGNED"] = "\'unsigned\'";
tokenNameRemap["TOKEN_VARYING"] = "\'varying\'"; tokenNameRemap["TOKEN_VARYING"] = "\'varying\'";
tokenNameRemap["TOKEN_VOID"] = "\'void\'"; tokenNameRemap["TOKEN_VOID"] = "\'void\'";
@@ -396,6 +398,7 @@ task { RT; return TOKEN_TASK; }
true { RT; return TOKEN_TRUE; } true { RT; return TOKEN_TRUE; }
typedef { RT; return TOKEN_TYPEDEF; } typedef { RT; return TOKEN_TYPEDEF; }
uniform { RT; return TOKEN_UNIFORM; } uniform { RT; return TOKEN_UNIFORM; }
unmasked { RT; return TOKEN_UNMASKED; }
unsigned { RT; return TOKEN_UNSIGNED; } unsigned { RT; return TOKEN_UNSIGNED; }
varying { RT; return TOKEN_VARYING; } varying { RT; return TOKEN_VARYING; }
void { RT; return TOKEN_VOID; } void { RT; return TOKEN_VOID; }

View File

@@ -707,9 +707,9 @@ Module::AddFunctionDeclaration(const std::string &name,
} }
// Get the LLVM FunctionType // Get the LLVM FunctionType
bool includeMask = (storageClass != SC_EXTERN_C); bool disableMask = (storageClass == SC_EXTERN_C);
llvm::FunctionType *llvmFunctionType = llvm::FunctionType *llvmFunctionType =
functionType->LLVMFunctionType(g->ctx, includeMask); functionType->LLVMFunctionType(g->ctx, disableMask);
if (llvmFunctionType == NULL) if (llvmFunctionType == NULL)
return; return;

View File

@@ -121,8 +121,8 @@ static const char *lBuiltinTokens[] = {
"goto", "if", "in", "inline", "goto", "if", "in", "inline",
"int", "int8", "int16", "int32", "int64", "launch", "new", "NULL", "int", "int8", "int16", "int32", "int64", "launch", "new", "NULL",
"print", "return", "signed", "sizeof", "static", "struct", "switch", "print", "return", "signed", "sizeof", "static", "struct", "switch",
"sync", "task", "true", "typedef", "uniform", "unsigned", "varying", "sync", "task", "true", "typedef", "uniform", "unmasked", "unsigned",
"void", "while", NULL "varying", "void", "while", NULL
}; };
static const char *lParamListTokens[] = { static const char *lParamListTokens[] = {
@@ -189,7 +189,7 @@ struct ForeachDimension {
%token TOKEN_SIZEOF TOKEN_NEW TOKEN_DELETE TOKEN_IN %token TOKEN_SIZEOF TOKEN_NEW TOKEN_DELETE TOKEN_IN
%token TOKEN_EXTERN TOKEN_EXPORT TOKEN_STATIC TOKEN_INLINE TOKEN_TASK TOKEN_DECLSPEC %token TOKEN_EXTERN TOKEN_EXPORT TOKEN_STATIC TOKEN_INLINE TOKEN_TASK TOKEN_DECLSPEC
%token TOKEN_UNIFORM TOKEN_VARYING TOKEN_TYPEDEF TOKEN_SOA %token TOKEN_UNIFORM TOKEN_VARYING TOKEN_TYPEDEF TOKEN_SOA TOKEN_UNMASKED
%token TOKEN_CHAR TOKEN_INT TOKEN_SIGNED TOKEN_UNSIGNED TOKEN_FLOAT TOKEN_DOUBLE %token TOKEN_CHAR TOKEN_INT TOKEN_SIGNED TOKEN_UNSIGNED TOKEN_FLOAT TOKEN_DOUBLE
%token TOKEN_INT8 TOKEN_INT16 TOKEN_INT64 TOKEN_CONST TOKEN_VOID TOKEN_BOOL %token TOKEN_INT8 TOKEN_INT16 TOKEN_INT64 TOKEN_CONST TOKEN_VOID TOKEN_BOOL
%token TOKEN_ENUM TOKEN_STRUCT TOKEN_TRUE TOKEN_FALSE %token TOKEN_ENUM TOKEN_STRUCT TOKEN_TRUE TOKEN_FALSE
@@ -1011,6 +1011,11 @@ specifier_qualifier_list
"function declarations."); "function declarations.");
$$ = $2; $$ = $2;
} }
else if ($1 == TYPEQUAL_UNMASKED) {
Error(@1, "\"unmasked\" qualifier is illegal outside of "
"function declarations.");
$$ = $2;
}
else if ($1 == TYPEQUAL_EXPORT) { else if ($1 == TYPEQUAL_EXPORT) {
Error(@1, "\"export\" qualifier is illegal outside of " Error(@1, "\"export\" qualifier is illegal outside of "
"function declarations."); "function declarations.");
@@ -1148,6 +1153,7 @@ type_qualifier
| TOKEN_UNIFORM { $$ = TYPEQUAL_UNIFORM; } | TOKEN_UNIFORM { $$ = TYPEQUAL_UNIFORM; }
| TOKEN_VARYING { $$ = TYPEQUAL_VARYING; } | TOKEN_VARYING { $$ = TYPEQUAL_VARYING; }
| TOKEN_TASK { $$ = TYPEQUAL_TASK; } | TOKEN_TASK { $$ = TYPEQUAL_TASK; }
| TOKEN_UNMASKED { $$ = TYPEQUAL_UNMASKED; }
| TOKEN_EXPORT { $$ = TYPEQUAL_EXPORT; } | TOKEN_EXPORT { $$ = TYPEQUAL_EXPORT; }
| TOKEN_INLINE { $$ = TYPEQUAL_INLINE; } | TOKEN_INLINE { $$ = TYPEQUAL_INLINE; }
| TOKEN_SIGNED { $$ = TYPEQUAL_SIGNED; } | TOKEN_SIGNED { $$ = TYPEQUAL_SIGNED; }

View File

@@ -1131,10 +1131,7 @@ PointerType::LLVMType(llvm::LLVMContext *ctx) const {
llvm::Type *ptype = NULL; llvm::Type *ptype = NULL;
const FunctionType *ftype = CastType<FunctionType>(baseType); const FunctionType *ftype = CastType<FunctionType>(baseType);
if (ftype != NULL) if (ftype != NULL)
// Get the type of the function variant that takes the mask as the ptype = llvm::PointerType::get(ftype->LLVMFunctionType(ctx), 0);
// last parameter--i.e. we don't allow taking function pointers of
// exported functions.
ptype = llvm::PointerType::get(ftype->LLVMFunctionType(ctx, true), 0);
else { else {
if (baseType == AtomicType::Void) if (baseType == AtomicType::Void)
ptype = LLVMTypes::VoidPointerType; ptype = LLVMTypes::VoidPointerType;
@@ -2625,10 +2622,12 @@ ReferenceType::GetDIType(llvm::DIDescriptor scope) const {
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// FunctionType // FunctionType
FunctionType::FunctionType(const Type *r, const llvm::SmallVector<const Type *, 8> &a, FunctionType::FunctionType(const Type *r,
const llvm::SmallVector<const Type *, 8> &a,
SourcePos p) SourcePos p)
: Type(FUNCTION_TYPE), isTask(false), isExported(false), isExternC(false), : Type(FUNCTION_TYPE), isTask(false), isExported(false), isExternC(false),
returnType(r), paramTypes(a), paramNames(llvm::SmallVector<std::string, 8>(a.size(), "")), isUnmasked(false), returnType(r), paramTypes(a),
paramNames(llvm::SmallVector<std::string, 8>(a.size(), "")),
paramDefaults(llvm::SmallVector<Expr *, 8>(a.size(), NULL)), paramDefaults(llvm::SmallVector<Expr *, 8>(a.size(), NULL)),
paramPositions(llvm::SmallVector<SourcePos, 8>(a.size(), p)) { paramPositions(llvm::SmallVector<SourcePos, 8>(a.size(), p)) {
Assert(returnType != NULL); Assert(returnType != NULL);
@@ -2637,13 +2636,15 @@ FunctionType::FunctionType(const Type *r, const llvm::SmallVector<const Type *,
} }
FunctionType::FunctionType(const Type *r, const llvm::SmallVector<const Type *, 8> &a, FunctionType::FunctionType(const Type *r,
const llvm::SmallVector<const Type *, 8> &a,
const llvm::SmallVector<std::string, 8> &an, const llvm::SmallVector<std::string, 8> &an,
const llvm::SmallVector<Expr *, 8> &ad, const llvm::SmallVector<Expr *, 8> &ad,
const llvm::SmallVector<SourcePos, 8> &ap, const llvm::SmallVector<SourcePos, 8> &ap,
bool it, bool is, bool ec) bool it, bool is, bool ec, bool ium)
: Type(FUNCTION_TYPE), isTask(it), isExported(is), isExternC(ec), returnType(r), : Type(FUNCTION_TYPE), isTask(it), isExported(is), isExternC(ec),
paramTypes(a), paramNames(an), paramDefaults(ad), paramPositions(ap) { isUnmasked(ium), returnType(r), paramTypes(a), paramNames(an),
paramDefaults(ad), paramPositions(ap) {
Assert(paramTypes.size() == paramNames.size() && Assert(paramTypes.size() == paramNames.size() &&
paramNames.size() == paramDefaults.size() && paramNames.size() == paramDefaults.size() &&
paramDefaults.size() == paramPositions.size()); paramDefaults.size() == paramPositions.size());
@@ -2743,7 +2744,7 @@ FunctionType::ResolveUnboundVariability(Variability v) const {
FunctionType *ret = new FunctionType(rt, pt, paramNames, paramDefaults, FunctionType *ret = new FunctionType(rt, pt, paramNames, paramDefaults,
paramPositions, isTask, isExported, paramPositions, isTask, isExported,
isExternC); isExternC, isUnmasked);
ret->isSafe = isSafe; ret->isSafe = isSafe;
ret->costOverride = costOverride; ret->costOverride = costOverride;
@@ -2784,6 +2785,9 @@ FunctionType::GetString() const {
std::string std::string
FunctionType::Mangle() const { FunctionType::Mangle() const {
std::string ret = "___"; std::string ret = "___";
if (isUnmasked)
ret += "UM_";
for (unsigned int i = 0; i < paramTypes.size(); ++i) for (unsigned int i = 0; i < paramTypes.size(); ++i)
if (paramTypes[i] == NULL) if (paramTypes[i] == NULL)
Assert(m->errorCount > 0); Assert(m->errorCount > 0);
@@ -2865,6 +2869,8 @@ FunctionType::GetReturnTypeString() const {
ret += "export "; ret += "export ";
if (isExternC) if (isExternC)
ret += "extern \"C\" "; ret += "extern \"C\" ";
if (isUnmasked)
ret += "unmasked ";
if (isSafe) if (isSafe)
ret += "/*safe*/ "; ret += "/*safe*/ ";
if (costOverride > 0) { if (costOverride > 0) {
@@ -2872,14 +2878,15 @@ FunctionType::GetReturnTypeString() const {
sprintf(buf, "/*cost=%d*/ ", costOverride); sprintf(buf, "/*cost=%d*/ ", costOverride);
ret += buf; ret += buf;
} }
return ret + returnType->GetString(); return ret + returnType->GetString();
} }
llvm::FunctionType * llvm::FunctionType *
FunctionType::LLVMFunctionType(llvm::LLVMContext *ctx, bool includeMask) const { FunctionType::LLVMFunctionType(llvm::LLVMContext *ctx, bool removeMask) const {
if (isTask == true) if (isTask == true)
Assert(includeMask == true); Assert(removeMask == false);
// 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;
@@ -2899,7 +2906,7 @@ FunctionType::LLVMFunctionType(llvm::LLVMContext *ctx, bool includeMask) const {
} }
// And add the function mask, if asked for // And add the function mask, if asked for
if (includeMask) if (!(removeMask || isUnmasked))
llvmArgTypes.push_back(LLVMTypes::MaskType); llvmArgTypes.push_back(LLVMTypes::MaskType);
std::vector<llvm::Type *> callTypes; std::vector<llvm::Type *> callTypes;
@@ -3263,7 +3270,8 @@ lCheckTypeEquality(const Type *a, const Type *b, bool ignoreConst) {
if (fta->isTask != ftb->isTask || if (fta->isTask != ftb->isTask ||
fta->isExported != ftb->isExported || fta->isExported != ftb->isExported ||
fta->isExternC != ftb->isExternC) fta->isExternC != ftb->isExternC ||
fta->isUnmasked != ftb->isUnmasked)
return false; return false;
if (fta->GetNumParameters() != ftb->GetNumParameters()) if (fta->GetNumParameters() != ftb->GetNumParameters())

15
type.h
View File

@@ -841,7 +841,7 @@ public:
const llvm::SmallVector<std::string, 8> &argNames, const llvm::SmallVector<std::string, 8> &argNames,
const llvm::SmallVector<Expr *, 8> &argDefaults, const llvm::SmallVector<Expr *, 8> &argDefaults,
const llvm::SmallVector<SourcePos, 8> &argPos, const llvm::SmallVector<SourcePos, 8> &argPos,
bool isTask, bool isExported, bool isExternC); bool isTask, bool isExported, bool isExternC, bool isUnmasked);
Variability GetVariability() const; Variability GetVariability() const;
@@ -873,11 +873,11 @@ public:
const std::string GetReturnTypeString() const; const std::string GetReturnTypeString() const;
/** This method returns the LLVM FunctionType that corresponds to this /** This method returns the LLVM FunctionType that corresponds to this
function type. The \c includeMask parameter indicates whether the function type. The \c disableMask parameter indicates whether the
llvm::FunctionType should have a mask as the last argument in its llvm::FunctionType should have the trailing mask parameter, if
function signature. */ present, removed from the return function signature. */
llvm::FunctionType *LLVMFunctionType(llvm::LLVMContext *ctx, llvm::FunctionType *LLVMFunctionType(llvm::LLVMContext *ctx,
bool includeMask = false) const; bool disableMask = false) const;
int GetNumParameters() const { return (int)paramTypes.size(); } int GetNumParameters() const { return (int)paramTypes.size(); }
const Type *GetParameterType(int i) const; const Type *GetParameterType(int i) const;
@@ -897,6 +897,11 @@ public:
function in the source program. */ function in the source program. */
const bool isExternC; const bool isExternC;
/** Indicates whether the function doesn't take an implicit mask
parameter (and thus should start execution with an "all on"
mask). */
const bool isUnmasked;
/** Indicates whether this function has been declared to be safe to run /** Indicates whether this function has been declared to be safe to run
with an all-off mask. */ with an all-off mask. */
bool isSafe; bool isSafe;