#ifdef INTELLISENSE_DIRECTIVES # pragma once # include "duffle/dsl.h" # include "duffle/memory.h" # include "duffle/text.h" #endif typedef Enum_(U1, X8616_InfoKind) { x8616_info_note = 0x0, x8616_info_warning = 0x1, x8616_info_error = 0x2, }; typedef Enum_(U1, X8616_InfoCode) { x8616_info_none = 0x00, x8616_info_invalid_opcode = 0x01, x8616_info_invalid_opcode_extension = 0x02, x8616_info_invalid_post_opcode = 0x03, x8616_info_truncated_instruction = 0x04, x8616_info_output_full = 0x05, x8616_info_gen_multiple_payloads = 0x06, x8616_info_gen_body_cap_exceeded = 0x07, x8616_info_gen_aux_cap_exceeded = 0x08, x8616_info_gen_ambiguous_decode = 0x09, x8616_info_gen_dispatch_mismatch = 0x0A, x8616_info_serialize_bad_request = 0x0B, x8616_info_serialize_invalid_record = 0x0C, x8616_info_serialize_unsupported_form = 0x0D, x8616_info_serialize_output_full = 0x0E, x8616_info_parse_bad_request = 0x0F, x8616_info_parse_syntax = 0x10, x8616_info_parse_unknown_mnemonic = 0x11, x8616_info_parse_output_full = 0x12, x8616_info_parse_invalid_record = 0x13, x8616_info_parse_unsupported_form = 0x14, x8616_info_encode_bad_request = 0x15, x8616_info_encode_invalid_record = 0x16, x8616_info_encode_output_full = 0x17, x8616_info_count, }; /* The hot path stores structured diagnostic facts only. Human-readable text is a projection of those facts. */ typedef Struct_(X8616_InfoMsg) { X8616_InfoMsg* next; X8616_InfoKind kind; X8616_InfoCode code; U2 source_size; U4 source_offset; U4 expected; U4 actual; Str8 text; }; /* Static templates use the same vocabulary as Duffle's str8_fmt_ktl_buf path. The decoder itself never expands these. */ RO_ global Str8 x8616_info_templates[x8616_info_count] = { [x8616_info_none] = slit8(""), [x8616_info_invalid_opcode] = slit8("Header is not in the Part 1 8086 decode table at ."), [x8616_info_invalid_opcode_extension] = slit8("Opcode extension does not match the selected encoding at ."), [x8616_info_invalid_post_opcode] = slit8("Post-opcode byte does not match expected at ."), [x8616_info_truncated_instruction] = slit8("Instruction at needs bytes; are available."), [x8616_info_output_full] = slit8("Decoded-instruction output is full: capacity , produced ."), [x8616_info_gen_multiple_payloads] = slit8("Encoding describes more than one stream payload."), [x8616_info_gen_body_cap_exceeded] = slit8("Encoding requires body bytes; decoder body capacity is ."), [x8616_info_gen_aux_cap_exceeded] = slit8("Generated auxiliary decode table exceeds capacity ."), [x8616_info_gen_ambiguous_decode] = slit8("Decode is ambiguous for header/second-byte key : plans and ."), [x8616_info_gen_dispatch_mismatch] = slit8("Generated dispatch mismatch for header/second-byte key : expected , actual ."), [x8616_info_serialize_bad_request] = slit8("Serialize request is missing instructions, output, scratch, or info arena."), [x8616_info_serialize_invalid_record] = slit8("Serialize record is not printable (op )."), [x8616_info_serialize_unsupported_form] = slit8("Serialize record has an unsupported display form (op )."), [x8616_info_serialize_output_full] = slit8("Serialize output is full at record : capacity , produced ."), [x8616_info_parse_bad_request] = slit8("Parse request is missing source, output, or info arena."), [x8616_info_parse_syntax] = slit8("Parse syntax error at ."), [x8616_info_parse_unknown_mnemonic] = slit8("Unknown mnemonic at ."), [x8616_info_parse_output_full] = slit8("Parse output is full: capacity , produced ."), [x8616_info_parse_invalid_record] = slit8("Parse record at is not a valid instruction (op )."), [x8616_info_parse_unsupported_form] = slit8("Parse record at has an unsupported form (op )."), [x8616_info_encode_bad_request] = slit8("Encode request is missing instructions, output, or info arena."), [x8616_info_encode_invalid_record] = slit8("Encode record is invalid or truncated (op )."), [x8616_info_encode_output_full] = slit8("Encode output is full at record : capacity , produced ."), }; typedef Struct_(X8616_InfoList) { X8616_InfoMsg* first; X8616_InfoMsg* last; U4 count; U4 error_count; U4 warning_count; U4 dropped_count; }; I_ Str8 x8616_info_template(X8616_InfoCode code) { return code < x8616_info_count ? x8616_info_templates[code] : x8616_info_templates[x8616_info_none]; } FI_ void x8616_info_push(FArena_R scratch , X8616_InfoList_R msgs , X8616_InfoKind kind , X8616_InfoCode code , U4 source_offset , U2 source_size , U4 expected , U4 actual ){ assert(scratch != nullptr); msgs->count += 1; msgs->error_count += kind == x8616_info_error; msgs->warning_count += kind == x8616_info_warning; U4 allocation_size = align_pow2(S_(X8616_InfoMsg), MEM_ALIGNMENT_DEFAULT); U4 left = scratch->capacity - scratch->used; if (allocation_size > left) { ++ msgs->dropped_count; return; } X8616_InfoMsg_R msg = farena_push_type(scratch, X8616_InfoMsg); // msg[0] = (X8616_InfoMsg){0}; msg->kind = kind; msg->code = code; msg->source_offset = source_offset; msg->source_size = source_size; msg->expected = expected; msg->actual = actual; msg->text = x8616_info_template(code); sll_queue_push_n(msgs->first, msgs->last, msg, next); } typedef Struct_(X8616_InfoTextValues) { Str8 offset; Str8 expected; Str8 actual; }; FI_ Str8 x8616_info_render(Slice output, X8616_InfoMsg_R msg, X8616_InfoTextValues values) { KTL_Slot_Str8 slots[] = { { ktl_str8_key("offset"), values.offset }, { ktl_str8_key("expected"), values.expected }, { ktl_str8_key("actual"), values.actual }, }; return str8_fmt_ktl_buf(output, ktl_str8_from_arr(slots), msg->text); }