mirror of
https://github.com/odin-lang/Odin.git
synced 2026-08-25 06:21:35 +00:00
Diagnose in an asm template instead of aborting with SIGILL
This commit is contained in:
@@ -825,6 +825,11 @@ gb_internal bool check_register(AsmCtx *asm_ctx, Operand *operand, AstAsmRegiste
|
||||
|
||||
u16 width_in_bits = asm_ctx->reg_size(r);
|
||||
switch (width_in_bits) {
|
||||
case 0:
|
||||
// a register whose class the width table cannot describe, `%rip` being the only one.
|
||||
// anchored on the name rather than the operand, which clobbers and pins do not have
|
||||
error(asm_reg->name, "Asm registers with no operand width are not supported: %%%.*s", LIT(name));
|
||||
return false;
|
||||
case 8:
|
||||
operand->type = t_u8;
|
||||
break;
|
||||
@@ -838,7 +843,7 @@ gb_internal bool check_register(AsmCtx *asm_ctx, Operand *operand, AstAsmRegiste
|
||||
operand->type = t_u64;
|
||||
break;
|
||||
case 80:
|
||||
error(operand->expr, "80-bit width asm registers are not supported");
|
||||
error(asm_reg->name, "80-bit width asm registers are not supported");
|
||||
return false;
|
||||
case 128:
|
||||
operand->type = alloc_type_simd_vector(4, t_f32);
|
||||
|
||||
@@ -46,6 +46,7 @@ set COMMON=-define:ODIN_TEST_FANCY=false -file -vet -strict-style -ignore-unused
|
||||
..\..\..\odin check ..\test_issue_ellipsis_type_call.odin -no-entry-point %COMMON% 2>&1 | find /c "Error:" | findstr /x "10" || exit /b
|
||||
..\..\..\odin check ..\test_issue_foreign_redeclaration.odin -no-entry-point %COMMON% || exit /b
|
||||
..\..\..\odin check ..\test_issue_foreign_redeclaration_mismatch.odin -no-entry-point %COMMON% 2>&1 | find /c "Error:" | findstr /x "1" || exit /b
|
||||
..\..\..\odin check ..\test_issue_asm_rip_register.odin -no-entry-point %COMMON% 2>&1 | find /c "Error:" | findstr /x "6" || exit /b
|
||||
..\..\..\odin build ..\test_issue_7037.odin %COMMON% -o:none || exit /b
|
||||
..\..\..\odin build ..\test_issue_7188.odin %COMMON% || exit /b
|
||||
clang -c ..\test_issue_sysv_abi.c -o test_issue_sysv_abi_c.o || exit /b
|
||||
|
||||
@@ -110,6 +110,16 @@ else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# `asm` templates are amd64-only, so this file is empty on every other architecture
|
||||
if [[ "$(uname -m)" == "x86_64" || "$(uname -m)" == "amd64" ]]; then
|
||||
if [[ $($ODIN check ../test_issue_asm_rip_register.odin -no-entry-point $COMMON_CHECK 2>&1 >/dev/null | grep -c "Error:") -eq 6 ]]; then
|
||||
echo "SUCCESSFUL 1/1"
|
||||
else
|
||||
echo "SUCCESSFUL 0/1"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $($ODIN build ../test_issue_7108.odin $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 2 ]]; then
|
||||
echo "SUCCESSFUL 1/1"
|
||||
else
|
||||
|
||||
15
tests/issues/test_issue_asm_rip_register.odin
Normal file
15
tests/issues/test_issue_asm_rip_register.odin
Normal file
@@ -0,0 +1,15 @@
|
||||
#+build amd64
|
||||
// `%rip` is in the amd64 register table, but its class carries no width, so the checker's width
|
||||
// switch reached its `GB_PANIC` default arm and aborted with SIGILL instead of diagnosing. Every
|
||||
// position that can name a register reached it, including `[%rip + disp]`.
|
||||
package test_issues
|
||||
|
||||
rip_src :: asm() -> (v: u64) { mov v, %rip; }
|
||||
rip_dst :: asm(x: u64) { mov %rip, x; }
|
||||
rip_mem :: asm() { mov %rax, [%rip + 8]; }
|
||||
rip_clob :: asm() [#clobber %rip] { nop; }
|
||||
rip_in :: asm(x: u64) [x = %rip] { nop; }
|
||||
rip_out :: asm() -> (r: u64) [r = %rip] { nop; }
|
||||
|
||||
// the nearest special-purpose register that does carry a class has to keep checking cleanly
|
||||
rsp_ok :: asm() -> (v: u64) { mov v, %rsp; }
|
||||
Reference in New Issue
Block a user