* Improved handling of registers used in assembler blocks. Assembler nodes no longer have lists of used registers attached to them. Instead, each specified register creates an allocation/deallocation pair and an additional tai_regalloc.markused item directly in the asmlist. This way, register lists are no longer limited to integer registers, and parsing no longer depends on paramanager to know which registers are volatile.

If assembler block has no modified register list, it is still handled in pass2, by allocating all volatile registers (not only the integer ones as before).

git-svn-id: trunk@30011 -
This commit is contained in:
sergei 2015-02-25 21:53:15 +00:00
parent 31fddaafe8
commit 657ac78304
3 changed files with 23 additions and 28 deletions

View File

@ -52,8 +52,7 @@ interface
p_asm : TAsmList; p_asm : TAsmList;
currenttai : tai; currenttai : tai;
{ Used registers in assembler block } { Used registers in assembler block }
used_regs_int, has_registerlist : boolean;
used_regs_fpu : tcpuregisterset;
constructor create(p : TAsmList);virtual; constructor create(p : TAsmList);virtual;
constructor create_get_position; constructor create_get_position;
destructor destroy;override; destructor destroy;override;
@ -642,8 +641,6 @@ implementation
inherited create(asmn); inherited create(asmn);
p_asm:=p; p_asm:=p;
currenttai:=nil; currenttai:=nil;
used_regs_int:=[];
used_regs_fpu:=[];
end; end;
@ -751,6 +748,7 @@ implementation
end end
else n.p_asm := nil; else n.p_asm := nil;
n.currenttai:=currenttai; n.currenttai:=currenttai;
n.has_registerlist:=has_registerlist;
result:=n; result:=n;
end; end;

View File

@ -255,7 +255,9 @@ interface
end; end;
{ Allocate registers used in the assembler block } { Allocate registers used in the assembler block }
cg.alloccpuregisters(current_asmdata.CurrAsmList,R_INTREGISTER,used_regs_int); { has_registerlist=true means that registers are specified and already allocated }
if (not has_registerlist) then
cg.allocallcpuregisters(current_asmdata.CurrAsmList);
if (po_inline in current_procinfo.procdef.procoptions) then if (po_inline in current_procinfo.procdef.procoptions) then
begin begin
@ -344,7 +346,8 @@ interface
end; end;
{ Release register used in the assembler block } { Release register used in the assembler block }
cg.dealloccpuregisters(current_asmdata.CurrAsmList,R_INTREGISTER,used_regs_int); if (not has_registerlist) then
cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
end; end;

View File

@ -1045,6 +1045,7 @@ implementation
reg : tregister; reg : tregister;
asmreader : tbaseasmreader; asmreader : tbaseasmreader;
entrypos : tfileposinfo; entrypos : tfileposinfo;
hl : TAsmList;
begin begin
Inside_asm_statement:=true; Inside_asm_statement:=true;
asmstat:=nil; asmstat:=nil;
@ -1052,7 +1053,14 @@ implementation
begin begin
asmreader:=asmmodeinfos[current_settings.asmmode]^.casmreader.create; asmreader:=asmmodeinfos[current_settings.asmmode]^.casmreader.create;
entrypos:=current_filepos; entrypos:=current_filepos;
asmstat:=casmnode.create(asmreader.assemble as TAsmList); hl:=asmreader.assemble as TAsmList;
if (not hl.empty) then
begin
{ mark boundaries of assembler block, this is necessary for optimizer }
hl.insert(tai_marker.create(mark_asmblockstart));
hl.concat(tai_marker.create(mark_asmblockend));
end;
asmstat:=casmnode.create(hl);
asmstat.fileinfo:=entrypos; asmstat.fileinfo:=entrypos;
asmreader.free; asmreader.free;
end end
@ -1068,11 +1076,6 @@ implementation
{ END is read, got a list of changed registers? } { END is read, got a list of changed registers? }
if try_to_consume(_LECKKLAMMER) then if try_to_consume(_LECKKLAMMER) then
begin begin
{$ifdef cpunofpu}
asmstat.used_regs_fpu:=[0..first_int_imreg-1];
{$else cpunofpu}
asmstat.used_regs_fpu:=[0..first_fpu_imreg-1];
{$endif cpunofpu}
if token<>_RECKKLAMMER then if token<>_RECKKLAMMER then
begin begin
if po_assembler in current_procinfo.procdef.procoptions then if po_assembler in current_procinfo.procdef.procoptions then
@ -1082,8 +1085,12 @@ implementation
reg:=std_regnum_search(lower(cstringpattern)); reg:=std_regnum_search(lower(cstringpattern));
if reg<>NR_NO then if reg<>NR_NO then
begin begin
if (getregtype(reg)=R_INTREGISTER) and not(po_assembler in current_procinfo.procdef.procoptions) then if not(po_assembler in current_procinfo.procdef.procoptions) then
include(asmstat.used_regs_int,getsupreg(reg)); begin
hl.Insert(tai_regalloc.alloc(reg,nil));
hl.Insert(tai_regalloc.markused(reg));
hl.Concat(tai_regalloc.dealloc(reg,nil));
end;
end end
else else
Message(asmr_e_invalid_register); Message(asmr_e_invalid_register);
@ -1091,24 +1098,11 @@ implementation
if not try_to_consume(_COMMA) then if not try_to_consume(_COMMA) then
break; break;
until false; until false;
asmstat.has_registerlist:=true;
end; end;
consume(_RECKKLAMMER); consume(_RECKKLAMMER);
end
else
begin
asmstat.used_regs_int:=paramanager.get_volatile_registers_int(current_procinfo.procdef.proccalloption);
asmstat.used_regs_fpu:=paramanager.get_volatile_registers_fpu(current_procinfo.procdef.proccalloption);
end; end;
{ mark the start and the end of the assembler block
this is needed for the optimizer }
If Assigned(AsmStat.p_asm) Then
Begin
Marker := Tai_Marker.Create(mark_AsmBlockStart);
AsmStat.p_asm.Insert(Marker);
Marker := Tai_Marker.Create(mark_AsmBlockEnd);
AsmStat.p_asm.Concat(Marker);
End;
Inside_asm_statement:=false; Inside_asm_statement:=false;
_asm_statement:=asmstat; _asm_statement:=asmstat;
end; end;