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 | /* generate a jump to a label */ | 1423 | /* generate a jump to a label */ |
| 1414 | int gjmp(int t) | 1424 | int gjmp(int t) |
| 1415 | { | 1425 | { |
| @@ -1276,6 +1276,16 @@ ST_FUNC void gfunc_epilog(void) · 1275 unmodified lines | |||
| 1276 | o(0xd65f03c0); // ret | 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 | // Generate forward branch to label: | 1289 | // Generate forward branch to label: |
| 1280 | ST_FUNC int gjmp(int t) | 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 | /* generate a jump to a label */ | 2048 | /* generate a jump to a label */ |
| 2039 | int gjmp(int t) | 2049 | int gjmp(int t) |
| 2040 | { | 2050 | { |
| @@ -157,6 +157,12 @@ static int oad(int c, int s) · 156 unmodified lines | |||
| 157 | return t; | 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 | /* generate jmp to a label */ | 166 | /* generate jmp to a label */ |
| 161 | #define gjmp2(instr,lbl) oad(instr,lbl) | 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 | ST_FUNC void gfunc_call(int nb_args); | 1475 | ST_FUNC void gfunc_call(int nb_args); |
| 1476 | ST_FUNC void gfunc_prolog(CType *func_type); | 1476 | ST_FUNC void gfunc_prolog(CType *func_type); |
| 1477 | ST_FUNC void gfunc_epilog(void); | 1477 | ST_FUNC void gfunc_epilog(void); |
| 1478 | ST_FUNC void gen_fill_nops(int); | ||
| 1478 | ST_FUNC int gjmp(int t); | 1479 | ST_FUNC int gjmp(int t); |
| 1479 | ST_FUNC void gjmp_addr(int a); | 1480 | ST_FUNC void gjmp_addr(int a); |
| 1480 | ST_FUNC int gtst(int inv, int t); | 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 | nocode_wanted = 0; | 7089 | nocode_wanted = 0; |
| 7090 | ind = cur_text_section->data_offset; | 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 | /* NOTE: we patch the symbol size later */ | 7098 | /* NOTE: we patch the symbol size later */ |
| 7092 | put_extern_sym(sym, cur_text_section, ind, 0); | 7099 | put_extern_sym(sym, cur_text_section, ind, 0); |
| 7093 | funcname = get_tok_str(sym->v, NULL); | 7100 | funcname = get_tok_str(sym->v, NULL); |
| @@ -2270,6 +2270,8 @@ int fib(int n) · 2269 unmodified lines | |||
| 2270 | return fib(n-1) + fib(n-2); | 2270 | return fib(n-1) + fib(n-2); |
| 2271 | } | 2271 | } |
| 2272 | 2272 | ||
| 2273 | void __attribute__((aligned(16))) aligned_function(int i) {} | ||
| 2274 | |||
| 2273 | void funcptr_test() | 2275 | void funcptr_test() |
| 2274 | { | 2276 | { |
| 2275 | void (*func)(int); | 2277 | void (*func)(int); |
| @@ -2300,6 +2302,10 @@ void funcptr_test() · 24 unmodified lines | |||
| 2300 | func(42); | 2302 | func(42); |
| 2301 | (func + diff)(42); | 2303 | (func + diff)(42); |
| 2302 | (num + a)(43); | 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 | void lloptest(long long a, long long b) | 2311 | void lloptest(long long a, long long b) |
| @@ -1639,6 +1639,12 @@ void gfunc_epilog(void) · 1638 unmodified lines | |||
| 1639 | 1639 | ||
| 1640 | #endif /* not PE */ | 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 | /* generate a jump to a label */ | 1648 | /* generate a jump to a label */ |
| 1643 | int gjmp(int t) | 1649 | int gjmp(int t) |
| 1644 | { | 1650 | { |