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 @@ -29,9 +29,10 @@ fuzzer with, including the corpus directory and the full path to objdump. For example: -$ 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 +$ 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 --march rv32imc \ + --assemble /full/path/to/riscv32-unknown-linux-gnu-as Run the script with the --verbose flag if you would like to see the output of the fuzzer as it runs. @@ -67,8 +68,6 @@ ------------------------------------------------------------------------------- Notes: ------------------------------------------------------------------------------- -The fuzzer currently supports all the instructions in the RV32I ISA, except -for the following instructions: FENCE, FENCE.I, ECALL, EBREAK, CSRRW, CSRRS, -CSRRC, CSRRWI, CSRRSI, and CSRRCI. Currently, running the Python script will -result in some failures as instructions are given aliases by the golden -disassembler, and therefore the diff fails. +Currently, running the Python script will result in some failures as +instructions are given aliases by the golden disassembler, and therefore +the diff fails. Index: tools/llvm-mc-assemble-proto-fuzzer/mcfuzz.py =================================================================== --- tools/llvm-mc-assemble-proto-fuzzer/mcfuzz.py +++ tools/llvm-mc-assemble-proto-fuzzer/mcfuzz.py @@ -8,135 +8,251 @@ import sys import tempfile -parser = argparse.ArgumentParser() - -# Flags for the directory names, corpus and outputdir. -parser.add_argument("--corpus", type=str, help="corpus directory name", \ - required=True) -parser.add_argument("--out", type=str, \ - help="output directory name for obj files", default=None) - -# Flags for llvm-mc-assemble-proto-fuzzer: triple, mattr, filetype. -parser.add_argument("--triple", type=str, help="specify the triple", \ - default="riscv32") -parser.add_argument("--mattr", type=str, help="specify mattr", \ - default="") -parser.add_argument("--filetype", type=str, help="asm or obj", \ - default="obj") - -# These args are passed in after the -fuzzer-args flag. -parser.add_argument("--runs", type=int, help="number of runs", default=100) -parser.add_argument("--max-len", type=int, \ - help="limit instruction size for fuzzing", default=40) - -# Flag specifies the name of objdump executable. -parser.add_argument("--objdump", type=str, help="specify the path to" \ - " objdump", default="/prj/llvm-arm/home/common/build_tools/" \ - "riscv32-gnu-7.2.0/bin/riscv32-unknown-linux-gnu-objdump") - -# Flag specifies that we should print out everything -parser.add_argument("--verbose", dest="verbose", action="store_true") -parser.set_defaults(verbose=False) - -parser.add_argument("--riscv-no-aliases", dest="NoAliases", - action="store_true") -parser.set_defaults(NoAliases=False) - -args = parser.parse_args() - -# Step 1: Invoke fuzzer to generate a corpus. -cmd = 'llvm-mc-assemble-proto-fuzzer-rv32i {corpus} -triple={triple} ' \ - '-mattr={mattr}' + ' -filetype={filetype} -fuzzer-args -runs={runs} ' \ - '-max_len={max_len}' -cmd = cmd.format(corpus=args.corpus, triple=args.triple, mattr=args.mattr, \ - filetype=args.filetype, runs=args.runs, max_len=args.max_len) -fuzz_command = shlex.split(cmd) - -fuzz_proc = subprocess.Popen(fuzz_command, stdout=subprocess.PIPE, \ - stderr=subprocess.STDOUT) -fuzz_out, fuzz_err = fuzz_proc.communicate() -if fuzz_proc.returncode != 0: - raise ValueError('failed to run fuzz {}: {}'.format(fuzz_command, fuzz_err)) -if args.verbose: - print(fuzz_out) - -# If user specified an output directory, proceed to step 2; otherwise, exit. -if args.out is None: - print("No output directory specified; exiting after populating " - "corpus directory.") - sys.exit(0) - -# Keep track of which diffs pass / fail. -passes = 0 -fails = 0 -list_of_failures = [] -# Iterate through the corpus body. -# For each file, generate a .s and a .o file. Then, use objdump to -# generate a .objdump file, which we will compare to the .s file. -# Diff the .s with the corresponding .objdump file. -for filename in os.listdir(args.corpus): - filename_prefix = args.out + "/" + filename +def main(): + parser = argparse.ArgumentParser() + parse_arguments(parser) + args = parser.parse_args() + + # Step 1: Invoke fuzzer to generate a corpus. + call_fuzzer(args) + + # If user did not specify output dir, skip steps 2-8; exit. + if args.out is None: + print("No output directory specified; exiting after populating " + "corpus directory.") + sys.exit(0) + + # List of corpus files that both LLVM AS and GNU AS fail to assemble. + list_of_llvm_as_and_gnu_as_fails = [] + # List of corpus files that only LLVM AS fails to assemble. + list_of_llvm_as_fails = [] + # List of corpus files that only GNU AS fails to assemble. + list_of_gnu_as_fails = [] + # List of corpus files that both LLVM AS and GNU AS can assemble. + list_of_llvm_as_and_gnu_as_passes = [] + # Keep track of which diffs pass / fail. + passes = 0 + fails = 0 + list_of_diffs = [] + + # Iterate through the corpus body. + + # For each file, re-run the fuzzer to generate an object file with the fuzz + # target. Also run the golden assembler (gnu as) to generate a reference + # object file. If both assemblers behave the same way, proceed to generate + # a .s file (using proto-to-asm tool), disassemble the object file + # generated by the fuzz target (using objdump) and then compare the + # resulting .objdump with your .s file. + for filename in os.listdir(args.corpus): + # Step 2: Run fuzzer with filetype=obj; check for error in fuzz target. + target_error_occurred = call_fuzzer_on_corpus_file(args, filename) + + # Step 3: Run proto-to-asm on corpus file to generate .s file. + call_proto_to_asm(args, filename) + + # Step 4: Run golden assembler (gnu) and check for error. + golden_error_occurred = call_golden_assembler(args, filename) + + # Step 5: Compare behavior of fuzz target and golden assembler. + #################################################################### + #-- Initial, tentative interpretation of results, based on the --# + #-- status (pass/fail) of tools (LLVM AS, GNU AS, GNU OBJDUMP) --# + #------------------------------------------------------------------# + # LLVM AS | GNU AS | GNU OBJDUMP | Conclusion # + #------------------------------------------------------------------# + # 0 | 0 | x | invalid/unimplemented instr # + # 0 | 1 | x | LLVM MC bug/unimplemented instr # + # 1 | 0 | x | LLVM MC bug # + # 1 | 1 | 0 | LLVM MC bug and GCC bug # + # 1 | 1 | 1 | success # + #################################################################### + if target_error_occurred and golden_error_occurred: + print("Both assemblers failed to assemble file: " + filename) + list_of_llvm_as_and_gnu_as_fails.append(filename) + continue + elif target_error_occurred: + print("Only the target AS failed to assemble file: " + filename) + list_of_llvm_as_fails.append(filename) + continue + elif golden_error_occurred: + print("Only the golden AS failed to assemble file: " + filename) + list_of_gnu_as_fails.append(filename) + continue + else: + print("Both assemblers assembled file: " + filename) + list_of_llvm_as_and_gnu_as_passes.append(filename) + + # Step 6: Call objdump on each .o file (generated by fuzz target) in + # the output directory, to generate corresponding .objdump files. + objdump_file = call_objdump(args, filename) + + # Step 7: Process files generated by objdump so that the files only + # contain instructions. + process_objdump_file(objdump_file, args, filename) + + # Step 8: Diff the .s file generated by proto-to-asm with .objdump file + # generated by objdump. + passes, fails, list_of_diffs = print_file_status(args, filename, + passes, fails, + list_of_diffs) + + print_result(passes, fails, list_of_llvm_as_and_gnu_as_fails, + list_of_llvm_as_fails, list_of_gnu_as_fails, + list_of_llvm_as_and_gnu_as_passes, list_of_diffs) - # Step 2: Run proto-to-asm on corpus file to generate .s file. - proto_to_asm_command = ["llvm-mc-assemble-proto-to-asm-rv32i", \ - args.corpus + "/" + filename, "-riscv-no-aliases=" + - str(args.NoAliases)] + sys.exit(0 if fails == 0 else 1) + + +def parse_arguments(parser): + # Flags for the directory names, corpus and outputdir. + parser.add_argument("--corpus", type=str, help="corpus directory name", + required=True) + parser.add_argument("--out", type=str, + help="output directory name for obj files", + default=None) + + # Flags for llvm-mc-assemble-proto-fuzzer: triple, mattr, filetype. + parser.add_argument("--triple", type=str, help="specify the triple", + default="riscv32") + parser.add_argument("--mattr", type=str, help="specify mattr", + default="") + parser.add_argument("--march", type=str, help="specify march", + default="rv32i") + parser.add_argument("--filetype", type=str, help="asm or obj", + default="obj") + + # These args are passed in after the -fuzzer-args flag. + parser.add_argument("--runs", type=int, help="number of runs", default=100) + parser.add_argument("--max-len", type=int, + help="limit instruction size for fuzzing", default=40) + + # Flag specifies the name of objdump executable. + parser.add_argument("--objdump", type=str, help="specify the path to" + " objdump", default="/prj/llvm-arm/home/common/" + "build_tools/riscv32-gnu-7.2.0/bin/" + "riscv32-unknown-linux-gnu-objdump") + + # Flag specifies the name of golden assembler executable. + parser.add_argument("--assemble", type=str, help="specify the path to" + " golden assembler", default="/prj/llvm-arm/home/" + "common/build_tools/riscv32-gnu-7.2.0/bin/" + "riscv32-unknown-linux-gnu-as") + + # Flag specifies that we should print out everything + parser.add_argument("--verbose", dest="verbose", action="store_true") + parser.set_defaults(verbose=False) + + parser.add_argument("--riscv-no-aliases", dest="NoAliases", + action="store_true") + parser.set_defaults(NoAliases=False) + + +# This function calls the llvm-mc-assemble-proto-fuzzer with a given extension +def call_fuzzer(args): + cmd = 'llvm-mc-assemble-proto-fuzzer-{march} {corpus} \ + -triple={triple} -mattr={mattr} -filetype={filetype} -fuzzer-args ' \ + + '-runs={runs} -max_len={max_len}' + cmd = cmd.format(march=args.march, corpus=args.corpus, triple=args.triple, + mattr=args.mattr, filetype=args.filetype, + runs=args.runs, max_len=args.max_len) + fuzz_command = shlex.split(cmd) + + fuzz_proc = subprocess.Popen(fuzz_command, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + fuzz_out, fuzz_err = fuzz_proc.communicate() + if fuzz_proc.returncode != 0: + raise ValueError('failed to run fuzz {}: {}'.format(fuzz_command, + fuzz_err)) + if args.verbose: + print(fuzz_out) + + +def call_fuzzer_on_corpus_file(args, filename): + target_error_occurred = False + cmd = 'llvm-mc-assemble-proto-fuzzer-{march} {corpus}/{file} ' \ + + '-triple={triple} -mattr={mattr} -out={out} ' \ + + '-filetype=obj -fuzzer-args -runs=1' + cmd = cmd.format(march=args.march, corpus=args.corpus, file=filename, + triple=args.triple, mattr=args.mattr, out=args.out) + target_as_command = shlex.split(cmd) + target_as_proc = subprocess.Popen(target_as_command, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + target_as_out, target_as_err = target_as_proc.communicate() + if target_as_proc.returncode != 0: + raise ValueError('failed to run fuzzer {}: {}'.format( + target_as_command, target_as_err)) + if target_as_out: + if "error" in target_as_out: + print("Fuzz Target failed to assemble this input: " + filename) + target_error_occurred = True + if args.verbose: + print(target_as_out) + return target_error_occurred + + +def call_proto_to_asm(args, filename): + filename_prefix = args.out + "/" + filename + cmd = 'llvm-mc-assemble-proto-to-asm-{march} {corpus}/{file}' \ + + ' -riscv-no-aliases={NoAliases}' + cmd = cmd.format(march=args.march, corpus=args.corpus, file=filename, + NoAliases=args.NoAliases) + proto_to_asm_command = shlex.split(cmd) asm_file = open(filename_prefix + ".s", "w+r") asm_proc = subprocess.Popen(proto_to_asm_command, stdout=asm_file, - stderr=subprocess.STDOUT) + stderr=subprocess.STDOUT) asm_out, asm_err = asm_proc.communicate() if asm_proc.returncode != 0: raise ValueError('failed to run {}: {}'.format(proto_to_asm_command, - asm_err)) + asm_err)) + elif asm_out: + print("Asm_out: " + asm_out) + asm_file.close() - # Step 3: Generate .o files in the outputdir. - cmd = 'llvm-mc-assemble-proto-fuzzer-rv32i {corpus}/{file} ' \ - + '-triple={triple} -mattr={mattr} -out={out} ' \ - + '-filetype=obj -fuzzer-args -runs=1' - cmd = cmd.format(corpus=args.corpus, file=filename, triple=args.triple, \ - mattr=args.mattr, out=args.out) - obj_files_command = shlex.split(cmd) - obj_proc = subprocess.Popen(obj_files_command, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - obj_out, obj_err = obj_proc.communicate() - if obj_proc.returncode != 0: - raise ValueError('failed to run fuzzer {}: {}'.format( \ - obj_files_command, obj_err)) - if args.verbose: - print(obj_out) - # Step 4: Call objdump on each .o file in the output directory, - # to generate corresponding .objdump files. +def call_golden_assembler(args, filename): + golden_error_occurred = False + cmd = '{assemble} {dirname}/{filename}.s -march={march} ' \ + + '-o {dirname}/{filename}.out' + cmd = cmd.format(assemble=args.assemble, march=args.march, + dirname=args.out, filename=filename) + golden_as_command = shlex.split(cmd) + golden_as_proc = subprocess.Popen(golden_as_command, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + golden_as_out, golden_as_err = golden_as_proc.communicate() + if golden_as_proc.returncode != 0: + if (golden_as_out): + print("golden_as_out: " + golden_as_out) + golden_error_occurred = True + elif args.verbose: + print(golden_as_out) + return golden_error_occurred + + +def call_objdump(args, filename): + filename_prefix = args.out + "/" + filename objdump_file = open(filename_prefix + ".objdump", "w+r") cmd = '{objdump} -dr -M numeric {filename}.o' cmd = cmd.format(objdump=args.objdump, filename=filename_prefix) objdump_command = shlex.split(cmd) objdump_proc = subprocess.Popen(objdump_command, - stdout=objdump_file, stderr=subprocess.STDOUT) + stdout=objdump_file, + stderr=subprocess.STDOUT) objdump_out, objdump_err = objdump_proc.communicate() if objdump_proc.returncode != 0: - raise ValueError('failed to run objdump {}: ' \ - + '{}'.format(objdump_command, objdump_err)) + raise ValueError('failed to run objdump {}: ' + + '{}'.format(objdump_command, objdump_err)) + return objdump_file - # Step 5: Process asm files so that files only contain asm instructions. - asm_file.seek(0) - lines = asm_file.readlines() - asm_file.close() - write_asm_file = open(filename_prefix + ".parsed_s", "w") - # Remove the first line of .s file, which contains the filename. For example: - # // corpus/dff0318decde43ce5065a4209412aa2c68d01318 - for line in lines: - if "\t" in line: - write_asm_file.write(line) - write_asm_file.close() - # Step 6: Process files generated by objdump so that the files only contain - # instructions. +def process_objdump_file(objdump_file, args, filename): + filename_prefix = args.out + "/" + filename objdump_file.seek(0) temp_objdump_file = tempfile.TemporaryFile("w+r") - # Only the lines containing asm instructions have tabs in them; remove all - # other lines (for example, header lines and whitespace). + # Only the lines containing asm instructions have tabs in them; remove + # all other lines (for example, header lines and whitespace). for line in objdump_file: if "\t" in line: temp_objdump_file.write(line) @@ -154,28 +270,78 @@ write_objdump_file.write("\n") temp_objdump_file.close() - # Step 7: Diff the .s file generated by proto-to-asm and the .objdump file - # generated by objdump. + +def print_file_status(args, filename, passes, fails, list_of_diffs): + filename_prefix = args.out + "/" + filename prefix = "Checking " + filename + "..." - file1 = open(filename_prefix + ".parsed_s", "r") + file1 = open(filename_prefix + ".s", "r") file2 = open(filename_prefix + ".parsed_objdump", "r") diff = difflib.ndiff(file1.readlines(), file2.readlines()) delta = ''.join(x[0:] for x in diff if x.startswith(('- ', '+ '))) if delta: print(prefix + "FAILURE!") fails = fails + 1 - list_of_failures.append(filename) - list_of_failures.append(delta) + list_of_diffs.append(filename) + list_of_diffs.append(delta) else: print(prefix + "SUCCESS!") passes = passes + 1 + file1.close() + file2.close() + return passes, fails, list_of_diffs + + +def print_result(passes, fails, list1, list2, list3, list4, list5): + print("Both llvm-mc-assembler and golden (gnu) assembler fail:") + count1 = 0 + str = "" + for item in list1: + count1 = count1 + 1 + str = str + item + "\t" + if (count1 % 3 == 0): + str = str + "\n" + print(str) + + str = "" + count2 = 0 + print("Target assembler llvm-mc fails:") + for item in list2: + count2 = count2 + 1 + str = str + item + "\t" + if (count2 % 3 == 0): + str = str + "\n" + print(str) + + str = "" + count3 = 0 + print("Golden (gnu) assembler fails:") + for item in list3: + count3 = count3 + 1 + str = str + item + "\t" + if (count3 % 3 == 0): + str = str + "\n" + print(str) -print("Succeeded: " + str(passes) + "\t\tFailed: " + str(fails) \ - + "\t\t[Total: " + str(passes + fails) + "]") + str = "" + count4 = 0 + print("Both assemblers pass:") + for item in list4: + count4 = count4 + 1 + str = str + item + "\t" + if (count4 % 3 == 0): + str = str + "\n" + print(str) -if (fails != 0): - print("The following files failed...") - for item in list_of_failures: - print(item) + if (fails != 0): + print("The following files failed...") + for item in list5: + print(item) + print("Both llvm as and gnu assembler fail: {}".format(count1)) + print("Only llvm as fails: {}".format(count2)) + print("Only gnu as fails: {}".format(count3)) + print("Both llvm as and gnu assembler pass: {}".format(count4)) + print("[Succeeded: {}/{}\tFailed: {}/{}]".format(passes, + passes + fails, fails, passes + fails)) -sys.exit(0 if fails == 0 else 1) +if __name__ == "__main__": + main() Index: tools/llvm-mc-assemble-proto-fuzzer/proto-files/rv32i_asm.proto =================================================================== --- tools/llvm-mc-assemble-proto-fuzzer/proto-files/rv32i_asm.proto +++ tools/llvm-mc-assemble-proto-fuzzer/proto-files/rv32i_asm.proto @@ -8,35 +8,22 @@ //===----------------------------------------------------------------------===// /// /// \file -/// This file describes a subset of ASM (RV32I) as a protobuf. It is used to -/// more easily find interesting inputs for fuzzing the llvm mc layer. +/// This file describes a subset of ASM (RV32I) as a protobuf, with no +/// constraints on register or immediate operands. It is used to more +/// easily find interesting inputs for fuzzing the llvm mc layer. +/// The fuzzer currently supports all the instructions in the RV32I ISA, +/// except for the following instructions: FENCE, FENCE.I, ECALL, EBREAK, +/// CSRRW, CSRRS, CSRRC, CSRRWI, CSRRSI, and CSRRCI. /// //===----------------------------------------------------------------------===// syntax = "proto2"; -message ITypeShiftImmediate { - required uint32 imm = 1; -} - -message ITypeImmediate { - required sint32 imm = 1; -} - -message STypeImmediate { - required sint32 imm = 1; -} - -message BTypeImmediate { - required sint32 imm = 1; -} - -message UTypeImmediate { - required uint32 imm = 1; -} - -message JTypeImmediate { - required sint32 imm = 1; +message Immediate { + oneof imm_oneof { + sint32 s_imm = 1; + uint32 u_imm = 2; + } } message Register { @@ -82,7 +69,7 @@ message ITypeOperands { required Register operand1 = 1; required Register operand2 = 2; - required ITypeImmediate operand3 = 3; + required Immediate operand3 = 3; } message ITypeStatement { @@ -100,7 +87,7 @@ message ITypeShiftOperands { required Register operand1 = 1; required Register operand2 = 2; - required ITypeShiftImmediate operand3 = 3; + required Immediate operand3 = 3; } message ITypeShiftStatement { @@ -117,7 +104,7 @@ message STypeOperands { required Register operand1 = 1; - required STypeImmediate operand2 = 2; + required Immediate operand2 = 2; required Register operand3 = 3; } @@ -137,7 +124,7 @@ message BTypeOperands { required Register operand1 = 1; required Register operand2 = 2; - required BTypeImmediate operand3 = 3; + required Immediate operand3 = 3; } message BTypeStatement { @@ -154,7 +141,7 @@ message UTypeOperands { required Register operand1 = 1; - required UTypeImmediate operand2 = 2; + required Immediate operand2 = 2; } message UTypeStatement { @@ -171,7 +158,7 @@ message JTypeOperands { required Register operand1 = 1; - required JTypeImmediate operand2 = 2; + required Immediate operand2 = 2; } message JTypeStatement { Index: tools/llvm-mc-assemble-proto-fuzzer/proto-to-asm/proto_to_asm_main.cpp =================================================================== --- tools/llvm-mc-assemble-proto-fuzzer/proto-to-asm/proto_to_asm_main.cpp +++ tools/llvm-mc-assemble-proto-fuzzer/proto-to-asm/proto_to_asm_main.cpp @@ -43,7 +43,6 @@ std::fstream in(NewArgv[i]); std::string str((std::istreambuf_iterator(in)), std::istreambuf_iterator()); - std::cout << "// " << NewArgv[i] << std::endl; std::cout << mc_proto_fuzzer::ProtoToASM( reinterpret_cast(str.data()), str.size(), (bool) NoAliases); Index: tools/llvm-mc-assemble-proto-fuzzer/proto-to-asm/proto_to_asm_rv32i.cpp =================================================================== --- tools/llvm-mc-assemble-proto-fuzzer/proto-to-asm/proto_to_asm_rv32i.cpp +++ tools/llvm-mc-assemble-proto-fuzzer/proto-to-asm/proto_to_asm_rv32i.cpp @@ -9,7 +9,7 @@ // // Implements functions for converting between protobufs for the assembly // language grammar for RV32I instruction set and assembly language -// instructions. +// instructions. // //===----------------------------------------------------------------------===// #include "proto_to_asm.h" @@ -22,29 +22,11 @@ static bool NoAliases = false; -std::ostream &operator<<(std::ostream &OS, const ITypeShiftImmediate &X) { - // Limit immediate range to [0,31]. - return OS << X.imm() % 32; -} -std::ostream &operator<<(std::ostream &OS, const ITypeImmediate &X) { - // Limit immediate range to [-2048, 2047]. - return OS << X.imm() % 2048; -} -std::ostream &operator<<(std::ostream &OS, const STypeImmediate &X) { - // Limit immediate range to [-2048, 2047]. - return OS << X.imm() % 2048; -} -std::ostream &operator<<(std::ostream &OS, const BTypeImmediate &X) { - // Limit immediate range to [-2048, 2046], in multiples of 2. - return OS << ((X.imm() % 2048) / 2) * 2; -} -std::ostream &operator<<(std::ostream &OS, const UTypeImmediate &X) { - // Limit immediate range to [0, 1048575]. - return OS << X.imm() % 1048576; -} -std::ostream &operator<<(std::ostream &OS, const JTypeImmediate &X) { - // Limit immediate range to [-1048576, 1048574], in multiples of 2. - return OS << (((X.imm() % 1048576) / 2) * 2); +std::ostream &operator<<(std::ostream &OS, const Immediate &X) { + if (X.has_s_imm()) + return OS << X.s_imm(); + else + return OS << X.u_imm(); } std::ostream &operator<<(std::ostream &OS, const Register &X) { switch (X.name()) { @@ -80,6 +62,7 @@ case Register::X29: OS << "x29"; break; case Register::X30: OS << "x30"; break; case Register::X31: OS << "x31"; break; + default: assert(!"The default case was reached."); } return OS; } @@ -95,6 +78,7 @@ case RTypeOpcode_Op_SRA: OS << "sra"; break; case RTypeOpcode_Op_OR: OS << "or"; break; case RTypeOpcode_Op_AND: OS << "and"; break; + default: assert(!"The default case was reached."); } return OS; } @@ -114,6 +98,7 @@ case ITypeShiftOpcode_Op_SRAI: OS << "srai"; break; case ITypeShiftOpcode_Op_SRLI: OS << "srli"; break; case ITypeShiftOpcode_Op_SLLI: OS << "slli"; break; + default: assert(!"The default case was reached."); } return OS; } @@ -137,6 +122,7 @@ case ITypeOpcode_Op_XORI: OS << "xori"; break; case ITypeOpcode_Op_SLTIU: OS << "sltiu"; break; case ITypeOpcode_Op_JALR: OS << "jalr"; break; + default: assert(!"The default case was reached."); } return OS; } @@ -156,6 +142,7 @@ case STypeOpcode_Op_SW: OS << "sw"; break; case STypeOpcode_Op_SH: OS << "sh"; break; case STypeOpcode_Op_SB: OS << "sb"; break; + default: assert(!"The default case was reached."); } return OS; } @@ -178,6 +165,7 @@ case BTypeOpcode_Op_BLT: OS << "blt"; break; case BTypeOpcode_Op_BGEU: OS << "bgeu"; break; case BTypeOpcode_Op_BLTU: OS << "bltu"; break; + default: assert(!"The default case was reached."); } return OS; } @@ -196,6 +184,7 @@ switch (X.op()) { case UTypeOpcode_Op_LUI: OS << "lui"; break; case UTypeOpcode_Op_AUIPC: OS << "auipc"; break; + default: assert(!"The default case was reached."); } return OS; } @@ -212,6 +201,7 @@ std::ostream &operator<<(std::ostream &OS, const JTypeOpcode &X) { switch (X.op()) { case JTypeOpcode_Op_JAL: OS << "jal"; break; + default: assert(!"The default case was reached."); } return OS; }