X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=SPIRV%2FspvIR.h;h=09691273abf38f21631a907a5e8ff213350a9595;hb=7a914ce9261dd591ec793df42b5aba11d6c02848;hp=7e2d4bc14525b6d408ed09c5804118d3fa1a5173;hpb=8aa9a7bb8f74869ab9cfd2c9bd51cef1741004e7;p=platform%2Fupstream%2Fglslang.git diff --git a/SPIRV/spvIR.h b/SPIRV/spvIR.h old mode 100755 new mode 100644 index 7e2d4bc..0969127 --- a/SPIRV/spvIR.h +++ b/SPIRV/spvIR.h @@ -55,6 +55,7 @@ #include #include #include +#include namespace spv { @@ -110,27 +111,23 @@ public: void addStringOperand(const char* str) { - unsigned int word; - char* wordString = (char*)&word; - char* wordPtr = wordString; - int charCount = 0; + unsigned int word = 0; + unsigned int shiftAmount = 0; char c; + do { c = *(str++); - *(wordPtr++) = c; - ++charCount; - if (charCount == 4) { + word |= ((unsigned int)c) << shiftAmount; + shiftAmount += 8; + if (shiftAmount == 32) { addImmediateOperand(word); - wordPtr = wordString; - charCount = 0; + word = 0; + shiftAmount = 0; } } while (c != 0); // deal with partial last word - if (charCount > 0) { - // pad with 0s - for (; charCount < 4; ++charCount) - *(wordPtr++) = 0; + if (shiftAmount > 0) { addImmediateOperand(word); } } @@ -226,6 +223,35 @@ public: return nullptr; } + // Change this block into a canonical dead merge block. Delete instructions + // as necessary. A canonical dead merge block has only an OpLabel and an + // OpUnreachable. + void rewriteAsCanonicalUnreachableMerge() { + assert(localVariables.empty()); + // Delete all instructions except for the label. + assert(instructions.size() > 0); + instructions.resize(1); + successors.clear(); + addInstruction(std::unique_ptr(new Instruction(OpUnreachable))); + } + // Change this block into a canonical dead continue target branching to the + // given header ID. Delete instructions as necessary. A canonical dead continue + // target has only an OpLabel and an unconditional branch back to the corresponding + // header. + void rewriteAsCanonicalUnreachableContinue(Block* header) { + assert(localVariables.empty()); + // Delete all instructions except for the label. + assert(instructions.size() > 0); + instructions.resize(1); + successors.clear(); + // Add OpBranch back to the header. + assert(header != nullptr); + Instruction* branch = new Instruction(OpBranch); + branch->addIdOperand(header->getId()); + addInstruction(std::unique_ptr(branch)); + successors.push_back(header); + } + bool isTerminated() const { switch (instructions.back()->getOpCode()) { @@ -233,8 +259,10 @@ public: case OpBranchConditional: case OpSwitch: case OpKill: + case OpTerminateInvocation: case OpReturn: case OpReturnValue: + case OpUnreachable: return true; default: return false; @@ -268,10 +296,24 @@ protected: bool unreachable; }; +// The different reasons for reaching a block in the inReadableOrder traversal. +enum ReachReason { + // Reachable from the entry block via transfers of control, i.e. branches. + ReachViaControlFlow = 0, + // A continue target that is not reachable via control flow. + ReachDeadContinue, + // A merge block that is not reachable via control flow. + ReachDeadMerge +}; + // Traverses the control-flow graph rooted at root in an order suited for // readable code generation. Invokes callback at every node in the traversal -// order. -void inReadableOrder(Block* root, std::function callback); +// order. The callback arguments are: +// - the block, +// - the reason we reached the block, +// - if the reason was that block is an unreachable continue or unreachable merge block +// then the last parameter is the corresponding header block. +void inReadableOrder(Block* root, std::function callback); // // SPIR-V IR Function. @@ -307,12 +349,44 @@ public: const std::vector& getBlocks() const { return blocks; } void addLocalVariable(std::unique_ptr inst); Id getReturnType() const { return functionInstruction.getTypeId(); } + Id getFuncId() const { return functionInstruction.getResultId(); } + void setReturnPrecision(Decoration precision) + { + if (precision == DecorationRelaxedPrecision) + reducedPrecisionReturn = true; + } + Decoration getReturnPrecision() const + { return reducedPrecisionReturn ? DecorationRelaxedPrecision : NoPrecision; } + + void setDebugLineInfo(Id fileName, int line, int column) { + lineInstruction = std::unique_ptr{new Instruction(OpLine)}; + lineInstruction->addIdOperand(fileName); + lineInstruction->addImmediateOperand(line); + lineInstruction->addImmediateOperand(column); + } + bool hasDebugLineInfo() const { return lineInstruction != nullptr; } void setImplicitThis() { implicitThis = true; } bool hasImplicitThis() const { return implicitThis; } + void addParamPrecision(unsigned param, Decoration precision) + { + if (precision == DecorationRelaxedPrecision) + reducedPrecisionParams.insert(param); + } + Decoration getParamPrecision(unsigned param) const + { + return reducedPrecisionParams.find(param) != reducedPrecisionParams.end() ? + DecorationRelaxedPrecision : NoPrecision; + } + void dump(std::vector& out) const { + // OpLine + if (lineInstruction != nullptr) { + lineInstruction->dump(out); + } + // OpFunction functionInstruction.dump(out); @@ -321,7 +395,7 @@ public: parameterInstructions[p]->dump(out); // Blocks - inReadableOrder(blocks[0], [&out](const Block* b) { b->dump(out); }); + inReadableOrder(blocks[0], [&out](const Block* b, ReachReason, Block*) { b->dump(out); }); Instruction end(0, 0, OpFunctionEnd); end.dump(out); } @@ -331,10 +405,13 @@ protected: Function& operator=(Function&); Module& parent; + std::unique_ptr lineInstruction; Instruction functionInstruction; std::vector parameterInstructions; std::vector blocks; bool implicitThis; // true if this is a member function expecting to be passed a 'this' as the first argument + bool reducedPrecisionReturn; + std::set reducedPrecisionParams; // list of parameter indexes that need a relaxed precision arg }; // @@ -395,7 +472,9 @@ protected: // - the OpFunction instruction // - all the OpFunctionParameter instructions __inline Function::Function(Id id, Id resultType, Id functionType, Id firstParamId, Module& parent) - : parent(parent), functionInstruction(id, resultType, OpFunction), implicitThis(false) + : parent(parent), lineInstruction(nullptr), + functionInstruction(id, resultType, OpFunction), implicitThis(false), + reducedPrecisionReturn(false) { // OpFunction functionInstruction.addImmediateOperand(FunctionControlMaskNone);