diff --git a/lex.ll b/lex.ll index 2dd38a36..df4761a6 100644 --- a/lex.ll +++ b/lex.ll @@ -63,31 +63,28 @@ inline int isatty(int) { return 0; } #endif // ISPC_IS_WINDOWS static int allTokens[] = { - TOKEN_ASSERT, TOKEN_BOOL, TOKEN_BREAK, TOKEN_CASE, - TOKEN_CDO, TOKEN_CFOR, TOKEN_CIF, TOKEN_CWHILE, - TOKEN_CONST, TOKEN_CONTINUE, TOKEN_DEFAULT, TOKEN_DO, - TOKEN_DELETE, TOKEN_DOUBLE, TOKEN_ELSE, TOKEN_ENUM, - TOKEN_EXPORT, TOKEN_EXTERN, TOKEN_FALSE, TOKEN_FLOAT, TOKEN_FOR, + TOKEN_ASSERT, TOKEN_BOOL, TOKEN_BREAK, TOKEN_CASE, TOKEN_CDO, TOKEN_CFOR, + TOKEN_CIF, TOKEN_CWHILE, TOKEN_CONST, TOKEN_CONTINUE, TOKEN_DEFAULT, TOKEN_DO, + TOKEN_DELETE, TOKEN_DOUBLE, TOKEN_ELSE, TOKEN_ENUM, TOKEN_EXPORT, + TOKEN_EXTERN, TOKEN_FALSE, TOKEN_FLOAT, TOKEN_FLOATING, TOKEN_FOR, TOKEN_FOREACH, TOKEN_FOREACH_ACTIVE, TOKEN_FOREACH_TILED, - TOKEN_FOREACH_UNIQUE, TOKEN_GOTO, TOKEN_IF, TOKEN_IN, TOKEN_INLINE, - 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_SIZEOF, TOKEN_STATIC, TOKEN_STRUCT, TOKEN_SWITCH, TOKEN_SYNC, - TOKEN_TASK, TOKEN_TRUE, TOKEN_TYPEDEF, TOKEN_UNIFORM, TOKEN_UNMASKED, - TOKEN_UNSIGNED, TOKEN_VARYING, TOKEN_VOID, TOKEN_WHILE, - TOKEN_STRING_C_LITERAL, TOKEN_DOTDOTDOT, - TOKEN_FLOAT_CONSTANT, TOKEN_DOUBLE_CONSTANT, - TOKEN_INT8_CONSTANT, TOKEN_UINT8_CONSTANT, - TOKEN_INT16_CONSTANT, TOKEN_UINT16_CONSTANT, - TOKEN_INT32_CONSTANT, TOKEN_UINT32_CONSTANT, - TOKEN_INT64_CONSTANT, TOKEN_UINT64_CONSTANT, + TOKEN_FOREACH_UNIQUE, TOKEN_GOTO, TOKEN_IF, TOKEN_IN, TOKEN_INLINE, TOKEN_INT, + TOKEN_INT8, TOKEN_INT16, TOKEN_INT, TOKEN_INT64, TOKEN_INTEGER, TOKEN_LAUNCH, + TOKEN_NEW, TOKEN_NULL, TOKEN_NUMBER, TOKEN_PRINT, TOKEN_RETURN, TOKEN_SOA, + TOKEN_SIGNED, TOKEN_SIZEOF, TOKEN_STATIC, TOKEN_STRUCT, TOKEN_SWITCH, + TOKEN_SYNC, TOKEN_TASK, TOKEN_TRUE, TOKEN_TYPEDEF, TOKEN_UNIFORM, + TOKEN_UNMASKED, TOKEN_UNSIGNED, TOKEN_VARYING, TOKEN_VOID, TOKEN_WHILE, + TOKEN_STRING_C_LITERAL, TOKEN_DOTDOTDOT, TOKEN_FLOAT_CONSTANT, + TOKEN_DOUBLE_CONSTANT, TOKEN_INT8_CONSTANT, TOKEN_UINT8_CONSTANT, + TOKEN_INT16_CONSTANT, TOKEN_UINT16_CONSTANT, TOKEN_INT32_CONSTANT, + TOKEN_UINT32_CONSTANT, TOKEN_INT64_CONSTANT, TOKEN_UINT64_CONSTANT, TOKEN_INC_OP, TOKEN_DEC_OP, TOKEN_LEFT_OP, TOKEN_RIGHT_OP, TOKEN_LE_OP, TOKEN_GE_OP, TOKEN_EQ_OP, TOKEN_NE_OP, TOKEN_AND_OP, TOKEN_OR_OP, TOKEN_MUL_ASSIGN, TOKEN_DIV_ASSIGN, TOKEN_MOD_ASSIGN, TOKEN_ADD_ASSIGN, TOKEN_SUB_ASSIGN, TOKEN_LEFT_ASSIGN, TOKEN_RIGHT_ASSIGN, TOKEN_AND_ASSIGN, TOKEN_XOR_ASSIGN, TOKEN_OR_ASSIGN, TOKEN_PTR_OP, ';', '{', '}', ',', ':', '=', '(', ')', '[', ']', '.', '&', '!', '~', '-', - '+', '*', '/', '%', '<', '>', '^', '|', '?', + '+', '*', '/', '%', '<', '>', '^', '|', '?', '$' }; std::map tokenToName; @@ -114,6 +111,7 @@ void ParserInit() { tokenToName[TOKEN_EXTERN] = "extern"; tokenToName[TOKEN_FALSE] = "false"; tokenToName[TOKEN_FLOAT] = "float"; + tokenToName[TOKEN_FLOATING] = "floating"; tokenToName[TOKEN_FOR] = "for"; tokenToName[TOKEN_FOREACH] = "foreach"; tokenToName[TOKEN_FOREACH_ACTIVE] = "foreach_active"; @@ -127,10 +125,12 @@ void ParserInit() { tokenToName[TOKEN_INT8] = "int8"; tokenToName[TOKEN_INT16] = "int16"; tokenToName[TOKEN_INT] = "int"; + tokenToName[TOKEN_INTEGER] = "integer"; tokenToName[TOKEN_INT64] = "int64"; tokenToName[TOKEN_LAUNCH] = "launch"; tokenToName[TOKEN_NEW] = "new"; tokenToName[TOKEN_NULL] = "NULL"; + tokenToName[TOKEN_NUMBER] = "number"; tokenToName[TOKEN_PRINT] = "print"; tokenToName[TOKEN_RETURN] = "return"; tokenToName[TOKEN_SOA] = "soa"; @@ -207,6 +207,7 @@ void ParserInit() { tokenToName['|'] = "|"; tokenToName['?'] = "?"; tokenToName[';'] = ";"; + tokenToName['$'] = "$"; tokenNameRemap["TOKEN_ASSERT"] = "\'assert\'"; tokenNameRemap["TOKEN_BOOL"] = "\'bool\'"; @@ -228,6 +229,7 @@ void ParserInit() { tokenNameRemap["TOKEN_EXTERN"] = "\'extern\'"; tokenNameRemap["TOKEN_FALSE"] = "\'false\'"; tokenNameRemap["TOKEN_FLOAT"] = "\'float\'"; + tokenNameRemap["TOKEN_FLOATING"] = "\'floating\'"; tokenNameRemap["TOKEN_FOR"] = "\'for\'"; tokenNameRemap["TOKEN_FOREACH"] = "\'foreach\'"; tokenNameRemap["TOKEN_FOREACH_ACTIVE"] = "\'foreach_active\'"; @@ -243,9 +245,11 @@ void ParserInit() { tokenNameRemap["TOKEN_INT16"] = "\'int16\'"; tokenNameRemap["TOKEN_INT"] = "\'int\'"; tokenNameRemap["TOKEN_INT64"] = "\'int64\'"; + tokenNameRemap["TOKEN_INTEGER"] = "\'integer\'"; tokenNameRemap["TOKEN_LAUNCH"] = "\'launch\'"; tokenNameRemap["TOKEN_NEW"] = "\'new\'"; tokenNameRemap["TOKEN_NULL"] = "\'NULL\'"; + tokenNameRemap["TOKEN_NUMBER"] = "\'number\'"; tokenNameRemap["TOKEN_PRINT"] = "\'print\'"; tokenNameRemap["TOKEN_RETURN"] = "\'return\'"; tokenNameRemap["TOKEN_SOA"] = "\'soa\'"; @@ -381,6 +385,7 @@ export { RT; return TOKEN_EXPORT; } extern { RT; return TOKEN_EXTERN; } false { RT; return TOKEN_FALSE; } float { RT; return TOKEN_FLOAT; } +floating { RT; return TOKEN_FLOATING; } for { RT; return TOKEN_FOR; } foreach { RT; return TOKEN_FOREACH; } foreach_active { RT; return TOKEN_FOREACH_ACTIVE; } @@ -395,9 +400,11 @@ int8 { RT; return TOKEN_INT8; } int16 { RT; return TOKEN_INT16; } int32 { RT; return TOKEN_INT; } int64 { RT; return TOKEN_INT64; } +integer { RT; return TOKEN_INTEGER; } launch { RT; return TOKEN_LAUNCH; } new { RT; return TOKEN_NEW; } NULL { RT; return TOKEN_NULL; } +number { RT; return TOKEN_NUMBER; } print { RT; return TOKEN_PRINT; } return { RT; return TOKEN_RETURN; } soa { RT; return TOKEN_SOA; } @@ -521,6 +528,7 @@ L?\"(\\.|[^\\"])*\" { lStringConst(&yylval, &yylloc); return TOKEN_STRING_LITERA "^" { RT; return '^'; } "|" { RT; return '|'; } "?" { RT; return '?'; } +"$" { RT; return '$'; } {WHITESPACE} { } diff --git a/parse.yy b/parse.yy index a5a95851..f1cf6f14 100644 --- a/parse.yy +++ b/parse.yy @@ -118,21 +118,20 @@ static void lFinalizeEnumeratorSymbols(std::vector &enums, const EnumType *enumType); static const char *lBuiltinTokens[] = { - "assert", "bool", "break", "case", "cdo", - "cfor", "cif", "cwhile", "const", "continue", "default", - "do", "delete", "double", "else", "enum", "export", "extern", "false", - "float", "for", "foreach", "foreach_active", "foreach_tiled", - "foreach_unique", "goto", "if", "in", "inline", - "int", "int8", "int16", "int32", "int64", "launch", "new", "NULL", - "print", "return", "signed", "sizeof", "static", "struct", "switch", - "sync", "task", "true", "typedef", "uniform", "unmasked", "unsigned", - "varying", "void", "while", NULL + "assert", "bool", "break", "case", "cdo", "cfor", "cif", "cwhile", "const", + "continue", "default", "do", "delete", "double", "else", "enum", "export", + "extern", "false", "float", "floating", "for", "foreach", "foreach_active", + "foreach_tiled", "foreach_unique", "goto", "if", "in", "inline", "int", + "int8", "int16", "int32", "int64", "integer", "launch", "new", "NULL", + "number", "print", "return", "signed", "sizeof", "static", "struct", + "switch", "sync", "task", "true", "typedef", "uniform", "unmasked", + "unsigned", "varying", "void", "while", NULL }; static const char *lParamListTokens[] = { - "bool", "const", "double", "enum", "false", "float", "int", - "int8", "int16", "int32", "int64", "signed", "struct", "true", - "uniform", "unsigned", "varying", "void", NULL + "bool", "const", "double", "enum", "false", "float", "floating", "int", + "int8", "int16", "int32", "int64", "integer", "number", "signed", "struct", + "true", "uniform", "unsigned", "varying", "void", NULL }; struct ForeachDimension { @@ -159,6 +158,7 @@ struct ForeachDimension { const Type *type; std::vector > *typeList; const AtomicType *atomicType; + const PolyType *polyType; int typeQualifier; StorageClass storageClass; Stmt *stmt; @@ -198,6 +198,7 @@ struct ForeachDimension { %token TOKEN_EXTERN TOKEN_EXPORT TOKEN_STATIC TOKEN_INLINE TOKEN_TASK TOKEN_DECLSPEC %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_INTEGER TOKEN_FLOATING TOKEN_NUMBER %token TOKEN_INT8 TOKEN_INT16 TOKEN_INT64 TOKEN_CONST TOKEN_VOID TOKEN_BOOL %token TOKEN_ENUM TOKEN_STRUCT TOKEN_TRUE TOKEN_FALSE @@ -244,6 +245,7 @@ struct ForeachDimension { %type short_vec_specifier %type type_specifier_list %type atomic_var_type_specifier +%type poly_type_specifier poly_quant_type_specifier %type type_qualifier type_qualifier_list %type storage_class_specifier @@ -364,60 +366,60 @@ launch_expression } | TOKEN_LAUNCH '[' assignment_expression ']' postfix_expression '(' argument_expression_list ')' - { + { ConstExpr *oneExpr = new ConstExpr(AtomicType::UniformInt32, (int32_t)1, @5); Expr *launchCount[3] = {$3, oneExpr, oneExpr}; $$ = new FunctionCallExpr($5, $7, Union(@5,@8), true, launchCount); } | TOKEN_LAUNCH '[' assignment_expression ']' postfix_expression '(' ')' - { + { ConstExpr *oneExpr = new ConstExpr(AtomicType::UniformInt32, (int32_t)1, @5); Expr *launchCount[3] = {$3, oneExpr, oneExpr}; $$ = new FunctionCallExpr($5, new ExprList(Union(@5,@6)), Union(@5,@7), true, launchCount); } | TOKEN_LAUNCH '[' assignment_expression ',' assignment_expression ']' postfix_expression '(' argument_expression_list ')' - { + { ConstExpr *oneExpr = new ConstExpr(AtomicType::UniformInt32, (int32_t)1, @7); Expr *launchCount[3] = {$3, $5, oneExpr}; $$ = new FunctionCallExpr($7, $9, Union(@7,@10), true, launchCount); } | TOKEN_LAUNCH '[' assignment_expression ',' assignment_expression ']' postfix_expression '(' ')' - { + { ConstExpr *oneExpr = new ConstExpr(AtomicType::UniformInt32, (int32_t)1, @7); Expr *launchCount[3] = {$3, $5, oneExpr}; $$ = new FunctionCallExpr($7, new ExprList(Union(@7,@8)), Union(@7,@9), true, launchCount); } | TOKEN_LAUNCH '[' assignment_expression ']' '[' assignment_expression ']' postfix_expression '(' argument_expression_list ')' - { + { ConstExpr *oneExpr = new ConstExpr(AtomicType::UniformInt32, (int32_t)1, @8); Expr *launchCount[3] = {$6, $3, oneExpr}; $$ = new FunctionCallExpr($8, $10, Union(@8,@11), true, launchCount); } | TOKEN_LAUNCH '[' assignment_expression ']' '[' assignment_expression ']' postfix_expression '(' ')' - { + { ConstExpr *oneExpr = new ConstExpr(AtomicType::UniformInt32, (int32_t)1, @8); Expr *launchCount[3] = {$6, $3, oneExpr}; $$ = new FunctionCallExpr($8, new ExprList(Union(@8,@9)), Union(@8,@10), true, launchCount); } | TOKEN_LAUNCH '[' assignment_expression ',' assignment_expression ',' assignment_expression ']' postfix_expression '(' argument_expression_list ')' - { + { Expr *launchCount[3] = {$3, $5, $7}; $$ = new FunctionCallExpr($9, $11, Union(@9,@12), true, launchCount); } | TOKEN_LAUNCH '[' assignment_expression ',' assignment_expression ',' assignment_expression ']' postfix_expression '(' ')' - { + { Expr *launchCount[3] = {$3, $5, $7}; $$ = new FunctionCallExpr($9, new ExprList(Union(@9,@10)), Union(@9,@11), true, launchCount); } | TOKEN_LAUNCH '[' assignment_expression ']' '[' assignment_expression ']' '[' assignment_expression ']' postfix_expression '(' argument_expression_list ')' - { + { Expr *launchCount[3] = {$9, $6, $3}; $$ = new FunctionCallExpr($11, $13, Union(@11,@14), true, launchCount); } | TOKEN_LAUNCH '[' assignment_expression ']' '[' assignment_expression ']' '[' assignment_expression ']' postfix_expression '(' ')' - { + { Expr *launchCount[3] = {$9, $6, $3}; $$ = new FunctionCallExpr($11, new ExprList(Union(@11,@12)), Union(@11,@13), true, launchCount); } @@ -908,6 +910,7 @@ storage_class_specifier type_specifier : atomic_var_type_specifier { $$ = $1; } + | poly_quant_type_specifier { $$ = $1; } | TOKEN_TYPE_NAME { const Type *t = m->symbolTable->LookupType(yytext); @@ -950,6 +953,20 @@ atomic_var_type_specifier | TOKEN_INT64 { $$ = AtomicType::UniformInt64->GetAsUnboundVariabilityType(); } ; +poly_type_specifier + : TOKEN_FLOATING { $$ = PolyType::UniformFloating->GetAsUnboundVariabilityType(); } + | TOKEN_INTEGER { $$ = PolyType::UniformInteger->GetAsUnboundVariabilityType(); } + | TOKEN_NUMBER { $$ = PolyType::UniformNumber->GetAsUnboundVariabilityType(); } + ; + +poly_quant_type_specifier + : poly_type_specifier '$' int_constant + { + $$ = $1->Quantify($3); + } + | poly_type_specifier { $$ = $1; } + ; + short_vec_specifier : atomic_var_type_specifier '<' int_constant '>' { @@ -2272,10 +2289,10 @@ static void lAddThreadIndexCountToSymbolTable(SourcePos pos) { Symbol *taskIndexSym = new Symbol("taskIndex", pos, type); m->symbolTable->AddVariable(taskIndexSym); - + Symbol *taskCountSym = new Symbol("taskCount", pos, type); m->symbolTable->AddVariable(taskCountSym); - + Symbol *taskIndexSym0 = new Symbol("taskIndex0", pos, type); m->symbolTable->AddVariable(taskIndexSym0); Symbol *taskIndexSym1 = new Symbol("taskIndex1", pos, type); @@ -2283,7 +2300,7 @@ static void lAddThreadIndexCountToSymbolTable(SourcePos pos) { Symbol *taskIndexSym2 = new Symbol("taskIndex2", pos, type); m->symbolTable->AddVariable(taskIndexSym2); - + Symbol *taskCountSym0 = new Symbol("taskCount0", pos, type); m->symbolTable->AddVariable(taskCountSym0); Symbol *taskCountSym1 = new Symbol("taskCount1", pos, type); diff --git a/tests_ispcpp/error_0.ispc b/tests_ispcpp/error_0.ispc index be8bc90f..39f57d0d 100644 --- a/tests_ispcpp/error_0.ispc +++ b/tests_ispcpp/error_0.ispc @@ -1,6 +1,6 @@ //@error //assigning mismatched polymorphic types -export void foo(floating<0> bar) { - floating<1> baz = bar; +export void foo(floating$0 bar) { + floating$1 baz = bar; } diff --git a/tests_ispcpp/error_1.ispc b/tests_ispcpp/error_1.ispc index 5cf8ac5f..428b3f41 100644 --- a/tests_ispcpp/error_1.ispc +++ b/tests_ispcpp/error_1.ispc @@ -1,6 +1,6 @@ //@error //assigning mismatched polymorphic types -export void foo(floating<0> bar) { +export void foo(floating$0 bar) { floating baz = bar; } diff --git a/tests_ispcpp/error_2.ispc b/tests_ispcpp/error_2.ispc index 64586296..6f4adfe0 100644 --- a/tests_ispcpp/error_2.ispc +++ b/tests_ispcpp/error_2.ispc @@ -1,6 +1,6 @@ //@error //assigning mismatched polymorphic types -export void foo(number<0> bar) { - floating<0> baz = bar; +export void foo(number$0 bar) { + floating$0 baz = bar; } diff --git a/tests_ispcpp/error_3.ispc b/tests_ispcpp/error_3.ispc index 1afab53c..a414b0fd 100644 --- a/tests_ispcpp/error_3.ispc +++ b/tests_ispcpp/error_3.ispc @@ -1,6 +1,6 @@ //@error //assigning mismatched polymorphic types -export void foo(number<0> bar) { +export void foo(number$0 bar) { integer baz = bar; } diff --git a/tests_ispcpp/error_4.ispc b/tests_ispcpp/error_4.ispc index 0d614053..1561f3dc 100644 --- a/tests_ispcpp/error_4.ispc +++ b/tests_ispcpp/error_4.ispc @@ -2,18 +2,18 @@ // cannot determine return type for mult -floating mult(floating<0> x, floating<1>y) { +floating mult(floating$0 x, floating$1 y) { return x * y; } export void saxpy(uniform int N, - uniform floating<0> scale, - uniform floating<1> X[], - uniform floating<1> Y[], - uniform floating<2> result[]) + uniform floating$0 scale, + uniform floating$1 X[], + uniform floating$1 Y[], + uniform floating$2 result[]) { foreach (i = 0 ... N) { - floating<2> tmp = mult(scale, X[i]) + Y[i]; + floating$2 tmp = mult(scale, X[i]) + Y[i]; result[i] = tmp; } } diff --git a/tests_ispcpp/hello.ispc b/tests_ispcpp/hello.ispc index 7ded8820..15c0af50 100644 --- a/tests_ispcpp/hello.ispc +++ b/tests_ispcpp/hello.ispc @@ -1,11 +1,11 @@ export void saxpy(uniform int N, - uniform floating<0> scale, - uniform floating<1> X[], - uniform floating<1> Y[], - uniform floating<2> result[]) + uniform floating$0 scale, + uniform floating$1 X[], + uniform floating$1 Y[], + uniform floating$2 result[]) { foreach (i = 0 ... N) { - floating<2> tmp = scale * X[i] + Y[i]; + floating$2 tmp = scale * X[i] + Y[i]; result[i] = tmp; } } diff --git a/tests_ispcpp/simple.ispc b/tests_ispcpp/simple.ispc new file mode 100644 index 00000000..da4642da --- /dev/null +++ b/tests_ispcpp/simple.ispc @@ -0,0 +1,6 @@ +export void foo(uniform int N, floating$1 X[]) +{ + foreach (i = 0 ... N) { + X[i] = X[i] + 1.0; + } +} diff --git a/type.cpp b/type.cpp index c829b87e..2c42bd25 100644 --- a/type.cpp +++ b/type.cpp @@ -673,6 +673,326 @@ llvm::DIType *AtomicType::GetDIType(llvm::DIScope *scope) const { } } +/////////////////////////////////////////////////////////////////////////// +// PolyType + +const PolyType *PolyType::UniformInteger = + new PolyType(PolyType::TYPE_INTEGER, Variability::Uniform, false); +const PolyType *PolyType::VaryingInteger = + new PolyType(PolyType::TYPE_INTEGER, Variability::Varying, false); +const PolyType *PolyType::UniformFloating = + new PolyType(PolyType::TYPE_FLOATING, Variability::Uniform, false); +const PolyType *PolyType::VaryingFloating = + new PolyType(PolyType::TYPE_FLOATING, Variability::Varying, false); +const PolyType *PolyType::UniformNumber = + new PolyType(PolyType::TYPE_NUMBER, Variability::Uniform, false); +const PolyType *PolyType::VaryingNumber = + new PolyType(PolyType::TYPE_NUMBER, Variability::Varying, false); + +PolyType::PolyType(PolyRestriction r, Variability v, bool ic) + : Type(POLY_TYPE), restriction(r), variability(v), isConst(ic), quant(-1) { + asOtherConstType = NULL; + asUniformType = asVaryingType = NULL; +} + +PolyType::PolyType(PolyRestriction r, Variability v, bool ic, int q) + : Type(POLY_TYPE), restriction(r), variability(v), isConst(ic), quant(q) { + asOtherConstType = NULL; + asUniformType = asVaryingType = NULL; +} + + +Variability +PolyType::GetVariability() const { + return variability; +} + + +bool +PolyType::IsFloatType() const { + return (restriction == TYPE_FLOATING); +} + +bool +PolyType::IsIntType() const { + return (restriction == TYPE_INTEGER); +} + + +bool +PolyType::IsUnsignedType() const { + return false; +} + + +bool +PolyType::IsBoolType() const { + return false; +} + + +bool +PolyType::IsConstType() const { + return isConst; +} + + +const PolyType * +PolyType::GetAsUnsignedType() const { + return NULL; +} + + +const PolyType * +PolyType::GetAsConstType() const { + if (isConst == true) + return this; + + if (asOtherConstType == NULL) { + asOtherConstType = new PolyType(restriction, variability, true); + asOtherConstType->asOtherConstType = this; + } + return asOtherConstType; +} + + +const PolyType * +PolyType::GetAsNonConstType() const { + if (isConst == false) + return this; + + if (asOtherConstType == NULL) { + asOtherConstType = new PolyType(restriction, variability, false); + asOtherConstType->asOtherConstType = this; + } + return asOtherConstType; +} + + +const PolyType * +PolyType::GetBaseType() const { + return this; +} + + +const PolyType * +PolyType::GetAsVaryingType() const { + if (variability == Variability::Varying) + return this; + + if (asVaryingType == NULL) { + asVaryingType = new PolyType(restriction, Variability::Varying, isConst); + if (variability == Variability::Uniform) + asVaryingType->asUniformType = this; + } + return asVaryingType; +} + + +const PolyType * +PolyType::GetAsUniformType() const { + if (variability == Variability::Uniform) + return this; + + if (asUniformType == NULL) { + asUniformType = new PolyType(restriction, Variability::Uniform, isConst); + if (variability == Variability::Varying) + asUniformType->asVaryingType = this; + } + return asUniformType; +} + + +const PolyType * +PolyType::GetAsUnboundVariabilityType() const { + if (variability == Variability::Unbound) + return this; + return new PolyType(restriction, Variability::Unbound, isConst); +} + + +const PolyType * +PolyType::GetAsSOAType(int width) const { + if (variability == Variability(Variability::SOA, width)) + return this; + return new PolyType(restriction, Variability(Variability::SOA, width), + isConst); +} + + +const PolyType * +PolyType::ResolveUnboundVariability(Variability v) const { + Assert(v != Variability::Unbound); + if (variability != Variability::Unbound) + return this; + return new PolyType(restriction, v, isConst); +} + +const PolyType * +PolyType::Quantify(int quant) const { + return new PolyType(restriction, variability, isConst, quant); +} + +std::string +PolyType::GetString() const { + std::string ret; + if (isConst) ret += "const "; + + ret += variability.GetString(); + ret += " "; + + switch (restriction) { + case TYPE_INTEGER: ret += "integer"; break; + case TYPE_FLOATING: ret += "floating"; break; + case TYPE_NUMBER: ret += "number"; break; + default: FATAL("Logic error in PolyType::GetString()"); + } + return ret; +} + + +std::string +PolyType::Mangle() const { + std::string ret; + if (isConst) ret += "C"; + ret += variability.MangleString(); + + switch (restriction) { + case TYPE_INTEGER: ret += "Z"; break; + case TYPE_FLOATING: ret += "Q"; break; + case TYPE_NUMBER: ret += "R"; break; + default: FATAL("Logic error in PolyType::Mangle()"); + } + return ret; +} + + +std::string +PolyType::GetCDeclaration(const std::string &name) const { + std::string ret; + if (variability == Variability::Unbound) { + Assert(m->errorCount > 0); + return ret; + } + if (isConst) ret += "const "; + + switch (restriction) { + case TYPE_INTEGER: ret += "int32_t"; break; + case TYPE_FLOATING: ret += "double"; break; + case TYPE_NUMBER: ret += "double"; break; + default: FATAL("Logic error in PolyType::GetCDeclaration()"); + } + + if (lShouldPrintName(name)) { + ret += " "; + ret += name; + } + + if (variability == Variability::SOA) { + char buf[32]; + sprintf(buf, "[%d]", variability.soaWidth); + ret += buf; + } + + return ret; +} + + +llvm::Type * +PolyType::LLVMType(llvm::LLVMContext *ctx) const { + Assert(variability.type != Variability::Unbound); + bool isUniform = (variability == Variability::Uniform); + bool isVarying = (variability == Variability::Varying); + + if (isUniform || isVarying) { + switch (restriction) { + case TYPE_INTEGER: + return isUniform ? LLVMTypes::Int32Type : LLVMTypes::Int32VectorType; + case TYPE_FLOATING: + case TYPE_NUMBER: + return isUniform ? LLVMTypes::DoubleType : LLVMTypes::DoubleVectorType; + default: + FATAL("logic error in PolyType::LLVMType"); + return NULL; + } + } + else { + ArrayType at(GetAsUniformType(), variability.soaWidth); + return at.LLVMType(ctx); + } +} + + +#if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6 +llvm::DIType PolyType::GetDIType(llvm::DIDescriptor scope) const { +#else //LLVM 3.7++ +llvm::DIType *PolyType::GetDIType(llvm::DIScope *scope) const { +#endif + Assert(variability.type != Variability::Unbound); + + if (variability.type == Variability::Uniform) { + switch (restriction) { +#if ISPC_LLVM_VERSION <= ISPC_LLVM_3_9 + case TYPE_INTEGER: + return m->diBuilder->createBasicType("int32", 32 /* size */, 32 /* align */, + llvm::dwarf::DW_ATE_signed); + break; + case TYPE_FLOATING: + case TYPE_NUMBER: + return m->diBuilder->createBasicType("double", 64 /* size */, 64 /* align */, + llvm::dwarf::DW_ATE_float); + break; +#else // LLVM 4.0+ + case TYPE_INTEGER: + return m->diBuilder->createBasicType("int32", 32 /* size */, + llvm::dwarf::DW_ATE_signed); + break; + case TYPE_FLOATING: + case TYPE_NUMBER: + return m->diBuilder->createBasicType("double", 64 /* size */, + llvm::dwarf::DW_ATE_float); + break; +#endif + + default: + FATAL("unhandled basic type in PolyType::GetDIType()"); +#if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6 + return llvm::DIType(); +#else //LLVM 3.7+ + return NULL; +#endif + } + } + else if (variability == Variability::Varying) { +#if ISPC_LLVM_VERSION == ISPC_LLVM_3_2 + llvm::Value *sub = m->diBuilder->getOrCreateSubrange(0, g->target->getVectorWidth()-1); +#elif ISPC_LLVM_VERSION > ISPC_VERSION_3_2 && ISPC_LLVM_VERSION <= ISPC_LLVM_3_5 + llvm::Value *sub = m->diBuilder->getOrCreateSubrange(0, g->target->getVectorWidth()); +#else // LLVM 3.6+ + llvm::Metadata *sub = m->diBuilder->getOrCreateSubrange(0, g->target->getVectorWidth()); +#endif +#if ISPC_LLVM_VERSION > ISPC_VERSION_3_2 && ISPC_LLVM_VERSION <= ISPC_LLVM_3_6 + llvm::DIArray subArray = m->diBuilder->getOrCreateArray(sub); + llvm::DIType unifType = GetAsUniformType()->GetDIType(scope); + uint64_t size = unifType.getSizeInBits() * g->target->getVectorWidth(); + uint64_t align = unifType.getAlignInBits() * g->target->getVectorWidth(); +#else // LLVM 3.7+ + llvm::DINodeArray subArray = m->diBuilder->getOrCreateArray(sub); + llvm::DIType *unifType = GetAsUniformType()->GetDIType(scope); + //llvm::DebugNodeArray subArray = m->diBuilder->getOrCreateArray(sub); + //llvm::MDType *unifType = GetAsUniformType()->GetDIType(scope); + uint64_t size = unifType->getSizeInBits() * g->target->getVectorWidth(); + uint64_t align = unifType->getAlignInBits()* g->target->getVectorWidth(); +#endif + return m->diBuilder->createVectorType(size, align, unifType, subArray); + } + else { + Assert(variability == Variability::SOA); + ArrayType at(GetAsUniformType(), variability.soaWidth); + return at.GetDIType(scope); + } +} + /////////////////////////////////////////////////////////////////////////// // EnumType diff --git a/type.h b/type.h index d8e9be86..195207de 100644 --- a/type.h +++ b/type.h @@ -89,7 +89,8 @@ enum TypeId { STRUCT_TYPE, // 5 UNDEFINED_STRUCT_TYPE, // 6 REFERENCE_TYPE, // 7 - FUNCTION_TYPE // 8 + FUNCTION_TYPE, // 8 + POLY_TYPE // 9 }; @@ -364,6 +365,67 @@ private: mutable const AtomicType *asOtherConstType, *asUniformType, *asVaryingType; }; +class PolyType : public Type { +public: + Variability GetVariability() const; + + bool IsBoolType() const; + bool IsFloatType() const; + bool IsIntType() const; + bool IsUnsignedType() const; + bool IsConstType() const; + + const PolyType *GetBaseType() const; + const PolyType *GetAsUniformType() const; + const PolyType *GetAsVaryingType() const; + const PolyType *GetAsUnboundVariabilityType() const; + const PolyType *GetAsSOAType(int width) const; + + const PolyType *ResolveUnboundVariability(Variability v) const; + const PolyType *GetAsUnsignedType() const; + const PolyType *GetAsConstType() const; + const PolyType *GetAsNonConstType() const; + + const PolyType *Quantify(int quant) const; + + std::string GetString() const; + std::string Mangle() const; + std::string GetCDeclaration(const std::string &name) const; + + llvm::Type *LLVMType(llvm::LLVMContext *ctx) const; +#if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6 + llvm::DIType GetDIType(llvm::DIDescriptor scope) const; +#else // LLVM 3.7++ + llvm::DIType *GetDIType(llvm::DIScope *scope) const; +#endif + + enum PolyRestriction { + TYPE_INTEGER, + TYPE_FLOATING, + TYPE_NUMBER + }; + + const PolyRestriction restriction; + + + static const PolyType *UniformInteger, *VaryingInteger; + static const PolyType *UniformFloating, *VaryingFloating; + static const PolyType *UniformNumber, *VaryingNumber; + + // Returns the list of AtomicTypes that are valid instantiations of the + // polymorphic type + const std::vector GetEnumeratedTypes() const; + +private: + const Variability variability; + const bool isConst; + const int quant; + PolyType(PolyRestriction type, Variability v, bool isConst); + PolyType(PolyRestriction type, Variability v, bool isConst, int quant); + + mutable const PolyType *asOtherConstType, *asUniformType, *asVaryingType; +}; + /** @brief Type implementation for enumerated types */