mirror of
https://github.com/odin-lang/Odin.git
synced 2026-08-20 12:18:59 +00:00
Improve error messages for register class printing
This commit is contained in:
@@ -493,6 +493,51 @@ main :: proc() {
|
||||
""")
|
||||
strings.write_string(&sb, "\n\n")
|
||||
|
||||
strings.write_string(&sb, """
|
||||
AsmRegClass reg_class_from_operand_type(OperandType type) {
|
||||
switch (type) {
|
||||
case OP_R8: case OP_R16: case OP_R32: case OP_R64:
|
||||
case OP_RM8: case OP_RM16: case OP_RM32: case OP_RM64:
|
||||
case OP_AL_IMPL: case OP_AX_IMPL: case OP_EAX_IMPL: case OP_RAX_IMPL:
|
||||
case OP_CL_IMPL: case OP_DX_IMPL:
|
||||
return AsmRegClass_Integer;
|
||||
|
||||
case OP_XMM: case OP_YMM: case OP_ZMM:
|
||||
case OP_XMM_M32: case OP_XMM_M64: case OP_XMM_M128:
|
||||
case OP_YMM_M256: case OP_ZMM_M512:
|
||||
case OP_XMM0_IMPL:
|
||||
return AsmRegClass_Vector;
|
||||
|
||||
case OP_K:
|
||||
case OP_K_M8: case OP_K_M16: case OP_K_M32: case OP_K_M64:
|
||||
return AsmRegClass_Mask;
|
||||
|
||||
case OP_STI:
|
||||
case OP_ST0_IMPL:
|
||||
return AsmRegClass_Float;
|
||||
|
||||
case OP_MM:
|
||||
case OP_MM_M64:
|
||||
return AsmRegClass_Vector;
|
||||
|
||||
case OP_SREG: case OP_CR: case OP_DR:
|
||||
case OP_M: case OP_M8: case OP_M16: case OP_M32: case OP_M64:
|
||||
case OP_M80: case OP_M128: case OP_M256: case OP_M512:
|
||||
case OP_MOFFS8: case OP_MOFFS16: case OP_MOFFS32: case OP_MOFFS64:
|
||||
case OP_M16_16: case OP_M16_32: case OP_M16_64:
|
||||
case OP_IMM8: case OP_IMM16: case OP_IMM32: case OP_IMM64:
|
||||
case OP_IMM8SX:
|
||||
case OP_ONE_IMPL:
|
||||
case OP_PTR16_16: case OP_PTR16_32: case OP_PTR16_64:
|
||||
case OP_REL8: case OP_REL32:
|
||||
case OP_NONE:
|
||||
default:
|
||||
return AsmRegClass_Unknown;
|
||||
}
|
||||
}
|
||||
""")
|
||||
strings.write_string(&sb, "\n\n")
|
||||
|
||||
strings.write_string(&sb, """
|
||||
bool operand_type_is_implicit(OperandType t) {
|
||||
switch (t) {
|
||||
|
||||
@@ -4,8 +4,25 @@ enum AsmRegClass : u8 {
|
||||
AsmRegClass_Float,
|
||||
AsmRegClass_Vector,
|
||||
AsmRegClass_Mask,
|
||||
|
||||
AsmRegClass_COUNT
|
||||
};
|
||||
|
||||
gb_global String const asm_reg_class_strings[AsmRegClass_COUNT] = {
|
||||
str_lit("unknown"),
|
||||
str_lit("integer"),
|
||||
str_lit("float"),
|
||||
str_lit("vector"),
|
||||
str_lit("mask"),
|
||||
};
|
||||
|
||||
gb_global String const asm_reg_class_strings_with_article[AsmRegClass_COUNT] = {
|
||||
str_lit("an unknown"),
|
||||
str_lit("an integer"),
|
||||
str_lit("a float"),
|
||||
str_lit("a vector"),
|
||||
str_lit("a mask"),
|
||||
};
|
||||
|
||||
enum AsmOperandKind : u8 {
|
||||
AsmOperand_Invalid,
|
||||
|
||||
@@ -510,6 +510,48 @@ struct Asm_amd64 {
|
||||
}
|
||||
}
|
||||
|
||||
AsmRegClass reg_class_from_operand_type(OperandType type) {
|
||||
switch (type) {
|
||||
case OP_R8: case OP_R16: case OP_R32: case OP_R64:
|
||||
case OP_RM8: case OP_RM16: case OP_RM32: case OP_RM64:
|
||||
case OP_AL_IMPL: case OP_AX_IMPL: case OP_EAX_IMPL: case OP_RAX_IMPL:
|
||||
case OP_CL_IMPL: case OP_DX_IMPL:
|
||||
return AsmRegClass_Integer;
|
||||
|
||||
case OP_XMM: case OP_YMM: case OP_ZMM:
|
||||
case OP_XMM_M32: case OP_XMM_M64: case OP_XMM_M128:
|
||||
case OP_YMM_M256: case OP_ZMM_M512:
|
||||
case OP_XMM0_IMPL:
|
||||
return AsmRegClass_Vector;
|
||||
|
||||
case OP_K:
|
||||
case OP_K_M8: case OP_K_M16: case OP_K_M32: case OP_K_M64:
|
||||
return AsmRegClass_Mask;
|
||||
|
||||
case OP_STI:
|
||||
case OP_ST0_IMPL:
|
||||
return AsmRegClass_Float;
|
||||
|
||||
case OP_MM:
|
||||
case OP_MM_M64:
|
||||
return AsmRegClass_Vector;
|
||||
|
||||
case OP_SREG: case OP_CR: case OP_DR:
|
||||
case OP_M: case OP_M8: case OP_M16: case OP_M32: case OP_M64:
|
||||
case OP_M80: case OP_M128: case OP_M256: case OP_M512:
|
||||
case OP_MOFFS8: case OP_MOFFS16: case OP_MOFFS32: case OP_MOFFS64:
|
||||
case OP_M16_16: case OP_M16_32: case OP_M16_64:
|
||||
case OP_IMM8: case OP_IMM16: case OP_IMM32: case OP_IMM64:
|
||||
case OP_IMM8SX:
|
||||
case OP_ONE_IMPL:
|
||||
case OP_PTR16_16: case OP_PTR16_32: case OP_PTR16_64:
|
||||
case OP_REL8: case OP_REL32:
|
||||
case OP_NONE:
|
||||
default:
|
||||
return AsmRegClass_Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
bool operand_type_is_implicit(OperandType t) {
|
||||
switch (t) {
|
||||
case OP_AL_IMPL: case OP_AX_IMPL:
|
||||
|
||||
@@ -818,6 +818,9 @@ gb_internal void check_mnemonic(AsmCtx *asm_ctx, CheckerContext *ctx, Entity *tm
|
||||
auto possible_kinds = slice_make<AsmOperandKind>(heap_allocator(), max_count);
|
||||
defer (slice_free(&possible_kinds, heap_allocator()));
|
||||
|
||||
auto possible_class_kinds = slice_make<AsmRegClass>(heap_allocator(), max_count);
|
||||
defer (slice_free(&possible_class_kinds, heap_allocator()));
|
||||
|
||||
bool matched = false;
|
||||
isize valid_form_index = -1;
|
||||
|
||||
@@ -950,6 +953,7 @@ gb_internal void check_mnemonic(AsmCtx *asm_ctx, CheckerContext *ctx, Entity *tm
|
||||
AsmOperandKind dst = asm_ctx->kind_from_operand_type(type);
|
||||
AsmOperandKind src = determine_asm_operand_kind(&operands[i]);
|
||||
possible_kinds[i] = dst;
|
||||
possible_class_kinds[i] = asm_ctx->reg_class_from_operand_type(type);
|
||||
|
||||
bool kind_ok = (dst == src) ||
|
||||
(dst == AsmOperand_Register_Or_Memory && (src == AsmOperand_Register || src == AsmOperand_Memory));
|
||||
@@ -983,6 +987,9 @@ gb_internal void check_mnemonic(AsmCtx *asm_ctx, CheckerContext *ctx, Entity *tm
|
||||
auto dst = possible_kinds[i];
|
||||
AsmOperandKind src = determine_asm_operand_kind(&operands[i]);
|
||||
|
||||
AsmRegClass dst_reg_class = possible_class_kinds[i];
|
||||
AsmRegClass src_reg_class = check_asm_reg_class_from_type(operands[i].type);
|
||||
|
||||
AsmMismatch m = (i < MAX_VARIANT_COUNT) ? mismatch[i] : AsmMismatch_None;
|
||||
|
||||
if (m == AsmMismatch_ImmRange) {
|
||||
@@ -1005,8 +1012,10 @@ gb_internal void check_mnemonic(AsmCtx *asm_ctx, CheckerContext *ctx, Entity *tm
|
||||
error(operands[i].expr, "'%.*s' operand-%td has the wrong size: expected a %u-bit operand, got %u-bit",
|
||||
LIT(name), i, cast(unsigned)want_bits[i], cast(unsigned)got_bits[i]);
|
||||
} else if (m == AsmMismatch_Class) {
|
||||
error(operands[i].expr, "'%.*s' operand-%td is in the wrong register class, expected %.*s operand, got %.*s",
|
||||
LIT(name), i, LIT(asm_operand_kind_expected_strings[dst]), LIT(asm_operand_kind_expected_strings[src]));
|
||||
error(operands[i].expr, "'%.*s' operand-%td is in the wrong register class, expected %d-bit %.*s %.*s, got %d-bit %.*s %.*s",
|
||||
LIT(name), i,
|
||||
want_bits[i], LIT(asm_reg_class_strings[dst_reg_class]), LIT(asm_operand_kind_strings[dst]),
|
||||
got_bits[i], LIT(asm_reg_class_strings[src_reg_class]), LIT(asm_operand_kind_strings[src]));
|
||||
} else if (dst) {
|
||||
error(operands[i].expr, "'%.*s' operand-%td has an invalid kind, expected %.*s operand",
|
||||
LIT(name), i, LIT(asm_operand_kind_expected_strings[dst]));
|
||||
|
||||
@@ -735,7 +735,14 @@ struct lbAsmGenerate_amd64 : lbAsmGenerate {
|
||||
|
||||
|
||||
gb_internal lbValue lb_emit_asm_template_call(lbProcedure *p, Entity *entity, Array<lbValue> const &args) {
|
||||
lbAsmGenerate_amd64 generator = {};
|
||||
generator.init(entity);
|
||||
return generator.emit_call(p, args);
|
||||
lbAsmGenerate *generator = nullptr;
|
||||
if (build_context.metrics.arch == TargetArch_amd64) {
|
||||
lbAsmGenerate_amd64 generator_amd64 = {};
|
||||
generator = &generator_amd64;
|
||||
} else {
|
||||
compiler_error("Architecture does not support asm templates");
|
||||
return {};
|
||||
}
|
||||
generator->init(entity);
|
||||
return generator->emit_call(p, args);
|
||||
}
|
||||
Reference in New Issue
Block a user