Просмотр исходного кода

* 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 -

sergei 10 лет назад
Родитель
Сommit
657ac78304
3 измененных файлов с 23 добавлено и 28 удалено
  1. 2 4
      compiler/nbas.pas
  2. 5 2
      compiler/ncgbas.pas
  3. 16 22
      compiler/pstatmnt.pas

+ 2 - 4
compiler/nbas.pas

@@ -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;
 

+ 5 - 2
compiler/ncgbas.pas

@@ -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;
 
 

+ 16 - 22
compiler/pstatmnt.pas

@@ -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;