mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-22 11:49:23 +02:00
+ create jump tables for case statements on x86-64
git-svn-id: trunk@11377 -
This commit is contained in:
parent
9e88af9a78
commit
a15d8778d6
@ -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;
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user