summaryrefslogtreecommitdiff
path: root/source/slang/slang-ir-constexpr.cpp
diff options
context:
space:
mode:
authorGangzheng Tong <tonggangzheng@gmail.com>2025-09-16 12:51:43 -0700
committerGitHub <noreply@github.com>2025-09-16 19:51:43 +0000
commitafb8146e10626887e3eb9f479480d4f8a1ad6128 (patch)
tree4a11668df1005f4c15e7e25d27615e3116961356 /source/slang/slang-ir-constexpr.cpp
parent8ad0ae17880480abe587617c997ab28b23abc146 (diff)
Diagnose error when the function args can't satisfy constexpr parameter requirements (#7269)
## Summary This PR enhances constexpr validation by adding proper error checking when function arguments cannot satisfy constexpr parameter requirements, addressing issue #6370. ## Problem Previously, when a function declared constexpr parameters, the compiler would attempt to propagate constexpr-ness to the call site arguments, but there was insufficient validation and error reporting when this propagation failed. This could lead silent failures where constexpr requirements weren't properly enforced ## Solution This PR adds checks that: 1. **Validates constexpr arguments**: When a function parameter is marked as `constexpr`, the compiler now explicitly checks that the corresponding argument can be marked as `constexpr` 2. **Issues clear compilation errors**: added `Diagnostics::argIsNotConstexpr`) 3. **Handles both call scenarios**: The validation works for both: - Direct function calls with IR-level function definitions - Calls to function from external modules Fixes #6370 --------- Co-authored-by: slangbot <ellieh+slangbot@nvidia.com> Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com>
Diffstat (limited to 'source/slang/slang-ir-constexpr.cpp')
-rw-r--r--source/slang/slang-ir-constexpr.cpp92
1 files changed, 32 insertions, 60 deletions
diff --git a/source/slang/slang-ir-constexpr.cpp b/source/slang/slang-ir-constexpr.cpp
index 0bdbe260a..825bc5c98 100644
--- a/source/slang/slang-ir-constexpr.cpp
+++ b/source/slang/slang-ir-constexpr.cpp
@@ -3,6 +3,7 @@
#include "slang-ir-dominators.h"
#include "slang-ir-insts.h"
+#include "slang-ir-util.h"
#include "slang-ir.h"
namespace Slang
@@ -59,8 +60,12 @@ bool isConstExpr(IRInst* value)
case kIROp_StructKey:
case kIROp_WitnessTable:
case kIROp_Generic:
+ case kIROp_GlobalConstant:
return true;
-
+ case kIROp_Param:
+ if (isGenericParam(value))
+ return true;
+ break;
default:
break;
}
@@ -156,8 +161,10 @@ bool opCanBeConstExprByForwardPass(IRInst* value)
{
// TODO: handle call inst here.
- if (value->getOp() == kIROp_Param)
+ if (value->getOp() == kIROp_Param || value->getOp() == kIROp_Specialize)
+ {
return false;
+ }
return opCanBeConstExpr(value->getOp());
}
@@ -393,12 +400,6 @@ bool propagateConstExprBackward(PropagateConstExprContext* context, IRGlobalValu
// the callee for this call statically, and if so try to propagate
// constexpr from the parameters back to the arguments.
auto callInst = (IRCall*)ii;
-
- UInt operandCount = callInst->getOperandCount();
-
- UInt firstCallArg = 1;
- UInt callArgCount = operandCount - firstCallArg;
-
auto callee = callInst->getOperand(0);
// If we are calling a generic operation, then
@@ -423,64 +424,35 @@ bool propagateConstExprBackward(PropagateConstExprContext* context, IRGlobalValu
}
auto calleeFunc = as<IRFunc>(callee);
- if (calleeFunc && isDefinition(calleeFunc))
+ auto calleeType = callee->getDataType();
+ if (auto caleeFuncType = as<IRFuncType>(calleeType))
{
- // We have an IR-level function definition we are calling,
- // and thus we can propagate `constexpr` information
- // through its `IRParam`s.
-
- auto calleeFuncType = calleeFunc->getDataType();
-
- UInt callParamCount = calleeFuncType->getParamCount();
- SLANG_RELEASE_ASSERT(callParamCount == callArgCount);
-
- // If the callee has a definition, then we can read `constexpr`
- // information off of the parameters of its first IR block.
- if (auto calleeFirstBlock = calleeFunc->getFirstBlock())
+ UInt operandCount = callInst->getOperandCount();
+ UInt firstCallArg = 1;
+ UInt callArgCount = operandCount - firstCallArg;
+ auto paramCount = caleeFuncType->getParamCount();
+ SLANG_RELEASE_ASSERT(paramCount == callArgCount);
+ for (UInt pp = 0; pp < paramCount; ++pp)
{
- UInt paramCounter = 0;
- for (auto pp = calleeFirstBlock->getFirstParam(); pp;
- pp = pp->getNextParam())
+ auto paramType = caleeFuncType->getParamType(pp);
+ if (isConstExpr(paramType))
{
- UInt paramIndex = paramCounter++;
-
- auto param = pp;
- auto arg = callInst->getOperand(firstCallArg + paramIndex);
-
- if (isConstExpr(param))
+ auto arg = callInst->getOperand(firstCallArg + pp);
+ if (maybeMarkConstExprBackwardPass(context, arg))
{
- if (maybeMarkConstExprBackwardPass(context, arg))
- {
- changedThisIteration = true;
- }
+ changedThisIteration = true;
}
- }
- }
- }
- else
- {
- // If we don't have a concrete callee function
- // definition, then we need to extract the
- // type of the callee instruction, and try to work
- // with that.
- //
- // Note that this does not allow us to propagate
- // `constexpr` information from the body of a callee
- // back to call sites.
- auto calleeType = callee->getDataType();
- if (auto caleeFuncType = as<IRFuncType>(calleeType))
- {
- auto paramCount = caleeFuncType->getParamCount();
- for (UInt pp = 0; pp < paramCount; ++pp)
- {
- auto paramType = caleeFuncType->getParamType(pp);
- auto arg = callInst->getOperand(firstCallArg + pp);
- if (isConstExpr(paramType))
+ // If arg is not constexpr after this, meaning it can't be
+ // marked constexpr for some reason, but the param requires
+ // that. This is not expected.
+ if (!isConstExpr(arg))
{
- if (maybeMarkConstExprBackwardPass(context, arg))
- {
- changedThisIteration = true;
- }
+ context->getSink()->diagnose(
+ callInst->sourceLoc,
+ Diagnostics::argIsNotConstexpr,
+ pp + 1,
+ calleeFunc);
+ return false;
}
}
}