summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/slang/slang-ast-builder.cpp1
-rw-r--r--source/slang/slang-ast-builder.h2
-rw-r--r--source/slang/slang-ast-type.cpp23
-rw-r--r--source/slang/slang-ast-type.h13
-rw-r--r--source/slang/slang-check-decl.cpp2
-rw-r--r--source/slang/slang-check-expr.cpp6
-rw-r--r--source/slang/slang-emit-base.cpp2
-rw-r--r--source/slang/slang-emit-c-like.cpp17
-rw-r--r--source/slang/slang-emit-spirv.cpp15
-rw-r--r--source/slang/slang-hlsl-intrinsic-set.cpp2
-rw-r--r--source/slang/slang-ir-glsl-legalize.cpp9
-rw-r--r--source/slang/slang-ir-inline.cpp16
-rw-r--r--source/slang/slang-ir-inst-defs.h10
-rw-r--r--source/slang/slang-ir-insts.h18
-rw-r--r--source/slang/slang-ir-legalize-types.cpp10
-rw-r--r--source/slang/slang-ir-legalize-varying-params.cpp2
-rw-r--r--source/slang/slang-ir-liveness.cpp5
-rw-r--r--source/slang/slang-ir-lower-error-handling.cpp16
-rw-r--r--source/slang/slang-ir-lower-error-handling.h2
-rw-r--r--source/slang/slang-ir-lower-generic-function.cpp2
-rw-r--r--source/slang/slang-ir-lower-result-type.cpp33
-rw-r--r--source/slang/slang-ir-restructure.cpp3
-rw-r--r--source/slang/slang-ir-specialize-dispatch.cpp3
-rw-r--r--source/slang/slang-ir-specialize-resources.cpp2
-rw-r--r--source/slang/slang-ir-specialize.cpp2
-rw-r--r--source/slang/slang-ir-synthesize-active-mask.cpp3
-rw-r--r--source/slang/slang-ir.cpp51
-rw-r--r--source/slang/slang-ir.h5
-rw-r--r--source/slang/slang-lower-to-ir.cpp6
-rw-r--r--source/slang/slang-serialize-ir.cpp12
-rw-r--r--source/slang/slang-syntax.h2
31 files changed, 165 insertions, 130 deletions
diff --git a/source/slang/slang-ast-builder.cpp b/source/slang/slang-ast-builder.cpp
index 7ac039187..7f23f5492 100644
--- a/source/slang/slang-ast-builder.cpp
+++ b/source/slang/slang-ast-builder.cpp
@@ -31,6 +31,7 @@ void SharedASTBuilder::init(Session* session)
// Create common shared types
m_errorType = m_astBuilder->create<ErrorType>();
+ m_bottomType = m_astBuilder->create<BottomType>();
m_initializerListType = m_astBuilder->create<InitializerListType>();
m_overloadedType = m_astBuilder->create<OverloadGroupType>();
diff --git a/source/slang/slang-ast-builder.h b/source/slang/slang-ast-builder.h
index 97aefd118..d8a8679ee 100644
--- a/source/slang/slang-ast-builder.h
+++ b/source/slang/slang-ast-builder.h
@@ -57,6 +57,7 @@ protected:
// State shared between ASTBuilders
Type* m_errorType = nullptr;
+ Type* m_bottomType = nullptr;
Type* m_initializerListType = nullptr;
Type* m_overloadedType = nullptr;
@@ -133,6 +134,7 @@ public:
Type* getInitializerListType() { return m_sharedASTBuilder->m_initializerListType; }
Type* getOverloadedType() { return m_sharedASTBuilder->m_overloadedType; }
Type* getErrorType() { return m_sharedASTBuilder->m_errorType; }
+ Type* getBottomType() { return m_sharedASTBuilder->m_bottomType; }
Type* getStringType() { return m_sharedASTBuilder->getStringType(); }
Type* getNullPtrType() { return m_sharedASTBuilder->getNullPtrType(); }
Type* getEnumTypeType() { return m_sharedASTBuilder->getEnumTypeType(); }
diff --git a/source/slang/slang-ast-type.cpp b/source/slang/slang-ast-type.cpp
index bcaf8f5a9..5ee0c5c70 100644
--- a/source/slang/slang-ast-type.cpp
+++ b/source/slang/slang-ast-type.cpp
@@ -148,6 +148,27 @@ HashCode ErrorType::_getHashCodeOverride()
return HashCode(size_t(this));
}
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! BottomType !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+void BottomType::_toTextOverride(StringBuilder& out) { out << toSlice("never"); }
+
+bool BottomType::_equalsImplOverride(Type* type)
+{
+ if (auto bottomType = as<BottomType>(type))
+ return true;
+ return false;
+}
+
+Type* BottomType::_createCanonicalTypeOverride() { return this; }
+
+Val* BottomType::_substituteImplOverride(
+ ASTBuilder* /* astBuilder */, SubstitutionSet /*subst*/, int* /*ioDiff*/)
+{
+ return this;
+}
+
+HashCode BottomType::_getHashCodeOverride() { return HashCode(size_t(this)); }
+
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DeclRefType !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
void DeclRefType::_toTextOverride(StringBuilder& out)
@@ -550,7 +571,7 @@ void FuncType::_toTextOverride(StringBuilder& out)
}
out << toSlice(") -> ") << getResultType();
- if (!getErrorType()->equals(getASTBuilder()->getVoidType()))
+ if (!getErrorType()->equals(getASTBuilder()->getBottomType()))
{
out << " throws " << getErrorType();
}
diff --git a/source/slang/slang-ast-type.h b/source/slang/slang-ast-type.h
index 8de047af5..dbca6b18b 100644
--- a/source/slang/slang-ast-type.h
+++ b/source/slang/slang-ast-type.h
@@ -47,6 +47,19 @@ class ErrorType : public Type
Val* _substituteImplOverride(ASTBuilder* astBuilder, SubstitutionSet subst, int* ioDiff);
};
+// The bottom/empty type that has no values.
+class BottomType : public Type
+{
+ SLANG_AST_CLASS(BottomType)
+
+ // Overrides should be public so base classes can access
+ void _toTextOverride(StringBuilder& out);
+ Type* _createCanonicalTypeOverride();
+ bool _equalsImplOverride(Type* type);
+ HashCode _getHashCodeOverride();
+ Val* _substituteImplOverride(ASTBuilder* astBuilder, SubstitutionSet subst, int* ioDiff);
+};
+
// A type that takes the form of a reference to some declaration
class DeclRefType : public Type
{
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp
index af19f484d..57704ff88 100644
--- a/source/slang/slang-check-decl.cpp
+++ b/source/slang/slang-check-decl.cpp
@@ -4406,7 +4406,7 @@ namespace Slang
}
else
{
- errorType = TypeExp(m_astBuilder->getVoidType());
+ errorType = TypeExp(m_astBuilder->getBottomType());
}
decl->errorType = errorType;
}
diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp
index 4b29de1bf..8a80398e9 100644
--- a/source/slang/slang-check-expr.cpp
+++ b/source/slang/slang-check-expr.cpp
@@ -1337,7 +1337,7 @@ namespace Slang
// if this is still an invoke expression, test arguments passed to inout/out parameter are LValues
if(auto funcType = as<FuncType>(invoke->functionExpr->type))
{
- if (!funcType->errorType->equals(m_astBuilder->getVoidType()))
+ if (!funcType->errorType->equals(m_astBuilder->getBottomType()))
{
// If the callee throws, make sure we are inside a try clause.
if (m_enclosingTryClauseType == TryClauseType::None)
@@ -1556,7 +1556,7 @@ namespace Slang
getSink()->diagnose(expr, Diagnostics::uncaughtTryCallInNonThrowFunc);
return expr;
}
- if (parentFunc->errorType->equals(m_astBuilder->getVoidType()))
+ if (parentFunc->errorType->equals(m_astBuilder->getBottomType()))
{
getSink()->diagnose(expr, Diagnostics::uncaughtTryCallInNonThrowFunc);
return expr;
@@ -1571,7 +1571,7 @@ namespace Slang
{
if (auto funcCallee = as<FuncDecl>(callee->declRef.getDecl()))
{
- if (funcCallee->errorType->equals(m_astBuilder->getVoidType()))
+ if (funcCallee->errorType->equals(m_astBuilder->getBottomType()))
{
getSink()->diagnose(expr, Diagnostics::tryInvokeCalleeShouldThrow, callee->declRef);
}
diff --git a/source/slang/slang-emit-base.cpp b/source/slang/slang-emit-base.cpp
index 0f1c54e70..d565edb24 100644
--- a/source/slang/slang-emit-base.cpp
+++ b/source/slang/slang-emit-base.cpp
@@ -25,7 +25,7 @@ IRInst* SourceEmitterBase::getSpecializedValue(IRSpecialize* specInst)
if (!lastBlock)
return base;
- auto returnInst = as<IRReturnVal>(lastBlock->getTerminator());
+ auto returnInst = as<IRReturn>(lastBlock->getTerminator());
if (!returnInst)
return base;
diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp
index 895421783..6b6d462b9 100644
--- a/source/slang/slang-emit-c-like.cpp
+++ b/source/slang/slang-emit-c-like.cpp
@@ -2104,13 +2104,13 @@ void CLikeSourceEmitter::_emitInst(IRInst* inst)
// folded into use site(s)
break;
- case kIROp_ReturnVoid:
- m_writer->emit("return;\n");
- break;
-
- case kIROp_ReturnVal:
- m_writer->emit("return ");
- emitOperand(((IRReturnVal*) inst)->getVal(), getInfo(EmitOp::General));
+ case kIROp_Return:
+ m_writer->emit("return");
+ if (((IRReturn*)inst)->getVal()->getOp() != kIROp_VoidLit)
+ {
+ m_writer->emit(" ");
+ emitOperand(((IRReturn*) inst)->getVal(), getInfo(EmitOp::General));
+ }
m_writer->emit(";\n");
break;
@@ -2268,8 +2268,7 @@ void CLikeSourceEmitter::emitRegion(Region* inRegion)
// its behavior has been folded into the next region.
break;
- case kIROp_ReturnVal:
- case kIROp_ReturnVoid:
+ case kIROp_Return:
case kIROp_discard:
// For extremely simple terminators, we just handle
// them here, so that we don't have to allocate
diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp
index 6b3b42e92..fa0d92512 100644
--- a/source/slang/slang-emit-spirv.cpp
+++ b/source/slang/slang-emit-spirv.cpp
@@ -1619,11 +1619,16 @@ struct SPIRVEmitContext
case kIROp_Rsh:
case kIROp_Lsh:
return emitArithmetic(parent, inst);
- case kIROp_ReturnVal:
- return emitInst(
- parent, inst, SpvOpReturnValue, as<IRReturnVal>(inst)->getVal());
- case kIROp_ReturnVoid:
- return emitInst(parent, inst, SpvOpReturn);
+ case kIROp_Return:
+ if (as<IRReturn>(inst)->getVal()->getOp() == kIROp_VoidLit)
+ {
+ return emitInst(parent, inst, SpvOpReturn);
+ }
+ else
+ {
+ return emitInst(
+ parent, inst, SpvOpReturnValue, as<IRReturn>(inst)->getVal());
+ }
case kIROp_discard:
return emitInst(parent, inst, SpvOpKill);
case kIROp_unconditionalBranch:
diff --git a/source/slang/slang-hlsl-intrinsic-set.cpp b/source/slang/slang-hlsl-intrinsic-set.cpp
index 8c7e4fc4c..e6010bda2 100644
--- a/source/slang/slang-hlsl-intrinsic-set.cpp
+++ b/source/slang/slang-hlsl-intrinsic-set.cpp
@@ -476,7 +476,7 @@ static IRInst* _getSpecializedValue(IRSpecialize* specInst)
if (!lastBlock)
return base;
- auto returnInst = as<IRReturnVal>(lastBlock->getTerminator());
+ auto returnInst = as<IRReturn>(lastBlock->getTerminator());
if (!returnInst)
return base;
diff --git a/source/slang/slang-ir-glsl-legalize.cpp b/source/slang/slang-ir-glsl-legalize.cpp
index 83b75033a..59f741050 100644
--- a/source/slang/slang-ir-glsl-legalize.cpp
+++ b/source/slang/slang-ir-glsl-legalize.cpp
@@ -1726,8 +1726,7 @@ void legalizeEntryPointParameterForGLSL(
default:
continue;
- case kIROp_ReturnVal:
- case kIROp_ReturnVoid:
+ case kIROp_Return:
break;
}
@@ -1862,10 +1861,10 @@ void legalizeEntryPointForGLSL(
// terminator...
for( auto ii = bb->getFirstInst(); ii; ii = ii->getNextInst() )
{
- if(ii->getOp() != kIROp_ReturnVal)
+ if(ii->getOp() != kIROp_Return)
continue;
- IRReturnVal* returnInst = (IRReturnVal*) ii;
+ IRReturn* returnInst = (IRReturn*) ii;
IRInst* returnValue = returnInst->getVal();
// Make sure we add these instructions to the right block
@@ -1874,7 +1873,7 @@ void legalizeEntryPointForGLSL(
// Write to our global variable(s) from the value being returned.
assign(&builder, resultGlobal, ScalarizedVal::value(returnValue));
- // Emit a `returnVoid` to end the block
+ // Emit a `return void_val` to end the block
auto returnVoid = builder.emitReturn();
// Remove the old `returnVal` instruction.
diff --git a/source/slang/slang-ir-inline.cpp b/source/slang/slang-ir-inline.cpp
index ed4b34875..77691d169 100644
--- a/source/slang/slang-ir-inline.cpp
+++ b/source/slang/slang-ir-inline.cpp
@@ -349,7 +349,7 @@ struct InliningPassBase
{
for (auto inst : block->getChildren())
{
- if (inst->getOp() == kIROp_ReturnVal || inst->getOp() == kIROp_ReturnVoid)
+ if (inst->getOp() == kIROp_Return)
{
// If the return is not at the end of the block, we cannot handle it.
if (inst != block->getTerminator())
@@ -494,18 +494,10 @@ struct InliningPassBase
_cloneInstWithSourceLoc(callSite, env, builder, inst);
break;
- case kIROp_ReturnVoid:
- // A return with no operand is replaced with a branch into `afterBlock`
+ case kIROp_Return:
+ // A return is replaced with a branch into `afterBlock`
// to return the control flow to the location after the original `call`.
- {
- auto returnBranch = builder->emitBranch(afterBlock);
- _setSourceLoc(returnBranch, inst, callSite);
- }
- break;
-
- case kIROp_ReturnVal:
- // A return with a value is similar to `returnVoid` except
- // that we need to note the (clone of the) value being
+ // We also need to note the (clone of the) value being
// returned, so that we can use it to replace the value
// of the original call.
//
diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h
index b1759026b..b77621720 100644
--- a/source/slang/slang-ir-inst-defs.h
+++ b/source/slang/slang-ir-inst-defs.h
@@ -248,7 +248,8 @@ INST(Block, block, 0, PARENT)
INST(FloatLit, float_constant, 0, 0)
INST(PtrLit, ptr_constant, 0, 0)
INST(StringLit, string_constant, 0, 0)
-INST_RANGE(Constant, BoolLit, StringLit)
+ INST(VoidLit, void_constant, 0, 0)
+INST_RANGE(Constant, BoolLit, VoidLit)
INST(CapabilitySet, capabilitySet, 0, 0)
@@ -276,7 +277,6 @@ INST(makeStruct, makeStruct, 0, 0)
INST(MakeTuple, makeTuple, 0, 0)
INST(GetTupleElement, getTupleElement, 2, 0)
INST(MakeResultValue, makeResultValue, 1, 0)
-INST(MakeResultValueVoid, makeResultValueVoid, 0, 0)
INST(MakeResultError, makeResultError, 1, 0)
INST(IsResultError, isResultError, 1, 0)
INST(GetResultError, getResultError, 1, 0)
@@ -422,9 +422,7 @@ INST(SwizzledStore, swizzledStore, 2, 0)
/* IRTerminatorInst */
- INST(ReturnVal, return_val, 1, 0)
- INST(ReturnVoid, return_void, 1, 0)
-
+ INST(Return, return_val, 1, 0)
/* IRUnconditionalBranch */
// unconditionalBranch <target>
INST(unconditionalBranch, unconditionalBranch, 1, 0)
@@ -455,7 +453,7 @@ INST(SwizzledStore, swizzledStore, 2, 0)
INST(Unreachable, unreachable, 0, 0)
INST_RANGE(Unreachable, MissingReturn, Unreachable)
-INST_RANGE(TerminatorInst, ReturnVal, Unreachable)
+INST_RANGE(TerminatorInst, Return, Unreachable)
// TODO: We should consider splitting the basic arithmetic/comparison
// ops into cases for signed integers, unsigned integers, and floating-point
diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h
index f7f7328a1..9c1569ca8 100644
--- a/source/slang/slang-ir-insts.h
+++ b/source/slang/slang-ir-insts.h
@@ -1427,18 +1427,12 @@ struct IRImageStore : IRInst
// Terminators
struct IRReturn : IRTerminatorInst
-{};
-
-struct IRReturnVal : IRReturn
{
- IRUse val;
+ IR_LEAF_ISA(Return);
- IRInst* getVal() { return val.get(); }
+ IRInst* getVal() { return getOperand(0); }
};
-struct IRReturnVoid : IRReturn
-{};
-
struct IRDiscard : IRTerminatorInst
{};
@@ -1801,12 +1795,6 @@ struct IRMakeResultValue : IRInst
IRInst* getValue() { return getOperand(0); }
};
-// Constructs an `Result<void,E>` value that represents success in a function that returns `void`.
-struct IRMakeResultValueVoid : IRInst
-{
- IR_LEAF_ISA(MakeResultValueVoid)
-};
-
// Determines if a `Result` value represents an error.
struct IRIsResultError : IRInst
{
@@ -2148,6 +2136,7 @@ public:
IRInst* getFloatValue(IRType* type, IRFloatingPointValue value);
IRStringLit* getStringValue(const UnownedStringSlice& slice);
IRPtrLit* getPtrValue(void* value);
+ IRVoidLit* getVoidValue();
IRInst* getCapabilityValue(CapabilitySet const& caps);
IRBasicType* getBasicType(BaseType baseType);
@@ -2415,7 +2404,6 @@ public:
IRInst* emitMakeResultError(IRType* resultType, IRInst* errorVal);
IRInst* emitMakeResultValue(IRType* resultType, IRInst* val);
- IRInst* emitMakeResultValueVoid(IRType* resultType);
IRInst* emitIsResultError(IRInst* result);
IRInst* emitGetResultError(IRInst* result);
IRInst* emitGetResultValue(IRInst* result);
diff --git a/source/slang/slang-ir-legalize-types.cpp b/source/slang/slang-ir-legalize-types.cpp
index 1b61e802e..e3f99fa49 100644
--- a/source/slang/slang-ir-legalize-types.cpp
+++ b/source/slang/slang-ir-legalize-types.cpp
@@ -548,7 +548,7 @@ struct LegalReturnBuilder
default:
// TODO: implement legalization of non-simple return types
- SLANG_UNEXPECTED("unimplemented legalized return type for IRReturnVal.");
+ SLANG_UNEXPECTED("unimplemented legalized return type for IRReturn.");
}
}
@@ -683,7 +683,7 @@ private:
default:
// TODO: implement legalization of non-simple return types
- SLANG_UNEXPECTED("unimplemented legalized return type for IRReturnVal.");
+ SLANG_UNEXPECTED("unimplemented legalized return type for IRReturn.");
}
}
@@ -697,7 +697,7 @@ private:
static LegalVal legalizeRetVal(
IRTypeLegalizationContext* context,
LegalVal retVal,
- IRReturnVal* returnInst)
+ IRReturn* returnInst)
{
LegalReturnBuilder builder(context, returnInst);
builder.returnVal(retVal);
@@ -1655,8 +1655,8 @@ static LegalVal legalizeInst(
case kIROp_Call:
return legalizeCall(context, (IRCall*)inst);
- case kIROp_ReturnVal:
- return legalizeRetVal(context, args[0], (IRReturnVal*)inst);
+ case kIROp_Return:
+ return legalizeRetVal(context, args[0], (IRReturn*)inst);
case kIROp_makeStruct:
return legalizeMakeStruct(
context,
diff --git a/source/slang/slang-ir-legalize-varying-params.cpp b/source/slang/slang-ir-legalize-varying-params.cpp
index 6fedc1f5f..f32fd9933 100644
--- a/source/slang/slang-ir-legalize-varying-params.cpp
+++ b/source/slang/slang-ir-legalize-varying-params.cpp
@@ -326,7 +326,7 @@ protected:
IRBuilder builder(m_sharedBuilder);
for( auto block : entryPointFunc->getBlocks() )
{
- auto returnValInst = as<IRReturnVal>(block->getTerminator());
+ auto returnValInst = as<IRReturn>(block->getTerminator());
if(!returnValInst)
continue;
diff --git a/source/slang/slang-ir-liveness.cpp b/source/slang/slang-ir-liveness.cpp
index 81de6d6c2..7b0e9bea8 100644
--- a/source/slang/slang-ir-liveness.cpp
+++ b/source/slang/slang-ir-liveness.cpp
@@ -886,10 +886,10 @@ bool LivenessContext::_isAccessTerminator(IRTerminatorInst* terminator)
//
// We need to detect if the return value accesses the root
- if (terminator->getOp() == kIROp_ReturnVal)
+ if (terminator->getOp() == kIROp_Return)
{
// We are going to special case return if it hits an alias
- auto returnVal = static_cast<IRReturnVal*>(terminator);
+ auto returnVal = static_cast<IRReturn*>(terminator);
auto val = returnVal->getVal();
@@ -1242,4 +1242,3 @@ static void _processFunction(IRFunc* funcInst, List<IRVar*>& ioVars)
}
} // namespace Slang
- \ No newline at end of file
diff --git a/source/slang/slang-ir-lower-error-handling.cpp b/source/slang/slang-ir-lower-error-handling.cpp
index 5a1389e57..387ab45b4 100644
--- a/source/slang/slang-ir-lower-error-handling.cpp
+++ b/source/slang/slang-ir-lower-error-handling.cpp
@@ -130,15 +130,8 @@ struct ErrorHandlingLoweringContext
auto resultType =
builder.getResultType(funcType->getResultType(), throwAttr->getErrorType());
IRInst* resultVal = nullptr;
- if (ret->getOp() == kIROp_ReturnVal)
- {
- auto val = cast<IRReturnVal>(ret)->getVal();
- resultVal = builder.emitMakeResultValue(resultType, val);
- }
- else
- {
- resultVal = builder.emitMakeResultValueVoid(resultType);
- }
+ auto val = cast<IRReturn>(ret)->getVal();
+ resultVal = builder.emitMakeResultValue(resultType, val);
builder.emitReturn(resultVal);
ret->removeAndDeallocate();
}
@@ -169,8 +162,7 @@ struct ErrorHandlingLoweringContext
case kIROp_TryCall:
processTryCall(cast<IRTryCall>(inst));
break;
- case kIROp_ReturnVal:
- case kIROp_ReturnVoid:
+ case kIROp_Return:
processReturn(cast<IRReturn>(inst));
break;
case kIROp_Throw:
@@ -206,7 +198,7 @@ struct ErrorHandlingLoweringContext
// Deduplicate equivalent types.
sharedBuilder.deduplicateAndRebuildGlobalNumberingMap();
- // Translate all IRTryCall, IRThrow, IRReturn, IRReturnVal.
+ // Translate all IRTryCall, IRThrow, IRReturn.
processInsts();
// Lower all functypes.
diff --git a/source/slang/slang-ir-lower-error-handling.h b/source/slang/slang-ir-lower-error-handling.h
index 92a65404c..25825766a 100644
--- a/source/slang/slang-ir-lower-error-handling.h
+++ b/source/slang/slang-ir-lower-error-handling.h
@@ -11,7 +11,7 @@ class DiagnosticSink;
/// A function with an error code type will be translated into a function that returns `Result<T,E>`, which can be
/// further lowered to standard return values and `out` parameters in a separate pass.
/// Call sites (`IRTryCall`) to error-throwing function will be rewritten to conform to the new function signature.
-/// `IRThrow` will be replaced with `IRReturnVal(IRMakeErrorResult(e))`.
+/// `IRThrow` will be replaced with `IRReturn(IRMakeErrorResult(e))`.
///
void lowerErrorHandling(IRModule* module, DiagnosticSink* sink);
diff --git a/source/slang/slang-ir-lower-generic-function.cpp b/source/slang/slang-ir-lower-generic-function.cpp
index a2636e8ed..bf20452d7 100644
--- a/source/slang/slang-ir-lower-generic-function.cpp
+++ b/source/slang/slang-ir-lower-generic-function.cpp
@@ -58,7 +58,7 @@ namespace Slang
{
if (genericChild == func)
continue;
- if (genericChild->getOp() == kIROp_ReturnVal)
+ if (genericChild->getOp() == kIROp_Return)
continue;
// Process all generic parameters and local type definitions.
auto clonedChild = cloneInst(&cloneEnv, &builder, genericChild);
diff --git a/source/slang/slang-ir-lower-result-type.cpp b/source/slang/slang-ir-lower-result-type.cpp
index e46a0ceb5..7e632241b 100644
--- a/source/slang/slang-ir-lower-result-type.cpp
+++ b/source/slang/slang-ir-lower-result-type.cpp
@@ -124,23 +124,19 @@ namespace Slang
builder->setInsertBefore(inst);
auto info = getLoweredResultType(builder, inst->getDataType());
- List<IRInst*> operands;
- operands.add(inst->getOperand(0));
- operands.add(getSuccessErrorValue(info->errorType));
- auto makeStruct = builder->emitMakeStruct(info->loweredType, operands);
- inst->replaceUsesWith(makeStruct);
- inst->removeAndDeallocate();
- }
-
- void processMakeResultValueVoid(IRMakeResultValueVoid* inst)
- {
- IRBuilder builderStorage(sharedBuilderStorage);
- auto builder = &builderStorage;
- builder->setInsertBefore(inst);
-
- auto info = getLoweredResultType(builder, inst->getDataType());
- auto errCode = getSuccessErrorValue(info->errorType);
- inst->replaceUsesWith(errCode);
+ if (info->loweredType->getOp() == kIROp_VoidType)
+ {
+ List<IRInst*> operands;
+ operands.add(inst->getOperand(0));
+ operands.add(getSuccessErrorValue(info->errorType));
+ auto makeStruct = builder->emitMakeStruct(info->loweredType, operands);
+ inst->replaceUsesWith(makeStruct);
+ }
+ else
+ {
+ auto errCode = getSuccessErrorValue(info->errorType);
+ inst->replaceUsesWith(errCode);
+ }
inst->removeAndDeallocate();
}
@@ -251,9 +247,6 @@ namespace Slang
case kIROp_MakeResultValue:
processMakeResultValue((IRMakeResultValue*)inst);
break;
- case kIROp_MakeResultValueVoid:
- processMakeResultValueVoid((IRMakeResultValueVoid*)inst);
- break;
case kIROp_MakeResultError:
processMakeResultError((IRMakeResultError*)inst);
break;
diff --git a/source/slang/slang-ir-restructure.cpp b/source/slang/slang-ir-restructure.cpp
index 7ab5b4417..7cd33406d 100644
--- a/source/slang/slang-ir-restructure.cpp
+++ b/source/slang/slang-ir-restructure.cpp
@@ -253,8 +253,7 @@ namespace Slang
; // fall through to:
case kIROp_Unreachable:
case kIROp_MissingReturn:
- case kIROp_ReturnVal:
- case kIROp_ReturnVoid:
+ case kIROp_Return:
case kIROp_discard:
// These cases are all simple terminators that can be handled as-is
// without needing to construct a separate `Region` to encapsulate them.
diff --git a/source/slang/slang-ir-specialize-dispatch.cpp b/source/slang/slang-ir-specialize-dispatch.cpp
index bcd7b494f..450867abb 100644
--- a/source/slang/slang-ir-specialize-dispatch.cpp
+++ b/source/slang/slang-ir-specialize-dispatch.cpp
@@ -32,8 +32,7 @@ IRFunc* specializeDispatchFunction(SharedGenericsLoweringContext* sharedContext,
case kIROp_lookup_interface_method:
lookupInst = cast<IRLookupWitnessMethod>(inst);
break;
- case kIROp_ReturnVal:
- case kIROp_ReturnVoid:
+ case kIROp_Return:
returnInst = cast<IRReturn>(inst);
break;
default:
diff --git a/source/slang/slang-ir-specialize-resources.cpp b/source/slang/slang-ir-specialize-resources.cpp
index 05a7c23de..ad6baea67 100644
--- a/source/slang/slang-ir-specialize-resources.cpp
+++ b/source/slang/slang-ir-specialize-resources.cpp
@@ -554,7 +554,7 @@ struct ResourceOutputSpecializationPass
//
for( auto block : func->getBlocks() )
{
- auto returnInst = as<IRReturnVal>(block->getTerminator());
+ auto returnInst = as<IRReturn>(block->getTerminator());
if(!returnInst)
continue;
diff --git a/source/slang/slang-ir-specialize.cpp b/source/slang/slang-ir-specialize.cpp
index 9ceb4dbe7..9cc2d9ad0 100644
--- a/source/slang/slang-ir-specialize.cpp
+++ b/source/slang/slang-ir-specialize.cpp
@@ -2170,7 +2170,7 @@ IRInst* specializeGenericImpl(
// We thus use that cloned value as the result of the
// specialization step.
//
- if( auto returnValInst = as<IRReturnVal>(ii) )
+ if( auto returnValInst = as<IRReturn>(ii) )
{
auto specializedVal = findCloneForOperand(&env, returnValInst->getVal());
diff --git a/source/slang/slang-ir-synthesize-active-mask.cpp b/source/slang/slang-ir-synthesize-active-mask.cpp
index 79d7df559..70d3b6180 100644
--- a/source/slang/slang-ir-synthesize-active-mask.cpp
+++ b/source/slang/slang-ir-synthesize-active-mask.cpp
@@ -1126,8 +1126,7 @@ struct SynthesizeActiveMaskForFunctionContext
}
break;
- case kIROp_ReturnVal:
- case kIROp_ReturnVoid:
+ case kIROp_Return:
{
// A `return` instruction is akin to an unconditional branch,
// except that it is guaranteed to exit any structured control
diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp
index c71954346..ee84cce73 100644
--- a/source/slang/slang-ir.cpp
+++ b/source/slang/slang-ir.cpp
@@ -486,8 +486,7 @@ namespace Slang
auto operands = terminator->getOperands();
switch (terminator->getOp())
{
- case kIROp_ReturnVal:
- case kIROp_ReturnVoid:
+ case kIROp_Return:
case kIROp_Unreachable:
case kIROp_MissingReturn:
case kIROp_discard:
@@ -762,8 +761,7 @@ namespace Slang
default:
return false;
- case kIROp_ReturnVal:
- case kIROp_ReturnVoid:
+ case kIROp_Return:
case kIROp_unconditionalBranch:
case kIROp_conditionalBranch:
case kIROp_loop:
@@ -1968,6 +1966,10 @@ namespace Slang
{
return getStringSlice() == rhs->getStringSlice();
}
+ case kIROp_VoidLit:
+ {
+ return true;
+ }
default: break;
}
@@ -2006,6 +2008,10 @@ namespace Slang
const UnownedStringSlice slice = getStringSlice();
return combineHash(code, Slang::getHashCode(slice.begin(), slice.getLength()));
}
+ case kIROp_VoidLit:
+ {
+ return code;
+ }
default:
{
SLANG_ASSERT(!"Invalid type");
@@ -2066,6 +2072,14 @@ namespace Slang
irValue->value.ptrVal = keyInst.value.ptrVal;
break;
}
+ case kIROp_VoidLit:
+ {
+ const size_t instSize = prefixSize;
+ irValue = static_cast<IRConstant*>(
+ _createInst(instSize, keyInst.getFullType(), keyInst.getOp()));
+ irValue->value.ptrVal = keyInst.value.ptrVal;
+ break;
+ }
case kIROp_StringLit:
{
const UnownedStringSlice slice = keyInst.getStringSlice();
@@ -2198,6 +2212,18 @@ namespace Slang
return (IRPtrLit*) _findOrEmitConstant(keyInst);
}
+ IRVoidLit* IRBuilder::getVoidValue()
+ {
+ IRType* type = getVoidType();
+
+ IRConstant keyInst;
+ memset(&keyInst, 0, sizeof(keyInst));
+ keyInst.m_op = kIROp_VoidLit;
+ keyInst.typeUse.usedValue = type;
+ keyInst.value.intVal= 0;
+ return (IRVoidLit*)_findOrEmitConstant(keyInst);
+ }
+
IRInst* IRBuilder::getCapabilityValue(CapabilitySet const& caps)
{
IRType* capabilityAtomType = getIntType();
@@ -3222,11 +3248,6 @@ namespace Slang
return emitIntrinsicInst(resultType, kIROp_MakeResultValue, 1, &value);
}
- IRInst* IRBuilder::emitMakeResultValueVoid(IRType* resultType)
- {
- return emitIntrinsicInst(resultType, kIROp_MakeResultValueVoid, 0, nullptr);
- }
-
IRInst* IRBuilder::emitIsResultError(IRInst* result)
{
return emitIntrinsicInst(getBoolType(), kIROp_IsResultError, 1, &result);
@@ -3930,9 +3951,9 @@ namespace Slang
IRInst* IRBuilder::emitReturn(
IRInst* val)
{
- auto inst = createInst<IRReturnVal>(
+ auto inst = createInst<IRReturn>(
this,
- kIROp_ReturnVal,
+ kIROp_Return,
nullptr,
val);
addInst(inst);
@@ -3941,10 +3962,8 @@ namespace Slang
IRInst* IRBuilder::emitReturn()
{
- auto inst = createInst<IRReturnVoid>(
- this,
- kIROp_ReturnVoid,
- nullptr);
+ auto voidVal = getVoidValue();
+ auto inst = createInst<IRReturn>(this, kIROp_Return, nullptr, voidVal);
addInst(inst);
return inst;
}
@@ -6001,7 +6020,7 @@ namespace Slang
if (!lastBlock)
return nullptr;
- auto returnInst = as<IRReturnVal>(lastBlock->getTerminator());
+ auto returnInst = as<IRReturn>(lastBlock->getTerminator());
if (!returnInst)
return nullptr;
diff --git a/source/slang/slang-ir.h b/source/slang/slang-ir.h
index 6593e4409..7a9a1ebee 100644
--- a/source/slang/slang-ir.h
+++ b/source/slang/slang-ir.h
@@ -898,6 +898,11 @@ struct IRPtrLit : IRConstant
void* getValue() { return value.ptrVal; }
};
+struct IRVoidLit : IRConstant
+{
+ IR_LEAF_ISA(VoidLit);
+};
+
// A instruction that ends a basic block (usually because of control flow)
struct IRTerminatorInst : IRInst
{
diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp
index 1448139fb..fc8180e12 100644
--- a/source/slang/slang-lower-to-ir.cpp
+++ b/source/slang/slang-lower-to-ir.cpp
@@ -1622,7 +1622,7 @@ struct ValLoweringVisitor : ValVisitor<ValLoweringVisitor, LoweredValInfo, Lower
{
paramTypes.add(lowerType(context, type->getParamType(pp)));
}
- if (type->errorType->equals(context->astBuilder->getVoidType()))
+ if (type->getErrorType()->equals(context->astBuilder->getBottomType()))
{
return getBuilder()->getFuncType(
paramCount,
@@ -2838,9 +2838,9 @@ void _lowerFuncDeclBaseTypeInfo(
irResultType = builder->getPtrType(irResultType);
}
- auto errorType = lowerType(context, getErrorCodeType(context->astBuilder, declRef));
- if (errorType->getOp() != kIROp_VoidType)
+ if (!getErrorCodeType(context->astBuilder, declRef)->equals(context->astBuilder->getBottomType()))
{
+ auto errorType = lowerType(context, getErrorCodeType(context->astBuilder, declRef));
IRAttr* throwTypeAttr = nullptr;
throwTypeAttr = builder->getAttr(kIROp_FuncThrowTypeAttr, 1, (IRInst**)&errorType);
outInfo.type = builder->getFuncType(
diff --git a/source/slang/slang-serialize-ir.cpp b/source/slang/slang-serialize-ir.cpp
index 221a97bc8..062f1ed1a 100644
--- a/source/slang/slang-serialize-ir.cpp
+++ b/source/slang/slang-serialize-ir.cpp
@@ -232,6 +232,11 @@ Result IRSerialWriter::write(IRModule* module, SerialSourceLocWriter* sourceLocW
dstInst.m_payload.m_uint32 = irConst->value.intVal ? 1 : 0;
break;
}
+ case kIROp_VoidLit:
+ {
+ dstInst.m_payloadType = PayloadType::Empty;
+ break;
+ }
default:
{
SLANG_RELEASE_ASSERT(!"Unhandled constant type");
@@ -795,6 +800,13 @@ Result IRSerialReader::read(const IRSerialData& data, Session* session, SerialSo
irConst->value.floatVal = srcInst.m_payload.m_float64;
break;
}
+ case kIROp_VoidLit:
+ {
+ SLANG_ASSERT(srcInst.m_payloadType == PayloadType::Empty);
+ irConst = static_cast<IRConstant*>(module->_allocateInst(
+ op, operandCount, prefixSize));
+ break;
+ }
case kIROp_StringLit:
{
SLANG_ASSERT(srcInst.m_payloadType == PayloadType::String_1);
diff --git a/source/slang/slang-syntax.h b/source/slang/slang-syntax.h
index b4463a77d..332661e12 100644
--- a/source/slang/slang-syntax.h
+++ b/source/slang/slang-syntax.h
@@ -170,7 +170,7 @@ namespace Slang
}
else
{
- return astBuilder->getVoidType();
+ return astBuilder->getBottomType();
}
}