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

View File

@ -255,7 +255,9 @@ interface
end;
{ 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
begin
@ -344,7 +346,8 @@ interface
end;
{ 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;

View File

@ -1045,6 +1045,7 @@ implementation
reg : tregister;
asmreader : tbaseasmreader;
entrypos : tfileposinfo;
hl : TAsmList;
begin
Inside_asm_statement:=true;
asmstat:=nil;
@ -1052,7 +1053,14 @@ implementation
begin
asmreader:=asmmodeinfos[current_settings.asmmode]^.casmreader.create;
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;
asmreader.free;
end
@ -1068,11 +1076,6 @@ implementation
{ END is read, got a list of changed registers? }
if try_to_consume(_LECKKLAMMER) then
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
begin
if po_assembler in current_procinfo.procdef.procoptions then
@ -1082,8 +1085,12 @@ implementation
reg:=std_regnum_search(lower(cstringpattern));
if reg<>NR_NO then
begin
if (getregtype(reg)=R_INTREGISTER) and not(po_assembler in current_procinfo.procdef.procoptions) then
include(asmstat.used_regs_int,getsupreg(reg));
if not(po_assembler in current_procinfo.procdef.procoptions) then
begin
hl.Insert(tai_regalloc.alloc(reg,nil));
hl.Insert(tai_regalloc.markused(reg));
hl.Concat(tai_regalloc.dealloc(reg,nil));
end;
end
else
Message(asmr_e_invalid_register);
@ -1091,24 +1098,11 @@ implementation
if not try_to_consume(_COMMA) then
break;
until false;
asmstat.has_registerlist:=true;
end;
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;
{ 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;
_asm_statement:=asmstat;
end;