summaryrefslogtreecommitdiffstats
path: root/source/slang/lower.cpp
diff options
context:
space:
mode:
authorTim Foley <tfoley@nvidia.com>2017-08-31 14:13:28 -0700
committerTim Foley <tfoley@nvidia.com>2017-09-05 12:15:28 -0700
commitff7c190b838dffc79e5acd555f41506cb52a9f47 (patch)
treea4543443ab301cf946089904e889d7018b08252e /source/slang/lower.cpp
parent620734080f825cb205b887fa1d6203e35dd60663 (diff)
Move implicit conversion operations to stdlib
- Previously, there were a variety of rules in `check.cpp` to pick the conversion cost for various cases involving scalar, vector, and matrix types. - The main problem of the previous approach is that any lowering pass would need to convert an arbitrary "type cast" node into the right low-level operation(s). - The new approach is that a type conversion (implicit or explicit) always resolves as a call to a constructor/initializer for the destination type. This means that the existing rules around marking operations as builtins should work for lowering. - The support this, the checking logic needs to perform lookup of intializers/constructors when asked to perform conversion between types. It does this by re-using the existing logic for lookup and overload resolution if/when a type was applied in an ordinary context. - Next, we define a modifier that can be attached to constructors/initializers to mark them as suitable for implicit conversion, and associate them with the correct cost to be used when doing overload comparisons. - We add the modifier to all the scalar-to-scalar cases in the stdlib, using the logic that previously existed in semantic checking. - Next we add cases for general vector-to-scalar conversions that also convert type, using the same cost computation as above. - This probably misses various cases, but at this point they can hopefully be added just in the stdlib. - One gotcha here is that in lowering, we need to make sure to lower any kind of call expression to another call expression of the same AST node class, so that we don't lose information on what casts were implicit/hidden in teh source-to-source case. Two notes for potential longer-term changes: 1. There is still some duplication between the type conversion declarations here and the "join" logic for types used for generic arguments. Ideally we'd eventually clean up the "join" logic to be based on convertability, but that isn't a high priority right now, as long as joins continue to pick the right type. 2. It is a bit gross to have to declare all the N^2 conversions for vector/matrix types to duplicate the cases for scalars. For the simple scalar-to-vector case, we might try to support multiple conversion "steps" where both a scalar-to-scalar and a scalar-to-vector step can be allowed (this could be tagged on the modifiers already introduced). That simple option doesn't scale to vector-to-vector element type conversions, though, where you'd really want to make it a generic with a constraint like: vector<T,N> init<U>(vector<U,N> value) where T : ConvertibleFrom<U>; Here the `ConvertibleFrom<U>` interface expresses the fact that a conforming type has an initializer that takes a `U`. What doesn't appear in this context is any notion of conversion costs. We'd need some kind of system for computing the conversion cost of the vector conversion from the cost of the `T` to `U` converion.
Diffstat (limited to 'source/slang/lower.cpp')
-rw-r--r--source/slang/lower.cpp42
1 files changed, 20 insertions, 22 deletions
diff --git a/source/slang/lower.cpp b/source/slang/lower.cpp
index 7a487d29f..f0d756a02 100644
--- a/source/slang/lower.cpp
+++ b/source/slang/lower.cpp
@@ -1781,19 +1781,9 @@ struct LoweringVisitor
LoweredExpr visitInvokeExpr(
InvokeExpr* expr)
{
- return LoweredExpr(lowerCallExpr(new InvokeExpr(), expr));
- }
-
- LoweredExpr visitInfixExpr(
- InfixExpr* expr)
- {
- return LoweredExpr(lowerCallExpr(new InfixExpr(), expr));
- }
-
- LoweredExpr visitPrefixExpr(
- PrefixExpr* expr)
- {
- return LoweredExpr(lowerCallExpr(new PrefixExpr(), expr));
+ // Create a clone with the same class
+ InvokeExpr* loweredExpr = (InvokeExpr*) expr->getClass().createInstance();
+ return LoweredExpr(lowerCallExpr(loweredExpr, expr));
}
LoweredExpr visitSelectExpr(
@@ -1804,12 +1794,6 @@ struct LoweringVisitor
return LoweredExpr(lowerCallExpr(new SelectExpr(), expr));
}
- LoweredExpr visitPostfixExpr(
- PostfixExpr* expr)
- {
- return LoweredExpr(lowerCallExpr(new PostfixExpr(), expr));
- }
-
LoweredExpr visitDerefExpr(
DerefExpr* expr)
{
@@ -2412,15 +2396,29 @@ struct LoweringVisitor
assign(expr, LoweredExpr(createVarRef(getPosition(expr), varDecl)));
}
+ RefPtr<Expr> createTypeExpr(
+ RefPtr<Type> type)
+ {
+ auto typeType = new TypeType();
+ typeType->type = type;
+
+ auto result = new SharedTypeExpr();
+ result->base.type = type;
+ result->type.type = typeType;
+
+ return result;
+ }
+
RefPtr<Expr> createCastExpr(
- RefPtr<Type> type,
+ RefPtr<Type> type,
RefPtr<Expr> expr)
{
RefPtr<ExplicitCastExpr> castExpr = new ExplicitCastExpr();
castExpr->loc = expr->loc;
castExpr->type.type = type;
- castExpr->TargetType.type = type;
- castExpr->Expression = expr;
+
+ castExpr->FunctionExpr = createTypeExpr(type);
+ castExpr->Arguments.Add(expr);
return castExpr;
}