summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/slang/core.meta.slang6
-rw-r--r--source/slang/core.meta.slang.h6
-rw-r--r--source/slang/emit.cpp20
-rw-r--r--source/slang/hlsl.meta.slang47
-rw-r--r--source/slang/hlsl.meta.slang.h47
-rw-r--r--source/slang/ir-insts.h10
-rw-r--r--source/slang/ir-serialize.cpp7
-rw-r--r--source/slang/ir.cpp54
-rw-r--r--source/slang/ir.h13
-rw-r--r--source/slang/lower-to-ir.cpp5
-rw-r--r--source/slang/modifier-defs.h8
11 files changed, 164 insertions, 59 deletions
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang
index 0502c9bf6..26bf1112d 100644
--- a/source/slang/core.meta.slang
+++ b/source/slang/core.meta.slang
@@ -1238,3 +1238,9 @@ attribute_syntax [__vulkanHitAttributes] : VulkanHitAttributesAttribute;
__attributeTarget(FunctionDeclBase)
attribute_syntax [mutating] : MutatingAttribute;
+
+ /// Indicates that a function computes its result as a function of its arguments without loading/storing any memory or other state.
+ ///
+ /// This is equivalent to the LLVM `readnone` function attribute.
+__attributeTarget(FunctionDeclBase)
+attribute_syntax [__readNone] : ReadNoneAttribute;
diff --git a/source/slang/core.meta.slang.h b/source/slang/core.meta.slang.h
index 97a2d1edd..5380bd90f 100644
--- a/source/slang/core.meta.slang.h
+++ b/source/slang/core.meta.slang.h
@@ -1256,3 +1256,9 @@ SLANG_RAW("attribute_syntax [__vulkanHitAttributes] : VulkanHitAttributesAttribu
SLANG_RAW("\n")
SLANG_RAW("__attributeTarget(FunctionDeclBase)\n")
SLANG_RAW("attribute_syntax [mutating] : MutatingAttribute;\n")
+SLANG_RAW("\n")
+SLANG_RAW(" /// Indicates that a function computes its result as a function of its arguments without loading/storing any memory or other state.\n")
+SLANG_RAW(" ///\n")
+SLANG_RAW(" /// This is equivalent to the LLVM `readnone` function attribute.\n")
+SLANG_RAW("__attributeTarget(FunctionDeclBase)\n")
+SLANG_RAW("attribute_syntax [__readNone] : ReadNoneAttribute;\n")
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index bb9a6ad8b..5c39dd50c 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -1168,8 +1168,8 @@ struct EmitVisitor
switch (type->op)
{
case kIROp_RaytracingAccelerationStructureType:
- requireGLSLExtension("GL_NVX_raytracing");
- Emit("accelerationStructureNVX");
+ requireGLSLExtension("GL_NV_ray_tracing");
+ Emit("accelerationStructureNV");
break;
// TODO: These "translations" are obviously wrong for GLSL.
@@ -3332,17 +3332,17 @@ struct EmitVisitor
case 'T':
{
// The `$XT` case handles selecting between
- // the `gl_HitTNVX` and `gl_RayTmaxNVX` builtins,
+ // the `gl_HitTNV` and `gl_RayTmaxNV` builtins,
// based on what stage we are using:
switch( ctx->shared->entryPoint->getStage() )
{
default:
- Emit("gl_RayTmaxNVX");
+ Emit("gl_RayTmaxNV");
break;
case Stage::AnyHit:
case Stage::ClosestHit:
- Emit("gl_HitTNVX");
+ Emit("gl_HitTNV");
break;
}
}
@@ -5363,11 +5363,11 @@ struct EmitVisitor
emit("layout(location = ");
Emit(getRayPayloadLocation(ctx, varDecl));
emit(")\n");
- emit("rayPayloadNVX\n");
+ emit("rayPayloadNV\n");
}
if(varDecl->findDecoration<IRVulkanHitAttributesDecoration>())
{
- emit("hitAttributeNVX\n");
+ emit("hitAttributeNV\n");
}
if (!layout)
@@ -5516,13 +5516,13 @@ struct EmitVisitor
case LayoutResourceKind::RayPayload:
{
- emit("rayPayloadInNVX ");
+ emit("rayPayloadInNV ");
}
break;
case LayoutResourceKind::HitAttributes:
{
- emit("hitAttributeNVX ");
+ emit("hitAttributeNV ");
}
break;
@@ -6535,7 +6535,7 @@ String emitEntryPoint(
case Stage::RayGeneration:
if( target == CodeGenTarget::GLSL )
{
- requireGLSLExtension(&context.shared->extensionUsageTracker, "GL_NVX_raytracing");
+ requireGLSLExtension(&context.shared->extensionUsageTracker, "GL_NV_ray_tracing");
requireGLSLVersionImpl(&context.shared->extensionUsageTracker, ProfileVersion::GLSL_460);
}
break;
diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang
index c666dadd3..56741f6b3 100644
--- a/source/slang/hlsl.meta.slang
+++ b/source/slang/hlsl.meta.slang
@@ -1369,8 +1369,8 @@ void TraceRay<payload_t>(
RayDesc Ray,
inout payload_t Payload);
-__target_intrinsic(glsl, "traceNVX")
-void __traceNVX(
+__target_intrinsic(glsl, "traceNV")
+void __traceNV(
RaytracingAccelerationStructure AccelerationStructure,
uint RayFlags,
uint InstanceInclusionMask,
@@ -1391,6 +1391,7 @@ void __traceNVX(
//
__generic<Payload>
__target_intrinsic(glsl, "$XP")
+[__readNone]
int __rayPayloadLocation(Payload payload);
__generic<payload_t>
@@ -1409,7 +1410,7 @@ void TraceRay(
static payload_t p;
p = Payload;
- __traceNVX(
+ __traceNV(
AccelerationStructure,
RayFlags,
InstanceInclusionMask,
@@ -1427,8 +1428,8 @@ void TraceRay(
// 10.3.3
bool ReportHit<A>(float tHit, uint hitKind, A attributes);
-__target_intrinsic(glsl, "reportIntersectionNVX")
-bool __reportIntersectionNVX(float tHit, uint hitKind);
+__target_intrinsic(glsl, "reportIntersectionNV")
+bool __reportIntersectionNV(float tHit, uint hitKind);
__generic<A>
__specialized_for_target(glsl)
@@ -1438,15 +1439,15 @@ bool ReportHit(float tHit, uint hitKind, A attributes)
static A a;
a = attributes;
- return __reportIntersectionNVX(tHit, hitKind);
+ return __reportIntersectionNV(tHit, hitKind);
}
// 10.3.4
-__target_intrinsic(glsl, ignoreIntersectionNVX)
+__target_intrinsic(glsl, ignoreIntersectionNV)
void IgnoreHit();
// 10.3.5
-__target_intrinsic(glsl, terminateRayNVX)
+__target_intrinsic(glsl, terminateRayNV)
void AcceptHitAndEndSearch();
// 10.4 - System Values and Special Semantics
@@ -1456,25 +1457,25 @@ void AcceptHitAndEndSearch();
// 10.4.1 - Ray Dispatch System Values
-__target_intrinsic(glsl, "uvec3(gl_LaunchIDNVX, 0)")
+__target_intrinsic(glsl, "(gl_LaunchIDNV)")
uint3 DispatchRaysIndex();
-__target_intrinsic(glsl, "uvec3(gl_LaunchSizeNVX, 0)")
+__target_intrinsic(glsl, "(gl_LaunchSizeNV)")
uint3 DispatchRaysDimensions();
// 10.4.2 - Ray System Values
-__target_intrinsic(glsl, "(gl_WorldRayOriginNVX)")
+__target_intrinsic(glsl, "(gl_WorldRayOriginNV)")
float3 WorldRayOrigin();
-__target_intrinsic(glsl, "(gl_WorldRayDirectionNVX)")
+__target_intrinsic(glsl, "(gl_WorldRayDirectionNV)")
float3 WorldRayDirection();
-__target_intrinsic(glsl, "(gl_RayTminNVX)")
+__target_intrinsic(glsl, "(gl_RayTminNV)")
float RayTMin();
// Note: The `RayTCurrent()` intrinsic should translate to
-// either `gl_HitTNVX` (for hit shaders) or `gl_RayTmaxNVX`
+// either `gl_HitTNV` (for hit shaders) or `gl_RayTmaxNV`
// (for intersection shaders). Right now we are handling this
// during code emission, for simplicity.
//
@@ -1486,12 +1487,12 @@ float RayTMin();
__target_intrinsic(glsl, "$XT")
float RayTCurrent();
-__target_intrinsic(glsl, "(gl_RayFlagsNVX)")
+__target_intrinsic(glsl, "(gl_IncomingRayFlagsNV)")
uint RayFlags();
// 10.4.3 - Primitive/Object Space System Values
-__target_intrinsic(glsl, "(gl_InstanceCustomIndexNVX)")
+__target_intrinsic(glsl, "(gl_InstanceCustomIndexNV)")
uint InstanceIndex();
__target_intrinsic(glsl, "(gl_InstanceID)")
@@ -1500,22 +1501,22 @@ uint InstanceID();
__target_intrinsic(glsl, "(gl_PrimitiveID)")
uint PrimitiveIndex();
-__target_intrinsic(glsl, "(gl_ObjectRayOriginNVX)")
+__target_intrinsic(glsl, "(gl_ObjectRayOriginNV)")
float3 ObjectRayOrigin();
-__target_intrinsic(glsl, "(gl_ObjectRayDirectionNVX)")
+__target_intrinsic(glsl, "(gl_ObjectRayDirectionNV)")
float3 ObjectRayDirection();
-__target_intrinsic(glsl, "transpose(gl_ObjectToWorldNVX)")
+__target_intrinsic(glsl, "transpose(gl_ObjectToWorldNV)")
float3x4 ObjectToWorld3x4();
-__target_intrinsic(glsl, "transpose(gl_WorldToObjectNVX)")
+__target_intrinsic(glsl, "transpose(gl_WorldToObjectNV)")
float3x4 WorldToObject3x4();
-__target_intrinsic(glsl, "(gl_ObjectToWorldNVX)")
+__target_intrinsic(glsl, "(gl_ObjectToWorldNV)")
float4x3 ObjectToWorld4x3();
-__target_intrinsic(glsl, "(gl_WorldToObjectNVX)")
+__target_intrinsic(glsl, "(gl_WorldToObjectNV)")
float4x3 WorldToObject4x3();
// Note: The provisional DXR spec included these unadorned
@@ -1531,5 +1532,5 @@ float3x4 ObjectToWorld() { return ObjectToWorld3x4(); }
float3x4 WorldToObject() { return WorldToObject3x4(); }
// 10.4.4 - Hit Specific System values
-__target_intrinsic(glsl, "(gl_HitKindNVX)")
+__target_intrinsic(glsl, "(gl_HitKindNV)")
uint HitKind();
diff --git a/source/slang/hlsl.meta.slang.h b/source/slang/hlsl.meta.slang.h
index 2db710ccb..5e00c2719 100644
--- a/source/slang/hlsl.meta.slang.h
+++ b/source/slang/hlsl.meta.slang.h
@@ -1417,8 +1417,8 @@ SLANG_RAW(" uint MissShaderIndex,\n")
SLANG_RAW(" RayDesc Ray,\n")
SLANG_RAW(" inout payload_t Payload);\n")
SLANG_RAW("\n")
-SLANG_RAW("__target_intrinsic(glsl, \"traceNVX\")\n")
-SLANG_RAW("void __traceNVX(\n")
+SLANG_RAW("__target_intrinsic(glsl, \"traceNV\")\n")
+SLANG_RAW("void __traceNV(\n")
SLANG_RAW(" RaytracingAccelerationStructure AccelerationStructure,\n")
SLANG_RAW(" uint RayFlags,\n")
SLANG_RAW(" uint InstanceInclusionMask,\n")
@@ -1439,6 +1439,7 @@ SLANG_RAW("// syntax works in a pinch.\n")
SLANG_RAW("//\n")
SLANG_RAW("__generic<Payload>\n")
SLANG_RAW("__target_intrinsic(glsl, \"$XP\")\n")
+SLANG_RAW("[__readNone]\n")
SLANG_RAW("int __rayPayloadLocation(Payload payload);\n")
SLANG_RAW("\n")
SLANG_RAW("__generic<payload_t>\n")
@@ -1457,7 +1458,7 @@ SLANG_RAW(" [__vulkanRayPayload]\n")
SLANG_RAW(" static payload_t p;\n")
SLANG_RAW("\n")
SLANG_RAW(" p = Payload;\n")
-SLANG_RAW(" __traceNVX(\n")
+SLANG_RAW(" __traceNV(\n")
SLANG_RAW(" AccelerationStructure,\n")
SLANG_RAW(" RayFlags,\n")
SLANG_RAW(" InstanceInclusionMask,\n")
@@ -1475,8 +1476,8 @@ SLANG_RAW("\n")
SLANG_RAW("// 10.3.3\n")
SLANG_RAW("bool ReportHit<A>(float tHit, uint hitKind, A attributes);\n")
SLANG_RAW("\n")
-SLANG_RAW("__target_intrinsic(glsl, \"reportIntersectionNVX\")\n")
-SLANG_RAW("bool __reportIntersectionNVX(float tHit, uint hitKind);\n")
+SLANG_RAW("__target_intrinsic(glsl, \"reportIntersectionNV\")\n")
+SLANG_RAW("bool __reportIntersectionNV(float tHit, uint hitKind);\n")
SLANG_RAW("\n")
SLANG_RAW("__generic<A>\n")
SLANG_RAW("__specialized_for_target(glsl)\n")
@@ -1486,15 +1487,15 @@ SLANG_RAW(" [__vulkanHitAttributes]\n")
SLANG_RAW(" static A a;\n")
SLANG_RAW("\n")
SLANG_RAW(" a = attributes;\n")
-SLANG_RAW(" return __reportIntersectionNVX(tHit, hitKind);\n")
+SLANG_RAW(" return __reportIntersectionNV(tHit, hitKind);\n")
SLANG_RAW("}\n")
SLANG_RAW("\n")
SLANG_RAW("// 10.3.4\n")
-SLANG_RAW("__target_intrinsic(glsl, ignoreIntersectionNVX)\n")
+SLANG_RAW("__target_intrinsic(glsl, ignoreIntersectionNV)\n")
SLANG_RAW("void IgnoreHit();\n")
SLANG_RAW("\n")
SLANG_RAW("// 10.3.5\n")
-SLANG_RAW("__target_intrinsic(glsl, terminateRayNVX)\n")
+SLANG_RAW("__target_intrinsic(glsl, terminateRayNV)\n")
SLANG_RAW("void AcceptHitAndEndSearch();\n")
SLANG_RAW("\n")
SLANG_RAW("// 10.4 - System Values and Special Semantics\n")
@@ -1504,25 +1505,25 @@ SLANG_RAW("// they can only be accessed from specific stages.\n")
SLANG_RAW("\n")
SLANG_RAW("// 10.4.1 - Ray Dispatch System Values\n")
SLANG_RAW("\n")
-SLANG_RAW("__target_intrinsic(glsl, \"uvec3(gl_LaunchIDNVX, 0)\")\n")
+SLANG_RAW("__target_intrinsic(glsl, \"(gl_LaunchIDNV)\")\n")
SLANG_RAW("uint3 DispatchRaysIndex();\n")
SLANG_RAW("\n")
-SLANG_RAW("__target_intrinsic(glsl, \"uvec3(gl_LaunchSizeNVX, 0)\")\n")
+SLANG_RAW("__target_intrinsic(glsl, \"(gl_LaunchSizeNV)\")\n")
SLANG_RAW("uint3 DispatchRaysDimensions();\n")
SLANG_RAW("\n")
SLANG_RAW("// 10.4.2 - Ray System Values\n")
SLANG_RAW("\n")
-SLANG_RAW("__target_intrinsic(glsl, \"(gl_WorldRayOriginNVX)\")\n")
+SLANG_RAW("__target_intrinsic(glsl, \"(gl_WorldRayOriginNV)\")\n")
SLANG_RAW("float3 WorldRayOrigin();\n")
SLANG_RAW("\n")
-SLANG_RAW("__target_intrinsic(glsl, \"(gl_WorldRayDirectionNVX)\")\n")
+SLANG_RAW("__target_intrinsic(glsl, \"(gl_WorldRayDirectionNV)\")\n")
SLANG_RAW("float3 WorldRayDirection();\n")
SLANG_RAW("\n")
-SLANG_RAW("__target_intrinsic(glsl, \"(gl_RayTminNVX)\")\n")
+SLANG_RAW("__target_intrinsic(glsl, \"(gl_RayTminNV)\")\n")
SLANG_RAW("float RayTMin();\n")
SLANG_RAW("\n")
SLANG_RAW("// Note: The `RayTCurrent()` intrinsic should translate to\n")
-SLANG_RAW("// either `gl_HitTNVX` (for hit shaders) or `gl_RayTmaxNVX`\n")
+SLANG_RAW("// either `gl_HitTNV` (for hit shaders) or `gl_RayTmaxNV`\n")
SLANG_RAW("// (for intersection shaders). Right now we are handling this\n")
SLANG_RAW("// during code emission, for simplicity.\n")
SLANG_RAW("//\n")
@@ -1534,12 +1535,12 @@ SLANG_RAW("//\n")
SLANG_RAW("__target_intrinsic(glsl, \"$XT\")\n")
SLANG_RAW("float RayTCurrent();\n")
SLANG_RAW("\n")
-SLANG_RAW("__target_intrinsic(glsl, \"(gl_RayFlagsNVX)\")\n")
+SLANG_RAW("__target_intrinsic(glsl, \"(gl_IncomingRayFlagsNV)\")\n")
SLANG_RAW("uint RayFlags();\n")
SLANG_RAW("\n")
SLANG_RAW("// 10.4.3 - Primitive/Object Space System Values\n")
SLANG_RAW("\n")
-SLANG_RAW("__target_intrinsic(glsl, \"(gl_InstanceCustomIndexNVX)\")\n")
+SLANG_RAW("__target_intrinsic(glsl, \"(gl_InstanceCustomIndexNV)\")\n")
SLANG_RAW("uint InstanceIndex();\n")
SLANG_RAW("\n")
SLANG_RAW("__target_intrinsic(glsl, \"(gl_InstanceID)\")\n")
@@ -1548,22 +1549,22 @@ SLANG_RAW("\n")
SLANG_RAW("__target_intrinsic(glsl, \"(gl_PrimitiveID)\")\n")
SLANG_RAW("uint PrimitiveIndex();\n")
SLANG_RAW("\n")
-SLANG_RAW("__target_intrinsic(glsl, \"(gl_ObjectRayOriginNVX)\")\n")
+SLANG_RAW("__target_intrinsic(glsl, \"(gl_ObjectRayOriginNV)\")\n")
SLANG_RAW("float3 ObjectRayOrigin();\n")
SLANG_RAW("\n")
-SLANG_RAW("__target_intrinsic(glsl, \"(gl_ObjectRayDirectionNVX)\")\n")
+SLANG_RAW("__target_intrinsic(glsl, \"(gl_ObjectRayDirectionNV)\")\n")
SLANG_RAW("float3 ObjectRayDirection();\n")
SLANG_RAW("\n")
-SLANG_RAW("__target_intrinsic(glsl, \"transpose(gl_ObjectToWorldNVX)\")\n")
+SLANG_RAW("__target_intrinsic(glsl, \"transpose(gl_ObjectToWorldNV)\")\n")
SLANG_RAW("float3x4 ObjectToWorld3x4();\n")
SLANG_RAW("\n")
-SLANG_RAW("__target_intrinsic(glsl, \"transpose(gl_WorldToObjectNVX)\")\n")
+SLANG_RAW("__target_intrinsic(glsl, \"transpose(gl_WorldToObjectNV)\")\n")
SLANG_RAW("float3x4 WorldToObject3x4();\n")
SLANG_RAW("\n")
-SLANG_RAW("__target_intrinsic(glsl, \"(gl_ObjectToWorldNVX)\")\n")
+SLANG_RAW("__target_intrinsic(glsl, \"(gl_ObjectToWorldNV)\")\n")
SLANG_RAW("float4x3 ObjectToWorld4x3();\n")
SLANG_RAW("\n")
-SLANG_RAW("__target_intrinsic(glsl, \"(gl_WorldToObjectNVX)\")\n")
+SLANG_RAW("__target_intrinsic(glsl, \"(gl_WorldToObjectNV)\")\n")
SLANG_RAW("float4x3 WorldToObject4x3();\n")
SLANG_RAW("\n")
SLANG_RAW("// Note: The provisional DXR spec included these unadorned\n")
@@ -1579,5 +1580,5 @@ SLANG_RAW("float3x4 ObjectToWorld() { return ObjectToWorld3x4(); }\n")
SLANG_RAW("float3x4 WorldToObject() { return WorldToObject3x4(); }\n")
SLANG_RAW("\n")
SLANG_RAW("// 10.4.4 - Hit Specific System values\n")
-SLANG_RAW("__target_intrinsic(glsl, \"(gl_HitKindNVX)\")\n")
+SLANG_RAW("__target_intrinsic(glsl, \"(gl_HitKindNV)\")\n")
SLANG_RAW("uint HitKind();\n")
diff --git a/source/slang/ir-insts.h b/source/slang/ir-insts.h
index 6075c247c..db61cae88 100644
--- a/source/slang/ir-insts.h
+++ b/source/slang/ir-insts.h
@@ -147,6 +147,11 @@ struct IRRequireGLSLExtensionDecoration : IRDecoration
StringRepresentation* extensionName;
};
+struct IRReadNoneDecoration : IRDecoration
+{
+ enum { kDecorationOp = kIRDecorationOp_ReadNone };
+};
+
// An instruction that specializes another IR value
// (representing a generic) to a particular set of generic arguments
// (instructions representing types, witness tables, etc.)
@@ -187,6 +192,11 @@ struct IRLookupWitnessTable : IRInst
struct IRCall : IRInst
{
IRUse func;
+
+ IRInst* getCallee() { return getOperand(0); }
+
+ UInt getArgCount() { return getOperandCount() - 1; }
+ IRInst* getArg(UInt index) { return getOperand(index + 1); }
};
struct IRLoad : IRInst
diff --git a/source/slang/ir-serialize.cpp b/source/slang/ir-serialize.cpp
index e2fd6d3f8..7cc3d6384 100644
--- a/source/slang/ir-serialize.cpp
+++ b/source/slang/ir-serialize.cpp
@@ -705,6 +705,7 @@ Result IRSerialWriter::write(IRModule* module, SourceManager* sourceManager, Opt
}
case kIRDecorationOp_VulkanRayPayload:
case kIRDecorationOp_VulkanHitAttributes:
+ case kIRDecorationOp_ReadNone:
{
dstInst.m_payloadType = PayloadType::Empty;
break;
@@ -1579,6 +1580,12 @@ IRDecoration* IRSerialReader::_createDecoration(const Ser::Inst& srcInst)
decor->languageVersion = Int(srcInst.m_payload.m_uint32);
return decor;
}
+ case kIRDecorationOp_ReadNone:
+ {
+ auto decor = createEmptyDecoration<IRReadNoneDecoration>(m_module);
+ SLANG_ASSERT(srcInst.m_payloadType == PayloadType::Empty);
+ return decor;
+ }
default:
{
SLANG_ASSERT(!"Unhandled decoration type");
diff --git a/source/slang/ir.cpp b/source/slang/ir.cpp
index cc3350aef..a66b26e93 100644
--- a/source/slang/ir.cpp
+++ b/source/slang/ir.cpp
@@ -2939,6 +2939,11 @@ namespace Slang
dump(context, "\n[__vulkanHitAttributes]");
}
break;
+ case kIRDecorationOp_ReadNone:
+ {
+ dump(context, "\n[__readNone]");
+ }
+ break;
}
}
}
@@ -3521,7 +3526,30 @@ namespace Slang
return true;
case kIROp_Call:
- // This is the most interesting.
+ {
+ // In the general case, a function call must be assumed to
+ // have almost arbitrary side effects.
+ //
+ // However, it is possible that the callee can be identified,
+ // and it may be a function with an attribute that explicitly
+ // limits the side effects it is allowed to have.
+ //
+ // For now, we will explicitly check for the `[__readNone]`
+ // attribute, which was used to mark functions that compute
+ // their result strictly as a function of the arguments (and
+ // not anything they point to, or other non-argument state).
+ // Calls to such functions cannot have side effects (except
+ // for things like stack overflow that abstract language models
+ // tend to ignore), and can be subject to dead code elimination,
+ // common subexpression elimination, etc.
+ //
+ auto call = cast<IRCall>(this);
+ auto callee = getResolvedInstForDecorations(call->getCallee());
+ if(callee->findDecoration<IRReadNoneDecoration>())
+ {
+ return false;
+ }
+ }
return true;
case kIROp_Nop:
@@ -5371,6 +5399,12 @@ namespace Slang
}
break;
+ case kIRDecorationOp_ReadNone:
+ {
+ context->builder->addDecoration<IRReadNoneDecoration>(clonedValue);
+ }
+ break;
+
default:
// Don't clone any decorations we don't understand.
break;
@@ -6005,6 +6039,24 @@ namespace Slang
return val;
}
+ IRInst* getResolvedInstForDecorations(IRInst* inst)
+ {
+ IRInst* candidate = inst;
+ while(auto specInst = as<IRSpecialize>(candidate))
+ {
+ auto genericInst = as<IRGeneric>(specInst->getBase());
+ if(!genericInst)
+ break;
+
+ auto returnVal = findGenericReturnVal(genericInst);
+ if(!returnVal)
+ break;
+
+ candidate = returnVal;
+ }
+ return candidate;
+ }
+
bool isDefinition(
IRGlobalValue* inVal)
{
diff --git a/source/slang/ir.h b/source/slang/ir.h
index 41c9ab6ab..def68098d 100644
--- a/source/slang/ir.h
+++ b/source/slang/ir.h
@@ -157,8 +157,9 @@ enum IRDecorationOp : uint16_t
kIRDecorationOp_VulkanHitAttributes,
kIRDecorationOp_RequireGLSLVersion,
kIRDecorationOp_RequireGLSLExtension,
-
- kIRDecorationOp_CountOf
+ kIRDecorationOp_ReadNone,
+
+ kIRDecorationOp_CountOf
};
// represents an object allocated in an IR memory arena
@@ -1048,6 +1049,14 @@ struct IRGeneric : IRGlobalValueWithParams
// a pass can glean information from it.
IRInst* findGenericReturnVal(IRGeneric* generic);
+// Resolve an instruction that might reference a static definition
+// to the most specific IR node possible, so that we can read
+// decorations from it (e.g., if this is a `specialize` instruction,
+// then try to chase down the generic being specialized, and what
+// it seems to return).
+//
+IRInst* getResolvedInstForDecorations(IRInst* inst);
+
// The IR module itself is represented as an instruction, which
// serves at the root of the tree of all instructions in the module.
struct IRModuleInst : IRParentInst
diff --git a/source/slang/lower-to-ir.cpp b/source/slang/lower-to-ir.cpp
index 806654ccb..815822495 100644
--- a/source/slang/lower-to-ir.cpp
+++ b/source/slang/lower-to-ir.cpp
@@ -5137,6 +5137,11 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
decoration->languageVersion = Int(getIntegerLiteralValue(versionMod->versionNumberToken));
}
+ if(decl->FindModifier<ReadNoneAttribute>())
+ {
+ getBuilder()->addDecoration<IRReadNoneDecoration>(irFunc);
+ }
+
// For convenience, ensure that any additional global
// values that were emitted while outputting the function
// body appear before the function itself in the list
diff --git a/source/slang/modifier-defs.h b/source/slang/modifier-defs.h
index dc4e99cdd..bb9aefcb7 100644
--- a/source/slang/modifier-defs.h
+++ b/source/slang/modifier-defs.h
@@ -405,6 +405,14 @@ SIMPLE_SYNTAX_CLASS(VulkanHitAttributesAttribute, Attribute)
//
SIMPLE_SYNTAX_CLASS(MutatingAttribute, Attribute)
+// A `[__readNone]` attribute, which indicates that a function
+// computes its results strictly based on argument values, without
+// reading or writing through any pointer arguments, or any other
+// state that could be observed by a caller.
+//
+SIMPLE_SYNTAX_CLASS(ReadNoneAttribute, Attribute)
+
+
// HLSL modifiers for geometry shader input topology
SIMPLE_SYNTAX_CLASS(HLSLGeometryShaderInputPrimitiveTypeModifier, Modifier)
SIMPLE_SYNTAX_CLASS(HLSLPointModifier , HLSLGeometryShaderInputPrimitiveTypeModifier)