Reject a non-constant argument to an template's immediate

This commit is contained in:
kalsprite
2026-08-23 22:22:15 -07:00
parent 965970af71
commit 6088dc8420
5 changed files with 51 additions and 2 deletions

4
.gitignore vendored
View File

@@ -277,6 +277,8 @@ odin
*.bin
demo.bin
libLLVM*.so*
*.a
*.o
# core:rexcode commits its generated encode/decode tables: each arch's tablegen
# emits human-readable Odin, serialized to tables/*.bin, which the library
@@ -321,5 +323,3 @@ build/
cmake-build*/
CMakeLists.txt
sandbox/
vendor/box3d/lib/box3d_wasm.o

View File

@@ -6996,6 +6996,18 @@ gb_internal CallArgumentError check_call_arguments_internal(CheckerContext *c, A
}
}
// an `asm` template's `$` parameter is encoded as an immediate, so only a constant can reach it
if (e && e->kind == Entity_Variable && (e->flags & EntityFlag_PolyConst)) {
if (o->mode != Addressing_Constant) {
if (show_error) {
gbString str = expr_to_string(o->expr);
error(o->expr, "Expected a constant value for the '$' immediate '%.*s', got %s", LIT(e->token.string), str);
gb_string_free(str);
}
err = CallArgumentError_NoneConstantParameter;
}
}
if (e && e->kind == Entity_Constant && is_type_proc(e->type)) {
bool ok = false;
if (o->mode == Addressing_Constant) {

View File

@@ -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_immediate_constant.odin -no-entry-point %COMMON% 2>&1 | find /c "Error:" | findstr /x "4" || 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

View File

@@ -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_immediate_constant.odin -no-entry-point $COMMON_CHECK 2>&1 >/dev/null | grep -c "Error:") -eq 4 ]]; 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

View File

@@ -0,0 +1,26 @@
#+build amd64
// An `asm` template's `$` parameter is encoded as an immediate, but a runtime value passed to
// one was accepted by the checker and only died in the backend, with an unlocated LLVM error.
package test_issues
shl_imm :: asm(a: i32, $n: i32) -> (r: i32) { mov r, a; shl r, n; }
opaque :: proc() -> i32 {
return 5
}
K :: 3
bad :: proc(v: i32) {
x: i32 = 2
_ = shl_imm(1, x)
_ = shl_imm(1, v)
_ = shl_imm(1, opaque())
_ = shl_imm(1, x + 1)
}
good :: proc(a: i32) {
_ = shl_imm(a, 2)
_ = shl_imm(a, K)
_ = shl_imm(a, 1 + 1)
}