diff --git a/arm-gen.c b/arm-gen.c index f535a09..634cffb 100644 --- a/arm-gen.c +++ b/arm-gen.c @@ -1410,6 +1410,16 @@ void gfunc_epilog(void) } } +ST_FUNC void gen_fill_nops(int bytes) +{ + if ((bytes & 3)) + tcc_error("alignment of code section not multiple of 4"); + while (bytes > 0) { + o(0xE1A00000); + bytes -= 4; + } +} + /* generate a jump to a label */ int gjmp(int t) { diff --git a/arm64-gen.c b/arm64-gen.c index 86b3af7..26cf5d1 100644 --- a/arm64-gen.c +++ b/arm64-gen.c @@ -1276,6 +1276,16 @@ ST_FUNC void gfunc_epilog(void) o(0xd65f03c0); // ret } +ST_FUNC void gen_fill_nops(int bytes) +{ + if ((bytes & 3)) + tcc_error("alignment of code section not multiple of 4"); + while (bytes > 0) { + o(0xd503201f); // nop + bytes -= 4; + } +} + // Generate forward branch to label: ST_FUNC int gjmp(int t) { diff --git a/c67-gen.c b/c67-gen.c index bcb4b0e..d21626a 100644 --- a/c67-gen.c +++ b/c67-gen.c @@ -2035,6 +2035,16 @@ void gfunc_epilog(void) } } +ST_FUNC void gen_fill_nops(int bytes) +{ + if ((bytes & 3)) + tcc_error("alignment of code section not multiple of 4"); + while (bytes > 0) { + C67_NOP(4); + bytes -= 4; + } +} + /* generate a jump to a label */ int gjmp(int t) { diff --git a/i386-gen.c b/i386-gen.c index b9c3599..b6629d4 100644 --- a/i386-gen.c +++ b/i386-gen.c @@ -157,6 +157,12 @@ static int oad(int c, int s) return t; } +ST_FUNC void gen_fill_nops(int bytes) +{ + while (bytes--) + g(0x90); +} + /* generate jmp to a label */ #define gjmp2(instr,lbl) oad(instr,lbl) diff --git a/tcc.h b/tcc.h index cd67973..c2aaa42 100644 --- a/tcc.h +++ b/tcc.h @@ -1475,6 +1475,7 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *align, int *reg ST_FUNC void gfunc_call(int nb_args); ST_FUNC void gfunc_prolog(CType *func_type); ST_FUNC void gfunc_epilog(void); +ST_FUNC void gen_fill_nops(int); ST_FUNC int gjmp(int t); ST_FUNC void gjmp_addr(int a); ST_FUNC int gtst(int inv, int t); diff --git a/tccgen.c b/tccgen.c index 6ef40e4..4f2e68b 100644 --- a/tccgen.c +++ b/tccgen.c @@ -7088,6 +7088,13 @@ static void gen_function(Sym *sym) { nocode_wanted = 0; ind = cur_text_section->data_offset; + if (sym->a.aligned) { + size_t newoff = section_add(cur_text_section, 0, + 1 << (sym->a.aligned - 1)); + if (ind != newoff) + gen_fill_nops(newoff - ind); + ind = newoff; + } /* NOTE: we patch the symbol size later */ put_extern_sym(sym, cur_text_section, ind, 0); funcname = get_tok_str(sym->v, NULL); diff --git a/tests/tcctest.c b/tests/tcctest.c index 56d51dc..3dc9f1d 100644 --- a/tests/tcctest.c +++ b/tests/tcctest.c @@ -2270,6 +2270,8 @@ int fib(int n) return fib(n-1) + fib(n-2); } +void __attribute__((aligned(16))) aligned_function(int i) {} + void funcptr_test() { void (*func)(int); @@ -2300,6 +2302,10 @@ void funcptr_test() func(42); (func + diff)(42); (num + a)(43); + + /* Check that we can align functions */ + func = aligned_function; + printf("aligned_function (should be zero): %d\n", ((int)func) & 15); } void lloptest(long long a, long long b) diff --git a/x86_64-gen.c b/x86_64-gen.c index e33a38a..9ca5c11 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -1639,6 +1639,12 @@ void gfunc_epilog(void) #endif /* not PE */ +ST_FUNC void gen_fill_nops(int bytes) +{ + while (bytes--) + g(0x90); +} + /* generate a jump to a label */ int gjmp(int t) {