Przeglądaj źródła

+ support for instruction operands that are tai themselves in the llvm
backend (required for inserting bitcasts/ptrtoint/... operations inside
typed constant declarations)
o taillvm constructors for creating bitcast-style and getlementptr
operations that accept a tai as their source/base operand

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

Jonas Maebe 11 lat temu
rodzic
commit
1e7d9c9f0e
3 zmienionych plików z 125 dodań i 50 usunięć
  1. 49 43
      compiler/aasmtai.pas
  2. 53 0
      compiler/llvm/aasmllvm.pas
  3. 23 7
      compiler/llvm/agllvm.pas

+ 49 - 43
compiler/aasmtai.pas

@@ -262,6 +262,7 @@ interface
 {$ifdef cpuextended}
        ,top_extended80
 {$endif cpuextended}
+       ,top_tai
        ,top_def
        ,top_fpcond
        ,top_cond
@@ -283,49 +284,6 @@ interface
       end;
       plocaloper = ^tlocaloper;
 
-      { please keep the size of this record <=12 bytes and keep it properly aligned }
-      toper = record
-        ot : longint;
-        case typ : toptype of
-          top_none   : ();
-          top_reg    : (reg:tregister);
-          top_ref    : (ref:preference);
-          top_const  : (val:tcgint);
-          top_bool   : (b:boolean);
-          { local varsym that will be inserted in pass_generate_code }
-          top_local  : (localoper:plocaloper);
-      {$ifdef arm}
-          top_regset : (regset:^tcpuregisterset; regtyp: tregistertype; subreg: tsubregister; usermode: boolean);
-          top_conditioncode : (cc : TAsmCond);
-          top_modeflags : (modeflags : tcpumodeflags);
-          top_specialreg : (specialreg:tregister; specialflags:tspecialregflags);
-      {$endif arm}
-      {$if defined(arm) or defined(aarch64)}
-          top_shifterop : (shifterop : pshifterop);
-      {$endif defined(arm) or defined(aarch64)}
-      {$ifdef m68k}
-          top_regset : (dataregset,addrregset:^tcpuregisterset);
-      {$endif m68k}
-      {$ifdef jvm}
-          top_single : (sval:single);
-          top_double : (dval:double);
-          top_string : (pcvallen: aint; pcval: pchar);
-          top_wstring : (pwstrval: pcompilerwidestring);
-      {$endif jvm}
-      {$ifdef llvm}
-          top_single : (sval:single);
-          top_double : (dval:double);
-        {$ifdef cpuextended}
-          top_extended80 : (eval:extended);
-        {$endif cpuextended}
-          top_def    : (def: tdef);
-          top_cond   : (cond: topcmp);
-          top_fpcond : (fpcond: tllvmfpcmp);
-          top_para   : (paras: tfplist);
-      {$endif llvm}
-      end;
-      poper=^toper;
-
     const
       { ait_* types which don't result in executable code or which don't influence
         the way the program runs/behaves, but which may be encountered by the
@@ -438,6 +396,52 @@ interface
       );
 
     type
+        tai = class;
+
+        { please keep the size of this record <=12 bytes and keep it properly aligned }
+        toper = record
+          ot : longint;
+          case typ : toptype of
+            top_none   : ();
+            top_reg    : (reg:tregister);
+            top_ref    : (ref:preference);
+            top_const  : (val:tcgint);
+            top_bool   : (b:boolean);
+            { local varsym that will be inserted in pass_generate_code }
+            top_local  : (localoper:plocaloper);
+        {$ifdef arm}
+            top_regset : (regset:^tcpuregisterset; regtyp: tregistertype; subreg: tsubregister; usermode: boolean);
+            top_conditioncode : (cc : TAsmCond);
+            top_modeflags : (modeflags : tcpumodeflags);
+            top_specialreg : (specialreg:tregister; specialflags:tspecialregflags);
+        {$endif arm}
+        {$if defined(arm) or defined(aarch64)}
+            top_shifterop : (shifterop : pshifterop);
+        {$endif defined(arm) or defined(aarch64)}
+        {$ifdef m68k}
+            top_regset : (dataregset,addrregset:^tcpuregisterset);
+        {$endif m68k}
+        {$ifdef jvm}
+            top_single : (sval:single);
+            top_double : (dval:double);
+            top_string : (pcvallen: aint; pcval: pchar);
+            top_wstring : (pwstrval: pcompilerwidestring);
+        {$endif jvm}
+        {$ifdef llvm}
+            top_single : (sval:single);
+            top_double : (dval:double);
+          {$ifdef cpuextended}
+            top_extended80 : (eval:extended);
+          {$endif cpuextended}
+            top_tai    : (ai: tai);
+            top_def    : (def: tdef);
+            top_cond   : (cond: topcmp);
+            top_fpcond : (fpcond: tllvmfpcmp);
+            top_para   : (paras: tfplist);
+        {$endif llvm}
+        end;
+        poper=^toper;
+
        { abstract assembler item }
        tai = class(TLinkedListItem)
 {$ifndef NOOPT}
@@ -2807,6 +2811,8 @@ implementation
 {$ifdef llvm}
               top_para:
                 paras.free;
+              top_tai:
+                ai.free;
 {$endif llvm}
             end;
             typ:=top_none;

+ 53 - 0
compiler/llvm/aasmllvm.pas

@@ -68,6 +68,8 @@ interface
 {$endif cpuextended}
         { e.g. dst = bitcast fromsize @globalvar to tosize }
         constructor op_reg_size_sym_size(op:tllvmop;dst:tregister;fromsize:tdef;src:TAsmSymbol;tosize:tdef);
+        { e.g. dst = bitcast fromsize <abstracttaidata> to tosize }
+        constructor op_reg_size_tai_size(op:tllvmop;dst:tregister;fromsize:tdef;src:tai;tosize:tdef);
 
         { e.g. dst = bitcast fromsize src to tosize }
         constructor op_reg_size_ref_size(op:tllvmop;dst:tregister;fromsize:tdef;const src:treference;tosize:tdef);
@@ -97,10 +99,12 @@ interface
         { e.g. dst = getelementptr ptrsize ref, i32 0 (if indirect), index1type index1 }
         constructor getelementptr_reg_size_ref_size_reg(dst:tregister;ptrsize:tdef;const ref:treference;indextype:tdef;index1:tregister;indirect:boolean);
         constructor getelementptr_reg_size_ref_size_const(dst:tregister;ptrsize:tdef;const ref:treference;indextype:tdef;index1:ptrint;indirect:boolean);
+        constructor getelementptr_reg_tai_size_const(dst:tregister;const ai:taillvm;indextype:tdef;index1:ptrint;indirect:boolean);
 
         { e.g. dst = call retsize (paras) }
         constructor call_size_name_paras(dst: tregister;retsize: tdef;name:tasmsymbol;paras: tfplist);
 
+        procedure loadtai(opidx: longint; _ai: tai);
         procedure loaddef(opidx: longint; _def: tdef);
         procedure loadsingle(opidx: longint; _sval: single);
         procedure loaddouble(opidx: longint; _dval: double);
@@ -232,6 +236,19 @@ uses
       end;
 
 
+    procedure taillvm.loadtai(opidx: longint; _ai: tai);
+      begin
+        allocate_oper(opidx+1);
+        with oper[opidx]^ do
+         begin
+           if typ<>top_tai then
+             clearop(opidx);
+           ai:=_ai;
+           typ:=top_tai;
+         end;
+      end;
+
+
     procedure taillvm.loaddef(opidx:longint;_def: tdef);
       begin
         allocate_oper(opidx+1);
@@ -605,6 +622,17 @@ uses
       end;
 
 
+    constructor taillvm.op_reg_size_tai_size(op:tllvmop;dst:tregister;fromsize:tdef;src:tai;tosize:tdef);
+      begin
+        create_llvm(op);
+        ops:=4;
+        loadreg(0,dst);
+        loaddef(1,fromsize);
+        loadtai(2,src);
+        loaddef(3,tosize);
+      end;
+
+
     constructor taillvm.op_reg_size_ref_size(op: tllvmop; dst: tregister; fromsize: tdef; const src: treference; tosize: tdef);
       begin
         create_llvm(op);
@@ -779,6 +807,31 @@ uses
         loadconst(index+1,index1);
       end;
 
+
+    constructor taillvm.getelementptr_reg_tai_size_const(dst: tregister; const ai: taillvm; indextype: tdef; index1: ptrint; indirect: boolean);
+      var
+        index: longint;
+      begin
+        create_llvm(la_getelementptr);
+        if indirect then
+          ops:=6
+        else
+          ops:=4;
+        loadreg(0,dst);
+        loadtai(1,ai);
+        if indirect then
+          begin
+            loaddef(2,s32inttype);
+            loadconst(3,0);
+            index:=4;
+          end
+        else
+          index:=2;
+        loaddef(index,indextype);
+        loadconst(index+1,index1);
+      end;
+
+
     constructor taillvm.call_size_name_paras(dst: tregister; retsize: tdef; name:tasmsymbol; paras: tfplist);
       begin
         create_llvm(la_call);

+ 23 - 7
compiler/llvm/agllvm.pas

@@ -71,6 +71,9 @@ interface
         procedure WriteInstruction(hp : tai);
        protected
         owner: TLLVMAssember;
+
+        function InstructionToString(hp : tai): TSymStr;
+        function getopstr(const o:toper; refwithalign: boolean) : TSymStr;
       end;
 
 
@@ -214,7 +217,7 @@ implementation
      end;
 
 
-   function getopstr(const o:toper; refwithalign: boolean) : ansistring;
+   function TLLVMInstrWriter.getopstr(const o:toper; refwithalign: boolean) : TSymStr;
      var
        hs : ansistring;
        doubleval: record
@@ -289,6 +292,10 @@ implementation
            begin
              result:=getparas(o);
            end;
+         top_tai:
+           begin
+             result:=InstructionToString(o.ai);
+           end;
 {$ifdef cpuextended}
          top_extended80:
            begin
@@ -303,12 +310,17 @@ implementation
      end;
 
 
-  procedure TLlvmInstrWriter.WriteInstruction(hp: tai);
+  procedure TLLVMInstrWriter.WriteInstruction(hp: tai);
+    begin
+      owner.AsmWriteLn(InstructionToString(hp));
+    end;
+
+
+  function TLLVMInstrWriter.InstructionToString(hp: tai): TSymStr;
     var
       op: tllvmop;
-      s: string;
+      s, sep: TSymStr;
       i, opstart: byte;
-      sep: string[3];
       done: boolean;
     begin
       op:=taillvm(hp).llvmopcode;
@@ -345,8 +357,12 @@ implementation
         la_ptrtoint, la_inttoptr,
         la_bitcast:
           begin
-            s:=s+getopstr(taillvm(hp).oper[0]^,false)+' = '+
-              llvm_op2str[op]+' '+
+            { destination can be empty in case of nested constructs, or
+              data initialisers }
+            if (taillvm(hp).oper[0]^.typ<>top_reg) or
+               (taillvm(hp).oper[0]^.reg<>NR_NO) then
+              s:=s+getopstr(taillvm(hp).oper[0]^,false)+' = ';
+            s:=s+llvm_op2str[op]+' '+
               getopstr(taillvm(hp).oper[1]^,false)+' '+
               getopstr(taillvm(hp).oper[2]^,false)+' to '+
               getopstr(taillvm(hp).oper[3]^,false);
@@ -380,7 +396,7 @@ implementation
         begin
           s:=s+getreferencealignstring(taillvm(hp).oper[0]^.ref^)
         end;
-      owner.AsmWriteLn(s);
+      result:=s;
     end;
 
 {****************************************************************************}