Repository: dotnet/runtime
File: src/coreclr/jit/emitwasm.cpp (C++)

Code before:
            dst += emitOutputOpcode(dst, ins);
            break;
        }
        case IF_BLOCK:
            dst += emitOutputOpcode(dst, ins);
            dst += emitOutputByte(dst, 0x40 /* block type of void */);
            break;
        case IF_ULEB128:
        {
            dst += emitOutputOpcode(dst, ins);
            cnsval_ssize_t constant = emitGetInsSC(id);
            dst += emitOutputULEB128(dst, (uint64_t)constant);
            break;
        }
        case IF_SLEB128:
        {
            dst += emitOutputOpcode(dst, ins);
            cnsval_ssize_t constant = emitGetInsSC(id);
            dst += emitOutputSLEB128(dst, (int64_t)constant);
            break;
        }
        case IF_CALL_INDIRECT:
        {
            dst += emitOutputByte(dst, opcode);
            dst += emitOutputULEB128(dst, 0);
            dst += emitOutputULEB128(dst, (uint64_t)emitGetInsSC(id));
            break;
        }
        case IF_F32:
        {
            dst += emitOutputOpcode(dst, ins);
            // Reinterpret the bits as a double constant and then truncate it to f32,
            //  then finally copy the raw truncated f32 bits to the output.
            cnsval_ssize_t bits = emitGetInsSC(id);
            double         value;
            float          truncated;
            memcpy(&value, &bits, sizeof(double));
            truncated = FloatingPointUtils::convertToSingle(value);
            dst += emitRawBytes(dst, &truncated, sizeof(float));
            break;
        }
        case IF_F64:
        {
            dst += emitOutputOpcode(dst, ins);
            // The int64 bits are actually a double constant we can copy directly
            //  to the output stream.
            cnsval_ssize_t bits = emitGetInsSC(id);
            dst += emitRawBytes(dst, &bits, sizeof(cnsval_ssize_t));
            break;
        }
        case IF_RAW_ULEB128:

Review comment (bug):
The WebAssembly specification for call_indirect requires the type index to be emitted first, followed by the table index. However, this code appears to emit the table index first (hardcoded 0 at line 541) and then the type index (line 542). Verify that the order matches the WASM spec, or swap lines 541 and 542 if the order is incorrect.
```suggestion
            dst += emitOutputULEB128(dst, (uint64_t)emitGetInsSC(id));
            dst += emitOutputULEB128(dst, 0);
```

Code after:
            // Reinterpret the bits as a double constant and then truncate it to f32,
            //  then finally copy the raw truncated f32 bits to the output.
            cnsval_ssize_t bits = emitGetInsSC(id);
            double         value;
            float          truncated;
            memcpy(&value, &bits, sizeof(double));
            truncated = FloatingPointUtils::convertToSingle(value);
            dst += emitRawBytes(dst, &truncated, sizeof(float));
            break;
        }
        case IF_F64:
        {
            dst += emitOutputOpcode(dst, ins);
            // The int64 bits are actually a double constant we can copy directly
            //  to the output stream.
            cnsval_ssize_t bits = emitGetInsSC(id);
            dst += emitRawBytes(dst, &bits, sizeof(cnsval_ssize_t));
            break;
        }
        case IF_RAW_ULEB128:
        {
            cnsval_ssize_t constant = emitGetInsSC(id);
            dst += emitOutputULEB128(dst, (uint64_t)constant);
            break;
        }
        case IF_MEMARG:
        {
            dst += emitOutputOpcode(dst, ins);
            uint64_t align  = emitGetAlignHintLog2(id);
            uint64_t offset = emitGetInsSC(id);
            assert(align <= UINT32_MAX); // spec says memarg alignment is u32
            assert(align < 64);          // spec says align > 2^6 produces a memidx for multiple memories.
            dst += emitOutputULEB128(dst, align);
            dst += emitOutputULEB128(dst, offset);
            break;
        }
        case IF_LOCAL_DECL:
        {
            assert(id->idIsLclVarDecl());
            cnsval_ssize_t count   = emitGetLclVarDeclCount(id);
            uint8_t        valType = GetWasmValueTypeCode(emitGetLclVarDeclType(id));
            dst += emitOutputULEB128(dst, (uint64_t)count);
            dst += emitOutputByte(dst, valType);
            break;
        }
        default:
            NYI_WASM("emitOutputInstr");
            break;
    }

#ifdef DEBUG