summaryrefslogtreecommitdiffstats
path: root/source/slang/lower-to-ir.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/lower-to-ir.cpp')
-rw-r--r--source/slang/lower-to-ir.cpp136
1 files changed, 102 insertions, 34 deletions
diff --git a/source/slang/lower-to-ir.cpp b/source/slang/lower-to-ir.cpp
index b99e2713f..8c858f4f3 100644
--- a/source/slang/lower-to-ir.cpp
+++ b/source/slang/lower-to-ir.cpp
@@ -4,6 +4,7 @@
#include "../../slang.h"
#include "ir.h"
+#include "ir-constexpr.h"
#include "ir-insts.h"
#include "ir-ssa.h"
#include "mangle.h"
@@ -1262,7 +1263,7 @@ struct ExprLoweringVisitorBase : ExprVisitor<Derived, LoweredValInfo>
// need to extract the value type from that pointer here.
//
IRValue* loweredBaseVal = getSimpleVal(context, loweredBase);
- RefPtr<Type> loweredBaseType = loweredBaseVal->getType();
+ RefPtr<Type> loweredBaseType = loweredBaseVal->getDataType();
if (loweredBaseType->As<PointerLikeType>()
|| loweredBaseType->As<PtrTypeBase>())
@@ -2580,7 +2581,7 @@ static LoweredValInfo maybeMoveMutableTemp(
default:
{
IRValue* irVal = getSimpleVal(context, val);
- auto type = irVal->getType();
+ auto type = irVal->getDataType();
auto var = createVar(context, type);
assign(context, var, LoweredValInfo::simple(irVal));
@@ -2660,7 +2661,7 @@ top:
// Now apply the swizzle
IRInst* irSwizzled = builder->emitSwizzleSet(
- irLeftVal->getType(),
+ irLeftVal->getDataType(),
irLeftVal,
irRightVal,
swizzleInfo->elementCount,
@@ -3503,6 +3504,30 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
return false;
}
+ bool isConstExprVar(Decl* decl)
+ {
+ if( decl->HasModifier<ConstExprModifier>() )
+ {
+ return true;
+ }
+ else if(decl->HasModifier<HLSLStaticModifier>() && decl->HasModifier<ConstModifier>())
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ RefPtr<Type> maybeGetConstExprType(Type* type, Decl* decl)
+ {
+ if(isConstExprVar(decl))
+ {
+ return context->getSession()->getConstExprType(type);
+ }
+
+ return type;
+ }
+
LoweredValInfo lowerFuncDecl(FunctionDeclBase* decl)
{
// Collect the parameter lists we will use for our new function.
@@ -3563,11 +3588,11 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
for( auto paramInfo : parameterLists.params )
{
RefPtr<Type> irParamType = lowerSimpleType(context, paramInfo.type);
+
switch( paramInfo.direction )
{
case kParameterDirection_In:
// Simple case of a by-value input parameter.
- paramTypes.Add(irParamType);
break;
// If the parameter is declared `out` or `inout`,
@@ -3575,18 +3600,26 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
// the IR, but we will use a specialized pointer
// type that encodes the parameter direction information.
case kParameterDirection_Out:
- paramTypes.Add(
- context->getSession()->getOutType(irParamType));
+ irParamType = context->getSession()->getOutType(irParamType);
break;
case kParameterDirection_InOut:
- paramTypes.Add(
- context->getSession()->getInOutType(irParamType));
+ irParamType = context->getSession()->getInOutType(irParamType);
break;
default:
SLANG_UNEXPECTED("unknown parameter direction");
break;
}
+
+ // If the parameter was explicitly marked as being a compile-time
+ // constant (`constexpr`), then attach that information to its
+ // IR-level type explicitly.
+ if( paramInfo.decl )
+ {
+ irParamType = maybeGetConstExprType(irParamType, paramInfo.decl);
+ }
+
+ paramTypes.Add(irParamType);
}
auto irResultType = lowerSimpleType(context, declForReturnType->ReturnType);
@@ -3600,11 +3633,6 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
//
IRType* irParamType = irResultType;
paramTypes.Add(irParamType);
- subBuilder->emitParam(irParamType);
-
- // TODO: we need some way to wire this up to the `newValue`
- // or whatever name we give for that parameter inside
- // the setter body.
// Instead, a setter always returns `void`
//
@@ -3660,11 +3688,11 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
//
// TODO: Is this the best representation we can use?
- auto irPtrType = irParamType.As<PtrTypeBase>();
-
- IRParam* irParamPtr = subBuilder->emitParam(irPtrType);
+ IRParam* irParamPtr = subBuilder->emitParam(irParamType);
if(auto paramDecl = paramInfo.decl)
+ {
subBuilder->addHighLevelDeclDecoration(irParamPtr, paramDecl);
+ }
paramVal = LoweredValInfo::ptr(irParamPtr);
@@ -3682,27 +3710,51 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
case kParameterDirection_In:
{
// Simple case of a by-value input parameter.
- // But note that HLSL allows an input parameter
- // to be used as a local variable inside of a
- // function body, so we need to introduce a temporary
- // and then copy over to it...
//
- // TODO: we could skip this step if we knew
- // the parameter was marked `const` or similar.
-
- paramTypes.Add(irParamType);
-
+ // We start by declaring an IR parameter of the same type.
+ //
+ auto paramDecl = paramInfo.decl;
IRParam* irParam = subBuilder->emitParam(irParamType);
- if(auto paramDecl = paramInfo.decl)
+ if( paramDecl )
+ {
subBuilder->addHighLevelDeclDecoration(irParam, paramDecl);
+ }
paramVal = LoweredValInfo::simple(irParam);
-
- auto irLocal = subBuilder->emitVar(irParamType);
- auto localVal = LoweredValInfo::ptr(irLocal);
-
- assign(subContext, localVal, paramVal);
-
- paramVal = localVal;
+ //
+ // HLSL allows a function parameter to be used as a local
+ // variable in the function body (just like C/C++), so
+ // we need to support that case as well.
+ //
+ // However, if we notice that the parameter was marked
+ // `const`, then we can skip this step.
+ //
+ // TODO: we should consider having all parameter be implicitly
+ // immutable except in a specific "compatibility mode."
+ //
+ if(paramDecl && paramDecl->FindModifier<ConstModifier>())
+ {
+ // This parameter was declared to be immutable,
+ // so there should be no assignment to it in the
+ // function body, and we don't need a temporary.
+ }
+ else
+ {
+ // The parameter migth get used as a temporary in
+ // the function body. We will allocate a mutable
+ // local variable for is value, and then assign
+ // from the parameter to the local at the start
+ // of the function.
+ //
+ auto irLocal = subBuilder->emitVar(irParamType);
+ auto localVal = LoweredValInfo::ptr(irLocal);
+ assign(subContext, localVal, paramVal);
+ //
+ // When code later in the body of the function refers
+ // to the parameter declaration, it will actually refer
+ // to the value stored in the local variable.
+ //
+ paramVal = localVal;
+ }
}
break;
}
@@ -3719,6 +3771,18 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
}
}
+ if (auto setterDecl = dynamic_cast<SetterDecl*>(decl))
+ {
+ // Add the IR parameter for the new value
+ IRType* irParamType = irResultType;
+ subBuilder->emitParam(irParamType);
+
+ // TODO: we need some way to wire this up to the `newValue`
+ // or whatever name we give for that parameter inside
+ // the setter body.
+ }
+
+
lowerStmt(subContext, decl->Body);
// We need to carefully add a terminator instruction to the end
@@ -4070,7 +4134,7 @@ LoweredValInfo maybeEmitSpecializeInst(IRGenContext* context,
DeclRef<Decl> newDeclRef = DeclRef<Decl>(declRef.decl, lowedNewSubst);
RefPtr<Type> type;
- if (auto declType = val->getType())
+ if (auto declType = val->getDataType())
{
type = declType->Substitute(newDeclRef.substitutions).As<Type>();
}
@@ -4225,6 +4289,10 @@ IRModule* generateIRForTranslationUnit(
// TODO: Do basic constant folding and DCE
+ // Propagate `constexpr`-ness through the dataflow graph (and the
+ // call graph) based on constraints imposed by different instructions.
+ propagateConstExpr(module, &compileRequest->mSink);
+
// TODO: give error messages if any `undefined` or
// `unreachable` instructions remain.