diff options
| author | Tim Foley <tim.foley.is@gmail.com> | 2017-07-08 18:58:42 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-07-08 18:58:42 -0700 |
| commit | 68df74b58a56b0a1fb19b9ec4ff0282969cd6a12 (patch) | |
| tree | 5eaa7eaab892504db53cca4b8044b0c8bcde58b3 /source/slang/emit.cpp | |
| parent | c07a6e6b5f5e0e4839b435ff6c15b821b6dead11 (diff) | |
| parent | 767d47a842700653b8deffe82ccb3c85ad582c13 (diff) | |
Merge pull request #60 from tfoleyNV/revise-rewriter
Revise rewriter
Diffstat (limited to 'source/slang/emit.cpp')
| -rw-r--r-- | source/slang/emit.cpp | 766 |
1 files changed, 412 insertions, 354 deletions
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp index df74d19e4..c135090c1 100644 --- a/source/slang/emit.cpp +++ b/source/slang/emit.cpp @@ -21,9 +21,6 @@ struct SharedEmitContext // The target language we want to generate code for CodeGenTarget target; - // A set of words reserved by the target - Dictionary<String, String> reservedWords; - // The string of code we've built so far StringBuilder sb; @@ -57,10 +54,6 @@ struct EmitContext { // The shared context that is in effect SharedEmitContext* shared; - - // Are we in "rewrite" mode, where we are trying to reproduce the input - // code as closely as posible? - bool isRewrite; }; // @@ -84,6 +77,194 @@ static String getStringOrIdentifierTokenValue( } +enum EPrecedence +{ +#define LEFT(NAME) \ + kEPrecedence_##NAME##_Left, \ + kEPrecedence_##NAME##_Right + +#define RIGHT(NAME) \ + kEPrecedence_##NAME##_Right, \ + kEPrecedence_##NAME##_Left + +#define NONASSOC(NAME) \ + kEPrecedence_##NAME##_Left, \ + kEPrecedence_##NAME##_Right = kEPrecedence_##NAME##_Left + + NONASSOC(None), + LEFT(Comma), + + NONASSOC(General), + + RIGHT(Assign), + + RIGHT(Conditional), + + LEFT(Or), + LEFT(And), + LEFT(BitOr), + LEFT(BitXor), + LEFT(BitAnd), + + LEFT(Equality), + LEFT(Relational), + LEFT(Shift), + LEFT(Additive), + LEFT(Multiplicative), + RIGHT(Prefix), + LEFT(Postfix), + NONASSOC(Atomic), + +#if 0 + + kEPrecedence_None, + kEPrecedence_Comma, + + kEPrecedence_Assign, + kEPrecedence_AddAssign = kEPrecedence_Assign, + kEPrecedence_SubAssign = kEPrecedence_Assign, + kEPrecedence_MulAssign = kEPrecedence_Assign, + kEPrecedence_DivAssign = kEPrecedence_Assign, + kEPrecedence_ModAssign = kEPrecedence_Assign, + kEPrecedence_LshAssign = kEPrecedence_Assign, + kEPrecedence_RshAssign = kEPrecedence_Assign, + kEPrecedence_OrAssign = kEPrecedence_Assign, + kEPrecedence_AndAssign = kEPrecedence_Assign, + kEPrecedence_XorAssign = kEPrecedence_Assign, + + kEPrecedence_General = kEPrecedence_Assign, + + kEPrecedence_Conditional, // "ternary" + kEPrecedence_Or, + kEPrecedence_And, + kEPrecedence_BitOr, + kEPrecedence_BitXor, + kEPrecedence_BitAnd, + + kEPrecedence_Eql, + kEPrecedence_Neq = kEPrecedence_Eql, + + kEPrecedence_Less, + kEPrecedence_Greater = kEPrecedence_Less, + kEPrecedence_Leq = kEPrecedence_Less, + kEPrecedence_Geq = kEPrecedence_Less, + + kEPrecedence_Lsh, + kEPrecedence_Rsh = kEPrecedence_Lsh, + + kEPrecedence_Add, + kEPrecedence_Sub = kEPrecedence_Add, + + kEPrecedence_Mul, + kEPrecedence_Div = kEPrecedence_Mul, + kEPrecedence_Mod = kEPrecedence_Mul, + + kEPrecedence_Prefix, + kEPrecedence_Postfix, + kEPrecedence_Atomic = kEPrecedence_Postfix + +#endif + +}; + +// Info on an op for emit purposes +struct EOpInfo +{ + char const* op; + EPrecedence leftPrecedence; + EPrecedence rightPrecedence; +}; + +#define OP(NAME, TEXT, PREC) \ +static const EOpInfo kEOp_##NAME = { TEXT, kEPrecedence_##PREC##_Left, kEPrecedence_##PREC##_Right, } + +OP(None, "", None); + +OP(Comma, ",", Comma); + +OP(General, "", General); + +OP(Assign, "=", Assign); +OP(AddAssign, "+=", Assign); +OP(SubAssign, "-=", Assign); +OP(MulAssign, "*=", Assign); +OP(DivAssign, "/=", Assign); +OP(ModAssign, "%=", Assign); +OP(LshAssign, "<<=", Assign); +OP(RshAssign, ">>=", Assign); +OP(OrAssign, "|=", Assign); +OP(AndAssign, "&=", Assign); +OP(XorAssign, "^=", Assign); + +OP(Conditional, "?:", Conditional); + +OP(Or, "||", Or); +OP(And, "&&", And); +OP(BitOr, "|", BitOr); +OP(BitXor, "^", BitXor); +OP(BitAnd, "&", BitAnd); + +OP(Eql, "==", Equality); +OP(Neq, "!=", Equality); + +OP(Less, "<", Relational); +OP(Greater, ">", Relational); +OP(Leq, "<=", Relational); +OP(Geq, ">=", Relational); + +OP(Lsh, "<<", Shift); +OP(Rsh, ">>", Shift); + +OP(Add, "+", Additive); +OP(Sub, "-", Additive); + +OP(Mul, "*", Multiplicative); +OP(Div, "/", Multiplicative); +OP(Mod, "%", Multiplicative); + +OP(Prefix, "", Prefix); +OP(Postfix, "", Postfix); +OP(Atomic, "", Atomic); + +#undef OP + +// Table to allow data-driven lookup of an op based on its +// name (to assist when outputting unchecked operator calls) +static EOpInfo const* const kInfixOpInfos[] = +{ + &kEOp_Comma, + &kEOp_Assign, + &kEOp_AddAssign, + &kEOp_SubAssign, + &kEOp_MulAssign, + &kEOp_DivAssign, + &kEOp_ModAssign, + &kEOp_LshAssign, + &kEOp_RshAssign, + &kEOp_OrAssign, + &kEOp_AndAssign, + &kEOp_XorAssign, + &kEOp_Or, + &kEOp_And, + &kEOp_BitOr, + &kEOp_BitXor, + &kEOp_BitAnd, + &kEOp_Eql, + &kEOp_Neq, + &kEOp_Less, + &kEOp_Greater, + &kEOp_Leq, + &kEOp_Geq, + &kEOp_Lsh, + &kEOp_Rsh, + &kEOp_Add, + &kEOp_Sub, + &kEOp_Mul, + &kEOp_Div, + &kEOp_Mod, +}; + + // // represents a declarator for use in emitting types @@ -113,7 +294,7 @@ struct TypeEmitArg struct ExprEmitArg { - int outerPrec; + EOpInfo outerPrec; }; struct DeclEmitArg @@ -201,46 +382,12 @@ struct EmitVisitor Emit(text.begin(), text.end()); } - bool isReservedWord(String const& name) - { - return context->shared->reservedWords.TryGetValue(name) != nullptr; - } - void emitName( String const& inName, CodePosition const& loc) { String name = inName; - // By default, we would like to emit a name in the generated - // code exactly as it appeared in the soriginal program. - // When that isn't possible, we'd like to emit a name as - // close to the original as possible (to ensure that existing - // debugging tools still work reasonably well). - // - // One reason why a name might not be allowed as-is is that - // it could collide with a reserved word in the target language. - // Another reason is that it might not follow a naming convention - // imposed by the target (e.g., in GLSL names starting with - // `gl_` or containing `__` are reserved). - // - // Given a name that should not be allowed, we want to - // change it to a name that *is* allowed. e.g., by adding - // `_` to the end of a reserved word. - // - // The next problem this creates is that the modified name - // could not collide with an existing use of the same - // (valid) name. - // - // For now we are going to solve this problem in a simple - // and ad hoc fashion, but longer term we'll want to do - // something sytematic. - - if (isReservedWord(name)) - { - name = name + "_"; - } - advanceToSourceLocation(loc); emit(name); } @@ -970,6 +1117,14 @@ struct EmitVisitor { e = derefExpr->base; } + + if (auto declRefExpr = e.As<DeclRefExpr>()) + { + auto decl = declRefExpr->declRef.getDecl(); + if (decl && decl->HasModifier<TransparentModifier>()) + return true; + } + // Is the expression referencing a constant buffer? if (auto cbufferType = e->Type->As<ConstantBufferType>()) { @@ -979,73 +1134,30 @@ struct EmitVisitor return false; } - enum - { - kPrecedence_None, - kPrecedence_Comma, - - kPrecedence_Assign, - kPrecedence_AddAssign = kPrecedence_Assign, - kPrecedence_SubAssign = kPrecedence_Assign, - kPrecedence_MulAssign = kPrecedence_Assign, - kPrecedence_DivAssign = kPrecedence_Assign, - kPrecedence_ModAssign = kPrecedence_Assign, - kPrecedence_LshAssign = kPrecedence_Assign, - kPrecedence_RshAssign = kPrecedence_Assign, - kPrecedence_OrAssign = kPrecedence_Assign, - kPrecedence_AndAssign = kPrecedence_Assign, - kPrecedence_XorAssign = kPrecedence_Assign, - - kPrecedence_General = kPrecedence_Assign, - - kPrecedence_Conditional, // "ternary" - kPrecedence_Or, - kPrecedence_And, - kPrecedence_BitOr, - kPrecedence_BitXor, - kPrecedence_BitAnd, - - kPrecedence_Eql, - kPrecedence_Neq = kPrecedence_Eql, - - kPrecedence_Less, - kPrecedence_Greater = kPrecedence_Less, - kPrecedence_Leq = kPrecedence_Less, - kPrecedence_Geq = kPrecedence_Less, - - kPrecedence_Lsh, - kPrecedence_Rsh = kPrecedence_Lsh, - - kPrecedence_Add, - kPrecedence_Sub = kPrecedence_Add, - - kPrecedence_Mul, - kPrecedence_Div = kPrecedence_Mul, - kPrecedence_Mod = kPrecedence_Mul, - - kPrecedence_Prefix, - kPrecedence_Postfix, - kPrecedence_Atomic = kPrecedence_Postfix - }; - +#if 0 void EmitPostfixExpr(RefPtr<ExpressionSyntaxNode> expr) { - EmitExprWithPrecedence(expr, kPrecedence_Postfix); + EmitExprWithPrecedence(expr, kEOp_Postfix); } +#endif void EmitExpr(RefPtr<ExpressionSyntaxNode> expr) { - EmitExprWithPrecedence(expr, kPrecedence_General); + EmitExprWithPrecedence(expr, kEOp_General); } - bool MaybeEmitParens(int outerPrec, int prec) + bool MaybeEmitParens(EOpInfo& outerPrec, EOpInfo prec) { - if (prec <= outerPrec) + bool needParens = (prec.leftPrecedence <= outerPrec.leftPrecedence) + || (prec.rightPrecedence <= outerPrec.rightPrecedence); + + if (needParens) { Emit("("); - return true; + + outerPrec = kEOp_None; } - return false; + return needParens; } // When we are going to emit an expression in an l-value context, @@ -1071,8 +1183,8 @@ struct EmitVisitor } void emitInfixExprImpl( - int outerPrec, - int prec, + EOpInfo outerPrec, + EOpInfo prec, char const* op, RefPtr<InvokeExpressionSyntaxNode> binExpr, bool isAssign) @@ -1085,30 +1197,30 @@ struct EmitVisitor left = prepareLValueExpr(left); } - EmitExprWithPrecedence(left, prec); + EmitExprWithPrecedence(left, leftSide(outerPrec, prec)); Emit(" "); Emit(op); Emit(" "); - EmitExprWithPrecedence(binExpr->Arguments[1], prec); + EmitExprWithPrecedence(binExpr->Arguments[1], rightSide(prec, outerPrec)); if (needsClose) { Emit(")"); } } - void EmitBinExpr(int outerPrec, int prec, char const* op, RefPtr<InvokeExpressionSyntaxNode> binExpr) + void EmitBinExpr(EOpInfo outerPrec, EOpInfo prec, char const* op, RefPtr<InvokeExpressionSyntaxNode> binExpr) { emitInfixExprImpl(outerPrec, prec, op, binExpr, false); } - void EmitBinAssignExpr(int outerPrec, int prec, char const* op, RefPtr<InvokeExpressionSyntaxNode> binExpr) + void EmitBinAssignExpr(EOpInfo outerPrec, EOpInfo prec, char const* op, RefPtr<InvokeExpressionSyntaxNode> binExpr) { emitInfixExprImpl(outerPrec, prec, op, binExpr, true); } void emitUnaryExprImpl( - int outerPrec, - int prec, + EOpInfo outerPrec, + EOpInfo prec, char const* preOp, char const* postOp, RefPtr<InvokeExpressionSyntaxNode> expr, @@ -1123,7 +1235,16 @@ struct EmitVisitor arg = prepareLValueExpr(arg); } - EmitExprWithPrecedence(arg, prec); + if (preOp) + { + EmitExprWithPrecedence(arg, rightSide(prec, outerPrec)); + } + else + { + assert(postOp); + EmitExprWithPrecedence(arg, leftSide(outerPrec, prec)); + } + Emit(postOp); if (needsClose) { @@ -1132,8 +1253,8 @@ struct EmitVisitor } void EmitUnaryExpr( - int outerPrec, - int prec, + EOpInfo outerPrec, + EOpInfo prec, char const* preOp, char const* postOp, RefPtr<InvokeExpressionSyntaxNode> expr) @@ -1142,8 +1263,8 @@ struct EmitVisitor } void EmitUnaryAssignExpr( - int outerPrec, - int prec, + EOpInfo outerPrec, + EOpInfo prec, char const* preOp, char const* postOp, RefPtr<InvokeExpressionSyntaxNode> expr) @@ -1206,9 +1327,10 @@ struct EmitVisitor // just an expression of the form `f(a0, a1, ...)` void emitSimpleCallExpr( RefPtr<InvokeExpressionSyntaxNode> callExpr, - int outerPrec) + EOpInfo outerPrec) { - bool needClose = MaybeEmitParens(outerPrec, kPrecedence_Postfix); + auto prec = kEOp_Postfix; + bool needClose = MaybeEmitParens(outerPrec, prec); auto funcExpr = callExpr->FunctionExpr; if (auto funcDeclRefExpr = funcExpr.As<DeclRefExpr>()) @@ -1222,13 +1344,13 @@ struct EmitVisitor else { // default case: just emit the decl ref - EmitExpr(funcExpr); + EmitExprWithPrecedence(funcExpr, leftSide(outerPrec, prec)); } } else { // default case: just emit the expression - EmitPostfixExpr(funcExpr); + EmitExprWithPrecedence(funcExpr, leftSide(outerPrec, prec)); } Emit("("); @@ -1273,7 +1395,23 @@ struct EmitVisitor emit("\""); } - void EmitExprWithPrecedence(RefPtr<ExpressionSyntaxNode> expr, int outerPrec) + EOpInfo leftSide(EOpInfo const& outerPrec, EOpInfo const& prec) + { + EOpInfo result; + result.leftPrecedence = outerPrec.leftPrecedence; + result.rightPrecedence = prec.leftPrecedence; + return result; + } + + EOpInfo rightSide(EOpInfo const& prec, EOpInfo const& outerPrec) + { + EOpInfo result; + result.leftPrecedence = prec.rightPrecedence; + result.rightPrecedence = outerPrec.rightPrecedence; + return result; + } + + void EmitExprWithPrecedence(RefPtr<ExpressionSyntaxNode> expr, EOpInfo outerPrec) { ExprEmitArg arg; arg.outerPrec = outerPrec; @@ -1281,6 +1419,14 @@ struct EmitVisitor ExprVisitorWithArg::dispatch(expr, arg); } + void EmitExprWithPrecedence(RefPtr<ExpressionSyntaxNode> expr, EPrecedence leftPrec, EPrecedence rightPrec) + { + EOpInfo outerPrec; + outerPrec.leftPrecedence = leftPrec; + outerPrec.rightPrecedence = rightPrec; + } + + #define UNEXPECTED(NAME) \ void visit##NAME(NAME*, ExprEmitArg const&) \ { Emit(#NAME); } @@ -1289,35 +1435,113 @@ struct EmitVisitor #undef UNEXPECTED - void visitSharedTypeExpr(SharedTypeExpr* expr, ExprEmitArg const& arg) + void visitSharedTypeExpr(SharedTypeExpr* expr, ExprEmitArg const&) { emitTypeExp(expr->base); } void visitSelectExpressionSyntaxNode(SelectExpressionSyntaxNode* selectExpr, ExprEmitArg const& arg) { + auto prec = kEOp_Conditional; auto outerPrec = arg.outerPrec; - bool needClose = MaybeEmitParens(outerPrec, kPrecedence_Conditional); + bool needClose = MaybeEmitParens(outerPrec, kEOp_Conditional); - EmitExprWithPrecedence(selectExpr->Arguments[0], kPrecedence_Conditional); + // TODO(tfoley): Need to ver the precedence here... + + EmitExprWithPrecedence(selectExpr->Arguments[0], leftSide(outerPrec, prec)); Emit(" ? "); - EmitExprWithPrecedence(selectExpr->Arguments[1], kPrecedence_Conditional); + EmitExprWithPrecedence(selectExpr->Arguments[1], prec); Emit(" : "); - EmitExprWithPrecedence(selectExpr->Arguments[2], kPrecedence_Conditional); + EmitExprWithPrecedence(selectExpr->Arguments[2], rightSide(prec, outerPrec)); if(needClose) Emit(")"); } + void visitParenExpr(ParenExpr* expr, ExprEmitArg const&) + { + Emit("("); + EmitExprWithPrecedence(expr->base, kEOp_None); + Emit(")"); + } + void visitAssignExpr(AssignExpr* assignExpr, ExprEmitArg const& arg) { + auto prec = kEOp_Assign; auto outerPrec = arg.outerPrec; - bool needClose = MaybeEmitParens(outerPrec, kPrecedence_Assign); - EmitExprWithPrecedence(assignExpr->left, kPrecedence_Assign); + bool needClose = MaybeEmitParens(outerPrec, prec); + EmitExprWithPrecedence(assignExpr->left, leftSide(outerPrec, prec)); Emit(" = "); - EmitExprWithPrecedence(assignExpr->right, kPrecedence_Assign); + EmitExprWithPrecedence(assignExpr->right, rightSide(prec, outerPrec)); if(needClose) Emit(")"); } + void emitUncheckedCallExpr( + RefPtr<InvokeExpressionSyntaxNode> callExpr, + String const& funcName, + ExprEmitArg const& arg) + { + auto outerPrec = arg.outerPrec; + auto funcExpr = callExpr->FunctionExpr; + + // This can occur when we are dealing with unchecked input syntax, + // because we are in "rewriter" mode. In this case we should go + // ahead and emit things in the form that they were written. + if( auto infixExpr = callExpr.As<InfixExpr>() ) + { + auto prec = kEOp_Comma; + for (auto opInfo : kInfixOpInfos) + { + if (funcName == opInfo->op) + { + prec = *opInfo; + break; + } + } + + EmitBinExpr( + outerPrec, + prec, + funcName.Buffer(), + callExpr); + } + else if( auto prefixExpr = callExpr.As<PrefixExpr>() ) + { + EmitUnaryExpr( + outerPrec, + kEOp_Prefix, + funcName.Buffer(), + "", + callExpr); + } + else if(auto postfixExpr = callExpr.As<PostfixExpr>()) + { + EmitUnaryExpr( + outerPrec, + kEOp_Postfix, + "", + funcName.Buffer(), + callExpr); + } + else + { + bool needClose = MaybeEmitParens(outerPrec, kEOp_Postfix); + + EmitExpr(funcExpr); + + Emit("("); + UInt argCount = callExpr->Arguments.Count(); + for (UInt aa = 0; aa < argCount; ++aa) + { + if (aa != 0) Emit(", "); + EmitExpr(callExpr->Arguments[aa]); + } + Emit(")"); + + if (needClose) Emit(")"); + } + } + + void visitInvokeExpressionSyntaxNode( RefPtr<InvokeExpressionSyntaxNode> callExpr, ExprEmitArg const& arg) @@ -1331,46 +1555,14 @@ struct EmitVisitor auto funcDecl = funcDeclRef.getDecl(); if(!funcDecl) { - // This can occur when we are dealing with unchecked input syntax, - // because we are in "rewriter" mode. In this case we should go - // ahead and emit things in the form that they were written. - if( auto infixExpr = callExpr.As<InfixExpr>() ) - { - EmitBinExpr( - outerPrec, - kPrecedence_Comma, - funcDeclRefExpr->name.Buffer(), - callExpr); - } - else if( auto prefixExpr = callExpr.As<PrefixExpr>() ) - { - EmitUnaryExpr( - outerPrec, - kPrecedence_Prefix, - funcDeclRefExpr->name.Buffer(), - "", - callExpr); - } - else if(auto postfixExpr = callExpr.As<PostfixExpr>()) - { - EmitUnaryExpr( - outerPrec, - kPrecedence_Postfix, - "", - funcDeclRefExpr->name.Buffer(), - callExpr); - } - else - { - emitSimpleCallExpr(callExpr, outerPrec); - } + emitUncheckedCallExpr(callExpr, funcDeclRef.GetName(), arg); return; } else if (auto intrinsicOpModifier = funcDecl->FindModifier<IntrinsicOpModifier>()) { switch (intrinsicOpModifier->op) { - #define CASE(NAME, OP) case IntrinsicOp::NAME: EmitBinExpr(outerPrec, kPrecedence_##NAME, #OP, callExpr); return + #define CASE(NAME, OP) case IntrinsicOp::NAME: EmitBinExpr(outerPrec, kEOp_##NAME, #OP, callExpr); return CASE(Mul, *); CASE(Div, / ); CASE(Mod, %); @@ -1391,7 +1583,7 @@ struct EmitVisitor CASE(Or, || ); #undef CASE - #define CASE(NAME, OP) case IntrinsicOp::NAME: EmitBinAssignExpr(outerPrec, kPrecedence_##NAME, #OP, callExpr); return + #define CASE(NAME, OP) case IntrinsicOp::NAME: EmitBinAssignExpr(outerPrec, kEOp_##NAME, #OP, callExpr); return CASE(Assign, =); CASE(AddAssign, +=); CASE(SubAssign, -=); @@ -1405,20 +1597,21 @@ struct EmitVisitor CASE(XorAssign, ^=); #undef CASE - case IntrinsicOp::Sequence: EmitBinExpr(outerPrec, kPrecedence_Comma, ",", callExpr); return; + case IntrinsicOp::Sequence: EmitBinExpr(outerPrec, kEOp_Comma, ",", callExpr); return; - #define CASE(NAME, OP) case IntrinsicOp::NAME: EmitUnaryExpr(outerPrec, kPrecedence_Prefix, #OP, "", callExpr); return + #define CASE(NAME, OP) case IntrinsicOp::NAME: EmitUnaryExpr(outerPrec, kEOp_Prefix, #OP, "", callExpr); return + CASE(Pos, +); CASE(Neg, -); CASE(Not, !); CASE(BitNot, ~); #undef CASE - #define CASE(NAME, OP) case IntrinsicOp::NAME: EmitUnaryAssignExpr(outerPrec, kPrecedence_Prefix, #OP, "", callExpr); return + #define CASE(NAME, OP) case IntrinsicOp::NAME: EmitUnaryAssignExpr(outerPrec, kEOp_Prefix, #OP, "", callExpr); return CASE(PreInc, ++); CASE(PreDec, --); #undef CASE - #define CASE(NAME, OP) case IntrinsicOp::NAME: EmitUnaryAssignExpr(outerPrec, kPrecedence_Postfix, "", #OP, callExpr); return + #define CASE(NAME, OP) case IntrinsicOp::NAME: EmitUnaryAssignExpr(outerPrec, kEOp_Postfix, "", #OP, callExpr); return CASE(PostInc, ++); CASE(PostDec, --); #undef CASE @@ -1603,6 +1796,11 @@ struct EmitVisitor } } } + else if (auto overloadedExpr = funcExpr.As<OverloadedExpr>()) + { + emitUncheckedCallExpr(callExpr, overloadedExpr->lookupResult2.getName(), arg); + return; + } // Fall through to default handling... emitSimpleCallExpr(callExpr, outerPrec); @@ -1612,8 +1810,9 @@ struct EmitVisitor void visitMemberExpressionSyntaxNode(MemberExpressionSyntaxNode* memberExpr, ExprEmitArg const& arg) { + auto prec = kEOp_Postfix; auto outerPrec = arg.outerPrec; - bool needClose = MaybeEmitParens(outerPrec, kPrecedence_Postfix); + bool needClose = MaybeEmitParens(outerPrec, prec); // TODO(tfoley): figure out a good way to reference // declarations that might be generic and/or might @@ -1629,21 +1828,31 @@ struct EmitVisitor } else { - EmitExprWithPrecedence(memberExpr->BaseExpression, kPrecedence_Postfix); + EmitExprWithPrecedence(memberExpr->BaseExpression, leftSide(outerPrec, prec)); Emit("."); } - emitName(memberExpr->declRef.GetName()); + if (!memberExpr->declRef) + { + // This case arises when checking didn't find anything, but we were + // in "rewrite" mode so we blazed ahead anyway. + emitName(memberExpr->name); + } + else + { + emit(memberExpr->declRef.GetName()); + } if(needClose) Emit(")"); } void visitSwizzleExpr(SwizzleExpr* swizExpr, ExprEmitArg const& arg) { + auto prec = kEOp_Postfix; auto outerPrec = arg.outerPrec; - bool needClose = MaybeEmitParens(outerPrec, kPrecedence_Postfix); + bool needClose = MaybeEmitParens(outerPrec, prec); - EmitExprWithPrecedence(swizExpr->base, kPrecedence_Postfix); + EmitExprWithPrecedence(swizExpr->base, leftSide(outerPrec, prec)); Emit("."); static const char* kComponentNames[] = { "x", "y", "z", "w" }; int elementCount = swizExpr->elementCount; @@ -1655,27 +1864,33 @@ struct EmitVisitor if(needClose) Emit(")"); } - void visitIndexExpressionSyntaxNode(IndexExpressionSyntaxNode* indexExpr, ExprEmitArg const& arg) + void visitIndexExpressionSyntaxNode(IndexExpressionSyntaxNode* subscriptExpr, ExprEmitArg const& arg) { + auto prec = kEOp_Postfix; auto outerPrec = arg.outerPrec; - bool needClose = MaybeEmitParens(outerPrec, kPrecedence_Postfix); + bool needClose = MaybeEmitParens(outerPrec, prec); - EmitExprWithPrecedence(indexExpr->BaseExpression, kPrecedence_Postfix); + EmitExprWithPrecedence(subscriptExpr->BaseExpression, leftSide(outerPrec, prec)); Emit("["); - EmitExpr(indexExpr->IndexExpression); + if (auto indexExpr = subscriptExpr->IndexExpression) + { + EmitExpr(indexExpr); + } Emit("]"); if(needClose) Emit(")"); } - void visitOverloadedExpr(OverloadedExpr* expr, ExprEmitArg const& arg) + void visitOverloadedExpr(OverloadedExpr* expr, ExprEmitArg const&) { emitName(expr->lookupResult2.getName()); } void visitVarExpressionSyntaxNode(VarExpressionSyntaxNode* varExpr, ExprEmitArg const& arg) { - bool needClose = MaybeEmitParens(arg.outerPrec, kPrecedence_Atomic); + auto prec = kEOp_Atomic; + auto outerPrec = arg.outerPrec; + bool needClose = MaybeEmitParens(outerPrec, kEOp_Atomic); // TODO: This won't be valid if we had to generate a qualified // reference for some reason. @@ -1696,7 +1911,7 @@ struct EmitVisitor } else { - emitName(varExpr->name); + emit(varExpr->name); } if(needClose) Emit(")"); @@ -1704,16 +1919,14 @@ struct EmitVisitor void visitDerefExpr(DerefExpr* derefExpr, ExprEmitArg const& arg) { - auto outerPrec = arg.outerPrec; - // TODO(tfoley): dereference shouldn't always be implicit - EmitExprWithPrecedence(derefExpr->base, outerPrec); + ExprVisitorWithArg::dispatch(derefExpr->base, arg); } void visitConstantExpressionSyntaxNode(ConstantExpressionSyntaxNode* litExpr, ExprEmitArg const& arg) { auto outerPrec = arg.outerPrec; - bool needClose = MaybeEmitParens(outerPrec, kPrecedence_Atomic); + bool needClose = MaybeEmitParens(outerPrec, kEOp_Atomic); char const* suffix = ""; auto type = litExpr->Type.type; @@ -1775,6 +1988,13 @@ struct EmitVisitor if(needClose) Emit(")"); } + void visitHiddenImplicitCastExpr(HiddenImplicitCastExpr* castExpr, ExprEmitArg const& arg) + { + // This was an implicit cast inserted in code parsed in "rewriter" mode, + // so we don't want to output it and change what the user's code looked like. + ExprVisitorWithArg::dispatch(castExpr->Expression, arg); + } + void visitTypeCastExpressionSyntaxNode(TypeCastExpressionSyntaxNode* castExpr, ExprEmitArg const& arg) { bool needClose = false; @@ -1791,19 +2011,23 @@ struct EmitVisitor default: // HLSL (and C/C++) prefer cast syntax // (In fact, HLSL doesn't allow constructor syntax for some conversions it allows as a cast) - needClose = MaybeEmitParens(arg.outerPrec, kPrecedence_Prefix); - - Emit("("); - EmitType(castExpr->Type); - Emit(")("); - EmitExpr(castExpr->Expression); - Emit(")"); + { + auto prec = kEOp_Prefix; + auto outerPrec = arg.outerPrec; + needClose = MaybeEmitParens(outerPrec, prec); + + Emit("("); + EmitType(castExpr->Type); + Emit(")("); + EmitExpr(castExpr->Expression); + Emit(")"); + } break; } if(needClose) Emit(")"); } - void visitInitializerListExpr(InitializerListExpr* expr, ExprEmitArg const& arg) + void visitInitializerListExpr(InitializerListExpr* expr, ExprEmitArg const&) { Emit("{ "); for(auto& arg : expr->args) @@ -1858,7 +2082,6 @@ struct EmitVisitor } } - void EmitUnparsedStmt(RefPtr<UnparsedStmt> stmt) { // TODO: actually emit the tokens that made up the statement... @@ -1946,12 +2169,10 @@ struct EmitVisitor // The one wrinkle is that HLSL implements the // bad approach to scoping a `for` loop variable, // so we need to avoid those outer `{...}` when - // we are generating HLSL via "rewrite" (that is, - // without our semantic checks). + // we are emitting code that was written in HLSL. // bool brokenScoping = false; - if (context->shared->target == CodeGenTarget::HLSL - && context->isRewrite) + if (forStmt.As<UnscopedForStmt>()) { brokenScoping = true; } @@ -3001,165 +3222,8 @@ struct EmitVisitor throw "unimplemented"; } } - - void registerReservedWord( - String const& name) - { - context->shared->reservedWords.Add(name, name); - } - - void registerReservedWords() - { - #define WORD(NAME) registerReservedWord(#NAME) - - switch (context->shared->target) - { - case CodeGenTarget::GLSL: - WORD(attribute); - WORD(const); - WORD(uniform); - WORD(varying); - WORD(buffer); - - WORD(shared); - WORD(coherent); - WORD(volatile); - WORD(restrict); - WORD(readonly); - WORD(writeonly); - WORD(atomic_unit); - WORD(layout); - WORD(centroid); - WORD(flat); - WORD(smooth); - WORD(noperspective); - WORD(patch); - WORD(sample); - WORD(break); - WORD(continue); - WORD(do); - WORD(for); - WORD(while); - WORD(switch); - WORD(case); - WORD(default); - WORD(if); - WORD(else); - WORD(subroutine); - WORD(in); - WORD(out); - WORD(inout); - WORD(float); - WORD(double); - WORD(int); - WORD(void); - WORD(bool); - WORD(true); - WORD(false); - WORD(invariant); - WORD(precise); - WORD(discard); - WORD(return); - - WORD(lowp); - WORD(mediump); - WORD(highp); - WORD(precision); - WORD(struct); - WORD(uint); - - WORD(common); - WORD(partition); - WORD(active); - WORD(asm); - WORD(class); - WORD(union); - WORD(enum); - WORD(typedef); - WORD(template); - WORD(this); - WORD(resource); - - WORD(goto); - WORD(inline); - WORD(noinline); - WORD(public); - WORD(static); - WORD(extern); - WORD(external); - WORD(interface); - WORD(long); - WORD(short); - WORD(half); - WORD(fixed); - WORD(unsigned); - WORD(superp); - WORD(input); - WORD(output); - WORD(filter); - WORD(sizeof); - WORD(cast); - WORD(namespace); - WORD(using); - - #define CASE(NAME) \ - WORD(NAME ## 2); WORD(NAME ## 3); WORD(NAME ## 4) - - CASE(mat); - CASE(dmat); - CASE(mat2x); - CASE(mat3x); - CASE(mat4x); - CASE(dmat2x); - CASE(dmat3x); - CASE(dmat4x); - CASE(vec); - CASE(ivec); - CASE(bvec); - CASE(dvec); - CASE(uvec); - CASE(hvec); - CASE(fvec); - - #undef CASE - - #define CASE(NAME) \ - WORD(NAME ## 1D); \ - WORD(NAME ## 2D); \ - WORD(NAME ## 3D); \ - WORD(NAME ## Cube); \ - WORD(NAME ## 1DArray); \ - WORD(NAME ## 2DArray); \ - WORD(NAME ## 3DArray); \ - WORD(NAME ## CubeArray);\ - WORD(NAME ## 2DMS); \ - WORD(NAME ## 2DMSArray) \ - /* end */ - - #define CASE2(NAME) \ - CASE(NAME); \ - CASE(i ## NAME); \ - CASE(u ## NAME) \ - /* end */ - - CASE2(sampler); - CASE2(image); - CASE2(texture); - - #undef CASE2 - #undef CASE - break; - - default: - break; - } - } }; -bool isRewriteRequest( - SourceLanguage sourceLanguage, - CodeGenTarget target); - String emitEntryPoint( EntryPointRequest* entryPoint, ProgramLayout* programLayout, @@ -3215,15 +3279,9 @@ String emitEntryPoint( EmitContext context; context.shared = &sharedContext; - context.isRewrite = isRewriteRequest( - translationUnit->sourceLanguage, - target); EmitVisitor visitor(&context); - // TODO: this should only need to take the shared context - visitor.registerReservedWords(); - auto translationUnitSyntax = translationUnit->SyntaxNode.Ptr(); |
