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:
Michael Matz 2018-04-06 23:01:45 +02:00
parent ef668aae1e
commit 671dcace82
8 changed files with 56 additions and 0 deletions

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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)

1
tcc.h
View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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)
{