diff options
Diffstat (limited to 'source/slang/emit.cpp')
| -rw-r--r-- | source/slang/emit.cpp | 96 |
1 files changed, 72 insertions, 24 deletions
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp index 6440c63a3..2deb0cea7 100644 --- a/source/slang/emit.cpp +++ b/source/slang/emit.cpp @@ -1367,7 +1367,7 @@ struct EmitVisitor { if(auto typeCastExpr = expr.As<TypeCastExpr>()) { - expr = typeCastExpr->Expression; + expr = typeCastExpr->Arguments[0]; } // TODO: any other cases? else @@ -1519,14 +1519,66 @@ struct EmitVisitor return bestModifier; } + void emitSimpleCallArgs( + RefPtr<InvokeExpr> callExpr) + { + Emit("("); + UInt argCount = callExpr->Arguments.Count(); + for (UInt aa = 0; aa < argCount; ++aa) + { + if (aa != 0) Emit(", "); + EmitExpr(callExpr->Arguments[aa]); + } + Emit(")"); + } + + void emitSimpleConstructorCallExpr( + RefPtr<InvokeExpr> callExpr, + EOpInfo outerPrec) + { + if(context->shared->target == CodeGenTarget::HLSL) + { + // HLSL needs to special-case a constructor call with a single argument. + if(callExpr->Arguments.Count() == 1) + { + auto prec = kEOp_Prefix; + bool needClose = MaybeEmitParens(outerPrec, prec); + + Emit("("); + EmitType(callExpr->type); + Emit(") "); + + EmitExprWithPrecedence(callExpr->Arguments[0], rightSide(outerPrec, prec)); + + if(needClose) Emit(")"); + return; + } + } + + + // Default handling is to emit what amounts to an ordinary call, + // but using the type of the expression directly as the "function" to call. + auto prec = kEOp_Postfix; + bool needClose = MaybeEmitParens(outerPrec, prec); + + EmitType(callExpr->type); + + emitSimpleCallArgs(callExpr); + + if (needClose) + { + Emit(")"); + } + } + // Emit a call expression that doesn't involve any special cases, // just an expression of the form `f(a0, a1, ...)` void emitSimpleCallExpr( RefPtr<InvokeExpr> callExpr, EOpInfo outerPrec) { - auto prec = kEOp_Postfix; - bool needClose = MaybeEmitParens(outerPrec, prec); + // We will first check if this represents a constructor call, + // since those may need to be handled differently. auto funcExpr = callExpr->FunctionExpr; if (auto funcDeclRefExpr = funcExpr.As<DeclRefExpr>()) @@ -1534,29 +1586,20 @@ struct EmitVisitor auto declRef = funcDeclRefExpr->declRef; if (auto ctorDeclRef = declRef.As<ConstructorDecl>()) { - // We really want to emit a reference to the type begin constructed - EmitType(callExpr->type); - } - else - { - // default case: just emit the decl ref - EmitExprWithPrecedence(funcExpr, leftSide(outerPrec, prec)); + emitSimpleConstructorCallExpr(callExpr, outerPrec); + return; } } - else - { - // default case: just emit the expression - EmitExprWithPrecedence(funcExpr, leftSide(outerPrec, prec)); - } - Emit("("); - UInt argCount = callExpr->Arguments.Count(); - for (UInt aa = 0; aa < argCount; ++aa) - { - if (aa != 0) Emit(", "); - EmitExpr(callExpr->Arguments[aa]); - } - Emit(")"); + // Once we've ruled out constructor calls, we can move on + // to just emitting an ordinary calll expression. + + auto prec = kEOp_Postfix; + bool needClose = MaybeEmitParens(outerPrec, prec); + + EmitExprWithPrecedence(funcExpr, leftSide(outerPrec, prec)); + + emitSimpleCallArgs(callExpr); if (needClose) { @@ -2416,11 +2459,15 @@ struct EmitVisitor { // 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); + ExprVisitorWithArg::dispatch(castExpr->Arguments[0], arg); } void visitTypeCastExpr(TypeCastExpr* castExpr, ExprEmitArg const& arg) { + // We emit a type cast expression as a constructor call + emitSimpleConstructorCallExpr(castExpr, arg.outerPrec); + +#if 0 bool needClose = false; switch(context->shared->target) { @@ -2449,6 +2496,7 @@ struct EmitVisitor break; } if(needClose) Emit(")"); +#endif } void visitInitializerListExpr(InitializerListExpr* expr, ExprEmitArg const&) |
