From 075abd62201048b6d45f49d0bfccad439e9b6e3b Mon Sep 17 00:00:00 2001
From: florian <florian@freepascal.org>
Date: Sun, 7 Apr 2013 21:00:38 +0000
Subject: [PATCH] + support of stackframesize for arm thumb + estimatedtempsize
 to get a good estimatation for architectures which require to know the stack
 size before

git-svn-id: trunk@24188 -
---
 compiler/arm/cgcpu.pas |  6 ++++++
 compiler/arm/cpupi.pas | 47 ++++++++++++++++++++++++++++++++++++++++--
 compiler/nbas.pas      |  1 +
 compiler/ncgutil.pas   | 11 ++--------
 compiler/ncnv.pas      |  2 ++
 compiler/nflw.pas      |  4 +++-
 compiler/procinfo.pas  |  4 ++++
 compiler/symtable.pas  | 15 ++++++++++++++
 8 files changed, 78 insertions(+), 12 deletions(-)

diff --git a/compiler/arm/cgcpu.pas b/compiler/arm/cgcpu.pas
index f76d815762..1bb698b2d7 100644
--- a/compiler/arm/cgcpu.pas
+++ b/compiler/arm/cgcpu.pas
@@ -3375,6 +3375,12 @@ unit cgcpu;
          imm1, imm2: DWord;
       begin
         LocalSize:=align(LocalSize,4);
+        if localsize>tarmprocinfo(current_procinfo).stackframesize then
+          begin
+            writeln(localsize);
+            writeln(tarmprocinfo(current_procinfo).stackframesize);
+            internalerror(2013040101);
+          end;
         { call instruction does not put anything on the stack }
         stackmisalignment:=0;
         if not(nostackframe) then
diff --git a/compiler/arm/cpupi.pas b/compiler/arm/cpupi.pas
index b148c0aec8..b35bbd6ee3 100644
--- a/compiler/arm/cpupi.pas
+++ b/compiler/arm/cpupi.pas
@@ -33,6 +33,11 @@ unit cpupi;
 
     type
        tarmprocinfo = class(tcgprocinfo)
+          { for arm thumb, we need to know the stackframe size before
+            starting procedure compilation, so this contains the stack frame size, the compiler
+            should assume
+            if this size is too little the procedure must be compiled again with a larger value }
+          stackframesize,
           floatregstart : aint;
           // procedure handle_body_start;override;
           // procedure after_pass1;override;
@@ -48,11 +53,15 @@ unit cpupi;
        globals,systems,
        cpubase,
        tgobj,
-       symconst,paramgr,
+       symconst,symtype,symsym,paramgr,
        cgbase,cgutils,
-       cgobj;
+       cgobj,
+       defutil;
 
     procedure tarmprocinfo.set_first_temp_offset;
+      var
+        localsize : aint;
+        i : longint;
       begin
         { We allocate enough space to save all registers because we can't determine
           the necessary space because the used registers aren't known before
@@ -84,6 +93,40 @@ unit cpupi;
           end
         else
           tg.setfirsttemp(maxpushedparasize);
+
+        { estimate stack frame size }
+        if current_settings.cputype in cpu_thumb then
+          begin
+            stackframesize:=maxpushedparasize+32;
+            localsize:=0;
+            for i:=0 to procdef.localst.SymList.Count-1 do
+              if tsym(procdef.localst.SymList[i]).typ=localvarsym then
+                inc(localsize,tabstractnormalvarsym(procdef.localst.SymList[i]).getsize);
+            inc(stackframesize,localsize);
+
+            localsize:=0;
+            for i:=0 to procdef.parast.SymList.Count-1 do
+              if tsym(procdef.parast.SymList[i]).typ=paravarsym then
+                if is_open_string(tabstractnormalvarsym(procdef.parast.SymList[i]).vardef) then
+                  inc(localsize,256)
+                else
+                  inc(localsize,tabstractnormalvarsym(procdef.parast.SymList[i]).getsize);
+
+            inc(stackframesize,localsize);
+
+            if pi_needs_implicit_finally in flags then
+              inc(stackframesize,40);
+
+            if pi_uses_exceptions in flags then
+              inc(stackframesize,40);
+
+            if procdef.proctypeoption in [potype_constructor] then
+              inc(stackframesize,40*2);
+
+            inc(stackframesize,estimatedtempsize);
+
+            stackframesize:=Align(stackframesize,8);
+          end;
       end;
 
 
diff --git a/compiler/nbas.pas b/compiler/nbas.pas
index a5f1f304cc..56c36e4e75 100644
--- a/compiler/nbas.pas
+++ b/compiler/nbas.pas
@@ -918,6 +918,7 @@ implementation
           firstpass(tempinfo^.withnode);
         if assigned(tempinfo^.tempinitcode) then
           firstpass(tempinfo^.tempinitcode);
+        inc(current_procinfo.estimatedtempsize,size);;
       end;
 
 
diff --git a/compiler/ncgutil.pas b/compiler/ncgutil.pas
index 28f4245232..ae5c46b0ac 100644
--- a/compiler/ncgutil.pas
+++ b/compiler/ncgutil.pas
@@ -392,15 +392,8 @@ implementation
 *****************************************************************************}
 
     procedure get_exception_temps(list:TAsmList;var t:texceptiontemps);
-      var
-        srsym : ttypesym;
-      begin
-        if jmp_buf_size=-1 then
-          begin
-            srsym:=search_system_type('JMP_BUF');
-            jmp_buf_size:=srsym.typedef.size;
-            jmp_buf_align:=srsym.typedef.alignment;
-          end;
+     begin
+        get_jumpbuf_size;
         tg.GetTemp(list,EXCEPT_BUF_SIZE,sizeof(pint),tt_persistent,t.envbuf);
         tg.GetTemp(list,jmp_buf_size,jmp_buf_align,tt_persistent,t.jmpbuf);
         tg.GetTemp(list,sizeof(pint),sizeof(pint),tt_persistent,t.reasonbuf);
diff --git a/compiler/ncnv.pas b/compiler/ncnv.pas
index a16a483431..7e3ae73b71 100644
--- a/compiler/ncnv.pas
+++ b/compiler/ncnv.pas
@@ -2856,6 +2856,8 @@ implementation
 
       begin
          first_char_to_string:=nil;
+         if tstringdef(resultdef).stringtype=st_shortstring then
+           inc(current_procinfo.estimatedtempsize,256);
          expectloc:=LOC_REFERENCE;
       end;
 
diff --git a/compiler/nflw.pas b/compiler/nflw.pas
index 9992fc2a16..788f90f29f 100644
--- a/compiler/nflw.pas
+++ b/compiler/nflw.pas
@@ -1995,6 +1995,7 @@ implementation
          { else block }
          if assigned(t1) then
            firstpass(t1);
+         inc(current_procinfo.estimatedtempsize,get_jumpbuf_size*2);
       end;
 
 
@@ -2051,6 +2052,8 @@ implementation
 
          if assigned(t1) then
            firstpass(t1);
+
+         inc(current_procinfo.estimatedtempsize,get_jumpbuf_size);
       end;
 
 
@@ -2067,7 +2070,6 @@ implementation
          end;
      end;
 
-
 {*****************************************************************************
                                 TONNODE
 *****************************************************************************}
diff --git a/compiler/procinfo.pas b/compiler/procinfo.pas
index 4724c6dcf2..ec3b4c4323 100644
--- a/compiler/procinfo.pas
+++ b/compiler/procinfo.pas
@@ -125,6 +125,10 @@ unit procinfo;
           { max. of space need for parameters }
           maxpushedparasize : aint;
 
+          { some architectures need to know a stack size before the first compilation pass
+            estimatedtempsize contains an estimated value how big temps will get }
+          estimatedtempsize : aint;
+
           { is this a constructor that calls another constructor on itself
             (either inherited, or another constructor of the same class)?
             Requires different entry code for some targets. }
diff --git a/compiler/symtable.pas b/compiler/symtable.pas
index a0405470c7..c898e5eb64 100644
--- a/compiler/symtable.pas
+++ b/compiler/symtable.pas
@@ -220,6 +220,7 @@ interface
     procedure hidesym(sym:TSymEntry);
     procedure duplicatesym(var hashedid:THashedIDString;dupsym,origsym:TSymEntry);
     function handle_generic_dummysym(sym:TSymEntry;var symoptions:tsymoptions):boolean;
+    function get_jumpbuf_size : longint;
 
 {*** Search ***}
     procedure addsymref(sym:tsym);
@@ -2046,6 +2047,20 @@ implementation
           end;
       end;
 
+
+    function get_jumpbuf_size : longint;
+      var
+        srsym : ttypesym;
+      begin
+        if jmp_buf_size=-1 then
+          begin
+            srsym:=search_system_type('JMP_BUF');
+            jmp_buf_size:=srsym.typedef.size;
+            jmp_buf_align:=srsym.typedef.alignment;
+          end;
+        result:=jmp_buf_size;
+      end;
+
 {*****************************************************************************
                                   Search
 *****************************************************************************}