mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-05-31 23:42:51 +02:00
+ x86_64: generate position-independent case jump tables (twice smaller than absolute ones and do not require dynamic relocations in .dll/.so).
git-svn-id: trunk@26519 -
This commit is contained in:
parent
eb508a18e9
commit
ca58cc1d64
@ -1,7 +1,7 @@
|
||||
{
|
||||
Copyright (c) 1998-2002 by Florian Klaempfl
|
||||
|
||||
Generate i386 assembler for in set/case nodes
|
||||
Generate x86_64 assembler for in set/case nodes
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -32,13 +32,26 @@ interface
|
||||
type
|
||||
tx8664casenode = class(tx86casenode)
|
||||
procedure optimizevalues(var max_linear_list:aint;var max_dist:aword);override;
|
||||
procedure genjumptable(hp : pcaselabel;min_,max_ : aint);override;
|
||||
end;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
systems,
|
||||
verbose,globals,constexp,
|
||||
symconst,symdef,defutil,
|
||||
aasmbase,aasmtai,aasmdata,aasmcpu,
|
||||
cgbase,pass_2,
|
||||
ncon,
|
||||
cpubase,cpuinfo,procinfo,
|
||||
cga,cgutils,cgobj,ncgutil,
|
||||
cgx86;
|
||||
|
||||
|
||||
{*****************************************************************************
|
||||
TI386CASENODE
|
||||
TX8664CASENODE
|
||||
*****************************************************************************}
|
||||
|
||||
procedure tx8664casenode.optimizevalues(var max_linear_list:aint;var max_dist:aword);
|
||||
@ -46,6 +59,79 @@ implementation
|
||||
inc(max_linear_list,9);
|
||||
end;
|
||||
|
||||
|
||||
{ Always generate position-independent jump table, it is twice less in size at a price
|
||||
of two extra instructions (which shouldn't cause more slowdown than pipeline trashing) }
|
||||
procedure tx8664casenode.genjumptable(hp : pcaselabel; min_,max_ : aint);
|
||||
var
|
||||
last: TConstExprInt;
|
||||
tablelabel: TAsmLabel;
|
||||
basereg,indexreg,jumpreg: TRegister;
|
||||
href: TReference;
|
||||
opcgsize: tcgsize;
|
||||
|
||||
procedure genitem(list:TAsmList;t : pcaselabel);
|
||||
var
|
||||
i : aint;
|
||||
begin
|
||||
if assigned(t^.less) then
|
||||
genitem(list,t^.less);
|
||||
{ fill possible hole }
|
||||
i:=last.svalue+1;
|
||||
while i<=t^._low.svalue-1 do
|
||||
begin
|
||||
list.concat(Tai_const.Create_rel_sym(aitconst_32bit,tablelabel,elselabel));
|
||||
inc(i);
|
||||
end;
|
||||
i:=t^._low.svalue;
|
||||
while i<=t^._high.svalue do
|
||||
begin
|
||||
list.concat(Tai_const.Create_rel_sym(aitconst_32bit,tablelabel,blocklabel(t^.blockid)));
|
||||
inc(i);
|
||||
end;
|
||||
last:=t^._high;
|
||||
if assigned(t^.greater) then
|
||||
genitem(list,t^.greater);
|
||||
end;
|
||||
|
||||
begin
|
||||
last:=min_;
|
||||
opcgsize:=def_cgsize(opsize);
|
||||
if not(jumptable_no_range) then
|
||||
begin
|
||||
{ a <= x <= b <-> unsigned(x-a) <= (b-a) }
|
||||
cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SUB,opcgsize,aint(min_),hregister);
|
||||
{ case expr greater than max_ => goto elselabel }
|
||||
cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opcgsize,OC_A,aint(max_)-aint(min_),hregister,elselabel);
|
||||
min_:=0;
|
||||
end;
|
||||
{ local label in order to avoid using GOT }
|
||||
current_asmdata.getlabel(tablelabel,alt_data);
|
||||
indexreg:=cg.makeregsize(current_asmdata.CurrAsmList,hregister,OS_ADDR);
|
||||
cg.a_load_reg_reg(current_asmdata.CurrAsmList,opcgsize,OS_ADDR,hregister,indexreg);
|
||||
{ load table address }
|
||||
reference_reset_symbol(href,tablelabel,0,4);
|
||||
basereg:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
||||
cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,basereg);
|
||||
{ load table slot, 32-bit sign extended }
|
||||
reference_reset_base(href,basereg,-aint(min_)*4,4);
|
||||
href.index:=indexreg;
|
||||
href.scalefactor:=4;
|
||||
jumpreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
||||
cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_S32,OS_ADDR,href,jumpreg);
|
||||
{ add table address }
|
||||
reference_reset_base(href,basereg,0,sizeof(pint));
|
||||
href.index:=jumpreg;
|
||||
href.scalefactor:=1;
|
||||
cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,jumpreg);
|
||||
{ and finally jump }
|
||||
emit_reg(A_JMP,S_NO,jumpreg);
|
||||
{ generate jump table }
|
||||
new_section(current_procinfo.aktlocaldata,sec_rodata,current_procinfo.procdef.mangledname,4);
|
||||
current_procinfo.aktlocaldata.concat(Tai_label.Create(tablelabel));
|
||||
genitem(current_procinfo.aktlocaldata,hp);
|
||||
end;
|
||||
|
||||
begin
|
||||
ccasenode:=tx8664casenode;
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user