Index: tools/llvm-mc-assemble-proto-fuzzer/CMakeLists.txt =================================================================== --- tools/llvm-mc-assemble-proto-fuzzer/CMakeLists.txt +++ tools/llvm-mc-assemble-proto-fuzzer/CMakeLists.txt @@ -27,6 +27,16 @@ proto-files/example_asm_proto.proto) protobuf_generate_cpp(RV32_PROTO_SRCS RV32_PROTO_HDRS proto-files/rv32.proto + proto-files/rv32_operands.proto + proto-files/rv32a.proto + proto-files/rv32c.proto + proto-files/rv32d.proto + proto-files/rv32f.proto + proto-files/rv32i.proto + proto-files/rv32m.proto) + protobuf_generate_cpp(RV32_OP_TYPES_SRCS RV32_OP_TYPES_HDRS + proto-files/rv32_operands.proto + proto-files/rv32_fuzz_operand_types.proto proto-files/rv32a.proto proto-files/rv32c.proto proto-files/rv32d.proto @@ -52,6 +62,14 @@ ${PROTOBUF_LIBRARIES} ) + add_clang_library(mcRv32FuzzOperandTypesASMProto + ${RV32_OP_TYPES_SRCS} + ${RV32_OP_TYPES_HDRS} + + LINK_LIBS + ${PROTOBUF_LIBRARIES} + ) + # Build and include libprotobuf-mutator include(ProtobufMutatorMC) include_directories(${ProtobufMutator_INCLUDE_DIRS}) @@ -75,6 +93,11 @@ RV32MCProtoFuzzer.cpp ) + add_clang_executable(llvm-mc-assemble-proto-fuzzer-rv32-fuzz-operand-types + ${DUMMY_MAIN} + RV32MCProtoFuzzer.cpp + ) + set(COMMON_PROTO_FUZZ_LIBRARIES ${ProtobufMutator_LIBRARIES} ${PROTOBUF_LIBRARIES} @@ -96,6 +119,13 @@ mcRv32ProtoToASM ) + target_link_libraries(llvm-mc-assemble-proto-fuzzer-rv32-fuzz-operand-types + PRIVATE + ${COMMON_PROTO_FUZZ_LIBRARIES} + mcRv32FuzzOperandTypesASMProto + mcRv32FuzzOperandTypesProtoToASM + ) + endif() add_clang_subdirectory(handle-asm) Index: tools/llvm-mc-assemble-proto-fuzzer/README.txt =================================================================== --- tools/llvm-mc-assemble-proto-fuzzer/README.txt +++ tools/llvm-mc-assemble-proto-fuzzer/README.txt @@ -33,7 +33,7 @@ $ python mcfuzz.py --corpus corpus --max-len 32 --runs 10 --triple riscv32 \ --out outputdir --objdump /full/path/to/riscv32-unknown-linux-gnu-objdump \ - --mattr +c,+m,+d,+f --march rv32imfdc \ + --mattr +a,+c,+d,+f,+m --march rv32imafdc \ --assemble /full/path/to/riscv32-unknown-linux-gnu-as Run the script with the --verbose flag if you would like to see the output Index: tools/llvm-mc-assemble-proto-fuzzer/proto-files/rv32.proto =================================================================== --- tools/llvm-mc-assemble-proto-fuzzer/proto-files/rv32.proto +++ tools/llvm-mc-assemble-proto-fuzzer/proto-files/rv32.proto @@ -16,6 +16,7 @@ syntax = "proto2"; +import "rv32_operands.proto"; import "rv32a.proto"; import "rv32c.proto"; import "rv32d.proto"; @@ -23,60 +24,6 @@ import "rv32i.proto"; import "rv32m.proto"; -message IORW { - enum IORWChar { - I = 0; - O = 1; - R = 2; - W = 3; - }; - required IORWChar iorwchar = 1; -} - -message IORWString { - repeated IORW iorwstring = 1; -} - -message Immediate { - oneof imm_oneof { - sint32 s_imm = 1; - uint32 u_imm = 2; - } -} - -message GenPurposeRegister { - enum RegName { - X0 = 0; X1 = 1; X2 = 2; X3 = 3; X4 = 4; - X5 = 5; X6 = 6; X7 = 7; X8 = 8; X9 = 9; - X10 = 10; X11 = 11; X12 = 12; X13 = 13; X14 = 14; - X15 = 15; X16 = 16; X17 = 17; X18 = 18; X19 = 19; - X20 = 20; X21 = 21; X22 = 22; X23 = 23; X24 = 24; - X25 = 25; X26 = 26; X27 = 27; X28 = 28; X29 = 29; - X30 = 30; X31 = 31; - }; - required RegName regname = 1; -} - -message FloatingPointRegister { - enum RegName { - F0 = 0; F1 = 1; F2 = 2; F3 = 3; F4 = 4; - F5 = 5; F6 = 6; F7 = 7; F8 = 8; F9 = 9; - F10 = 10; F11 = 11; F12 = 12; F13 = 13; F14 = 14; - F15 = 15; F16 = 16; F17 = 17; F18 = 18; F19 = 19; - F20 = 20; F21 = 21; F22 = 22; F23 = 23; F24 = 24; - F25 = 25; F26 = 26; F27 = 27; F28 = 28; F29 = 29; - F30 = 30; F31 = 31; - }; - required RegName regname = 1; -} - -message Register { - oneof reg_oneof { - GenPurposeRegister reg1 = 1; - FloatingPointRegister reg2 = 2; - } -} - // Note: The order of the fields does not matter for the grammar since // the structure of the fuzzed ASM statements is handled in proto_to_asm. message RegRegRegRegStmt { Index: tools/llvm-mc-assemble-proto-fuzzer/proto-files/rv32_fuzz_operand_types.proto =================================================================== --- /dev/null +++ tools/llvm-mc-assemble-proto-fuzzer/proto-files/rv32_fuzz_operand_types.proto @@ -0,0 +1,166 @@ +//===-- rv32_fuzz_operand_types.proto - Protobuf description of ASM -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file is the fully unconstrained protobuf representation of the +/// RV32 ISA of the RISC-V ASM, which contains valid opcodes (such as add +/// and sub), combined with a mixture of valid and invalid operand sequences. +/// +/// It might mutate an ASM string to generate an instruction such as: +/// "c.addi x0,x3,x5", which contains the wrong number and incorrect type +/// of operands. +/// +/// It is useful for uncovering parser bugs. +/// +//===----------------------------------------------------------------------===// + +syntax = "proto2"; + +import "rv32_operands.proto"; +import "rv32a.proto"; +import "rv32c.proto"; +import "rv32d.proto"; +import "rv32f.proto"; +import "rv32i.proto"; +import "rv32m.proto"; + +// Note: The order of the fields does not matter for the grammar since +// the structure of the fuzzed ASM statements is handled in proto_to_asm. +message RegRegRegRegOperandSeq { + required Register operand1 = 1; + required Register operand2 = 2; + required Register operand3 = 3; + required Register operand4 = 4; +} + +message RegRegRegOperandSeq1 { + required Register operand1 = 1; + required Register operand2 = 2; + required Register operand3 = 3; +} + +message RegRegRegOperandSeq2 { + required Register operand1 = 1; + required Register operand2 = 2; + required Register operand3 = 3; +} + +message RegRegImmOperandSeq1 { + required Register operand1 = 1; + required Register operand2 = 2; + required Immediate operand3 = 3; +} + +message RegRegImmOperandSeq2 { + required Register operand1 = 1; + required Register operand2 = 2; + required Immediate operand3 = 3; +} + +message RegRegOperandSeq1 { + required Register operand1 = 1; + required Register operand2 = 2; +} + +message RegRegOperandSeq2 { + required Register operand1 = 1; + required Register operand2 = 2; +} + +message RegImmOperandSeq { + required Register operand1 = 1; + required Immediate operand2 = 2; +} + +message RegImmRegOperandSeq { + required Register operand1 = 1; + required Immediate operand2 = 2; + required Register operand3 = 3; +} + +message RegImmImmOperandSeq { + required Register operand1 = 1; + required Immediate operand2 = 2; + required Immediate operand3 = 3; +} + +message RegOperandSeq { + required Register operand1 = 1; +} + +message ImmOperandSeq { + required Immediate operand1 = 1; +} + +message Opcode { + oneof opcode_oneof { + A_RFormat1Opcode opcode1 = 1; + A_RFormat2Opcode opcode2 = 2; + C_CBFormatOpcode opcode3 = 3; + C_CIFormatOpcode opcode4 = 4; + C_CIWFormatOpcode opcode5 = 5; + C_CJFormatOpcode opcode6 = 6; + C_CLFormatOpcode opcode7 = 7; + C_CRFormat1Opcode opcode8 = 8; + C_CRFormat2Opcode opcode9 = 9; + C_CSFormat1Opcode opcode10 = 10; + C_CSFormat2Opcode opcode11 = 11; + C_CSSFormatOpcode opcode12 = 12; + D_IFormatLoadOpcode opcode13 = 13; + D_R4FormatOpcode opcode14 = 14; + D_RFormat1Opcode opcode15 = 15; + D_RFormat2Opcode opcode16 = 16; + D_SFormatOpcode opcode17 = 17; + F_CSR_IFormat1Opcode opcode18 = 18; + F_CSR_IFormat2Opcode opcode19 = 19; + F_IFormatLoadOpcode opcode20 = 20; + F_R4FormatOpcode opcode21 = 21; + F_RFormat1Opcode opcode22 = 22; + F_RFormat2Opcode opcode23 = 23; + F_SFormatOpcode opcode24 = 24; + I_BFormatOpcode opcode25 = 25; + I_CSR_IFormat1Opcode opcode26 = 26; + I_CSR_IFormat2Opcode opcode27 = 27; + I_IFormatOpcode opcode28 = 28; + I_IFormatLoadOpcode opcode29 = 29; + I_JFormatOpcode opcode30 = 30; + I_RFormatOpcode opcode31 = 31; + I_SFormatOpcode opcode32 = 32; + I_UFormatOpcode opcode33 = 33; + M_RFormatOpcode opcode34 = 34; + } +} + +message AsmStmt { + required Opcode opcode = 1; + oneof operand_seq { + ImmOperandSeq seq1 = 2; + RegImmOperandSeq seq2 = 3; + RegImmRegOperandSeq seq3 = 4; + RegImmImmOperandSeq seq4 = 5; + RegOperandSeq seq5 = 6; + RegRegImmOperandSeq1 seq6 = 7; + RegRegImmOperandSeq2 seq7 = 8; + RegRegOperandSeq1 seq8 = 9; + RegRegOperandSeq2 seq9 = 10; + RegRegRegOperandSeq1 seq10 = 11; + RegRegRegOperandSeq2 seq11 = 12; + RegRegRegRegOperandSeq seq12 = 13; + } +} + +message AsmStmtSeq { + repeated AsmStmt stmts = 1; +} + +message Assembly { + required AsmStmtSeq asmstmts = 1; +} + +package mc_proto_fuzzer; Index: tools/llvm-mc-assemble-proto-fuzzer/proto-files/rv32_operands.proto =================================================================== --- /dev/null +++ tools/llvm-mc-assemble-proto-fuzzer/proto-files/rv32_operands.proto @@ -0,0 +1,72 @@ +//===-- rv32_operands.proto - Protobuf description of ASM -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains the protobuf representation of operands (immediates and +/// registers) for the RV32 ISA of the RISC-V ASM. +/// +//===----------------------------------------------------------------------===// + +syntax = "proto2"; + +message IORW { + enum IORWChar { + I = 0; + O = 1; + R = 2; + W = 3; + }; + required IORWChar iorwchar = 1; +} + +message IORWString { + repeated IORW iorwstring = 1; +} + +message Immediate { + oneof imm_oneof { + sint32 s_imm = 1; + uint32 u_imm = 2; + } +} + +message GenPurposeRegister { + enum RegName { + X0 = 0; X1 = 1; X2 = 2; X3 = 3; X4 = 4; + X5 = 5; X6 = 6; X7 = 7; X8 = 8; X9 = 9; + X10 = 10; X11 = 11; X12 = 12; X13 = 13; X14 = 14; + X15 = 15; X16 = 16; X17 = 17; X18 = 18; X19 = 19; + X20 = 20; X21 = 21; X22 = 22; X23 = 23; X24 = 24; + X25 = 25; X26 = 26; X27 = 27; X28 = 28; X29 = 29; + X30 = 30; X31 = 31; + }; + required RegName regname = 1; +} + +message FloatingPointRegister { + enum RegName { + F0 = 0; F1 = 1; F2 = 2; F3 = 3; F4 = 4; + F5 = 5; F6 = 6; F7 = 7; F8 = 8; F9 = 9; + F10 = 10; F11 = 11; F12 = 12; F13 = 13; F14 = 14; + F15 = 15; F16 = 16; F17 = 17; F18 = 18; F19 = 19; + F20 = 20; F21 = 21; F22 = 22; F23 = 23; F24 = 24; + F25 = 25; F26 = 26; F27 = 27; F28 = 28; F29 = 29; + F30 = 30; F31 = 31; + }; + required RegName regname = 1; +} + +message Register { + oneof reg_oneof { + GenPurposeRegister reg1 = 1; + FloatingPointRegister reg2 = 2; + } +} + +package mc_proto_fuzzer; Index: tools/llvm-mc-assemble-proto-fuzzer/proto-to-asm/CMakeLists.txt =================================================================== --- tools/llvm-mc-assemble-proto-fuzzer/proto-to-asm/CMakeLists.txt +++ tools/llvm-mc-assemble-proto-fuzzer/proto-to-asm/CMakeLists.txt @@ -3,7 +3,7 @@ # Needed by LLVM's CMake checks because this file defines multiple targets. set(LLVM_OPTIONAL_SOURCES example_proto_to_asm.cpp proto_to_asm_main.cpp - proto_to_asm_rv32.cpp) + proto_to_asm_rv32.cpp proto_to_asm_rv32_fuzz_operand_types.cpp) add_clang_library(mcProtoToASM example_proto_to_asm.cpp DEPENDS mcASMProto @@ -15,10 +15,20 @@ LINK_LIBS mcRv32ASMProto ${PROTOBUF_LIBRARIES} ) +add_clang_library(mcRv32FuzzOperandTypesProtoToASM + proto_to_asm_rv32_fuzz_operand_types.cpp + DEPENDS mcRv32FuzzOperandTypesASMProto + LINK_LIBS mcRv32FuzzOperandTypesASMProto ${PROTOBUF_LIBRARIES} + ) + add_clang_executable(llvm-mc-assemble-proto-to-asm proto_to_asm_main.cpp) add_clang_executable(llvm-mc-assemble-proto-to-asm-rv32 proto_to_asm_main.cpp) +add_clang_executable(llvm-mc-assemble-proto-to-asm-rv32-fuzz-operand-types + proto_to_asm_main.cpp) target_link_libraries(llvm-mc-assemble-proto-to-asm PRIVATE mcProtoToASM) target_link_libraries(llvm-mc-assemble-proto-to-asm-rv32 PRIVATE mcRv32ProtoToASM) +target_link_libraries(llvm-mc-assemble-proto-to-asm-rv32-fuzz-operand-types + PRIVATE mcRv32FuzzOperandTypesProtoToASM) Index: tools/llvm-mc-assemble-proto-fuzzer/proto-to-asm/proto_to_asm_rv32.cpp =================================================================== --- tools/llvm-mc-assemble-proto-fuzzer/proto-to-asm/proto_to_asm_rv32.cpp +++ tools/llvm-mc-assemble-proto-fuzzer/proto-to-asm/proto_to_asm_rv32.cpp @@ -14,6 +14,7 @@ //===----------------------------------------------------------------------===// #include "proto_to_asm.h" #include "rv32.pb.h" +#include "rv32_operands.pb.h" #include "rv32a.pb.h" #include "rv32c.pb.h" #include "rv32d.pb.h" Index: tools/llvm-mc-assemble-proto-fuzzer/proto-to-asm/proto_to_asm_rv32_fuzz_operand_types.cpp =================================================================== --- /dev/null +++ tools/llvm-mc-assemble-proto-fuzzer/proto-to-asm/proto_to_asm_rv32_fuzz_operand_types.cpp @@ -0,0 +1,360 @@ +//==-- proto_to_asm_rv32_fuzz_operand_types.cpp - Protobuf-ASM conversion --==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implements functions for converting between protobufs for the assembly +// language grammar for RV32I instruction set and assembly language +// instructions. +// +//===----------------------------------------------------------------------===// +#include "proto_to_asm.h" +#include "rv32_operands.pb.h" +#include "rv32_fuzz_operand_types.pb.h" +#include "rv32a.pb.h" +#include "rv32c.pb.h" +#include "rv32d.pb.h" +#include "rv32f.pb.h" +#include "rv32i.pb.h" +#include "rv32m.pb.h" + + +#include +#include +#include +#include +#include +#include + +using namespace google::protobuf; + +#define EMIT_ASM(X,Y) \ + { \ + const EnumDescriptor * ED = X; \ + if (ED) \ + return OS << EmitAsm(ED, Y); \ + assert(!"Could not find descriptor."); \ + } + +static std::string EmitAsm(const EnumDescriptor * Enum, + int Num) { + const EnumValueDescriptor * D = Enum->FindValueByNumber(Num); + std::string Msg = D->name(); + std::transform(Msg.begin(), Msg.end(), Msg.begin(), ::tolower); + std::replace(Msg.begin(), Msg.end(), '_', '.'); + return Msg; +} + +namespace mc_proto_fuzzer { +std::ostream &operator<<(std::ostream &OS, const Immediate &X) { + if (X.has_s_imm()) + return OS << X.s_imm(); + if (X.has_u_imm()) + return OS << X.u_imm(); + return OS << "0"; +} +std::ostream &operator<<(std::ostream &OS, const GenPurposeRegister &X) { + EMIT_ASM(GenPurposeRegister_RegName_descriptor(), X.regname()); +} +std::ostream &operator<<(std::ostream &OS, const FloatingPointRegister &X) { + EMIT_ASM(FloatingPointRegister_RegName_descriptor(), X.regname()); +} +std::ostream &operator<<(std::ostream &OS, const Register &X) { + if (X.has_reg1()) + return OS << X.reg1(); + if (X.has_reg2()) + return OS << X.reg2(); + return OS << "x0"; +} +std::ostream &operator<<(std::ostream &OS, const A_RFormat1Opcode &X) { + EMIT_ASM(A_RFormat1Opcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const A_RFormat2Opcode &X) { + EMIT_ASM(A_RFormat2Opcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const C_CBFormatOpcode &X) { + EMIT_ASM(C_CBFormatOpcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const C_CIFormatOpcode &X) { + EMIT_ASM(C_CIFormatOpcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const C_CIWFormatOpcode &X) { + EMIT_ASM(C_CIWFormatOpcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const C_CJFormatOpcode &X) { + EMIT_ASM(C_CJFormatOpcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const C_CLFormatOpcode &X) { + EMIT_ASM(C_CLFormatOpcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const C_CRFormat1Opcode &X) { + EMIT_ASM(C_CRFormat1Opcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const C_CRFormat2Opcode &X) { + EMIT_ASM(C_CRFormat2Opcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const C_CSFormat1Opcode &X) { + EMIT_ASM(C_CSFormat1Opcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const C_CSFormat2Opcode &X) { + EMIT_ASM(C_CSFormat2Opcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const C_CSSFormatOpcode &X) { + EMIT_ASM(C_CSSFormatOpcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const D_IFormatLoadOpcode &X) { + EMIT_ASM(D_IFormatLoadOpcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const D_R4FormatOpcode &X) { + EMIT_ASM(D_R4FormatOpcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const D_RFormat1Opcode &X) { + EMIT_ASM(D_RFormat1Opcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const D_RFormat2Opcode &X) { + EMIT_ASM(D_RFormat2Opcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const D_SFormatOpcode &X) { + EMIT_ASM(D_SFormatOpcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const F_CSR_IFormat1Opcode &X) { + EMIT_ASM(F_CSR_IFormat1Opcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const F_CSR_IFormat2Opcode &X) { + EMIT_ASM(F_CSR_IFormat2Opcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const F_IFormatLoadOpcode &X) { + EMIT_ASM(F_IFormatLoadOpcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const F_R4FormatOpcode &X) { + EMIT_ASM(F_R4FormatOpcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const F_RFormat1Opcode &X) { + EMIT_ASM(F_RFormat1Opcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const F_RFormat2Opcode &X) { + EMIT_ASM(F_RFormat2Opcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const F_SFormatOpcode &X) { + EMIT_ASM(F_SFormatOpcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const I_BFormatOpcode &X) { + EMIT_ASM(I_BFormatOpcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const I_CSR_IFormat1Opcode &X) { + EMIT_ASM(I_CSR_IFormat1Opcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const I_CSR_IFormat2Opcode &X) { + EMIT_ASM(I_CSR_IFormat2Opcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const I_IFormatOpcode &X) { + EMIT_ASM(I_IFormatOpcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const I_IFormatLoadOpcode &X) { + EMIT_ASM(I_IFormatLoadOpcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const I_JFormatOpcode &X) { + EMIT_ASM(I_JFormatOpcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const I_RFormatOpcode &X) { + EMIT_ASM(I_RFormatOpcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const I_SFormatOpcode &X) { + EMIT_ASM(I_SFormatOpcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const I_UFormatOpcode &X) { + EMIT_ASM(I_UFormatOpcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const M_RFormatOpcode &X) { + EMIT_ASM(M_RFormatOpcode_Op_descriptor(), X.op()); +} +std::ostream &operator<<(std::ostream &OS, const Opcode &X) { + if (X.has_opcode1()) + return OS << X.opcode1(); + if (X.has_opcode2()) + return OS << X.opcode2(); + if (X.has_opcode3()) + return OS << X.opcode3(); + if (X.has_opcode4()) + return OS << X.opcode4(); + if (X.has_opcode5()) + return OS << X.opcode5(); + if (X.has_opcode6()) + return OS << X.opcode6(); + if (X.has_opcode7()) + return OS << X.opcode7(); + if (X.has_opcode8()) + return OS << X.opcode8(); + if (X.has_opcode9()) + return OS << X.opcode9(); + if (X.has_opcode10()) + return OS << X.opcode10(); + if (X.has_opcode11()) + return OS << X.opcode11(); + if (X.has_opcode12()) + return OS << X.opcode12(); + if (X.has_opcode13()) + return OS << X.opcode13(); + if (X.has_opcode14()) + return OS << X.opcode14(); + if (X.has_opcode15()) + return OS << X.opcode15(); + if (X.has_opcode16()) + return OS << X.opcode16(); + if (X.has_opcode17()) + return OS << X.opcode17(); + if (X.has_opcode18()) + return OS << X.opcode18(); + if (X.has_opcode19()) + return OS << X.opcode19(); + if (X.has_opcode20()) + return OS << X.opcode20(); + if (X.has_opcode21()) + return OS << X.opcode21(); + if (X.has_opcode22()) + return OS << X.opcode22(); + if (X.has_opcode23()) + return OS << X.opcode23(); + if (X.has_opcode24()) + return OS << X.opcode24(); + if (X.has_opcode25()) + return OS << X.opcode25(); + if (X.has_opcode26()) + return OS << X.opcode26(); + if (X.has_opcode27()) + return OS << X.opcode27(); + if (X.has_opcode28()) + return OS << X.opcode28(); + if (X.has_opcode29()) + return OS << X.opcode29(); + if (X.has_opcode30()) + return OS << X.opcode30(); + if (X.has_opcode31()) + return OS << X.opcode31(); + if (X.has_opcode32()) + return OS << X.opcode32(); + if (X.has_opcode33()) + return OS << X.opcode33(); + if (X.has_opcode34()) + return OS << X.opcode34(); + return OS << "add"; +} +std::ostream &operator<<(std::ostream &OS, const RegRegRegRegOperandSeq &X) { + OS << X.operand1() << ","; + OS << X.operand2() << ","; + OS << X.operand3() << ","; + OS << X.operand4() << "\n"; + return OS; +} +std::ostream &operator<<(std::ostream &OS, const RegRegRegOperandSeq1 &X) { + OS << X.operand1() << ","; + OS << X.operand2() << ","; + OS << X.operand3() << "\n"; + return OS; +} +std::ostream &operator<<(std::ostream &OS, const RegRegRegOperandSeq2 &X) { + OS << X.operand1() << ","; + OS << X.operand2() << ",("; + OS << X.operand3() << ")\n"; + return OS; +} +std::ostream &operator<<(std::ostream &OS, const RegRegImmOperandSeq1 &X) { + OS << X.operand1() << ","; + OS << X.operand2() << ","; + OS << X.operand3() << "\n"; + return OS; +} +std::ostream &operator<<(std::ostream &OS, const RegRegImmOperandSeq2 &X) { + OS << X.operand1() << ","; + OS << X.operand3() << "("; + OS << X.operand2() << ")\n"; + return OS; +} +std::ostream &operator<<(std::ostream &OS, const RegRegOperandSeq1 &X) { + OS << X.operand1() << "," << X.operand2() << "\n"; + return OS; +} +std::ostream &operator<<(std::ostream &OS, const RegRegOperandSeq2 &X) { + OS << X.operand1() << ",(" << X.operand2() << ")\n"; + return OS; +} +std::ostream &operator<<(std::ostream &OS, const RegImmOperandSeq &X) { + OS << X.operand1() << "," << X.operand2() << "\n"; + return OS; +} +std::ostream &operator<<(std::ostream &OS, const RegImmImmOperandSeq &X) { + OS << X.operand1() << ","; + OS << X.operand2() << ","; + OS << X.operand3() << "\n"; + return OS; +} +std::ostream &operator<<(std::ostream &OS, const RegImmRegOperandSeq &X) { + OS << X.operand1() << ","; + OS << X.operand2() << ","; + OS << X.operand3() << "\n"; + return OS; +} +std::ostream &operator<<(std::ostream &OS, const RegOperandSeq &X) { + OS << X.operand1() << "\n"; + return OS; +} +std::ostream &operator<<(std::ostream &OS, const ImmOperandSeq &X) { + OS << X.operand1() << "\n"; + return OS; +} +std::ostream &operator<<(std::ostream &OS, const AsmStmt &X) { + OS << "\t" << X.opcode() << "\t"; + if (X.has_seq1()) + return OS << X.seq1(); + if (X.has_seq2()) + return OS << X.seq2(); + if (X.has_seq3()) + return OS << X.seq3(); + if (X.has_seq4()) + return OS << X.seq4(); + if (X.has_seq5()) + return OS << X.seq5(); + if (X.has_seq6()) + return OS << X.seq6(); + if (X.has_seq7()) + return OS << X.seq7(); + if (X.has_seq8()) + return OS << X.seq8(); + if (X.has_seq9()) + return OS << X.seq9(); + if (X.has_seq10()) + return OS << X.seq10(); + if (X.has_seq11()) + return OS << X.seq11(); + if (X.has_seq12()) + return OS << X.seq12(); + return OS << "\tnop\n"; +} +std::ostream &operator<<(std::ostream &OS, const AsmStmtSeq &X) { + for (auto &ST : X.stmts()) + OS << ST; + return OS; +} +std::ostream &operator<<(std::ostream &OS, const Assembly &X) { + return OS << X.asmstmts(); +} + +// --------------------------------- + +std::string FunctionToString(const Assembly &Input) { + std::ostringstream OS; + OS << Input; + return OS.str(); +} +std::string ProtoToASM(const uint8_t *Data, size_t Size) { + Assembly Message; + if (!Message.ParsePartialFromArray(Data, Size)) + return "#error invalid proto\n"; + return FunctionToString(Message); +} + +} // namespace mc_proto_fuzzer