Exemple #1
0
// Loop over all the instructions, in order, processing each.
// Boiler plate for each is handled here directly, the rest is dispatched.
void SpirvStream::processInstructions()
{
    // Instructions
    while (word < size) {
        int instructionStart = word;

        // Instruction wordCount and opcode
        unsigned int firstWord = stream[word];
        unsigned wordCount = firstWord >> WordCountShift;
        Op opCode = (Op)(firstWord & OpCodeMask);
        int nextInst = word + wordCount;
        ++word;

        // Presence of full instruction
        if (nextInst > size)
            Kill(out, "stream instruction terminated too early");

        // Base for computing number of operands; will be updated as more is learned
        unsigned numOperands = wordCount - 1;

        // Type <id>
        Id typeId = 0;
        if (InstructionDesc[opCode].hasType()) {
            typeId = stream[word++];
            --numOperands;
        }

        // Result <id>
        Id resultId = 0;
        if (InstructionDesc[opCode].hasResult()) {
            resultId = stream[word++];
            --numOperands;

            // save instruction for future reference
            idInstruction[resultId] = instructionStart;
        }

        outputResultId(resultId);
        outputTypeId(typeId);
        outputIndent();

        // Hand off the Op and all its operands
        disassembleInstruction(resultId, typeId, opCode, numOperands);
        if (word != nextInst) {
            out << " ERROR, incorrect number of operands consumed.  At " << word << " instead of " << nextInst << " instruction start was " << instructionStart;
            word = nextInst;
        }
        out << std::endl;
    }
}
Exemple #2
0
void outputField ( FudgeField * field, unsigned int indent )
{
    /* Output the field's type, name (if present) and ordinal (if present) */
    outputIndent ( indent );
    outputType ( field->type );
    printf ( " " );
    if ( field->flags & FUDGE_FIELD_HAS_NAME )
    {   
        outputString ( field->name );

        if ( field->flags & FUDGE_FIELD_HAS_ORDINAL )
            printf ( "/" );
    }
    if ( field->flags & FUDGE_FIELD_HAS_ORDINAL )
        printf ( "ord(%d)", field->ordinal );
    printf ( ": " );

    /* Output the field contents */
    switch ( field->type )
    {
        case FUDGE_TYPE_INDICATOR:      break;
        case FUDGE_TYPE_BOOLEAN:        printf ( field->data.boolean ? "true" : "false" ); break;
        case FUDGE_TYPE_BYTE:           printf ( "%d", field->data.byte ); break;
        case FUDGE_TYPE_SHORT:          printf ( "%d", field->data.i16 ); break;
        case FUDGE_TYPE_INT:            printf ( "%d", field->data.i32 ); break;
        case FUDGE_TYPE_LONG:           printf ( "%ld", ( long int ) field->data.i64 ); break;
        case FUDGE_TYPE_FLOAT:          printf ( "%f", field->data.f32 ); break;
        case FUDGE_TYPE_DOUBLE:         printf ( "%f", field->data.f64 ); break;
        case FUDGE_TYPE_SHORT_ARRAY:    outputArray ( field->data.bytes, field->numbytes, "%d", 2, 8 ); break;
        case FUDGE_TYPE_INT_ARRAY:      outputArray ( field->data.bytes, field->numbytes, "%d", 4, 8 ); break;
        case FUDGE_TYPE_LONG_ARRAY:     outputArray ( field->data.bytes, field->numbytes, "%lu", 8, 4 ); break;
        case FUDGE_TYPE_FLOAT_ARRAY:    outputArray ( field->data.bytes, field->numbytes, "%f", 4, 4 ); break;
        case FUDGE_TYPE_DOUBLE_ARRAY:   outputArray ( field->data.bytes, field->numbytes, "%f", 8, 4 ); break;
        case FUDGE_TYPE_STRING:         outputString ( field->data.string ); break;
        case FUDGE_TYPE_BYTE_ARRAY: 
        case FUDGE_TYPE_BYTE_ARRAY_4:
        case FUDGE_TYPE_BYTE_ARRAY_8:
        case FUDGE_TYPE_BYTE_ARRAY_16:
        case FUDGE_TYPE_BYTE_ARRAY_20:
        case FUDGE_TYPE_BYTE_ARRAY_32:
        case FUDGE_TYPE_BYTE_ARRAY_64:
        case FUDGE_TYPE_BYTE_ARRAY_128:
        case FUDGE_TYPE_BYTE_ARRAY_256:
        case FUDGE_TYPE_BYTE_ARRAY_512:
            outputArray ( field->data.bytes, field->numbytes, "%d", 1, 10 ); 
            break;
        case FUDGE_TYPE_FUDGE_MSG:
            printf ( "\n" );
            outputIndent ( indent );
            printf ( "{\n" );
            outputMessage ( field->data.message, indent + 1 );
            outputIndent ( indent );
            printf ( "}" );
            break;
        default:
            printf ( "%d bytes ", field->numbytes );
            outputArray ( field->data.bytes, field->numbytes, "%d", 1, 8 ); 
            break;
    }

    printf ( "\n" );
}
Exemple #3
0
void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode, int numOperands)
{
    // Process the opcode

    out << (OpcodeString(opCode) + 2);  // leave out the "Op"

    if (opCode == OpLoopMerge || opCode == OpSelectionMerge)
        nextNestedControl = stream[word];
    else if (opCode == OpBranchConditional || opCode == OpSwitch) {
        if (nextNestedControl) {
            nestedControl.push(nextNestedControl);
            nextNestedControl = 0;
        }
    } else if (opCode == OpExtInstImport) {
        idDescriptor[resultId] = (const char*)(&stream[word]);
    }
    else {
        if (resultId != 0 && idDescriptor[resultId].size() == 0) {
            switch (opCode) {
            case OpTypeInt:
                idDescriptor[resultId] = "int";
                break;
            case OpTypeFloat:
                idDescriptor[resultId] = "float";
                break;
            case OpTypeBool:
                idDescriptor[resultId] = "bool";
                break;
            case OpTypeStruct:
                idDescriptor[resultId] = "struct";
                break;
            case OpTypePointer:
                idDescriptor[resultId] = "ptr";
                break;
            case OpTypeVector:
                if (idDescriptor[stream[word]].size() > 0)
                    idDescriptor[resultId].append(idDescriptor[stream[word]].begin(), idDescriptor[stream[word]].begin() + 1);
                idDescriptor[resultId].append("vec");
                switch (stream[word + 1]) {
                case 2:   idDescriptor[resultId].append("2");   break;
                case 3:   idDescriptor[resultId].append("3");   break;
                case 4:   idDescriptor[resultId].append("4");   break;
                case 8:   idDescriptor[resultId].append("8");   break;
                case 16:  idDescriptor[resultId].append("16");  break;
                case 32:  idDescriptor[resultId].append("32");  break;
                default: break;
                }
                break;
            default:
                break;
            }
        }
    }

    // Process the operands.  Note, a new context-dependent set could be
    // swapped in mid-traversal.

    // Handle images specially, so can put out helpful strings.
    if (opCode == OpTypeImage) {
        out << " ";
        disassembleIds(1);
        out << " " << DimensionString((Dim)stream[word++]);
        out << (stream[word++] != 0 ? " depth" : "");
        out << (stream[word++] != 0 ? " array" : "");
        out << (stream[word++] != 0 ? " multi-sampled" : "");
        switch (stream[word++]) {
        case 0: out << " runtime";    break;
        case 1: out << " sampled";    break;
        case 2: out << " nonsampled"; break;
        }
        out << " format:" << ImageFormatString((ImageFormat)stream[word++]);

        if (numOperands == 8) {
            out << " " << AccessQualifierString(stream[word++]);
        }
        return;
    }

    // Handle all the parameterized operands
    for (int op = 0; op < InstructionDesc[opCode].operands.getNum() && numOperands > 0; ++op) {
        out << " ";
        OperandClass operandClass = InstructionDesc[opCode].operands.getClass(op);
        switch (operandClass) {
        case OperandId:
        case OperandScope:
        case OperandMemorySemantics:
            disassembleIds(1);
            --numOperands;
            // Get names for printing "(XXX)" for readability, *after* this id
            if (opCode == OpName)
                idDescriptor[stream[word - 1]] = (const char*)(&stream[word]);
            break;
        case OperandVariableIds:
            disassembleIds(numOperands);
            return;
        case OperandImageOperands:
            outputMask(OperandImageOperands, stream[word++]);
            --numOperands;
            disassembleIds(numOperands);
            return;
        case OperandOptionalLiteral:
        case OperandVariableLiterals:
            if ((opCode == OpDecorate && stream[word - 1] == DecorationBuiltIn) ||
                (opCode == OpMemberDecorate && stream[word - 1] == DecorationBuiltIn)) {
                out << BuiltInString(stream[word++]);
                --numOperands;
                ++op;
            }
            disassembleImmediates(numOperands);
            return;
        case OperandVariableIdLiteral:
            while (numOperands > 0) {
                out << std::endl;
                outputResultId(0);
                outputTypeId(0);
                outputIndent();
                out << "     Type ";
                disassembleIds(1);
                out << ", member ";
                disassembleImmediates(1);
                numOperands -= 2;
            }
            return;
        case OperandVariableLiteralId:
            while (numOperands > 0) {
                out << std::endl;
                outputResultId(0);
                outputTypeId(0);
                outputIndent();
                out << "     case ";
                disassembleImmediates(1);
                out << ": ";
                disassembleIds(1);
                numOperands -= 2;
            }
            return;
        case OperandLiteralNumber:
            disassembleImmediates(1);
            --numOperands;
            if (opCode == OpExtInst) {
                ExtInstSet extInstSet = GLSL450Inst;
                const char* name = idDescriptor[stream[word - 2]].c_str();
                if (0 == memcmp("OpenCL", name, 6)) {
                    extInstSet = OpenCLExtInst;
#ifdef AMD_EXTENSIONS
                } else if (strcmp(spv::E_SPV_AMD_shader_ballot, name) == 0 ||
                           strcmp(spv::E_SPV_AMD_shader_trinary_minmax, name) == 0 ||
                           strcmp(spv::E_SPV_AMD_shader_explicit_vertex_parameter, name) == 0 ||
                           strcmp(spv::E_SPV_AMD_gcn_shader, name) == 0) {
                    extInstSet = GLSLextAMDInst;
#endif
#ifdef NV_EXTENSIONS
                }else if (strcmp(spv::E_SPV_NV_sample_mask_override_coverage, name) == 0 ||
                          strcmp(spv::E_SPV_NV_geometry_shader_passthrough, name) == 0 ||
                          strcmp(spv::E_SPV_NV_viewport_array2, name) == 0 ||
                          strcmp(spv::E_SPV_NVX_multiview_per_view_attributes, name) == 0) {
                    extInstSet = GLSLextNVInst;
#endif
                }
                unsigned entrypoint = stream[word - 1];
                if (extInstSet == GLSL450Inst) {
                    if (entrypoint < GLSLstd450Count) {
                        out << "(" << GlslStd450DebugNames[entrypoint] << ")";
                    }
#ifdef AMD_EXTENSIONS
                } else if (extInstSet == GLSLextAMDInst) {
                    out << "(" << GLSLextAMDGetDebugNames(name, entrypoint) << ")";
#endif
#ifdef NV_EXTENSIONS
                }
                else if (extInstSet == GLSLextNVInst) {
                    out << "(" << GLSLextNVGetDebugNames(name, entrypoint) << ")";
#endif
                }
            }
            break;
        case OperandOptionalLiteralString:
        case OperandLiteralString:
            numOperands -= disassembleString();
            break;
        default:
            assert(operandClass >= OperandSource && operandClass < OperandOpcode);

            if (OperandClassParams[operandClass].bitmask)
                outputMask(operandClass, stream[word++]);
            else
                out << OperandClassParams[operandClass].getName(stream[word++]);
            --numOperands;

            break;
        }
    }

    return;
}