浏览代码

+ no stackframe is generated for i386 if possible

git-svn-id: trunk@2162 -
florian 19 年之前
父节点
当前提交
f7d2c47f73
共有 5 个文件被更改,包括 94 次插入5 次删除
  1. 3 1
      compiler/globtype.pas
  2. 1 1
      compiler/i386/cgcpu.pas
  3. 29 1
      compiler/ncal.pas
  4. 59 1
      compiler/psub.pas
  5. 2 1
      compiler/x86/cgx86.pas

+ 3 - 1
compiler/globtype.pas

@@ -240,7 +240,9 @@ than 255 characters. That's why using Ansi Strings}
          pi_needs_got,
          { references var/proc/type/const in static symtable,
            i.e. not allowed for inlining from other units }
-         pi_uses_static_symtable
+         pi_uses_static_symtable,
+         { set if the procedure has to push parameters onto the stack }
+         pi_has_stackparameter
        );
        tprocinfoflags=set of tprocinfoflag;
 

+ 1 - 1
compiler/i386/cgcpu.pas

@@ -264,7 +264,7 @@ unit cgcpu;
               end
             else
               list.concat(Taicpu.op_none(A_LEAVE,S_NO));
-            list.concat(tai_regalloc.dealloc(NR_FRAME_POINTER_REG,nil));
+            list.concat(tai_regalloc.dealloc(current_procinfo.framepointer,nil));
           end;
 
         { return from proc }

+ 29 - 1
compiler/ncal.pas

@@ -130,6 +130,9 @@ interface
           procedure printnodedata(var t:text);override;
           function  para_count:longint;
           function  get_load_methodpointer:tnode;
+          { checks if there are any parameters which end up at the stack, i.e.
+            which have LOC_REFERENCE and set pi_has_stackparameter if this applies }
+          procedure check_stack_parameters;
        private
           AbstractMethodsList : TStringList;
        end;
@@ -2333,6 +2336,22 @@ type
       end;
 
 
+    procedure tcallnode.check_stack_parameters;
+      var
+        hp : tcallparanode;
+      begin
+        hp:=tcallparanode(left);
+        while assigned(hp) do
+          begin
+             if assigned(hp.parasym) and
+                assigned(hp.parasym.paraloc[callerside].location) and
+               (hp.parasym.paraloc[callerside].location^.loc=LOC_REFERENCE) then
+               include(current_procinfo.flags,pi_has_stackparameter);
+             hp:=tcallparanode(hp.right);
+          end;
+      end;
+
+
     function tcallnode.pass_1 : tnode;
       var
         st : tsymtable;
@@ -2378,7 +2397,16 @@ type
 
          { work trough all parameters to get the register requirements }
          if assigned(left) then
-           tcallparanode(left).det_registers;
+           begin
+             tcallparanode(left).det_registers;
+
+             if cs_optimize in aktglobalswitches then
+               begin
+                 { check for stacked parameters }
+                 check_stack_parameters;
+               end;
+           end;
+
 
          { order parameters }
          order_parameters;

+ 59 - 1
compiler/psub.pas

@@ -54,6 +54,8 @@ interface
         procedure add_to_symtablestack;
         procedure remove_from_symtablestack;
         procedure parse_body;
+
+        function stack_tainting_parameter : boolean;
       end;
 
 
@@ -96,7 +98,7 @@ implementation
        scanner,import,gendef,
        pbase,pstatmnt,pdecl,pdecsub,pexports,
        { codegen }
-       tgobj,cgobj,dbgbase,
+       tgobj,cgbase,cgobj,dbgbase,
        ncgutil,regvars
 {$if defined(arm) or defined(powerpc) or defined(powerpc64)}
        ,aasmcpu
@@ -604,6 +606,29 @@ implementation
       end;
 
 
+    procedure check_for_stack(p : tnamedindexitem;arg:pointer);
+      begin
+         if tsym(p).typ=paravarsym then
+           begin
+             { check if there no parameter of the current procedure is stack dependend }
+             if is_open_array(tparavarsym(p).vartype.def) or
+               is_array_of_const(tparavarsym(p).vartype.def) then
+               pboolean(arg)^:=true;
+             if assigned(p) and
+                assigned(tparavarsym(p).paraloc[calleeside].location) and
+               (tparavarsym(p).paraloc[calleeside].location^.loc=LOC_REFERENCE) then
+               pboolean(arg)^:=true;
+           end;
+      end;
+
+
+    function tcgprocinfo.stack_tainting_parameter : boolean;
+      begin
+        result:=false;
+        procdef.parast.foreach_static(@check_for_stack,@result);
+      end;
+
+
     procedure tcgprocinfo.generate_code;
       var
         oldprocinfo : tprocinfo;
@@ -680,6 +705,38 @@ implementation
             { set the start offset to the start of the temp area in the stack }
             tg:=ttgobj.create;
 
+{$ifdef i386}
+            { try to strip the stack frame }
+            { set the framepointer to esp if:
+              - no assembler directive, those are handled elsewhere
+              - no exceptions are used
+              - no debug info
+              - no pushes are used/esp modifications, could be:
+                * outgoing parameters on the stack
+                * incoming parameters on the stack
+                * open arrays
+              - no inline assembler
+            }
+            if (cs_optimize in aktglobalswitches) and
+               not(po_assembler in procdef.procoptions) and
+               ((flags*[pi_has_assembler_block,pi_uses_exceptions,pi_is_assembler,
+                       pi_needs_implicit_finally,pi_has_implicit_finally,pi_has_stackparameter])=[]) then
+               begin
+                 { we need the parameter info here to determine if the procedure gets
+                   parameters on the stack
+
+                   calling generate_parameter_info doesn't hurt but it costs time
+                 }
+                 generate_parameter_info;
+                 if not(stack_tainting_parameter) then
+                   begin
+                     { Only need to set the framepointer }
+                     framepointer:=NR_STACK_POINTER_REG;
+                     tg.direction:=1;
+                   end;
+               end;
+{$endif i386}
+
             { Create register allocator }
             cg.init_register_allocators;
 
@@ -713,6 +770,7 @@ implementation
                 procdef.has_paraloc_info:=true;
               end;
 
+
             { generate code for the node tree }
             do_secondpass(code);
             aktproccode.concatlist(exprasmlist);

+ 2 - 1
compiler/x86/cgx86.pas

@@ -1839,11 +1839,12 @@ unit cgx86;
         { save old framepointer }
         if not nostackframe then
           begin
+            list.concat(tai_regalloc.alloc(current_procinfo.framepointer,nil));
             if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
               CGmessage(cg_d_stackframe_omited)
             else
               begin
-                list.concat(tai_regalloc.alloc(NR_FRAME_POINTER_REG,nil));
+
                 include(rg[R_INTREGISTER].preserved_by_proc,RS_FRAME_POINTER_REG);
                 list.concat(Taicpu.op_reg(A_PUSH,tcgsize2opsize[OS_ADDR],NR_FRAME_POINTER_REG));
                 { Return address and FP are both on stack }