commit 55f70c4d9fb4303165e20806c82894de002ad621 parent 1929bac14f4b1e285d9593ac5ec3f94e105862ee Author: Ryan Sepassi <rsepassi@gmail.com> Date: Tue, 19 May 2026 23:00:12 -0700 Fix SQLite-driven codegen and Mach-O addends Diffstat:
16 files changed, 257 insertions(+), 3 deletions(-)
diff --git a/lang/c/parse/parse_expr.c b/lang/c/parse/parse_expr.c @@ -3180,7 +3180,18 @@ void parse_assign_expr(Parser* p) { if (compound == BO_IADD || compound == BO_ISUB) { emit_add_or_sub(p, compound); } else { - cg_binop(p->cg, compound); + const Type* lt = cg_top2_type(p->cg); + const Type* rt = cg_top_type(p->cg); + const Type* common = common_fp_type(p, lt, rt); + if (common) { + if (compound == BO_SREM) + perr(p, "operator '%%=' requires integer operands"); + emit_fp_binop(p, compound, common); + } else { + const Type* icommon = cint_common_type(p, lt, rt); + coerce_arith_operands(p, icommon); + cg_binop(p->cg, int_div_rem_binop(compound, icommon)); + } } coerce_top_to_type(p, lhs); if (p->cg_type_sp >= 2) p->cg_type_stack[p->cg_type_sp - 2u] = lhs; diff --git a/src/cg/data.c b/src/cg/data.c @@ -45,6 +45,17 @@ static void api_data_tls_reloc(CfreeCg* g, CfreeCgSym target, int64_t addend, r->addend = addend; } +static void api_data_encode_addend(CfreeCg* g, u8* out, u32 width, + int64_t addend) { + uint64_t v; + if (!g || !out) return; + v = (uint64_t)addend; + for (u32 i = 0; i < width; ++i) { + u32 shift = g->c->target.big_endian ? (width - 1u - i) * 8u : i * 8u; + out[i] = (u8)(v >> shift); + } +} + void cfree_cg_data_begin(CfreeCg* g, CfreeCgSym cg_sym, CfreeCgDataDefAttrs attrs) { Compiler* c; @@ -318,13 +329,13 @@ void api_cg_data_reloc(CfreeCg* g, CfreeCgSym target, int64_t addend, ob = g->obj; rk = api_data_reloc_kind(pcrel, width); if (rk == R_NONE) return; + memset(pad, 0, sizeof pad); + api_data_encode_addend(g, pad, width, addend); if (g->data_tls_collect) { api_data_tls_reloc(g, target, addend, rk); - memset(pad, 0, sizeof pad); api_data_tls_write(g, pad, width); return; } - memset(pad, 0, sizeof pad); obj_write(ob, g->data_sec, pad, width); obj_reloc(ob, g->data_sec, g->data_base + (u32)g->data_size, rk, (ObjSymId)target, addend); diff --git a/src/obj/macho_read.c b/src/obj/macho_read.c @@ -427,6 +427,21 @@ ObjBuilder* read_macho(Compiler* c, const char* name, const u8* data, int use_inplace_addend = 0; if (r_extern) { if (r_symbolnum < nsyms) target = sym_macho_to_obj[r_symbolnum]; + if (!have_pending && r_type == ARM64_RELOC_UNSIGNED) { + u32 rsz = 1u << r_length; + if ((u64)m->fileoff + r_address + rsz > len) + compiler_panic(c, no_loc(), + "read_macho: extern unsigned reloc r_address out " + "of range"); + const u8* pv = data + m->fileoff + r_address; + u64 inplace; + if (r_length == 3) inplace = rd_u64_le(pv); + else if (r_length == 2) inplace = (u64)rd_u32_le(pv); + else if (r_length == 1) inplace = (u64)rd_u16_le(pv); + else inplace = (u64)pv[0]; + inplace_addend_override = (i64)inplace; + use_inplace_addend = 1; + } } else { /* Section-relative reloc — clang emits these for compact unwind, * EH frame, and DWARF debug info. r_symbolnum is the 1-based diff --git a/test/link/cases/39_macho_external_ptr_addend/a.c b/test/link/cases/39_macho_external_ptr_addend/a.c @@ -0,0 +1,11 @@ +const unsigned char table[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, +}; + +const unsigned char *p = &table[6 - 2]; + +int test_main(void) { + if (p[0] != 4) return 1; + if (p[2] != 6) return 2; + return 42; +} diff --git a/test/link/cases/39_macho_external_ptr_addend/expected b/test/link/cases/39_macho_external_ptr_addend/expected @@ -0,0 +1 @@ +42 diff --git a/test/link/cases/39_macho_external_ptr_addend/targets b/test/link/cases/39_macho_external_ptr_addend/targets @@ -0,0 +1 @@ +aa64-macho diff --git a/test/parse/cases/6_5_02_pointer_index_offset_table.c b/test/parse/cases/6_5_02_pointer_index_offset_table.c @@ -0,0 +1,22 @@ +int test_main(void) { + unsigned char table[274] = {0}; + table[256] = 1; + table[259] = 1; + table[260] = 1; + table[263] = 1; + table[265] = 1; + table[267] = 1; + table[268] = 1; + table[270] = 1; + table[273] = 1; + const unsigned char *lt = &table[256 - 53]; + const unsigned char *eq = &table[256 + 6 - 53]; + const unsigned char *gt = &table[256 + 12 - 53]; + if (lt[53] != 1) return 1; + if (eq[53] != 0) return 2; + if (gt[53] != 1) return 3; + if (lt[54] != 0) return 4; + if (eq[54] != 1) return 5; + if (gt[54] != 0) return 6; + return 42; +} diff --git a/test/parse/cases/6_5_02_pointer_index_offset_table.expected b/test/parse/cases/6_5_02_pointer_index_offset_table.expected @@ -0,0 +1 @@ +42 diff --git a/test/parse/cases/6_5_16_compound_fp_mul.c b/test/parse/cases/6_5_16_compound_fp_mul.c @@ -0,0 +1,7 @@ +int test_main(void) { + double x = 14.75; + double y = 100.0; + x *= y; + if (x < 1474.5 || x > 1475.5) return 1; + return 42; +} diff --git a/test/parse/cases/6_5_16_compound_fp_mul.expected b/test/parse/cases/6_5_16_compound_fp_mul.expected @@ -0,0 +1 @@ +42 diff --git a/test/parse/cases/6_5_63_ptr_post_inc_scale.c b/test/parse/cases/6_5_63_ptr_post_inc_scale.c @@ -0,0 +1,9 @@ +int test_main(void) { + long a[3] = {11, 22, 33}; + long *p = a; + long *old = p++; + if (old != a) return 1; + if (p != a + 1) return 2; + if (*p != 22) return 3; + return 42; +} diff --git a/test/parse/cases/6_5_63_ptr_post_inc_scale.expected b/test/parse/cases/6_5_63_ptr_post_inc_scale.expected @@ -0,0 +1 @@ +42 diff --git a/test/parse/cases/6_7_9_34_static_ptr_array_addend.c b/test/parse/cases/6_7_9_34_static_ptr_array_addend.c @@ -0,0 +1,11 @@ +const unsigned char table[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, +}; + +const unsigned char *p = &table[6 - 2]; + +int test_main(void) { + if (p[0] != 4) return 1; + if (p[2] != 6) return 2; + return 42; +} diff --git a/test/parse/cases/6_7_9_34_static_ptr_array_addend.expected b/test/parse/cases/6_7_9_34_static_ptr_array_addend.expected @@ -0,0 +1 @@ +42 diff --git a/test/parse/cases/6_8_26_switch_many_cases.c b/test/parse/cases/6_8_26_switch_many_cases.c @@ -0,0 +1,150 @@ +static int pick(unsigned short x) { + switch (x) { + case 0: return 0; + case 1: return 1; + case 2: return 2; + case 3: return 3; + case 4: return 4; + case 5: return 5; + case 6: return 6; + case 7: return 7; + case 8: return 8; + case 9: return 9; + case 10: return 10; + case 11: return 11; + case 12: return 12; + case 13: return 13; + case 14: return 14; + case 15: return 15; + case 16: return 16; + case 17: return 17; + case 18: return 18; + case 19: return 19; + case 20: return 20; + case 21: return 21; + case 22: return 22; + case 23: return 23; + case 24: return 24; + case 25: return 25; + case 26: return 26; + case 27: return 27; + case 28: return 28; + case 29: return 29; + case 30: return 30; + case 31: return 31; + case 32: return 32; + case 33: return 33; + case 34: return 34; + case 35: return 35; + case 36: return 36; + case 37: return 37; + case 38: return 38; + case 39: return 39; + case 40: return 40; + case 41: return 41; + case 42: return 42; + case 43: return 43; + case 44: return 44; + case 45: return 45; + case 46: return 46; + case 47: return 47; + case 48: return 48; + case 49: return 49; + case 50: return 50; + case 51: return 51; + case 52: return 52; + case 53: return 53; + case 54: return 54; + case 55: return 55; + case 56: return 56; + case 57: return 57; + case 58: return 58; + case 59: return 59; + case 60: return 60; + case 61: return 61; + case 62: return 62; + case 63: return 63; + case 64: return 64; + case 65: return 65; + case 66: return 66; + case 67: return 67; + case 68: return 68; + case 69: return 69; + case 70: return 70; + case 71: return 71; + case 72: return 72; + case 73: return 73; + case 74: return 74; + case 75: return 75; + case 76: return 76; + case 77: return 77; + case 78: return 78; + case 79: return 79; + case 80: return 80; + case 81: return 81; + case 82: return 82; + case 83: return 83; + case 84: return 84; + case 85: return 85; + case 86: return 86; + case 87: return 87; + case 88: return 88; + case 89: return 89; + case 90: return 90; + case 91: return 91; + case 92: return 92; + case 93: return 93; + case 94: return 94; + case 95: return 95; + case 96: return 96; + case 97: return 97; + case 98: return 98; + case 99: return 99; + case 100: return 100; + case 101: return 101; + case 102: return 102; + case 103: return 103; + case 104: return 104; + case 105: return 105; + case 106: return 106; + case 107: return 107; + case 108: return 108; + case 109: return 109; + case 110: return 110; + case 111: return 111; + case 112: return 112; + case 113: return 113; + case 114: return 114; + case 115: return 115; + case 116: return 116; + case 117: return 117; + case 118: return 118; + case 119: return 119; + case 120: return 120; + case 121: return 121; + case 122: return 122; + case 123: return 123; + case 124: return 124; + case 125: return 125; + case 126: return 126; + case 127: return 127; + case 128: return 128; + case 129: return 129; + case 130: return 130; + case 131: return 131; + case 132: return 132; + case 133: return 133; + case 134: return 134; + case 135: return 135; + case 136: return 136; + case 137: return 137; + case 138: return 138; + case 139: return 139; + case 140: return 140; + default: return -1; + } +} + +int test_main(void) { + return pick(5) + pick(95) + pick(123) + pick(140) + pick(500) + 1; +} diff --git a/test/parse/cases/6_8_26_switch_many_cases.expected b/test/parse/cases/6_8_26_switch_many_cases.expected @@ -0,0 +1 @@ +107