summaryrefslogtreecommitdiffstats
path: root/source/slang/emit.cpp
diff options
context:
space:
mode:
authorTim Foley <tfoley@nvidia.com>2017-06-16 09:09:09 -0700
committerTim Foley <tfoley@nvidia.com>2017-06-16 09:09:09 -0700
commit9ba8ce30f8314a79169e6d9cfa12e5db7239693f (patch)
tree587db9fd5b9920f39104ea6467de59d265188370 /source/slang/emit.cpp
parent0bf3d6d4db7409fcd288ff69e75e8e8b4f082969 (diff)
Bug fix: handle unchecked operator application in emit logic
When in rewriter mode, the emit logic will never see function applications inside function bodies, but it *will* see function application expressions at global scope, and some of these expressions might be unchecked. The challenge here is that even simple math operations now show up as function calls, so we need a bit of special-case logic to detect unchecked calls and then emit them using the syntax they were written with (e.g., use infix syntax if they were written as an infix expression).
Diffstat (limited to 'source/slang/emit.cpp')
-rw-r--r--source/slang/emit.cpp126
1 files changed, 88 insertions, 38 deletions
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index a2a1e9e21..ef5df830f 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -448,6 +448,51 @@ static String getStringOrIdentifierTokenValue(
}
}
+// Emit a call expression that doesn't involve any special cases,
+// just an expression of the form `f(a0, a1, ...)`
+static void emitSimpleCallExpr(
+ EmitContext* context,
+ RefPtr<InvokeExpressionSyntaxNode> callExpr,
+ int outerPrec)
+{
+ bool needClose = MaybeEmitParens(context, outerPrec, kPrecedence_Postfix);
+
+ auto funcExpr = callExpr->FunctionExpr;
+ if (auto funcDeclRefExpr = funcExpr.As<DeclRefExpr>())
+ {
+ auto declRef = funcDeclRefExpr->declRef;
+ if (auto ctorDeclRef = declRef.As<ConstructorDecl>())
+ {
+ // We really want to emit a reference to the type begin constructed
+ EmitType(context, callExpr->Type);
+ }
+ else
+ {
+ // default case: just emit the decl ref
+ EmitExpr(context, funcExpr);
+ }
+ }
+ else
+ {
+ // default case: just emit the expression
+ EmitPostfixExpr(context, funcExpr);
+ }
+
+ Emit(context, "(");
+ int argCount = callExpr->Arguments.Count();
+ for (int aa = 0; aa < argCount; ++aa)
+ {
+ if (aa != 0) Emit(context, ", ");
+ EmitExpr(context, callExpr->Arguments[aa]);
+ }
+ Emit(context, ")");
+
+ if (needClose)
+ {
+ Emit(context, ")");
+ }
+}
+
static void emitCallExpr(
EmitContext* context,
RefPtr<InvokeExpressionSyntaxNode> callExpr,
@@ -458,7 +503,47 @@ static void emitCallExpr(
{
auto funcDeclRef = funcDeclRefExpr->declRef;
auto funcDecl = funcDeclRef.getDecl();
- if (auto intrinsicOpModifier = funcDecl->FindModifier<IntrinsicOpModifier>())
+ 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(
+ context,
+ outerPrec,
+ kPrecedence_Comma,
+ funcDeclRefExpr->name.Buffer(),
+ callExpr);
+ }
+ else if( auto prefixExpr = callExpr.As<PrefixExpr>() )
+ {
+ EmitUnaryExpr(
+ context,
+ outerPrec,
+ kPrecedence_Prefix,
+ funcDeclRefExpr->name.Buffer(),
+ "",
+ callExpr);
+ }
+ else if(auto postfixExpr = callExpr.As<PostfixExpr>())
+ {
+ EmitUnaryExpr(
+ context,
+ outerPrec,
+ kPrecedence_Postfix,
+ "",
+ funcDeclRefExpr->name.Buffer(),
+ callExpr);
+ }
+ else
+ {
+ emitSimpleCallExpr(context, callExpr, outerPrec);
+ }
+ return;
+ }
+ else if (auto intrinsicOpModifier = funcDecl->FindModifier<IntrinsicOpModifier>())
{
switch (intrinsicOpModifier->op)
{
@@ -641,42 +726,7 @@ static void emitCallExpr(
}
// Fall through to default handling...
-
- bool needClose = MaybeEmitParens(context, outerPrec, kPrecedence_Postfix);
-
- if (auto funcDeclRefExpr = funcExpr.As<DeclRefExpr>())
- {
- auto declRef = funcDeclRefExpr->declRef;
- if (auto ctorDeclRef = declRef.As<ConstructorDecl>())
- {
- // We really want to emit a reference to the type begin constructed
- EmitType(context, callExpr->Type);
- }
- else
- {
- // default case: just emit the decl ref
- EmitExpr(context, funcExpr);
- }
- }
- else
- {
- // default case: just emit the expression
- EmitPostfixExpr(context, funcExpr);
- }
-
- Emit(context, "(");
- int argCount = callExpr->Arguments.Count();
- for (int aa = 0; aa < argCount; ++aa)
- {
- if (aa != 0) Emit(context, ", ");
- EmitExpr(context, callExpr->Arguments[aa]);
- }
- Emit(context, ")");
-
- if (needClose)
- {
- Emit(context, ")");
- }
+ emitSimpleCallExpr(context, callExpr, outerPrec);
}
static void EmitExprWithPrecedence(EmitContext* context, RefPtr<ExpressionSyntaxNode> expr, int outerPrec)
@@ -761,7 +811,7 @@ static void EmitExprWithPrecedence(EmitContext* context, RefPtr<ExpressionSyntax
}
else
{
- emitName(context, varExpr->Variable);
+ emitName(context, varExpr->name);
}
}
else if (auto derefExpr = expr.As<DerefExpr>())