浏览代码

+ support for merging multiple tai_strings/tai_consts emitted as part of the
same string constant to be merged together into a single tai_string
(required to efficiently represent string constants in llvm assembler
--i.e., without splitting them into bytes--, while keeping the
flexibility in the typed constant parser to mix individual elements
and strings)

git-svn-id: branches/hlcgllvm@28135 -

Jonas Maebe 11 年之前
父节点
当前提交
e0c1c4d3bf
共有 2 个文件被更改,包括 92 次插入1 次删除
  1. 91 1
      compiler/aasmcnst.pas
  2. 1 0
      compiler/llvm/nllvmtcon.pas

+ 91 - 1
compiler/aasmcnst.pas

@@ -79,10 +79,16 @@ type
 
 
     protected
     protected
      fvalues: tfplist;
      fvalues: tfplist;
+     fisstring: boolean;
+
+     { converts the existing data to a single tai_string }
+     procedure convert_to_string;
+     procedure add_to_string(strtai: tai_string; othertai: tai);
     public
     public
      constructor create(_adetyp: ttypedconstkind; _fdef: tdef);
      constructor create(_adetyp: ttypedconstkind; _fdef: tdef);
      function getenumerator: tadeenumerator;
      function getenumerator: tadeenumerator;
      procedure addvalue(val: tai_abstracttypedconst);
      procedure addvalue(val: tai_abstracttypedconst);
+     procedure finish;
      destructor destroy; override;
      destructor destroy; override;
    end;
    end;
 
 
@@ -241,9 +247,56 @@ implementation
                             tai_aggregatetypedconst
                             tai_aggregatetypedconst
  ****************************************************************************}
  ****************************************************************************}
 
 
+   procedure tai_aggregatetypedconst.convert_to_string;
+     var
+       ai: tai_abstracttypedconst;
+       newstr: tai_string;
+     begin
+       newstr:=tai_string.Create('');
+       for ai in self do
+          begin
+            if ai.adetyp<>tck_simple then
+              internalerror(2014070103);
+            add_to_string(newstr,tai_simpletypedconst(ai).val);
+            ai.free;
+          end;
+       fvalues.count:=0;
+       { the "nil" def will be replaced with an array def of the appropriate
+         size once we're finished adding data, so we don't create intermediate
+         arraydefs all the time }
+       fvalues.add(tai_simpletypedconst.create(tck_simple,nil,newstr));
+     end;
+
+   procedure tai_aggregatetypedconst.add_to_string(strtai: tai_string; othertai: tai);
+     begin
+       case othertai.typ of
+         ait_string:
+           begin
+             strtai.str:=reallocmem(strtai.str,strtai.len+tai_string(othertai).len+1);
+             { also copy null terminator }
+             move(tai_string(othertai).str[0],strtai.str[strtai.len],tai_string(othertai).len+1);
+             { the null terminator is not part of the length }
+             strtai.len:=strtai.len+tai_string(othertai).len;
+           end;
+         ait_const:
+           begin
+             if tai_const(othertai).size<>1 then
+               internalerror(2014070101);
+             strtai.str:=reallocmem(strtai.str,strtai.len+1);
+             strtai.str[strtai.len]:=ansichar(tai_const(othertai).value);
+             strtai.str[strtai.len+1]:=#0;
+             inc(strtai.len);
+           end;
+         else
+           internalerror(2014070102);
+       end;
+     end;
+
+
    constructor tai_aggregatetypedconst.create(_adetyp: ttypedconstkind; _fdef: tdef);
    constructor tai_aggregatetypedconst.create(_adetyp: ttypedconstkind; _fdef: tdef);
      begin
      begin
        inherited;
        inherited;
+       fisstring:=false;
        fvalues:=tfplist.create;
        fvalues:=tfplist.create;
      end;
      end;
 
 
@@ -256,7 +309,44 @@ implementation
 
 
    procedure tai_aggregatetypedconst.addvalue(val: tai_abstracttypedconst);
    procedure tai_aggregatetypedconst.addvalue(val: tai_abstracttypedconst);
      begin
      begin
-       fvalues.add(val);
+       { merge string constants and ordinal constants added in an array of
+         char, to unify the length and the string data }
+       if fisstring or
+          ((val.adetyp=tck_simple) and
+           (tai_simpletypedconst(val).val.typ=ait_string)) then
+         begin
+           if not fisstring and
+              (fvalues.count>0) then
+             convert_to_string;
+           fisstring:=true;
+           case fvalues.count of
+             0: fvalues.add(val);
+             1:
+               begin
+                 add_to_string(tai_string(tai_simpletypedconst(fvalues[0]).val),tai_simpletypedconst(val).val);
+                 val.free
+               end
+             else
+               internalerror(2014070104);
+           end;
+         end
+       else
+         fvalues.add(val);
+     end;
+
+
+   procedure tai_aggregatetypedconst.finish;
+     begin
+       if fisstring then
+         begin
+           { set the def: an array of char with the same length as the string
+             data }
+           if fvalues.count<>1 then
+             internalerror(2014070105);
+           tai_simpletypedconst(fvalues[0]).fdef:=
+             getarraydef(cansichartype,
+               tai_string(tai_simpletypedconst(fvalues[0]).val).len);
+         end;
      end;
      end;
 
 
 
 

+ 1 - 0
compiler/llvm/nllvmtcon.pas

@@ -209,6 +209,7 @@ implementation
           if not assigned(faggregates) or
           if not assigned(faggregates) or
              (faggregates.count=0) then
              (faggregates.count=0) then
             internalerror(2014060101);
             internalerror(2014060101);
+          tai_aggregatetypedconst(faggregates[faggregates.count-1]).finish;
           { already added to the asmlist if necessary }
           { already added to the asmlist if necessary }
           faggregates.count:=faggregates.count-1;
           faggregates.count:=faggregates.count-1;
         end;
         end;