diff options
| -rw-r--r-- | source/slang/ir-serialize.cpp | 274 | ||||
| -rw-r--r-- | source/slang/ir-serialize.h | 66 |
2 files changed, 164 insertions, 176 deletions
diff --git a/source/slang/ir-serialize.cpp b/source/slang/ir-serialize.cpp index 854b60419..2645e445d 100644 --- a/source/slang/ir-serialize.cpp +++ b/source/slang/ir-serialize.cpp @@ -27,6 +27,20 @@ to an IRType derived type. Its 'ok' as long as it's an instruction that can be u bother to check if it's correct, and just casts it. */ +/* static */const IRSerialData::PayloadInfo IRSerialData::s_payloadInfos[int(Inst::PayloadType::CountOf)] = +{ + { 0, 0 }, // Empty + { 1, 0 }, // Operand_1 + { 2, 0 }, // Operand_2 + { 1, 0 }, // OperandAndUInt32, + { 0, 0 }, // OperandExternal - This isn't correct, Operand has to be specially handled + { 0, 1 }, // String_1, + { 0, 2 }, // String_2, + { 0, 0 }, // UInt32, + { 0, 0 }, // Float64, + { 0, 0 } // Int64, +}; + static bool isParentDerived(IROp opIn) { const int op = (kIROpMeta_PseudoOpMask & opIn); @@ -112,7 +126,6 @@ void IRSerialWriter::_addInstruction(IRInst* inst) } } - IRSerialData::StringIndex IRSerialWriter::getStringIndex(Name* name) { return name ? getStringIndex(name->text.getStringRepresentation()) : Ser::kNullStringIndex; @@ -297,8 +310,9 @@ Result IRSerialWriter::write(IRModule* module, IRSerialData* serialData) IRTextureTypeBase* textureBase = as<IRTextureTypeBase>(srcInst); if (textureBase) { - dstInst.m_payloadType = Ser::Inst::PayloadType::UInt32; - dstInst.m_payload.m_uint32 = uint32_t(srcInst->op) >> kIROpMeta_OtherShift; + dstInst.m_payloadType = Ser::Inst::PayloadType::OperandAndUInt32; + dstInst.m_payload.m_operandAndUInt32.m_uint32 = uint32_t(srcInst->op) >> kIROpMeta_OtherShift; + dstInst.m_payload.m_operandAndUInt32.m_operand = getInstIndex(textureBase->getElementType()); continue; } @@ -315,7 +329,7 @@ Result IRSerialWriter::write(IRModule* module, IRSerialData* serialData) } else { - dstInst.m_payloadType = Ser::Inst::PayloadType::ExternalOperand; + dstInst.m_payloadType = Ser::Inst::PayloadType::OperandExternal; int operandArrayBaseIndex = int(m_serialData->m_externalOperands.Count()); m_serialData->m_externalOperands.SetSize(operandArrayBaseIndex + numOperands); @@ -407,6 +421,13 @@ Result IRSerialWriter::write(IRModule* module, IRSerialData* serialData) dstInst.m_payload.m_stringIndices[0] = getStringIndex(semanticDecor->semanticName); break; } + case kIRDecorationOp_InterpolationMode: + { + auto semanticDecor = static_cast<IRInterpolationModeDecoration*>(srcDecor); + dstInst.m_payloadType = Ser::Inst::PayloadType::UInt32; + dstInst.m_payload.m_uint32 = uint32_t(semanticDecor->mode); + break; + } case kIRDecorationOp_NameHint: { auto nameDecor = static_cast<IRNameHintDecoration*>(srcDecor); @@ -790,42 +811,98 @@ void IRSerialReader::_calcStringStarts() memset(m_stringRepresentationCache.begin(), 0, sizeof(StringRepresentation*) * m_stringStarts.Count()); } -/* static */Result IRSerialReader::read(const IRSerialData& data, TranslationUnitRequest* translationUnit, IRModule** moduleOut) +IRDecoration* IRSerialReader::_createDecoration(const Ser::Inst& srcInst) { typedef Ser::Inst::PayloadType PayloadType; - *moduleOut = nullptr; - - m_serialData = &data; - _calcStringStarts(); - - auto compileRequest = translationUnit->compileRequest; - - //SharedIRGenContext sharedContextStorage; - //SharedIRGenContext* sharedContext = &sharedContextStorage; + IRDecorationOp decorOp = IRDecorationOp(srcInst.m_op - kIROpCount); + SLANG_ASSERT(decorOp < kIRDecorationOp_CountOf); - //sharedContext->compileRequest = compileRequest; - //sharedContext->mainModuleDecl = translationUnit->SyntaxNode; - - //IRGenContext contextStorage(sharedContext); - //IRGenContext* context = &contextStorage; - - SharedIRBuilder sharedBuilderStorage; - SharedIRBuilder* sharedBuilder = &sharedBuilderStorage; - sharedBuilder->module = nullptr; - sharedBuilder->session = compileRequest->mSession; + switch (decorOp) + { + case kIRDecorationOp_HighLevelDecl: + { + // TODO! + // Decl* decl; + return createEmptyDecoration<IRHighLevelDeclDecoration>(m_module); + } + case kIRDecorationOp_Layout: + { + // TODO! + // Layout* layout; + return createEmptyDecoration<IRLayoutDecoration>(m_module); + } + case kIRDecorationOp_LoopControl: + { + auto decor = createEmptyDecoration<IRLoopControlDecoration>(m_module); + SLANG_ASSERT(srcInst.m_payloadType == PayloadType::UInt32); + decor->mode = IRLoopControl(srcInst.m_payload.m_uint32); + return decor; + } + case kIRDecorationOp_Target: + { + auto decor = createEmptyDecoration<IRTargetDecoration>(m_module); + SLANG_ASSERT(srcInst.m_payloadType == PayloadType::String_1); + decor->targetName = getStringRepresentation(srcInst.m_payload.m_stringIndices[0]); + return decor; + } + case kIRDecorationOp_TargetIntrinsic: + { + auto decor = createEmptyDecoration<IRTargetIntrinsicDecoration>(m_module); + SLANG_ASSERT(srcInst.m_payloadType == PayloadType::String_2); + decor->targetName = getStringRepresentation(srcInst.m_payload.m_stringIndices[0]); + decor->definition = getStringRepresentation(srcInst.m_payload.m_stringIndices[1]); + return decor; + } + case kIRDecorationOp_GLSLOuterArray: + { + auto decor = createEmptyDecoration<IRGLSLOuterArrayDecoration>(m_module); + SLANG_ASSERT(srcInst.m_payloadType == PayloadType::String_1); + decor->outerArrayName = getCStr(srcInst.m_payload.m_stringIndices[0]); + return decor; + } + case kIRDecorationOp_Semantic: + { + auto decor = createEmptyDecoration<IRSemanticDecoration>(m_module); + SLANG_ASSERT(srcInst.m_payloadType == PayloadType::String_1); + decor->semanticName = getName(srcInst.m_payload.m_stringIndices[0]); + return decor; + } + case kIRDecorationOp_InterpolationMode: + { + auto decor = createEmptyDecoration<IRInterpolationModeDecoration>(m_module); + SLANG_ASSERT(srcInst.m_payloadType == Ser::Inst::PayloadType::UInt32); + decor->mode = IRInterpolationMode(srcInst.m_payload.m_uint32); + return decor; + } + case kIRDecorationOp_NameHint: + { + auto decor = createEmptyDecoration<IRNameHintDecoration>(m_module); + SLANG_ASSERT(srcInst.m_payloadType == PayloadType::String_1); + decor->name = getName(srcInst.m_payload.m_stringIndices[0]); + return decor; + } + default: + { + SLANG_ASSERT(!"Unhandled decoration type"); + return nullptr; + } + } +} - IRBuilder builderStorage; - IRBuilder* builder = &builderStorage; - builder->sharedBuilder = sharedBuilder; +/* static */Result IRSerialReader::read(const IRSerialData& data, Session* session, RefPtr<IRModule>& moduleOut) +{ + typedef Ser::Inst::PayloadType PayloadType; - RefPtr<IRModule> module = builder->createModule(); - sharedBuilder->module = module; + m_serialData = &data; + _calcStringStarts(); + auto module = new IRModule(); + moduleOut = module; m_module = module; - - //context->irBuilder = builder; + module->session = session; + // Add all the instructions List<IRInst*> insts; @@ -842,17 +919,20 @@ void IRSerialReader::_calcStringStarts() decorations.SetSize(numDecorations); // 0 holds null - // The first instruction must be the module + // 1 holds the IRModuleInst { // Check that insts[1] is the module inst const Ser::Inst& srcInst = data.m_insts[1]; SLANG_RELEASE_ASSERT(srcInst.m_op == kIROp_Module); - SLANG_ASSERT(srcInst.getNumOperands() == 0); SLANG_ASSERT(srcInst.m_payloadType == PayloadType::Empty); - // We don't need to create the moduleInst, because it's constructed via the createModule call - SLANG_ASSERT(module->moduleInst); - insts[1] = module->moduleInst; + // Create the module inst + auto moduleInst = static_cast<IRModuleInst*>(createEmptyInstWithSize(module, kIROp_Module, sizeof(IRModuleInst))); + module->moduleInst = moduleInst; + moduleInst->module = module; + + // Set the IRModuleInst + insts[1] = moduleInst; } for (int i = 2; i < numInsts; ++i) @@ -945,11 +1025,11 @@ void IRSerialReader::_calcStringStarts() } else if (isTextureTypeBase(op)) { - IRTextureTypeBase* inst = static_cast<IRTextureTypeBase*>(createEmptyInstWithSize(module, op, sizeof(IRTextureTypeBase))); - SLANG_ASSERT(srcInst.m_payloadType == PayloadType::UInt32); + IRTextureTypeBase* inst = static_cast<IRTextureTypeBase*>(createEmptyInst(module, op, 1)); + SLANG_ASSERT(srcInst.m_payloadType == PayloadType::OperandAndUInt32); // Reintroduce the texture type bits into the the - const uint32_t other = srcInst.m_payload.m_uint32; + const uint32_t other = srcInst.m_payload.m_operandAndUInt32.m_uint32; inst->op = IROp(uint32_t(inst->op) | (other << kIROpMeta_OtherShift)); insts[i] = inst; @@ -963,7 +1043,6 @@ void IRSerialReader::_calcStringStarts() } // Patch up the operands - for (int i = 1; i < numInsts; ++i) { const Ser::Inst& srcInst = data.m_insts[i]; @@ -995,7 +1074,6 @@ void IRSerialReader::_calcStringStarts() } // Patch up the children - { const int numChildRuns = int(data.m_childRuns.Count()); for (int i = 0; i < numChildRuns; i++) @@ -1016,98 +1094,15 @@ void IRSerialReader::_calcStringStarts() } } - // Add the decorations + // Create the decorations for (int i = 0; i < numDecorations; ++i) { - const Ser::Inst& srcInst = data.m_insts[i + numInsts]; - IRDecorationOp decorOp = IRDecorationOp(srcInst.m_op - kIROpCount); - SLANG_ASSERT(decorOp < kIRDecorationOp_CountOf); - - switch (decorOp) + IRDecoration* decor = _createDecoration(data.m_insts[i + numInsts]); + if (!decor) { - case kIRDecorationOp_HighLevelDecl: - { - auto decor = createEmptyDecoration<IRHighLevelDeclDecoration>(m_module); - decorations[i] = decor; - - // TODO! - // Decl* decl; - break; - } - case kIRDecorationOp_Layout: - { - auto decor = createEmptyDecoration<IRLayoutDecoration>(m_module); - decorations[i] = decor; - - // TODO! - // Layout* layout; - break; - } - case kIRDecorationOp_LoopControl: - { - auto decor = createEmptyDecoration<IRLoopControlDecoration>(m_module); - decorations[i] = decor; - - SLANG_ASSERT(srcInst.m_payloadType == PayloadType::UInt32); - decor->mode = IRLoopControl(srcInst.m_payload.m_uint32); - - break; - } - case kIRDecorationOp_Target: - { - auto decor = createEmptyDecoration<IRTargetDecoration>(m_module); - decorations[i] = decor; - - SLANG_ASSERT(srcInst.m_payloadType == PayloadType::String_1); - decor->targetName = getStringRepresentation(srcInst.m_payload.m_stringIndices[0]); - break; - } - case kIRDecorationOp_TargetIntrinsic: - { - auto decor = createEmptyDecoration<IRTargetIntrinsicDecoration>(m_module); - decorations[i] = decor; - - SLANG_ASSERT(srcInst.m_payloadType == PayloadType::String_2); - decor->targetName = getStringRepresentation(srcInst.m_payload.m_stringIndices[0]); - decor->definition = getStringRepresentation(srcInst.m_payload.m_stringIndices[1]); - break; - } - case kIRDecorationOp_GLSLOuterArray: - { - auto decor = createEmptyDecoration<IRGLSLOuterArrayDecoration>(m_module); - decorations[i] = decor; - - SLANG_ASSERT(srcInst.m_payloadType == PayloadType::String_1); - decor->outerArrayName = getCStr(srcInst.m_payload.m_stringIndices[0]); - break; - } - case kIRDecorationOp_Semantic: - { - auto decor = createEmptyDecoration<IRSemanticDecoration>(m_module); - decorations[i] = decor; - - SLANG_ASSERT(srcInst.m_payloadType == PayloadType::String_1); - decor->semanticName = getName(srcInst.m_payload.m_stringIndices[0]); - break; - } - case kIRDecorationOp_NameHint: - { - auto decor = createEmptyDecoration<IRNameHintDecoration>(m_module); - decorations[i] = decor; - - SLANG_ASSERT(srcInst.m_payloadType == PayloadType::String_1); - decor->name = getName(srcInst.m_payload.m_stringIndices[0]); - break; - } - default: - { - SLANG_ASSERT(!"Unhandled decoration type"); - return SLANG_FAIL; - } + return SLANG_FAIL; } - - // Make sure something is set - SLANG_ASSERT(decorations[i]); + decorations[i] = decor; } // Associate the decorations with the instructions @@ -1126,11 +1121,13 @@ void IRSerialReader::_calcStringStarts() IRInst* inst = insts[int(run.m_parentIndex)]; SLANG_ASSERT(int(run.m_startInstIndex) >= decorationBaseIndex && int(run.m_startInstIndex) + run.m_numChildren <= m_serialData->m_insts.Count()); + // Calculate the offset in the decoration list, which index 0, is decorationBaseIndex in instruction indices + const int decorStartIndex = int(run.m_startInstIndex) - decorationBaseIndex; + // Go in reverse order so that linked list is in same order as original for (int j = int(run.m_numChildren) - 1; j >= 0; --j) { - IRDecoration* decor = decorations[int(run.m_startInstIndex) + j - decorationBaseIndex]; - + IRDecoration* decor = decorations[decorStartIndex + j]; // And to the linked list on the decor->next = inst->firstDecoration; inst->firstDecoration = decor; @@ -1138,13 +1135,11 @@ void IRSerialReader::_calcStringStarts() } } - *moduleOut = module.detach(); return SLANG_OK; } // !!!!!!!!!!!!!!!!!!!!!!!!!!!! Free functions !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - Result serializeModule(IRModule* module, Stream* stream) { IRSerialWriter serializer; @@ -1160,22 +1155,13 @@ Result serializeModule(IRModule* module, Stream* stream) return SLANG_OK; } -Result readModule(TranslationUnitRequest* translationUnit, Stream* stream, IRModule** moduleOut) +Result readModule(Session* session, Stream* stream, RefPtr<IRModule>& moduleOut) { - *moduleOut = nullptr; - IRSerialData serialData; IRSerialReader::readStream(stream, &serialData); - RefPtr<IRModule> module; IRSerialReader reader; - - SLANG_RETURN_ON_FAIL(reader.read(serialData, translationUnit, module.writeRef())); - - *moduleOut = module.detach(); - - return SLANG_OK; + return reader.read(serialData, session, moduleOut); } - } // namespace Slang diff --git a/source/slang/ir-serialize.h b/source/slang/ir-serialize.h index e949e1239..31e8aa6ee 100644 --- a/source/slang/ir-serialize.h +++ b/source/slang/ir-serialize.h @@ -41,37 +41,39 @@ struct IRSerialData SizeType m_numChildren; ///< The number of children }; + struct PayloadInfo + { + uint8_t m_numOperands; + uint8_t m_numStrings; + }; + // Instruction... // We can store SourceLoc values separately. Just store per index information. // Parent information is stored in m_childRuns // Decoration information is stored in m_decorationRuns struct Inst { + // NOTE! Can't change order or list without changing approprite s_payloadInfos enum class PayloadType : uint8_t { Empty, ///< Has no payload (or operands) Operand_1, ///< 1 Operand Operand_2, ///< 2 Operands - ExternalOperand, ///< Operands are held externally + OperandAndUInt32, ///< 1 Operand and a single UInt32 + OperandExternal, ///< Operands are held externally String_1, ///< 1 String String_2, ///< 2 Strings UInt32, ///< Holds an unsigned 32 bit integral (might represent a type) - Float64, + Float64, Int64, + CountOf, }; /// Get the number of operands - int getNumOperands() const + SLANG_FORCE_INLINE int getNumOperands() const { - switch (m_payloadType) - { - default: /* fallthru */ - case PayloadType::Empty: return 0; - case PayloadType::Operand_1: return 1; - case PayloadType::Operand_2: return 2; - case PayloadType::ExternalOperand: return m_payload.m_externalOperand.m_size; - } + return (m_payloadType == PayloadType::OperandExternal) ? m_payload.m_externalOperand.m_size : s_payloadInfos[int(m_payloadType)].m_numOperands; } uint8_t m_op; ///< For now one of IROp @@ -86,6 +88,12 @@ struct IRSerialData SizeType m_size; ///< The amount of entries in that table }; + struct OperandAndUInt32 + { + InstIndex m_operand; + uint32_t m_uint32; + }; + union Payload { double m_float64; @@ -96,6 +104,7 @@ struct IRSerialData InstIndex m_operands[kNumOperands]; ///< For items that 2 or less operands it can use this. StringIndex m_stringIndices[kNumOperands]; ExternalOperandPayload m_externalOperand; ///< Operands are stored in an an index of an operand array + OperandAndUInt32 m_operandAndUInt32; }; Payload m_payload; @@ -119,27 +128,17 @@ struct IRSerialData m_decorationBaseIndex = 0; } - int getOperands(const Inst& inst, const InstIndex** operandsOut) const + SLANG_FORCE_INLINE int getOperands(const Inst& inst, const InstIndex** operandsOut) const { - switch (inst.m_payloadType) + if (inst.m_payloadType == Inst::PayloadType::OperandExternal) + { + *operandsOut = m_externalOperands.begin() + int(inst.m_payload.m_externalOperand.m_arrayIndex); + return int(inst.m_payload.m_externalOperand.m_size); + } + else { - default: - case Inst::PayloadType::Empty: - { - *operandsOut = nullptr; - return 0; - } - case Inst::PayloadType::Operand_1: - case Inst::PayloadType::Operand_2: - { - *operandsOut = inst.m_payload.m_operands; - return int(inst.m_payloadType) - int(Inst::PayloadType::Empty); - } - case Inst::PayloadType::ExternalOperand: - { - *operandsOut = m_externalOperands.begin() + int(inst.m_payload.m_externalOperand.m_arrayIndex); - return int(inst.m_payload.m_externalOperand.m_size); - } + *operandsOut = inst.m_payload.m_operands; + return s_payloadInfos[int(inst.m_payloadType)].m_numOperands; } } @@ -158,6 +157,8 @@ struct IRSerialData List<char> m_strings; ///< All strings. Indexed into by StringIndex + static const PayloadInfo s_payloadInfos[int(Inst::PayloadType::CountOf)]; + int m_decorationBaseIndex; ///< All decorations insts are at indices >= to this value }; @@ -247,7 +248,7 @@ struct IRSerialReader static Result readStream(Stream* stream, IRSerialData* dataOut); /// Read a module from serial data - Result read(const IRSerialData& data, TranslationUnitRequest* translationUnit, IRModule** moduleOut); + Result read(const IRSerialData& data, Session* session, RefPtr<IRModule>& moduleOut); Name* getName(Ser::StringIndex index); String getString(Ser::StringIndex index); @@ -266,6 +267,7 @@ struct IRSerialReader protected: void _calcStringStarts(); + IRDecoration* _createDecoration(const Ser::Inst& srcIns); List<Ser::StringOffset> m_stringStarts; List<StringRepresentation*> m_stringRepresentationCache; @@ -276,7 +278,7 @@ struct IRSerialReader Result serializeModule(IRModule* module, Stream* stream); -Result readModule(TranslationUnitRequest* translationUnit, Stream* stream, IRModule** moduleOut); +Result readModule(Session* session, Stream* stream, RefPtr<IRModule>& moduleOut); } // namespace Slang |
