summaryrefslogtreecommitdiffstats
path: root/source/slang/emit.cpp
diff options
context:
space:
mode:
authorTim Foley <tim.foley.is@gmail.com>2017-07-08 18:58:42 -0700
committerGitHub <noreply@github.com>2017-07-08 18:58:42 -0700
commit68df74b58a56b0a1fb19b9ec4ff0282969cd6a12 (patch)
tree5eaa7eaab892504db53cca4b8044b0c8bcde58b3 /source/slang/emit.cpp
parentc07a6e6b5f5e0e4839b435ff6c15b821b6dead11 (diff)
parent767d47a842700653b8deffe82ccb3c85ad582c13 (diff)
Merge pull request #60 from tfoleyNV/revise-rewriter
Revise rewriter
Diffstat (limited to 'source/slang/emit.cpp')
-rw-r--r--source/slang/emit.cpp766
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();