+ create jump tables for case statements on x86-64

git-svn-id: trunk@11377 -
This commit is contained in:
florian 2008-07-13 10:26:25 +00:00
parent 9e88af9a78
commit a15d8778d6
2 changed files with 89 additions and 78 deletions

View File

@ -27,13 +27,11 @@ interface
uses
globtype,
node,nset,pass_1,ncgset;
node,nset,pass_1,nx86set;
type
ti386casenode = class(tcgcasenode)
ti386casenode = class(tx86casenode)
procedure optimizevalues(var max_linear_list:aint;var max_dist:aword);override;
function has_jumptable : boolean;override;
procedure genjumptable(hp : pcaselabel;min_,max_ : aint);override;
procedure genlinearlist(hp : pcaselabel);override;
end;
@ -70,74 +68,6 @@ implementation
end;
function ti386casenode.has_jumptable : boolean;
begin
has_jumptable:=true;
end;
procedure ti386casenode.genjumptable(hp : pcaselabel;min_,max_ : aint);
var
table : tasmlabel;
last : TConstExprInt;
indexreg : tregister;
href : treference;
jtlist: tasmlist;
sectype: TAsmSectiontype;
procedure genitem(list:TAsmList;t : pcaselabel);
var
i : aint;
begin
if assigned(t^.less) then
genitem(list,t^.less);
{ fill possible hole }
for i:=last.svalue+1 to t^._low.svalue-1 do
list.concat(Tai_const.Create_sym(elselabel));
for i:=t^._low.svalue to t^._high.svalue do
list.concat(Tai_const.Create_sym(blocklabel(t^.blockid)));
last:=t^._high;
if assigned(t^.greater) then
genitem(list,t^.greater);
end;
begin
last:=min_;
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,opsize,aint(min_),hregister);
{ case expr greater than max_ => goto elselabel }
cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,OC_A,aint(max_)-aint(min_),hregister,elselabel);
min_:=0;
end;
current_asmdata.getjumplabel(table);
{ make it a 32bit register }
indexreg:=cg.makeregsize(current_asmdata.CurrAsmList,hregister,OS_INT);
cg.a_load_reg_reg(current_asmdata.CurrAsmList,opsize,OS_INT,hregister,indexreg);
{ create reference }
reference_reset_symbol(href,table,0);
href.offset:=(-aint(min_))*4;
href.index:=indexreg;
href.scalefactor:=4;
emit_ref(A_JMP,S_NO,href);
{ generate jump table }
if (target_info.system = system_i386_darwin) then
begin
jtlist:=current_asmdata.asmlists[al_const];
sectype:=sec_rodata;
end
else
begin
jtlist:=current_procinfo.aktlocaldata;
sectype:=sec_data;
end;
new_section(jtlist,sectype,current_procinfo.procdef.mangledname,sizeof(aint));
jtlist.concat(Tai_label.Create(table));
genitem(jtlist,hp);
end;
procedure ti386casenode.genlinearlist(hp : pcaselabel);
var
first : boolean;

View File

@ -26,20 +26,24 @@ unit nx86set;
interface
uses
node,nset,pass_1,ncgset;
globtype,
node,nset,pass_1,ncgset;
type
tx86innode = class(tinnode)
procedure pass_generate_code;override;
function pass_1 : tnode;override;
procedure pass_generate_code;override;
function pass_1 : tnode;override;
end;
tx86casenode = class(tcgcasenode)
function has_jumptable : boolean;override;
procedure genjumptable(hp : pcaselabel;min_,max_ : aint);override;
end;
implementation
uses
globtype,systems,constexp,
systems,constexp,
verbose,globals,
symconst,symdef,defutil,
aasmbase,aasmtai,aasmdata,aasmcpu,
@ -47,7 +51,8 @@ implementation
ncon,
cpubase,
cga,cgobj,cgutils,ncgutil,
cgx86;
cgx86,
procinfo;
{*****************************************************************************
TX86INNODE
@ -66,6 +71,81 @@ implementation
end;
function tx86casenode.has_jumptable : boolean;
begin
has_jumptable:=true;
end;
procedure tx86casenode.genjumptable(hp : pcaselabel;min_,max_ : aint);
var
table : tasmlabel;
last : TConstExprInt;
indexreg : tregister;
href : treference;
jtlist: tasmlist;
sectype: TAsmSectiontype;
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_sym(elselabel));
inc(i);
end;
i:=t^._low.svalue;
while i<=t^._high.svalue do
begin
list.concat(Tai_const.Create_sym(blocklabel(t^.blockid)));
inc(i);
end;
last:=t^._high;
if assigned(t^.greater) then
genitem(list,t^.greater);
end;
begin
last:=min_;
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,opsize,aint(min_),hregister);
{ case expr greater than max_ => goto elselabel }
cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,OC_A,aint(max_)-aint(min_),hregister,elselabel);
min_:=0;
end;
current_asmdata.getjumplabel(table);
{ make it a 32bit register }
indexreg:=cg.makeregsize(current_asmdata.CurrAsmList,hregister,OS_INT);
cg.a_load_reg_reg(current_asmdata.CurrAsmList,opsize,OS_INT,hregister,indexreg);
{ create reference }
reference_reset_symbol(href,table,0);
href.offset:=(-aint(min_))*sizeof(aint);
href.index:=indexreg;
href.scalefactor:=sizeof(aint);
emit_ref(A_JMP,S_NO,href);
{ generate jump table }
if (target_info.system = system_i386_darwin) then
begin
jtlist:=current_asmdata.asmlists[al_const];
sectype:=sec_rodata;
end
else
begin
jtlist:=current_procinfo.aktlocaldata;
sectype:=sec_data;
end;
new_section(jtlist,sectype,current_procinfo.procdef.mangledname,sizeof(aint));
jtlist.concat(Tai_label.Create(table));
genitem(jtlist,hp);
end;
procedure tx86innode.pass_generate_code;
type
@ -468,4 +548,5 @@ implementation
begin
cinnode:=tx86innode;
ccasenode:=tx86casenode;
end.