From ec5e6cbabb3fad5c61dd7106eaaffe6fb1de6b29 Mon Sep 17 00:00:00 2001 From: Rangi Date: Tue, 21 Jul 2026 14:51:58 -0400 Subject: [PATCH] Handle `-Wtruncation` for link-time `jr` values Fixes #2028 --- src/link/patch.cpp | 9 ++++++--- test/link/jr-truncation/a.asm | 2 ++ test/link/jr-truncation/b.asm | 1 + test/link/jr-truncation/out.err | 2 ++ test/link/jr-truncation/ref.out.bin | Bin 0 -> 16384 bytes test/link/jr-truncation/ref.out.sym | 2 ++ test/link/test.sh | 11 +++++++++++ 7 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 test/link/jr-truncation/a.asm create mode 100644 test/link/jr-truncation/b.asm create mode 100644 test/link/jr-truncation/out.err create mode 100644 test/link/jr-truncation/ref.out.bin create mode 100644 test/link/jr-truncation/ref.out.sym diff --git a/src/link/patch.cpp b/src/link/patch.cpp index 8a0e43f7..4efca6a3 100644 --- a/src/link/patch.cpp +++ b/src/link/patch.cpp @@ -585,12 +585,15 @@ static void applyFilePatches(Section §ion, Section &dataSection) { rpnErrorAt(patch, "PC has no value outside of a section"); dataSection.data[offset] = 0; } else { + // A `jr` is *encoded* in ROM as a 1-byte (8-bit) offset, so here `typeSize == 8`, + // but the object's *value* size is a 16-bit absolute address, so we pass 16 here. + checkPatchSize(patch, value, 16); // Offset is relative to the byte *after* the operand // PC as operand to `jr` is lower than reference PC by 2 uint16_t address = patch.pcSection->org + patch.pcOffset + 2; - // The truncation of `value - address` is intentional, since - // a low ROM0 address may `jr` to a high HRAM one. - int16_t jumpOffset = value - address; + // The 16-bit truncation of `value - address` is intentional, since + // a low ROM0 address may `jr` backwards to a high HRAM one. + int16_t jumpOffset = static_cast(value - address); if (jumpOffset < -128 || jumpOffset > 127) { firstErrorAt( diff --git a/test/link/jr-truncation/a.asm b/test/link/jr-truncation/a.asm new file mode 100644 index 00000000..59313abc --- /dev/null +++ b/test/link/jr-truncation/a.asm @@ -0,0 +1,2 @@ +SECTION "jr", ROM0 + jr CONSTANT diff --git a/test/link/jr-truncation/b.asm b/test/link/jr-truncation/b.asm new file mode 100644 index 00000000..be516d73 --- /dev/null +++ b/test/link/jr-truncation/b.asm @@ -0,0 +1 @@ +EXPORT DEF CONSTANT EQU $1234_0078 diff --git a/test/link/jr-truncation/out.err b/test/link/jr-truncation/out.err new file mode 100644 index 00000000..4f2e1af8 --- /dev/null +++ b/test/link/jr-truncation/out.err @@ -0,0 +1,2 @@ +warning: Value $12340078 is not 16-bit [-Wtruncation] + at jr-truncation/a.asm(2) diff --git a/test/link/jr-truncation/ref.out.bin b/test/link/jr-truncation/ref.out.bin new file mode 100644 index 0000000000000000000000000000000000000000..2d59eb9333170054ddfbb44ddf4b6f0306ed2452 GIT binary patch literal 16384 zcmeIuF#!Mo3<99VFzNCe!v`XeKMWW!V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA tz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<`1AKmoy*0FM9w literal 0 HcmV?d00001 diff --git a/test/link/jr-truncation/ref.out.sym b/test/link/jr-truncation/ref.out.sym new file mode 100644 index 00000000..d05a90ab --- /dev/null +++ b/test/link/jr-truncation/ref.out.sym @@ -0,0 +1,2 @@ +; File generated by rgblink +12340078 CONSTANT diff --git a/test/link/test.sh b/test/link/test.sh index cb30efc3..f1f48656 100755 --- a/test/link/test.sh +++ b/test/link/test.sh @@ -201,6 +201,17 @@ tryCmpRom "$test"/ref.out.bin tryDiff "$test"/ref.out.sym "$outtemp2" evaluateTest +test="jr-truncation" +startTest +"$RGBASM" -o "$otemp" "$test"/a.asm +"$RGBASM" -o "$outtemp" "$test"/b.asm +continueTest +rgblinkQuiet -o "$gbtemp" -n "$outtemp2" "$otemp" "$outtemp" 2>"$outtemp3" +tryDiff "$test"/out.err "$outtemp3" +tryCmpRom "$test"/ref.out.bin +tryDiff "$test"/ref.out.sym "$outtemp2" +evaluateTest + test="high-low" startTest "$RGBASM" -o "$otemp" "$test"/a.asm