diff options
Diffstat (limited to 'source')
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(); } } |
