Unified · Split
| @@ -38,7 +38,7 @@ · 37 unmodified lines | ||
| 38 | 38 | |
| 39 | 39 | #define MAX_ALIGN 16 |
| 40 | 40 | |
| 41 | −#ifndef TCC_TARGET_MACHO | |
| 41 | +#if !defined(TCC_TARGET_MACHO) && !defined(TCC_TARGET_PE) | |
| 42 | 42 | #define CHAR_IS_UNSIGNED |
| 43 | 43 | #endif |
| 44 | 44 | |
| @@ -79,7 +79,11 @@ ST_DATA const int reg_classes[NB_REGS] = { · 34 unmodified lines | ||
| 79 | 79 | RC_INT | RC_R(15), |
| 80 | 80 | RC_INT | RC_R(16), |
| 81 | 81 | RC_INT | RC_R(17), |
| 82 | +#ifdef TCC_TARGET_PE | |
| 83 | + RC_R(18), /* (x18 reserved on Windows) */ | |
| 84 | +#else | |
| 82 | 85 | RC_INT | RC_R(18), |
| 86 | +#endif | |
| 83 | 87 | RC_R30, // not in RC_INT as we make special use of x30 |
| 84 | 88 | RC_FLOAT | RC_F(0), |
| 85 | 89 | RC_FLOAT | RC_F(1), |
| @@ -468,10 +472,18 @@ static void arm64_strv(int sz_, int dst, int bas, uint64_t off) · 382 unmodified lines | ||
| 468 | 472 | |
| 469 | 473 | static void arm64_sym(int r, Sym *sym, unsigned long addend) |
| 470 | 474 | { |
| 475 | +#ifdef TCC_TARGET_PE | |
| 476 | + /* PE links symbol addresses directly; there is no ELF-style GOT here. */ | |
| 477 | + greloca(cur_text_section, sym, ind, R_AARCH64_ADR_PREL_PG_HI21, 0); | |
| 478 | + o(ARM64_ADRP | r); // adrp xr, #sym | |
| 479 | + greloca(cur_text_section, sym, ind, R_AARCH64_ADD_ABS_LO12_NC, 0); | |
| 480 | + o(ARM64_ADD_IMM | ARM64_SF(1) | ARM64_RN(r) | r); // add xr, xr, #sym | |
| 481 | +#else | |
| 471 | 482 | greloca(cur_text_section, sym, ind, R_AARCH64_ADR_GOT_PAGE, 0); |
| 472 | 483 | o(0x90000000 | r); // adrp xr, #sym |
| 473 | 484 | greloca(cur_text_section, sym, ind, R_AARCH64_LD64_GOT_LO12_NC, 0); |
| 474 | 485 | o(0xf9400000 | r | (r << 5)); // ld xr,[xr, #sym] |
| 486 | +#endif | |
| 475 | 487 | if (addend) { |
| 476 | 488 | // add xr, xr, #addend |
| 477 | 489 | if (addend & 0xffful) |
| @@ -820,6 +832,7 @@ static unsigned long arm64_pcs_aux(int variadic, int n, CType **type, unsigned l · 342 unmodified lines | ||
| 820 | 832 | |
| 821 | 833 | for (i = 0; i < n; i++) { |
| 822 | 834 | int hfa = arm64_hfa(type[i], 0); |
| 835 | + int win_vararg_float = 0; | |
| 823 | 836 | int size, align; |
| 824 | 837 | |
| 825 | 838 | if ((type[i]->t & VT_ARRAY) || |
| @@ -833,6 +846,16 @@ static unsigned long arm64_pcs_aux(int variadic, int n, CType **type, unsigned l · 7 unmodified lines | ||
| 833 | 846 | nx = 8; |
| 834 | 847 | nv = 8; |
| 835 | 848 | } |
| 849 | + | |
| 850 | +#elif defined(TCC_TARGET_PE) | |
| 851 | + if (variadic && i >= variadic && (hfa || is_float(type[i]->t))) { | |
| 852 | + hfa = 0; | |
| 853 | + if (is_float(type[i]->t)) { | |
| 854 | + win_vararg_float = 1; | |
| 855 | + size = 8; | |
| 856 | + align = 8; | |
| 857 | + } | |
| 858 | + } | |
| 836 | 859 | #endif |
| 837 | 860 | if (hfa) |
| 838 | 861 | // B.2 |
| @@ -853,7 +876,7 @@ static unsigned long arm64_pcs_aux(int variadic, int n, CType **type, unsigned l · 14 unmodified lines | ||
| 853 | 876 | size = (size + 7) & ~7; |
| 854 | 877 | |
| 855 | 878 | // C.1 |
| 856 | − if (is_float(type[i]->t) && nv < 8) { | |
| 879 | + if (!win_vararg_float && is_float(type[i]->t) && nv < 8) { | |
| 857 | 880 | a[i] = 16 + (nv++ << 1); |
| 858 | 881 | continue; |
| 859 | 882 | } |
| @@ -882,7 +905,7 @@ static unsigned long arm64_pcs_aux(int variadic, int n, CType **type, unsigned l · 22 unmodified lines | ||
| 882 | 905 | size = 8; |
| 883 | 906 | |
| 884 | 907 | // C.6 |
| 885 | − if (hfa || is_float(type[i]->t)) { | |
| 908 | + if (!win_vararg_float && (hfa || is_float(type[i]->t))) { | |
| 886 | 909 | a[i] = ns; |
| 887 | 910 | ns += size; |
| 888 | 911 | continue; |
| @@ -1044,7 +1067,11 @@ ST_FUNC void gfunc_call(int nb_args) · 155 unmodified lines | ||
| 1044 | 1067 | for (i = 0; i < nb_args; i++) |
| 1045 | 1068 | t[nb_args - i] = &vtop[-i].type; |
| 1046 | 1069 | |
| 1047 | − stack = arm64_pcs(variadic ? var_nb_arg : 0, nb_args, t, a); | |
| 1070 | + stack = arm64_pcs( | |
| 1071 | +#ifdef TCC_TARGET_PE | |
| 1072 | + old_style ? -1 : | |
| 1073 | +#endif | |
| 1074 | + var_nb_arg, nb_args, t, a); | |
| 1048 | 1075 | |
| 1049 | 1076 | // Allocate space for structs replaced by pointer: |
| 1050 | 1077 | for (i = nb_args; i; i--) |
| @@ -1214,11 +1241,21 @@ static int arm64_func_sub_sp_offset; · 163 unmodified lines | ||
| 1214 | 1241 | static unsigned arm64_func_start_offset; |
| 1215 | 1242 | #define ARM64_FUNC_STACK_SETUP_SLOTS 6 |
| 1216 | 1243 | |
| 1244 | +#ifdef TCC_TARGET_PE | |
| 1245 | +static unsigned long arm64_pe_param_off(unsigned long a) | |
| 1246 | +{ | |
| 1247 | + return a < 16 ? 160 + a / 2 * 8 : | |
| 1248 | + a < 32 ? 16 + (a - 16) / 2 * 16 : | |
| 1249 | + 224 + ((a - 32) >> 1 << 1); | |
| 1250 | +} | |
| 1251 | +#endif | |
| 1252 | + | |
| 1217 | 1253 | ST_FUNC void gfunc_prolog(Sym *func_sym) |
| 1218 | 1254 | { |
| 1219 | 1255 | CType *func_type = &func_sym->type; |
| 1220 | 1256 | int n = 0; |
| 1221 | 1257 | int i = 0; |
| 1258 | + int pcs_n; | |
| 1222 | 1259 | Sym *sym; |
| 1223 | 1260 | CType **t; |
| 1224 | 1261 | unsigned long *a; |
| @@ -1227,18 +1264,34 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 2 unmodified lines | ||
| 1227 | 1264 | int last_float = 0; |
| 1228 | 1265 | int variadic = func_sym->type.ref->f.func_type == FUNC_ELLIPSIS; |
| 1229 | 1266 | int var_nb_arg = n_func_args(&func_sym->type); |
| 1267 | + int c; | |
| 1230 | 1268 | |
| 1231 | 1269 | func_vc = 144; // offset of where x8 is stored |
| 1232 | 1270 | |
| 1233 | 1271 | for (sym = func_type->ref; sym; sym = sym->next) |
| 1234 | 1272 | ++n; |
| 1235 | − t = n ? tcc_malloc(n * sizeof(*t)) : NULL; | |
| 1236 | − a = n ? tcc_malloc(n * sizeof(*a)) : NULL; | |
| 1273 | + pcs_n = n - 1; | |
| 1274 | + c = n + variadic; | |
| 1275 | + t = tcc_malloc(c * sizeof(*t)); | |
| 1276 | + a = tcc_malloc(c * sizeof(*a)); | |
| 1237 | 1277 | |
| 1238 | 1278 | for (sym = func_type->ref; sym; sym = sym->next) |
| 1239 | 1279 | t[i++] = &sym->type; |
| 1240 | 1280 | |
| 1241 | − arm64_func_va_list_stack = arm64_pcs(variadic ? var_nb_arg : 0, n - 1, t, a); | |
| 1281 | +#ifdef TCC_TARGET_PE | |
| 1282 | + if (variadic) { | |
| 1283 | + t[i++] = &int_type; | |
| 1284 | + ++pcs_n; | |
| 1285 | + } | |
| 1286 | +#endif | |
| 1287 | + | |
| 1288 | + arm64_func_va_list_stack = arm64_pcs(variadic ? var_nb_arg : 0, | |
| 1289 | + pcs_n, t, a); | |
| 1290 | + | |
| 1291 | +#ifdef TCC_TARGET_PE | |
| 1292 | + if (variadic) | |
| 1293 | + arm64_func_va_list_stack = arm64_pe_param_off(a[n]); | |
| 1294 | +#endif | |
| 1242 | 1295 | |
| 1243 | 1296 | #if !defined(TCC_TARGET_MACHO) |
| 1244 | 1297 | if (variadic) { |
| @@ -1333,6 +1386,14 @@ ST_FUNC void gen_va_start(void) · 88 unmodified lines | ||
| 1333 | 1386 | gaddrof(); |
| 1334 | 1387 | r = intr(gv(RC_INT)); |
| 1335 | 1388 | |
| 1389 | +#ifdef TCC_TARGET_PE | |
| 1390 | + if (arm64_func_va_list_stack) { | |
| 1391 | + arm64_movimm(30, arm64_func_va_list_stack); | |
| 1392 | + o(0x8b1e03be); // add x30,x29,x30 | |
| 1393 | + } else | |
| 1394 | + o(0x910283be); // add x30,x29,#160 | |
| 1395 | + o(0xf900001e | r << 5); // str x30,[x(r)] | |
| 1396 | +#else | |
| 1336 | 1397 | if (arm64_func_va_list_stack) { |
| 1337 | 1398 | //xx could use add (immediate) here |
| 1338 | 1399 | arm64_movimm(30, arm64_func_va_list_stack + 224); |
| @@ -1359,6 +1420,7 @@ ST_FUNC void gen_va_start(void) · 20 unmodified lines | ||
| 1359 | 1420 | |
| 1360 | 1421 | arm64_movimm(30, arm64_func_va_list_vr_offs); |
| 1361 | 1422 | o(0xb9001c1e | r << 5); // str w30,[x(r),#28] |
| 1423 | +#endif | |
| 1362 | 1424 | #endif |
| 1363 | 1425 | |
| 1364 | 1426 | --vtop; |
| @@ -1367,14 +1429,45 @@ ST_FUNC void gen_va_start(void) · 2 unmodified lines | ||
| 1367 | 1429 | ST_FUNC void gen_va_arg(CType *t) |
| 1368 | 1430 | { |
| 1369 | 1431 | int align, size = type_size(t, &align); |
| 1370 | − unsigned fsize, hfa = arm64_hfa(t, &fsize); | |
| 1371 | 1432 | uint32_t r0, r1; |
| 1372 | 1433 | |
| 1373 | − if (is_float(t->t)) { | |
| 1374 | − hfa = 1; | |
| 1375 | − fsize = size; | |
| 1434 | +#ifdef TCC_TARGET_PE | |
| 1435 | + int indirect = 0, slot = (size + 7) & -8; | |
| 1436 | + | |
| 1437 | + if (size > 16) | |
| 1438 | + indirect = 1, slot = 8; | |
| 1439 | + | |
| 1440 | + gaddrof(); | |
| 1441 | + r0 = intr(gv(RC_INT)); | |
| 1442 | + r1 = get_reg(RC_INT); | |
| 1443 | + vtop[0].r = r1 | VT_LVAL; | |
| 1444 | + r1 = intr(r1); | |
| 1445 | + | |
| 1446 | + o(0xF9400000 | r0 << 5 | r1); // ldr x(r1),[x(r0)] // ap | |
| 1447 | + if (slot) { | |
| 1448 | + if (slot == 16) { | |
| 1449 | + o(0x910363be); // add x30,x29,#216 | |
| 1450 | + o(0xeb1e003f | r1 << 5); // cmp x(r1),x30 | |
| 1451 | + o(0x54000041); // b.ne .+8 | |
| 1452 | + o(0x910383a0 | r1 | 29 << 5); // add x(r1),x29,#224 | |
| 1453 | + } | |
| 1454 | + if (align == 16) { | |
| 1455 | + o(0x91003c00 | r1 | r1 << 5); // add x(r1),x(r1),#15 | |
| 1456 | + o(0x927cec00 | r1 | r1 << 5); // and x(r1),x(r1),#-16 | |
| 1457 | + } | |
| 1458 | + o(0x9100001e | r1 << 5 | slot << 10); // add x30,x(r1),#(slot) | |
| 1459 | + o(0xf900001e | r0 << 5); // str x30,[x(r0)] // ap += slot | |
| 1376 | 1460 | } |
| 1377 | 1461 | |
| 1462 | + if (indirect) | |
| 1463 | + o(0xF9400000 | ARM64_RN(r1) | r1); // ldr x(r1),[x(r1)] | |
| 1464 | + | |
| 1465 | +#else /* !PE */ | |
| 1466 | + unsigned fsize = size, hfa = 1; | |
| 1467 | + | |
| 1468 | + if (!is_float(t->t)) | |
| 1469 | + hfa = arm64_hfa(t, &fsize); | |
| 1470 | + | |
| 1378 | 1471 | gaddrof(); |
| 1379 | 1472 | r0 = intr(gv(RC_INT)); |
| 1380 | 1473 | r1 = get_reg(RC_INT); |
| @@ -1451,6 +1544,7 @@ ST_FUNC void gen_va_arg(CType *t) · 70 unmodified lines | ||
| 1451 | 1544 | write32le(cur_text_section->data + b2, 0x14000000 | (ind - b2) >> 2); |
| 1452 | 1545 | #endif |
| 1453 | 1546 | } |
| 1547 | +#endif /* not pe */ | |
| 1454 | 1548 | } |
| 1455 | 1549 | |
| 1456 | 1550 | ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, |
| @@ -1530,6 +1624,10 @@ ST_FUNC void gfunc_epilog(void) · 73 unmodified lines | ||
| 1530 | 1624 | o(0xa8ce7bfd); // ldp x29,x30,[sp],#224 |
| 1531 | 1625 | |
| 1532 | 1626 | o(0xd65f03c0); // ret |
| 1627 | + | |
| 1628 | +#ifdef TCC_TARGET_PE | |
| 1629 | + pe_add_unwind_data(arm64_func_start_offset, ind, -loc); | |
| 1630 | +#endif | |
| 1533 | 1631 | } |
| 1534 | 1632 | |
| 1535 | 1633 | ST_FUNC void gen_fill_nops(int bytes) |