which requires being able to emit an arbitrary number of NOP instructions, which is also implemented here. For x86 we could emit other sequences but these are the easiest.
Unified · Split
| @@ -1410,6 +1410,16 @@ void gfunc_epilog(void) · 1409 unmodified lines | ||
| 1410 | 1410 | } |
| 1411 | 1411 | } |
| 1412 | 1412 | |
| 1413 | +ST_FUNC void gen_fill_nops(int bytes) | |
| 1414 | +{ | |
| 1415 | + if ((bytes & 3)) | |
| 1416 | + tcc_error("alignment of code section not multiple of 4"); | |
| 1417 | + while (bytes > 0) { | |
| 1418 | + o(0xE1A00000); | |
| 1419 | + bytes -= 4; | |
| 1420 | + } | |
| 1421 | +} | |
| 1422 | + | |
| 1413 | 1423 | /* generate a jump to a label */ |
| 1414 | 1424 | int gjmp(int t) |
| 1415 | 1425 | { |
| @@ -1276,6 +1276,16 @@ ST_FUNC void gfunc_epilog(void) · 1275 unmodified lines | ||
| 1276 | 1276 | o(0xd65f03c0); // ret |
| 1277 | 1277 | } |
| 1278 | 1278 | |
| 1279 | +ST_FUNC void gen_fill_nops(int bytes) | |
| 1280 | +{ | |
| 1281 | + if ((bytes & 3)) | |
| 1282 | + tcc_error("alignment of code section not multiple of 4"); | |
| 1283 | + while (bytes > 0) { | |
| 1284 | + o(0xd503201f); // nop | |
| 1285 | + bytes -= 4; | |
| 1286 | + } | |
| 1287 | +} | |
| 1288 | + | |
| 1279 | 1289 | // Generate forward branch to label: |
| 1280 | 1290 | ST_FUNC int gjmp(int t) |
| 1281 | 1291 | { |
| @@ -2035,6 +2035,16 @@ void gfunc_epilog(void) · 2034 unmodified lines | ||
| 2035 | 2035 | } |
| 2036 | 2036 | } |
| 2037 | 2037 | |
| 2038 | +ST_FUNC void gen_fill_nops(int bytes) | |
| 2039 | +{ | |
| 2040 | + if ((bytes & 3)) | |
| 2041 | + tcc_error("alignment of code section not multiple of 4"); | |
| 2042 | + while (bytes > 0) { | |
| 2043 | + C67_NOP(4); | |
| 2044 | + bytes -= 4; | |
| 2045 | + } | |
| 2046 | +} | |
| 2047 | + | |
| 2038 | 2048 | /* generate a jump to a label */ |
| 2039 | 2049 | int gjmp(int t) |
| 2040 | 2050 | { |
| @@ -157,6 +157,12 @@ static int oad(int c, int s) · 156 unmodified lines | ||
| 157 | 157 | return t; |
| 158 | 158 | } |
| 159 | 159 | |
| 160 | +ST_FUNC void gen_fill_nops(int bytes) | |
| 161 | +{ | |
| 162 | + while (bytes--) | |
| 163 | + g(0x90); | |
| 164 | +} | |
| 165 | + | |
| 160 | 166 | /* generate jmp to a label */ |
| 161 | 167 | #define gjmp2(instr,lbl) oad(instr,lbl) |
| 162 | 168 | |
| @@ -1475,6 +1475,7 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *align, int *reg · 1474 unmodified lines | ||
| 1475 | 1475 | ST_FUNC void gfunc_call(int nb_args); |
| 1476 | 1476 | ST_FUNC void gfunc_prolog(CType *func_type); |
| 1477 | 1477 | ST_FUNC void gfunc_epilog(void); |
| 1478 | +ST_FUNC void gen_fill_nops(int); | |
| 1478 | 1479 | ST_FUNC int gjmp(int t); |
| 1479 | 1480 | ST_FUNC void gjmp_addr(int a); |
| 1480 | 1481 | ST_FUNC int gtst(int inv, int t); |
| @@ -7088,6 +7088,13 @@ static void gen_function(Sym *sym) · 7087 unmodified lines | ||
| 7088 | 7088 | { |
| 7089 | 7089 | nocode_wanted = 0; |
| 7090 | 7090 | ind = cur_text_section->data_offset; |
| 7091 | + if (sym->a.aligned) { | |
| 7092 | + size_t newoff = section_add(cur_text_section, 0, | |
| 7093 | + 1 << (sym->a.aligned - 1)); | |
| 7094 | + if (ind != newoff) | |
| 7095 | + gen_fill_nops(newoff - ind); | |
| 7096 | + ind = newoff; | |
| 7097 | + } | |
| 7091 | 7098 | /* NOTE: we patch the symbol size later */ |
| 7092 | 7099 | put_extern_sym(sym, cur_text_section, ind, 0); |
| 7093 | 7100 | funcname = get_tok_str(sym->v, NULL); |
| @@ -2270,6 +2270,8 @@ int fib(int n) · 2269 unmodified lines | ||
| 2270 | 2270 | return fib(n-1) + fib(n-2); |
| 2271 | 2271 | } |
| 2272 | 2272 | |
| 2273 | +void __attribute__((aligned(16))) aligned_function(int i) {} | |
| 2274 | + | |
| 2273 | 2275 | void funcptr_test() |
| 2274 | 2276 | { |
| 2275 | 2277 | void (*func)(int); |
| @@ -2300,6 +2302,10 @@ void funcptr_test() · 24 unmodified lines | ||
| 2300 | 2302 | func(42); |
| 2301 | 2303 | (func + diff)(42); |
| 2302 | 2304 | (num + a)(43); |
| 2305 | + | |
| 2306 | + /* Check that we can align functions */ | |
| 2307 | + func = aligned_function; | |
| 2308 | + printf("aligned_function (should be zero): %d\n", ((int)func) & 15); | |
| 2303 | 2309 | } |
| 2304 | 2310 | |
| 2305 | 2311 | void lloptest(long long a, long long b) |
| @@ -1639,6 +1639,12 @@ void gfunc_epilog(void) · 1638 unmodified lines | ||
| 1639 | 1639 | |
| 1640 | 1640 | #endif /* not PE */ |
| 1641 | 1641 | |
| 1642 | +ST_FUNC void gen_fill_nops(int bytes) | |
| 1643 | +{ | |
| 1644 | + while (bytes--) | |
| 1645 | + g(0x90); | |
| 1646 | +} | |
| 1647 | + | |
| 1642 | 1648 | /* generate a jump to a label */ |
| 1643 | 1649 | int gjmp(int t) |
| 1644 | 1650 | { |