mirror of
https://github.com/odin-lang/Odin.git
synced 2026-10-09 22:32:13 -04:00
Add more MOV forms; fix liveness check for lanes
This commit is contained in:
1 parent
07b5c2ee0f
commit
4f8a91092b
12 files changed
+2044
-1937
No files matched your search
+15
-8
@@ -319,7 +319,8 @@ gb_internal bool check_asm_operand_size_class(AsmCtx *asm_ctx, typename AsmCtx::
|
||||
// must not be held against the slot's register class. Only width matters for the
|
||||
// memory interpretation. Register operands still get the full class check.
|
||||
if (want_class != AsmRegClass_Unknown && !is_memory) {
|
||||
if (!asm_reg_class_compatible(want_class, got_class)) {
|
||||
bool is_lane = asm_ctx->operand_type_is_lane(slot);
|
||||
if (!is_lane && !asm_reg_class_compatible(want_class, got_class)) {
|
||||
if (mismatch_) *mismatch_ = AsmMismatch_Class;
|
||||
return false;
|
||||
}
|
||||
@@ -1687,7 +1688,6 @@ gb_internal bool check_mnemonic(AsmCtx *asm_ctx, CheckerContext *ctx, Entity *tm
|
||||
|
||||
u16 written_ops = cast(u16)clobber.written;
|
||||
u16 pinned_param_writes = 0;
|
||||
auto const &decls = tmpl_entity->AsmTemplate.decls;
|
||||
for_array(i, operands) {
|
||||
int tslot = user_operand_target_index(cast(int)i);
|
||||
if (tslot < 0 || tslot >= 4 || (written_ops & (1u << tslot)) == 0) {
|
||||
@@ -1700,12 +1700,15 @@ gb_internal bool check_mnemonic(AsmCtx *asm_ctx, CheckerContext *ctx, Entity *tm
|
||||
explicit_writes |= b;
|
||||
continue;
|
||||
}
|
||||
Entity *pe = entity_of_node(operands[i].expr);
|
||||
if (pe != nullptr && pe->kind == Entity_Variable) {
|
||||
i32 di = -1;
|
||||
check_asm_find_group(pe, decls, &di); // reuse existing index finder
|
||||
pinned_param_writes |= asm_decl_resolve_pin_bit(asm_ctx, decls, di);
|
||||
// NOTE(bill): A lane operand `v[idx]` is an IndexExpr with no entity of its own
|
||||
Ast *op_expr = operands[i].expr;
|
||||
if (op_expr != nullptr && op_expr->kind == Ast_IndexExpr) {
|
||||
op_expr = op_expr->IndexExpr.expr;
|
||||
}
|
||||
Entity *pe = entity_of_node(op_expr);
|
||||
if (pe == nullptr || pe->kind != Entity_Variable) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_pseudo &&
|
||||
@@ -2251,7 +2254,11 @@ gb_internal void check_asm_instruction_operand(AsmCtx *asm_ctx, CheckerContext *
|
||||
}
|
||||
|
||||
// base and index must be the same width
|
||||
if (have_base && have_index && base_w != index_w) {
|
||||
// AArch64 register-offset addressing allows a 32-bit index with a 64-bit base
|
||||
// (extended-register form: uxtw/sxtw). Other targets require equal widths.
|
||||
bool ext_index_ok = build_context.metrics.arch == TargetArch_arm64 &&
|
||||
base_w == 64 && index_w == 32;
|
||||
if (have_base && have_index && base_w != index_w && !ext_index_ok) {
|
||||
Ast *at = mem_op->base ? mem_op->base : expr;
|
||||
error(at, "A memory operand's base and index registers must be the same width, got a %d-bit base and a %d-bit index",
|
||||
cast(int)base_w, cast(int)index_w);
|
||||
|
||||
Reference in new issue
Block a user