Implement function alignment via attributes
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.
This commit is contained in:
parent
ef668aae1e
commit
671dcace82
8 changed files with 56 additions and 0 deletions
10
arm-gen.c
10
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 */
|
/* generate a jump to a label */
|
||||||
int gjmp(int t)
|
int gjmp(int t)
|
||||||
{
|
{
|
||||||
|
|
10
arm64-gen.c
10
arm64-gen.c
|
@ -1276,6 +1276,16 @@ ST_FUNC void gfunc_epilog(void)
|
||||||
o(0xd65f03c0); // ret
|
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:
|
// Generate forward branch to label:
|
||||||
ST_FUNC int gjmp(int t)
|
ST_FUNC int gjmp(int t)
|
||||||
{
|
{
|
||||||
|
|
10
c67-gen.c
10
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 */
|
/* generate a jump to a label */
|
||||||
int gjmp(int t)
|
int gjmp(int t)
|
||||||
{
|
{
|
||||||
|
|
|
@ -157,6 +157,12 @@ static int oad(int c, int s)
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ST_FUNC void gen_fill_nops(int bytes)
|
||||||
|
{
|
||||||
|
while (bytes--)
|
||||||
|
g(0x90);
|
||||||
|
}
|
||||||
|
|
||||||
/* generate jmp to a label */
|
/* generate jmp to a label */
|
||||||
#define gjmp2(instr,lbl) oad(instr,lbl)
|
#define gjmp2(instr,lbl) oad(instr,lbl)
|
||||||
|
|
||||||
|
|
1
tcc.h
1
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_call(int nb_args);
|
||||||
ST_FUNC void gfunc_prolog(CType *func_type);
|
ST_FUNC void gfunc_prolog(CType *func_type);
|
||||||
ST_FUNC void gfunc_epilog(void);
|
ST_FUNC void gfunc_epilog(void);
|
||||||
|
ST_FUNC void gen_fill_nops(int);
|
||||||
ST_FUNC int gjmp(int t);
|
ST_FUNC int gjmp(int t);
|
||||||
ST_FUNC void gjmp_addr(int a);
|
ST_FUNC void gjmp_addr(int a);
|
||||||
ST_FUNC int gtst(int inv, int t);
|
ST_FUNC int gtst(int inv, int t);
|
||||||
|
|
7
tccgen.c
7
tccgen.c
|
@ -7088,6 +7088,13 @@ static void gen_function(Sym *sym)
|
||||||
{
|
{
|
||||||
nocode_wanted = 0;
|
nocode_wanted = 0;
|
||||||
ind = cur_text_section->data_offset;
|
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 */
|
/* NOTE: we patch the symbol size later */
|
||||||
put_extern_sym(sym, cur_text_section, ind, 0);
|
put_extern_sym(sym, cur_text_section, ind, 0);
|
||||||
funcname = get_tok_str(sym->v, NULL);
|
funcname = get_tok_str(sym->v, NULL);
|
||||||
|
|
|
@ -2270,6 +2270,8 @@ int fib(int n)
|
||||||
return fib(n-1) + fib(n-2);
|
return fib(n-1) + fib(n-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __attribute__((aligned(16))) aligned_function(int i) {}
|
||||||
|
|
||||||
void funcptr_test()
|
void funcptr_test()
|
||||||
{
|
{
|
||||||
void (*func)(int);
|
void (*func)(int);
|
||||||
|
@ -2300,6 +2302,10 @@ void funcptr_test()
|
||||||
func(42);
|
func(42);
|
||||||
(func + diff)(42);
|
(func + diff)(42);
|
||||||
(num + a)(43);
|
(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)
|
void lloptest(long long a, long long b)
|
||||||
|
|
|
@ -1639,6 +1639,12 @@ void gfunc_epilog(void)
|
||||||
|
|
||||||
#endif /* not PE */
|
#endif /* not PE */
|
||||||
|
|
||||||
|
ST_FUNC void gen_fill_nops(int bytes)
|
||||||
|
{
|
||||||
|
while (bytes--)
|
||||||
|
g(0x90);
|
||||||
|
}
|
||||||
|
|
||||||
/* generate a jump to a label */
|
/* generate a jump to a label */
|
||||||
int gjmp(int t)
|
int gjmp(int t)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue