diff options
| author | Yong He <yonghe@outlook.com> | 2018-01-17 14:48:07 -0500 |
|---|---|---|
| committer | Yong He <yonghe@outlook.com> | 2018-01-17 20:54:56 -0500 |
| commit | caf6f7a03793be3fc74683994414776f3604ad8a (patch) | |
| tree | d9d3e3a4e4a45d5e09d613159be2faaf137e0e72 | |
| parent | 68f529af8d0eb8ec45a2d73e82c4ee372015ce01 (diff) | |
All compiler fixes to get ir branch work with falcor feature demo.
- support overloaded generic function. this involves adding a new expression type, `OverloadedExpr2` to hold the candidate expressions for the generic function decl being referenced.
- make BitNot a normal IROp instead of an IRPseudoOp
- make sure we clone the decorations of parameters when cloning ir functions
- propagate geometry shader entry point attributes (`[maxvertexcount]` and `[instance]`) through HLSL emit
- IR emit: handle geometry shader entry-point parameter decorations, such as 'triangle'.
- IR emit: treat geometry shader stream output typed ir value as `should fold into use`.
| -rw-r--r-- | source/slang/ast-legalize.cpp | 8 | ||||
| -rw-r--r-- | source/slang/check.cpp | 64 | ||||
| -rw-r--r-- | source/slang/emit.cpp | 54 | ||||
| -rw-r--r-- | source/slang/expr-defs.h | 12 | ||||
| -rw-r--r-- | source/slang/ir-inst-defs.h | 2 | ||||
| -rw-r--r-- | source/slang/ir.cpp | 1 | ||||
| -rw-r--r-- | source/slang/lower-to-ir.cpp | 7 | ||||
| -rw-r--r-- | source/slang/mangle.cpp | 6 | ||||
| -rw-r--r-- | source/slang/modifier-defs.h | 10 | ||||
| -rw-r--r-- | source/slang/slang-stdlib.cpp | 2 | ||||
| -rw-r--r-- | tests/compute/generics-overload.expected.txt | 4 | ||||
| -rw-r--r-- | tests/compute/generics-overload.slang | 32 |
12 files changed, 186 insertions, 16 deletions
diff --git a/source/slang/ast-legalize.cpp b/source/slang/ast-legalize.cpp index 996a66eac..5df6b80f5 100644 --- a/source/slang/ast-legalize.cpp +++ b/source/slang/ast-legalize.cpp @@ -5091,6 +5091,14 @@ struct FindIRDeclUsedByASTVisitor // TODO: need to walk the lookup result too } + void visitOverloadedExpr2(OverloadedExpr2* expr) + { + walkExpr(expr->base); + for (auto & candidate : expr->candidiateExprs) + walkExpr(candidate); + } + + void visitConstantExpr(ConstantExpr*) {} diff --git a/source/slang/check.cpp b/source/slang/check.cpp index 3fe4f8c5d..dfc09c485 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -1466,7 +1466,9 @@ namespace Slang // For now we will do this in a completely ad hoc fashion, // but it would be nice to have some generic routine to // do the needed type checking/coercion. - if(getText(hlslUncheckedAttribute->getName()) == "numthreads") + auto attribText = getText(hlslUncheckedAttribute->getName()); + + if(attribText == "numthreads") { if(hlslUncheckedAttribute->args.Count() != 3) return m; @@ -1490,8 +1492,33 @@ namespace Slang return hlslNumThreadsAttribute; } - } + else if (attribText == "maxvertexcount") + { + if (hlslUncheckedAttribute->args.Count() != 1) + return m; + auto val = checkConstantIntVal(hlslUncheckedAttribute->args[0]); + auto hlslMaxVertexCountAttrib = new HLSLMaxVertexCountAttribute(); + + hlslMaxVertexCountAttrib->loc = hlslUncheckedAttribute->loc; + hlslMaxVertexCountAttrib->name = hlslUncheckedAttribute->getName(); + hlslMaxVertexCountAttrib->args = hlslUncheckedAttribute->args; + hlslMaxVertexCountAttrib->value = (int32_t)val->value; + return hlslMaxVertexCountAttrib; + } + else if (attribText == "instance") + { + if (hlslUncheckedAttribute->args.Count() != 1) + return m; + auto val = checkConstantIntVal(hlslUncheckedAttribute->args[0]); + auto attrib = new HLSLInstanceAttribute(); + attrib->loc = hlslUncheckedAttribute->loc; + attrib->name = hlslUncheckedAttribute->getName(); + attrib->args = hlslUncheckedAttribute->args; + attrib->value = (int32_t)val->value; + return attrib; + } + } // Default behavior is to leave things as they are, // and assume that modifiers are mostly already checked. // @@ -2202,9 +2229,10 @@ namespace Slang // to avoid recursion here. if (functionNode->Body) { + auto oldFunc = function; this->function = functionNode; checkStmt(functionNode->Body); - this->function = nullptr; + this->function = oldFunc; } } } @@ -2630,6 +2658,7 @@ namespace Slang { if (functionNode->IsChecked(DeclCheckState::CheckedHeader)) return; functionNode->SetCheckState(DeclCheckState::CheckingHeader); + auto oldFunc = this->function; this->function = functionNode; auto returnType = CheckProperType(functionNode->ReturnType); functionNode->ReturnType = returnType; @@ -2648,7 +2677,7 @@ namespace Slang else paraNames.Add(para->getName()); } - this->function = NULL; + this->function = oldFunc; functionNode->SetCheckState(DeclCheckState::CheckedHeader); // One last bit of validation: check if we are redeclaring an existing function @@ -5745,6 +5774,13 @@ namespace Slang AddDeclRefOverloadCandidates(item, context); } } + else if (auto overloadedExpr2 = funcExpr.As<OverloadedExpr2>()) + { + for (auto item : overloadedExpr2->candidiateExprs) + { + AddOverloadCandidates(item, context); + } + } else if (auto typeType = funcExprType->As<TypeType>()) { // If none of the above cases matched, but we are @@ -5944,6 +5980,10 @@ namespace Slang { context.baseExpr = funcOverloadExpr->base; } + else if (auto funcOverloadExpr2 = funcExpr.As<OverloadedExpr2>()) + { + context.baseExpr = funcOverloadExpr2->base; + } AddOverloadCandidates(funcExpr, context); if (context.bestCandidates.Count() > 0) @@ -6172,15 +6212,14 @@ namespace Slang // There were multiple viable candidates, but that isn't an error: we just need // to complete all of them and create an overloaded expression as a result. - LookupResult result; + auto overloadedExpr = new OverloadedExpr2(); + overloadedExpr->base = context.baseExpr; for (auto candidate : context.bestCandidates) { auto candidateExpr = CompleteOverloadCandidate(context, candidate); + overloadedExpr->candidiateExprs.Add(candidateExpr); } - - throw "what now?"; -// auto overloadedExpr = new OverloadedExpr(); -// return overloadedExpr; + return overloadedExpr; } } else if (context.bestCandidate) @@ -6400,6 +6439,13 @@ namespace Slang return expr; } + RefPtr<Expr> visitOverloadedExpr2(OverloadedExpr2* expr) + { + SLANG_DIAGNOSE_UNEXPECTED(getSink(), expr, "should not appear in input syntax"); + return expr; + } + + RefPtr<Expr> visitAggTypeCtorExpr(AggTypeCtorExpr* expr) { SLANG_DIAGNOSE_UNEXPECTED(getSink(), expr, "should not appear in input syntax"); diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp index 33328fbb1..18a10460f 100644 --- a/source/slang/emit.cpp +++ b/source/slang/emit.cpp @@ -2315,7 +2315,7 @@ struct EmitVisitor CASE(kIRPseudoOp_Pos, +); CASE(kIROp_Neg, -); CASE(kIROp_Not, !); - CASE(kIRPseudoOp_BitNot, ~); + CASE(kIROp_BitNot, ~); #undef CASE #define CASE(NAME, OP) case kIRPseudoOp_##NAME: EmitUnaryAssignExpr(outerPrec, kEOp_Prefix, #OP, "", callExpr); return @@ -2554,6 +2554,11 @@ struct EmitVisitor emitName(expr->lookupResult2.getName()); } + void visitOverloadedExpr2(OverloadedExpr2* expr, ExprEmitArg const& arg) + { + ExprVisitorWithArg<Slang::EmitVisitor, Slang::ExprEmitArg>::dispatch(expr->candidiateExprs[0].Ptr(), arg); + } + void setSampleRateFlag() { context->shared->entryPointLayout->flags |= EntryPointLayout::Flag::usesAnySampleRateInput; @@ -4928,6 +4933,10 @@ emitDeclImpl(decl, nullptr); // types. return true; } + else if (type->As<HLSLStreamOutputType>()) + { + return true; + } else if(type->As<TextureTypeBase>()) { // GLSL doesn't allow texture/resource types to @@ -5512,7 +5521,12 @@ emitDeclImpl(decl, nullptr); emitIROperand(ctx, inst->getArg(0)); } break; - + case kIROp_BitNot: + { + emit("~"); + emitIROperand(ctx, inst->getArg(0)); + } + break; case kIROp_Sample: emitIROperand(ctx, inst->getArg(0)); emit(".Sample("); @@ -6266,7 +6280,22 @@ emitDeclImpl(decl, nullptr); emit(")]\n"); } break; - + case Stage::Geometry: + { + if (auto attrib = entryPointLayout->entryPoint->FindModifier<HLSLMaxVertexCountAttribute>()) + { + emit("[maxvertexcount("); + Emit(attrib->value); + emit(")]\n"); + } + if (auto attrib = entryPointLayout->entryPoint->FindModifier<HLSLInstanceAttribute>()) + { + emit("[instance("); + Emit(attrib->value); + emit(")]\n"); + } + } + break; // TODO: There are other stages that will need this kind of handling. default: break; @@ -6279,6 +6308,7 @@ emitDeclImpl(decl, nullptr); emit("("); auto firstParam = func->getFirstParam(); + int pIdx = 0; for( auto pp = firstParam; pp; pp = pp->getNextParam() ) { if(pp != firstParam) @@ -6286,9 +6316,27 @@ emitDeclImpl(decl, nullptr); auto paramName = getIRName(pp); auto paramType = pp->getType(); + if (auto decor = pp->findDecoration<IRHighLevelDeclDecoration>()) + { + if (decor->decl) + { + auto primType = decor->decl->FindModifier<HLSLGeometryShaderInputPrimitiveTypeModifier>(); + if (dynamic_cast<HLSLTriangleModifier*>(primType)) + emit("triangle "); + else if (dynamic_cast<HLSLPointModifier*>(primType)) + emit("point "); + else if (dynamic_cast<HLSLLineModifier*>(primType)) + emit("line "); + else if (dynamic_cast<HLSLLineAdjModifier*>(primType)) + emit("lineadj "); + else if (dynamic_cast<HLSLTriangleAdjModifier*>(primType)) + emit("triangleadj "); + } + } emitIRParamType(ctx, paramType, paramName); emitIRSemantics(ctx, pp); + pIdx++; } emit(")"); diff --git a/source/slang/expr-defs.h b/source/slang/expr-defs.h index e3c16a674..4b47cc883 100644 --- a/source/slang/expr-defs.h +++ b/source/slang/expr-defs.h @@ -30,6 +30,18 @@ SYNTAX_CLASS(OverloadedExpr, Expr) FIELD(LookupResult, lookupResult2) END_SYNTAX_CLASS() +// An expression that references an overloaded set of declarations +// having the same name. +SYNTAX_CLASS(OverloadedExpr2, Expr) + + // Optional: the base expression is this overloaded result + // arose from a member-reference expression. + SYNTAX_FIELD(RefPtr<Expr>, base) + + // The lookup result that was ambiguous + FIELD(List<RefPtr<Expr>>, candidiateExprs) +END_SYNTAX_CLASS() + SYNTAX_CLASS(ConstantExpr, Expr) FIELD(Token, token) diff --git a/source/slang/ir-inst-defs.h b/source/slang/ir-inst-defs.h index cc5474842..fa02da683 100644 --- a/source/slang/ir-inst-defs.h +++ b/source/slang/ir-inst-defs.h @@ -231,6 +231,7 @@ INTRINSIC(Pos) INST(Neg, neg, 1, 0) INST(Not, not, 1, 0) +INST(BitNot, bitnot, 1, 0) #if 0 INTRINSIC(PreInc) @@ -286,7 +287,6 @@ PSEUDO_INST(XorAssign ) PSEUDO_INST(LshAssign) PSEUDO_INST(RshAssign) PSEUDO_INST(Assign) -PSEUDO_INST(BitNot) PSEUDO_INST(And) PSEUDO_INST(Or) diff --git a/source/slang/ir.cpp b/source/slang/ir.cpp index f65af2ba4..994ac82ff 100644 --- a/source/slang/ir.cpp +++ b/source/slang/ir.cpp @@ -3591,6 +3591,7 @@ namespace Slang IRParam* clonedParam = builder->emitParam( context->maybeCloneType( originalParam->getType())); + cloneDecorations(context, clonedParam, originalParam); registerClonedValue(context, clonedParam, originalParam); } } diff --git a/source/slang/lower-to-ir.cpp b/source/slang/lower-to-ir.cpp index c8e010f7d..5e7e05a23 100644 --- a/source/slang/lower-to-ir.cpp +++ b/source/slang/lower-to-ir.cpp @@ -705,7 +705,6 @@ LoweredValInfo emitCallToDeclRef( CASE(kIRPseudoOp_PostInc, kIROp_Add); CASE(kIRPseudoOp_PostDec, kIROp_Sub); #undef CASE - default: SLANG_UNIMPLEMENTED_X("IR pseudo-op"); break; @@ -1197,6 +1196,11 @@ struct ExprLoweringVisitorBase : ExprVisitor<Derived, LoweredValInfo> SLANG_UNEXPECTED("overloaded expressions should not occur in checked AST"); } + LoweredValInfo visitOverloadedExpr2(OverloadedExpr2* /*expr*/) + { + SLANG_UNEXPECTED("overloaded expressions should not occur in checked AST"); + } + LoweredValInfo visitIndexExpr(IndexExpr* expr) { auto type = lowerType(context, expr->type); @@ -3521,7 +3525,6 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> for( auto paramInfo : parameterLists.params ) { RefPtr<Type> irParamType = lowerSimpleType(context, paramInfo.type); - switch( paramInfo.direction ) { case kParameterDirection_In: diff --git a/source/slang/mangle.cpp b/source/slang/mangle.cpp index 1a412d041..29446d942 100644 --- a/source/slang/mangle.cpp +++ b/source/slang/mangle.cpp @@ -124,6 +124,12 @@ namespace Slang { emitQualifiedName(context, declRefType->declRef); } + else if (auto arrType = dynamic_cast<ArrayExpressionType*>(type)) + { + emitRaw(context, "a"); + emitSimpleIntVal(context, arrType->ArrayLength); + emitType(context, arrType->baseType); + } else { SLANG_UNEXPECTED("unimplemented case in mangling"); diff --git a/source/slang/modifier-defs.h b/source/slang/modifier-defs.h index cd8f2524b..124dd2882 100644 --- a/source/slang/modifier-defs.h +++ b/source/slang/modifier-defs.h @@ -305,6 +305,16 @@ SYNTAX_CLASS(HLSLNumThreadsAttribute, HLSLAttribute) FIELD(int32_t, z) END_SYNTAX_CLASS() +SYNTAX_CLASS(HLSLMaxVertexCountAttribute, HLSLAttribute) + // The number of max vertex count for geometry shader + FIELD(int32_t, value) +END_SYNTAX_CLASS() + +SYNTAX_CLASS(HLSLInstanceAttribute, HLSLAttribute) + // The number of instances to run for geometry shader + FIELD(int32_t, value) +END_SYNTAX_CLASS() + // HLSL modifiers for geometry shader input topology SIMPLE_SYNTAX_CLASS(HLSLGeometryShaderInputPrimitiveTypeModifier, Modifier) SIMPLE_SYNTAX_CLASS(HLSLPointModifier , HLSLGeometryShaderInputPrimitiveTypeModifier) diff --git a/source/slang/slang-stdlib.cpp b/source/slang/slang-stdlib.cpp index 3e526e96c..bee823d69 100644 --- a/source/slang/slang-stdlib.cpp +++ b/source/slang/slang-stdlib.cpp @@ -199,7 +199,7 @@ namespace Slang { kIRPseudoOp_Pos, "+", ARITHMETIC_MASK }, { kIROp_Neg, "-", ARITHMETIC_MASK }, { kIROp_Not, "!", ANY_MASK }, - { kIRPseudoOp_BitNot, "~", INT_MASK }, + { kIROp_BitNot, "~", INT_MASK }, { kIRPseudoOp_PreInc, "++", ARITHMETIC_MASK | ASSIGNMENT }, { kIRPseudoOp_PreDec, "--", ARITHMETIC_MASK | ASSIGNMENT }, { kIRPseudoOp_PostInc, "++", ARITHMETIC_MASK | ASSIGNMENT | POSTFIX }, diff --git a/tests/compute/generics-overload.expected.txt b/tests/compute/generics-overload.expected.txt new file mode 100644 index 000000000..98798bd61 --- /dev/null +++ b/tests/compute/generics-overload.expected.txt @@ -0,0 +1,4 @@ +0 +3F800000 +40000000 +40400000
\ No newline at end of file diff --git a/tests/compute/generics-overload.slang b/tests/compute/generics-overload.slang new file mode 100644 index 000000000..e530acb59 --- /dev/null +++ b/tests/compute/generics-overload.slang @@ -0,0 +1,32 @@ +//TEST(smoke,compute):COMPARE_COMPUTE:-xslang -use-ir +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +// Confirm that generics syntax can be used in user +// code and generates valid output. + +RWStructuredBuffer<float> outputBuffer; + + +__generic<T> +T test(T val) +{ + return val; +} + +__generic<T> +T test(T val, int a) +{ + return val; +} + + +[numthreads(4, 1, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + uint tid = dispatchThreadID.x; + + float inVal = float(tid); + + float outVal = test<float>(inVal, 0); + + outputBuffer[tid] = outVal; +}
\ No newline at end of file |
