Quellcode durchsuchen

+ partial implementation of llvm tcgobj descendant (mainly missing
parameter handling, calls and conditional branches)
o the memory handling currently assumes that all pointer types
are defined as i8* at the LLVM level, so that we don't have to
pass their type around all the time. If we need a different type,
we just bitcast it as necessary
* added getflagsregister() method to tgobj (LLVM uses 1 bit "registers"
for the results of comparisons, but this doesn't work yet because
both the cpu-specific and the llvm code generator have to be in
the compiler binary to support pure assembler routines, and
right now we would need a different tresflags definition for both;
maybe it should become a variant record or so)

git-svn-id: branches/llvm@15823 -

Jonas Maebe vor 15 Jahren
Ursprung
Commit
cb80a4676c
6 geänderte Dateien mit 1292 neuen und 323 gelöschten Zeilen
  1. 1 0
      .gitattributes
  2. 2 0
      compiler/aasmtai.pas
  3. 18 7
      compiler/cgobj.pas
  4. 141 311
      compiler/llvm/aasmllvm.pas
  5. 1064 0
      compiler/llvm/cgllvm.pas
  6. 66 5
      compiler/llvm/llvmbase.pas

+ 1 - 0
.gitattributes

@@ -203,6 +203,7 @@ compiler/impdef.pas svneol=native#text/plain
 compiler/import.pas svneol=native#text/plain
 compiler/import.pas svneol=native#text/plain
 compiler/link.pas svneol=native#text/plain
 compiler/link.pas svneol=native#text/plain
 compiler/llvm/aasmllvm.pas svneol=native#text/plain
 compiler/llvm/aasmllvm.pas svneol=native#text/plain
+compiler/llvm/cgllvm.pas svneol=native#text/plain
 compiler/llvm/llvmbase.pas svneol=native#text/plain
 compiler/llvm/llvmbase.pas svneol=native#text/plain
 compiler/llvm/tgllvm.pas svneol=native#text/plain
 compiler/llvm/tgllvm.pas svneol=native#text/plain
 compiler/llvmdef.pas svneol=native#text/plain
 compiler/llvmdef.pas svneol=native#text/plain

+ 2 - 0
compiler/aasmtai.pas

@@ -200,6 +200,7 @@ interface
 {$endif m68k}
 {$endif m68k}
 {$ifdef support_llvm}
 {$ifdef support_llvm}
        ,top_string
        ,top_string
+       ,top_def
 {$endif support_llvm}
 {$endif support_llvm}
        { i386 only});
        { i386 only});
 
 
@@ -238,6 +239,7 @@ interface
       {$endif m68k}
       {$endif m68k}
       {$ifdef support_llvm}
       {$ifdef support_llvm}
           top_string : (str: pchar);
           top_string : (str: pchar);
+          top_def    : (def: tdef);
       {$endif support_llvm}
       {$endif support_llvm}
       end;
       end;
       poper=^toper;
       poper=^toper;

+ 18 - 7
compiler/cgobj.pas

@@ -83,7 +83,8 @@ unit cgobj;
           function getaddressregister(list:TAsmList):Tregister;virtual;
           function getaddressregister(list:TAsmList):Tregister;virtual;
           function getfpuregister(list:TAsmList;size:Tcgsize):Tregister;virtual;
           function getfpuregister(list:TAsmList;size:Tcgsize):Tregister;virtual;
           function getmmregister(list:TAsmList;size:Tcgsize):Tregister;virtual;
           function getmmregister(list:TAsmList;size:Tcgsize):Tregister;virtual;
-          function getflagregister(list:TAsmList;size:Tcgsize):Tregister;virtual;
+          function getflagsregister(list:TAsmList):Tregister;virtual;
+          function getaggregateregister(list:TAsmList):Tregister;virtual;
           {Does the generic cg need SIMD registers, like getmmxregister? Or should
           {Does the generic cg need SIMD registers, like getmmxregister? Or should
            the cpu specific child cg object have such a method?}
            the cpu specific child cg object have such a method?}
 
 
@@ -711,6 +712,22 @@ implementation
       end;
       end;
 
 
 
 
+    function tcg.getflagsregister(list:TAsmList):Tregister;
+      begin
+        if not assigned(rg[R_FLAGSREGISTER]) then
+          internalerror(2010081305);
+        result:=rg[R_FLAGSREGISTER].getregister(list,R_SUBWHOLE);
+      end;
+
+
+    function tcg.getaggregateregister(list:TAsmList):Tregister;
+      begin
+        if not assigned(rg[R_AGGREGATEREGISTER]) then
+          internalerror(2010081306);
+        result:=rg[R_AGGREGATEREGISTER].getregister(list,R_SUBWHOLE);
+      end;
+
+
     function Tcg.makeregsize(list:TAsmList;reg:Tregister;size:Tcgsize):Tregister;
     function Tcg.makeregsize(list:TAsmList;reg:Tregister;size:Tcgsize):Tregister;
       var
       var
         subreg:Tsubregister;
         subreg:Tsubregister;
@@ -4234,12 +4251,6 @@ implementation
       end;
       end;
 
 
 
 
-    function tcg.getflagregister(list: TAsmList; size: Tcgsize): Tregister;
-      begin
-        Result:=TRegister(0);
-        internalerror(200807238);
-      end;
-
 {*****************************************************************************
 {*****************************************************************************
                                     TCG64
                                     TCG64
 *****************************************************************************}
 *****************************************************************************}

+ 141 - 311
compiler/llvm/aasmllvm.pas

@@ -25,32 +25,67 @@ unit aasmllvm;
 
 
 interface
 interface
 
 
-uses
-  globtype,verbose,
-  aasmbase,aasmtai,aasmdata,
-  cpubase,cgbase,cgutils,
-  symdef,
-  llvmbase;
+    uses
+      globtype,verbose,
+      aasmbase,aasmtai,aasmdata,
+      cpubase,cgbase,cgutils,
+      symtype,symdef,
+      llvmbase;
 
 
     type
     type
+
+      { taillvm }
+
       taillvm = class(tai_cpu_abstract)
       taillvm = class(tai_cpu_abstract)
         llvmopcode: tllvmop;
         llvmopcode: tllvmop;
-        // switch_end (= ']'), unreachable
+        size1, size2: tllvmopsize;
+        cond: topcmp;
+
         constructor create_llvm(op: tllvmop);
         constructor create_llvm(op: tllvmop);
+
         constructor op_none(op : tllvmop);
         constructor op_none(op : tllvmop);
-        constructor op_const_reg(op:tllvmop;_size1,_size2:tasmsymbol;_op1: aint; _op2:tregister);
-        constructor load_ref_reg_align(_type1:tasmsymbol; const ref: treference; reg: tregister; align: aint);
-        constructor store_reg_ref_align(_type1,_type2:tasmsymbol; reg: tregister; const ref: treference; align: aint);
-        constructor opcnv_reg_reg_type(op:tllvmop; reg1: tregister; fromtyp: tasmsymbol; reg2: tregister; totyp: tasmsymbol);
 
 
+        { e.g. dst = add size src1, src2 }
+        constructor op_reg_size_reg_reg(op:tllvmop;dst:tregister;size:tllvmopsize;src1,src2:tregister);
+        { e.g. dst = sub size 0, src2 }
+        constructor op_reg_size_const_reg(op:tllvmop;dst:tregister;size:tllvmopsize;src1:aint;src2:tregister);
+        { e.g. dst = bitcast size1 src to tosize }
+        constructor op_reg_size_reg_size(op:tllvmop;dst:tregister;fromsize:tllvmopsize;src:tregister;tosize:tllvmopsize);
+        { e.g. dst = bitcast fromsize 255 to tosize }
+        constructor op_reg_size_const_size(op:tllvmop;dst:tregister;fromsize:tllvmopsize;src:aint;tosize:tllvmopsize);
+
+        { e.g. dst = bitcast fromsize src to tosize }
+        constructor op_reg_size_ref_size(op:tllvmop;dst:tregister;fromsize:tllvmopsize;const src:treference;tosize:tllvmopsize);
+        { e.g. store fromsize src, ptrsize toref}
+        constructor op_size_reg_size_ref(op:tllvmop;fromsize:tllvmopsize;src:tregister;ptrsize:tllvmopsize;const toref:treference);
+        { e.g. dst = load presize fromref }
+        constructor op_reg_size_ref(op:tllvmop;dst:tregister;fromsize:tllvmopsize;const fromref:treference);
+
+        { e.g. dst = icmp cmpcond size reg1, reg2 }
+        constructor op_reg_cond_size_reg_reg(op:tllvmop;dst:tregister;cmpcond:topcmp;size:tllvmopsize;reg1,reg2:tregister);
+        { e.g. br label lab }
+        constructor op_lab(op:tllvmop;lab:tasmlabel);
+        { e.g. br i1 condreg, label iftrue, label iffalse }
+        constructor op_size_reg_lab_lab(op:tllvmop;fromsize:tllvmopsize;condreg:tregister;labtrue,labfalse: tasmlabel);
+
+        { e.g. la_ret retdef retval }
+        constructor op_def_reg(op:tllvmop;def: tdef;reg: tregister);
+
+        { e.g. dst = getelementptr ptrsize ref, index1type index1 }
+        constructor getelementptr_reg_size_ref_size_reg(dst:tregister;ptrsize:tllvmopsize;const ref:treference;indextype: tllvmopsize;index1:tregister);
+
+        { older variants, will be removed }
         constructor op_ressym_string(op: tllvmop; restyp: tasmsymbol; const str: ansistring);
         constructor op_ressym_string(op: tllvmop; restyp: tasmsymbol; const str: ansistring);
+
         procedure loadstring(opidx:longint;_str: pchar);
         procedure loadstring(opidx:longint;_str: pchar);
+        procedure loaddef(opidx:longint;_def: tdef);
       end;
       end;
 (*
 (*
     procedure InitLlvmAsm;
     procedure InitLlvmAsm;
     procedure DoneLlvmAsm;
     procedure DoneLlvmAsm;
 *)
 *)
 
 
+
 implementation
 implementation
 
 
 uses
 uses
@@ -73,14 +108,26 @@ uses
         allocate_oper(opidx+1);
         allocate_oper(opidx+1);
         with oper[opidx]^ do
         with oper[opidx]^ do
          begin
          begin
-           if typ<>top_reg then
-             clearop(opidx);
+           clearop(opidx);
            str:=strnew(_str);
            str:=strnew(_str);
            typ:=top_string;
            typ:=top_string;
          end;
          end;
       end;
       end;
 
 
 
 
+    procedure taillvm.loaddef(opidx:longint;_def: tdef);
+      begin
+        allocate_oper(opidx+1);
+        with oper[opidx]^ do
+         begin
+           if typ<>top_def then
+             clearop(opidx);
+           def:=_def;
+           typ:=top_def;
+         end;
+      end;
+
+
     constructor taillvm.op_ressym_string(op: tllvmop; restyp: tasmsymbol; const str: ansistring);
     constructor taillvm.op_ressym_string(op: tllvmop; restyp: tasmsymbol; const str: ansistring);
       begin
       begin
         create_llvm(op);
         create_llvm(op);
@@ -93,353 +140,136 @@ uses
     constructor taillvm.op_none(op : tllvmop);
     constructor taillvm.op_none(op : tllvmop);
       begin
       begin
         create_llvm(op);
         create_llvm(op);
+        ops:=0;
       end;
       end;
 
 
 
 
-(*
-
-    constructor taicpu.op_reg(op : tllvmop;_op1 : tregister);
-      begin
-         inherited create(op);
-         ops:=1;
-         loadreg(0,_op1);
-      end;
-
-
-    constructor taicpu.op_const(op : tllvmop;_op1 : aint);
-      begin
-         inherited create(op);
-         ops:=1;
-         loadconst(0,_op1);
-      end;
-
-
-    constructor taicpu.op_reg_reg(op : tllvmop;_op1,_op2 : tregister);
-      begin
-         inherited create(op);
-         ops:=2;
-         loadreg(0,_op1);
-         loadreg(1,_op2);
-      end;
-
-    constructor taicpu.op_reg_const(op:tllvmop; _op1: tregister; _op2: aint);
-      begin
-         inherited create(op);
-         ops:=2;
-         loadreg(0,_op1);
-         loadconst(1,_op2);
-      end;
-*)
-
-    constructor taillvm.op_const_reg(op:tllvmop; _size1, _size2: tasmsymbol; _op1: aint; _op2: tregister);
+    constructor taillvm.op_reg_size_reg_reg(op: tllvmop; dst: tregister;size: tllvmopsize; src1, src2: tregister);
       begin
       begin
         create_llvm(op);
         create_llvm(op);
-        ops:=4;
-        loadsymbol(0,_size1,0);
-        loadconst(1,_op1);
-        loadsymbol(2,_size2,0);
-        loadreg(3,_op2);
-      end;
-
-
-    constructor taillvm.load_ref_reg_align(_type1:tasmsymbol; const ref: treference; reg: tregister; align: aint);
-      begin
-        create_llvm(la_load);
-        ops:=4;
-        loadreg(0,reg);
-        loadsymbol(1,_type1,0);
-        loadref(2,ref);
-        loadconst(3,align);
+        ops:=2;
+        size1:=size;
+        loadreg(0,dst);
+        loadreg(1,src1);
+        loadreg(2,src2);
       end;
       end;
 
 
 
 
-    constructor taillvm.store_reg_ref_align(_type1,_type2:tasmsymbol; reg: tregister; const ref: treference; align: aint);
-      begin
-        create_llvm(la_store);
-        ops:=5;
-        loadsymbol(0,_type1,0);
-        loadreg(1,reg);
-        loadsymbol(2,_type2,0);
-        loadref(3,ref);
-        loadconst(4,align);
-      end;
-
-    constructor taillvm.opcnv_reg_reg_type(op:tllvmop; reg1: tregister; fromtyp: tasmsymbol; reg2: tregister; totyp: tasmsymbol);
+    constructor taillvm.op_reg_size_const_reg(op: tllvmop; dst: tregister; size: tllvmopsize; src1: aint; src2: tregister);
       begin
       begin
         create_llvm(op);
         create_llvm(op);
-        ops:=4;
-        loadreg(0,reg1);
-        loadsymbol(1,fromtyp,0);
-        loadreg(2,reg2);
-        loadsymbol(3,totyp,0);
-      end;
-
-(*
-    constructor taicpu.op_reg_ref(op : tllvmop;_op1 : tregister;const _op2 : treference);
-      begin
-         inherited create(op);
-         ops:=2;
-         loadreg(0,_op1);
-         loadref(1,_op2);
-      end;
-
-
-    constructor taicpu.op_const_const(op : tllvmop;_op1,_op2 : aint);
-      begin
-         inherited create(op);
-         ops:=2;
-         loadconst(0,_op1);
-         loadconst(1,_op2);
-      end;
-
-
-    constructor taicpu.op_reg_reg_reg(op : tllvmop;_op1,_op2,_op3 : tregister);
-      begin
-         inherited create(op);
-         ops:=3;
-         loadreg(0,_op1);
-         loadreg(1,_op2);
-         loadreg(2,_op3);
-      end;
-
-     constructor taicpu.op_reg_reg_const(op : tllvmop;_op1,_op2 : tregister; _op3: aint);
-       begin
-         inherited create(op);
-         ops:=3;
-         loadreg(0,_op1);
-         loadreg(1,_op2);
-         loadconst(2,_op3);
-      end;
-
-     constructor taicpu.op_reg_reg_sym_ofs(op : tllvmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: aint);
-       begin
-         inherited create(op);
-         ops:=3;
-         loadreg(0,_op1);
-         loadreg(1,_op2);
-         loadsymbol(0,_op3,_op3ofs);
-      end;
-
-     constructor taicpu.op_reg_reg_ref(op : tllvmop;_op1,_op2 : tregister; const _op3: treference);
-       begin
-         inherited create(op);
-         ops:=3;
-         loadreg(0,_op1);
-         loadreg(1,_op2);
-         loadref(2,_op3);
-      end;
-
-    constructor taicpu.op_const_reg_reg(op : tllvmop;_op1 : aint;_op2, _op3 : tregister);
-      begin
-         inherited create(op);
-         ops:=3;
-         loadconst(0,_op1);
-         loadreg(1,_op2);
-         loadreg(2,_op3);
-      end;
-
-     constructor taicpu.op_const_reg_const(op : tllvmop;_op1 : aint;_op2 : tregister;_op3 : aint);
-      begin
-         inherited create(op);
-         ops:=3;
-         loadconst(0,_op1);
-         loadreg(1,_op2);
-         loadconst(2,_op3);
-      end;
-
-
-     constructor taicpu.op_const_const_const(op : tllvmop;_op1 : aint;_op2 : aint;_op3 : aint);
-      begin
-         inherited create(op);
-         ops:=3;
-         loadconst(0,_op1);
-         loadconst(1,_op2);
-         loadconst(2,_op3);
-      end;
-
-
-     constructor taicpu.op_reg_reg_reg_reg(op : tllvmop;_op1,_op2,_op3,_op4 : tregister);
-      begin
-         inherited create(op);
-         ops:=4;
-         loadreg(0,_op1);
-         loadreg(1,_op2);
-         loadreg(2,_op3);
-         loadreg(3,_op4);
-      end;
-
-     constructor taicpu.op_reg_bool_reg_reg(op : tllvmop;_op1: tregister;_op2:boolean;_op3,_op4:tregister);
-      begin
-         inherited create(op);
-         ops:=4;
-         loadreg(0,_op1);
-         loadbool(1,_op2);
-         loadreg(2,_op3);
-         loadreg(3,_op4);
-      end;
-
-     constructor taicpu.op_reg_bool_reg_const(op : tllvmop;_op1: tregister;_op2:boolean;_op3:tregister;_op4: aint);
-      begin
-         inherited create(op);
-         ops:=4;
-         loadreg(0,_op1);
-         loadbool(0,_op2);
-         loadreg(0,_op3);
-         loadconst(0,cardinal(_op4));
-      end;
-
-
-     constructor taicpu.op_reg_reg_reg_const_const(op : tllvmop;_op1,_op2,_op3 : tregister;_op4,_op5 : aint);
-      begin
-         inherited create(op);
-         ops:=5;
-         loadreg(0,_op1);
-         loadreg(1,_op2);
-         loadreg(2,_op3);
-         loadconst(3,cardinal(_op4));
-         loadconst(4,cardinal(_op5));
-      end;
-
-     constructor taicpu.op_reg_reg_const_const_const(op : tllvmop;_op1,_op2 : tregister;_op3,_op4,_op5 : aint);
-      begin
-         inherited create(op);
-         ops:=5;
-         loadreg(0,_op1);
-         loadreg(1,_op2);
-         loadconst(2,_op3);
-         loadconst(3,_op4);
-         loadconst(4,_op5);
-      end;
-
-    constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
-      begin
-         inherited create(op);
-         condition:=cond;
-         ops:=1;
-         loadsymbol(0,_op1,0);
-      end;
-
-     constructor taicpu.op_const_const_sym(op : tasmop;_op1,_op2 : aint; _op3: tasmsymbol);
-      begin
-         inherited create(op);
-         ops:=3;
-         loadconst(0,_op1);
-         loadconst(1,_op2);
-         loadsymbol(2,_op3,0);
+        ops:=2;
+        size1:=size;
+        loadreg(0,dst);
+        loadconst(1,src1);
+        loadreg(2,src2);
       end;
       end;
 
 
 
 
-    constructor taicpu.op_sym(op : tasmop;_op1 : tasmsymbol);
+    constructor taillvm.op_reg_size_reg_size(op: tllvmop; dst: tregister; fromsize: tllvmopsize; src: tregister; tosize: tllvmopsize);
       begin
       begin
-         inherited create(op);
-         ops:=1;
-         loadsymbol(0,_op1,0);
+        create_llvm(op);
+        ops:=2;
+        size1:=fromsize;
+        size2:=tosize;
+        loadreg(0,dst);
+        loadreg(1,src);
       end;
       end;
 
 
 
 
-    constructor taicpu.op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:aint);
+    constructor taillvm.op_reg_size_const_size(op: tllvmop; dst: tregister; fromsize: tllvmopsize; src: aint; tosize: tllvmopsize);
       begin
       begin
-         inherited create(op);
-         ops:=1;
-         loadsymbol(0,_op1,_op1ofs);
+        create_llvm(op);
+        ops:=2;
+        size1:=fromsize;
+        size2:=tosize;
+        loadreg(0,dst);
+        loadconst(1,src);
       end;
       end;
 
 
 
 
-     constructor taicpu.op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : aint);
+    constructor taillvm.op_reg_size_ref_size(op: tllvmop; dst: tregister; fromsize: tllvmopsize; const src: treference; tosize: tllvmopsize);
       begin
       begin
-         inherited create(op);
-         ops:=2;
-         loadreg(0,_op1);
-         loadsymbol(1,_op2,_op2ofs);
+        create_llvm(op);
+        ops:=2;
+        size1:=fromsize;
+        size2:=tosize;
+        loadreg(0,dst);
+        loadref(1,src);
       end;
       end;
 
 
 
 
-    constructor taicpu.op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:aint;const _op2 : treference);
+    constructor taillvm.op_size_reg_size_ref(op: tllvmop; fromsize: tllvmopsize; src: tregister; ptrsize: tllvmopsize; const toref: treference);
       begin
       begin
-         inherited create(op);
-         ops:=2;
-         loadsymbol(0,_op1,_op1ofs);
-         loadref(1,_op2);
+        create_llvm(op);
+        ops:=2;
+        size1:=fromsize;
+        size2:=ptrsize;
+        loadreg(0,src);
+        loadref(1,toref);
       end;
       end;
 
 
 
 
-{ ****************************** newra stuff *************************** }
-
-    function taicpu.is_same_reg_move(regtype: Tregistertype):boolean;
+    constructor taillvm.op_reg_size_ref(op: tllvmop; dst: tregister; fromsize: tllvmopsize; const fromref: treference);
       begin
       begin
-        result :=
-          (((opcode=A_MR) and
-            (regtype = R_INTREGISTER)) or
-           ((opcode = A_FMR) and
-            (regtype = R_FPUREGISTER))) and
-          { these opcodes can only have registers as operands }
-          (oper[0]^.reg=oper[1]^.reg);
+        create_llvm(op);
+        ops:=2;
+        size1:=fromsize;
+        loadreg(0,dst);
+        loadref(1,fromref);
       end;
       end;
 
 
 
 
-    function taicpu.spilling_get_operation_type(opnr: aint): topertype;
+    constructor taillvm.op_reg_cond_size_reg_reg(op: tllvmop; dst: tregister; cmpcond: topcmp; size: tllvmopsize; reg1, reg2: tregister);
       begin
       begin
-        result := operand_read;
-        case opcode of
-            A_STMW,A_LMW:
-              internalerror(2005021805);
-            A_STBU, A_STBUX, A_STHU, A_STHUX, A_STWU, A_STWUX, A_STFSU, A_STFSUX, A_STFDU, A_STFDUX, A_STB, A_STBX, A_STH, A_STHX, A_STW, A_STWX, A_STFS, A_STFSX, A_STFD, A_STFDX, A_STFIWX, A_STHBRX, A_STWBRX, A_STWCX_, A_CMP, A_CMPI, A_CMPL, A_CMPLI, A_DCBA, A_DCBI, A_DCBST, A_DCBT, A_DCBTST, A_DCBZ, A_ECOWX, A_FCMPO, A_FCMPU, A_MTMSR, A_TLBIE, A_TW, A_TWI, A_CMPWI, A_CMPW, A_CMPLWI, A_CMPLW, A_MT, A_MTLR, A_MTCTR:;
-            A_RLWIMI:
-              if opnr = 0 then
-                result := operand_readwrite;
-          else
-            if opnr = 0 then
-              result := operand_write;
-          end;
+        create_llvm(op);
+        ops:=3;
+        size1:=size;
+        cond:=cmpcond;
+        loadreg(0,dst);
+        loadreg(1,reg1);
+        loadreg(2,reg2);
       end;
       end;
 
 
 
 
-    function taicpu.spilling_get_operation_type_ref(opnr: aint; reg: tregister): topertype;
-      begin
-        result := operand_read;
-        case opcode of
-          A_STBU, A_STBUX, A_STHU, A_STHUX, A_STWU, A_STWUX, A_STFSU, A_STFSUX, A_STFDU, A_STFDUX:
-            if (oper[opnr]^.ref^.base = reg) then
-              result := operand_readwrite;
-        end;
-      end;
-
-    function spilling_create_load(const ref:treference;r:tregister): tai;
+    constructor taillvm.op_lab(op: tllvmop; lab: tasmlabel);
       begin
       begin
-        case getregtype(r) of
-          R_INTREGISTER:
-            result:=taicpu.op_reg_ref(A_LWZ,r,ref);
-          R_FPUREGISTER:
-            result:=taicpu.op_reg_ref(A_LFD,r,ref);
-          else
-            internalerror(2005123101);
-        end;
+        create_llvm(op);
+        ops:=1;
+        loadsymbol(0,lab,0);
       end;
       end;
 
 
 
 
-    function spilling_create_store(r:tregister; const ref:treference): tai;
+    constructor taillvm.op_size_reg_lab_lab(op: tllvmop; fromsize: tllvmopsize; condreg: tregister; labtrue, labfalse: tasmlabel);
       begin
       begin
-        case getregtype(r) of
-          R_INTREGISTER:
-            result:=taicpu.op_reg_ref(A_STW,r,ref);
-          R_FPUREGISTER:
-            result:=taicpu.op_reg_ref(A_STFD,r,ref);
-          else
-            internalerror(2005123102);
-        end;
+        create_llvm(op);
+        size1:=fromsize;
+        ops:=3;
+        loadreg(0,condreg);
+        loadsymbol(1,labtrue,0);
+        loadsymbol(2,labfalse,0);
       end;
       end;
 
 
 
 
-    procedure InitAsm;
+    constructor taillvm.op_def_reg(op: tllvmop; def: tdef; reg: tregister);
       begin
       begin
+        create_llvm(op);
+        ops:=2;
+        loaddef(0,def);
+        loadreg(1,reg);
       end;
       end;
 
 
 
 
-    procedure DoneAsm;
-      begin
-      end;
-
+    constructor taillvm.getelementptr_reg_size_ref_size_reg(dst: tregister; ptrsize: tllvmopsize; const ref: treference; indextype: tllvmopsize; index1: tregister);
+    begin
+      create_llvm(la_getelementptr);
+      ops:=3;
+      size1:=ptrsize;
+      size2:=indextype;
+      loadreg(0,dst);
+      loadref(1,ref);
+      loadreg(2,index1);
+    end;
 
 
-*)
 
 
 end.
 end.

+ 1064 - 0
compiler/llvm/cgllvm.pas

@@ -0,0 +1,1064 @@
+{
+
+    Copyright (c) 2010 by Florian Klaempfl and Jonas Maebe
+    Member of the Free Pascal development team
+
+    This unit implements the code generator for LLVM
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cgllvm;
+
+{$i fpcdefs.inc}
+
+  interface
+
+    uses
+      globtype,symtype,symdef,
+      cgbase,cgutils,cgobj,
+      aasmbase,aasmcpu,aasmtai,aasmdata,
+      parabase,
+      cpubase,cpuinfo,node,cg64f32,rgcpu;
+
+
+    type
+
+     { tcgllvm }
+
+     tcgllvm = class(tcg)
+       procedure init_register_allocators; override;
+       procedure done_register_allocators; override;
+
+       procedure a_load_const_cgpara(list : TAsmList;size : tcgsize;a : aint;const paraloc : TCGPara);override;
+       procedure a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const paraloc : TCGPara);override;
+       procedure a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : TCGPara);override;
+
+       procedure a_call_name(list : TAsmList;const s : string; weak: boolean);override;
+       procedure a_call_reg(list : TAsmList;reg: tregister);override;
+       procedure a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: aint; reg: TRegister); override;
+       procedure a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister); override;
+
+       procedure a_op_const_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; a: aint; src, dst: tregister); override;
+       procedure a_op_reg_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister); override;
+       procedure a_op_const_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; a: aint; src, dst: tregister;setflags : boolean;var ovloc : tlocation);override;
+       procedure a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister;setflags : boolean;var ovloc : tlocation);override;
+
+       { move instructions }
+       procedure a_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);override;
+       procedure a_load_reg_reg(list : TAsmList; fromsize, tosize : tcgsize;reg1,reg2 : tregister);override;
+       procedure a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);override;
+       procedure a_load_const_reg(list : TAsmList; size: tcgsize; a : aint;reg : tregister);override;
+
+       { fpu move instructions }
+       procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister); override;
+       procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister); override;
+       procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference); override;
+
+       procedure a_loadfpu_ref_cgpara(list : TAsmList;size : tcgsize;const ref : treference;const paraloc : TCGPara);override;
+       {  comparison operations }
+       procedure a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : aint;reg : tregister;
+         l : tasmlabel);override;
+       procedure a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); override;
+
+       procedure a_jmp_name(list : TAsmList;const s : string); override;
+       procedure a_jmp_always(list : TAsmList;l: tasmlabel); override;
+{$ifdef using_llvm_tresflags}
+       procedure a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel); override;
+
+       procedure g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister); override;
+{$endif}
+       procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);override;
+       procedure g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean); override;
+
+       procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
+
+       procedure g_concatcopy(list : TAsmList;const source,dest : treference;len : aint);override;
+
+       procedure g_overflowcheck(list: TAsmList; const l: tlocation; def: tdef); override;
+       procedure g_overflowCheck_loc(List:TAsmList;const Loc:TLocation;def:TDef;ovloc : tlocation);override;
+
+       procedure g_save_registers(list : TAsmList);override;
+       procedure g_restore_registers(list : TAsmList);override;
+
+       procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
+       procedure g_stackpointer_alloc(list : TAsmList;size : longint);override;
+
+     private
+       function make_simple_ref(list: TAsmList; const ref: treference): treference;
+       function make_simple_ref_of_ptrsize(list: TAsmList; const ref: treference; tosize: tcgsize): treference;
+     end;
+
+    procedure create_codegen;
+
+  implementation
+
+
+    uses
+      globals,verbose,systems,cutils,
+      fmodule,
+      symconst,symsym,
+      tgobj,rgobj,
+      procinfo,cpupi,
+      paramgr,
+      llvmbase,
+      aasmllvm,defutil;
+
+
+    procedure tcgllvm.init_register_allocators;
+      begin
+        inherited init_register_allocators;
+        rg[R_INTREGISTER]:=trgobj.create(R_INTREGISTER,R_SUBWHOLE,[RS_INVALID],RS_INVALID,[]);
+        rg[R_FPUREGISTER]:=trgobj.create(R_FPUREGISTER,R_SUBNONE,[RS_INVALID],RS_INVALID,[]);
+        rg[R_MMREGISTER]:=trgobj.create(R_FPUREGISTER,R_SUBNONE,[RS_INVALID],RS_INVALID,[]);
+        rg[R_ADDRESSREGISTER]:=trgobj.create(R_ADDRESSREGISTER,R_SUBNONE,[RS_INVALID],RS_INVALID,[]);
+        rg[R_FLAGSREGISTER]:=trgobj.create(R_FLAGSREGISTER,R_SUBNONE,[RS_INVALID],RS_INVALID,[]);
+        rg[R_AGGREGATEREGISTER]:=trgobj.create(R_AGGREGATEREGISTER,R_SUBNONE,[RS_INVALID],RS_INVALID,[]);
+      end;
+
+
+    procedure tcgllvm.done_register_allocators;
+     begin
+       rg[R_INTREGISTER].free;
+       rg[R_FPUREGISTER].free;
+       rg[R_MMREGISTER].free;
+       rg[R_ADDRESSREGISTER].free;
+       rg[R_FLAGSREGISTER].free;
+       rg[R_AGGREGATEREGISTER].free;
+       inherited done_register_allocators;
+     end;
+
+
+    procedure tcgllvm.a_load_const_cgpara(list : TAsmList;size : tcgsize;a : aint;const paraloc : TCGPara);
+     //var
+     //  ref: treference;
+     begin
+       { TODO }
+       internalerror(2010081318);
+       //paraloc.check_simple_location;
+       //paramanager.allocparaloc(list,paraloc.location);
+       //case paraloc.location^.loc of
+       //  LOC_REGISTER,LOC_CREGISTER:
+       //    a_load_const_reg(list,size,a,paraloc.location^.register);
+       //  LOC_REFERENCE:
+       //    begin
+       //       reference_reset(ref,paraloc.alignment);
+       //       ref.base:=paraloc.location^.reference.index;
+       //       ref.offset:=paraloc.location^.reference.offset;
+       //       a_load_const_ref(list,size,a,ref);
+       //    end;
+       //  else
+       //    internalerror(2002081101);
+       //end;
+     end;
+
+
+    procedure tcgllvm.a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const paraloc : TCGPara);
+     var
+       tmpref, ref: treference;
+       location: pcgparalocation;
+       sizeleft: aint;
+     begin
+       { TODO }
+       internalerror(2010081317);
+       //location := paraloc.location;
+       //tmpref := r;
+       //sizeleft := paraloc.intsize;
+       //while assigned(location) do
+       //  begin
+       //    paramanager.allocparaloc(list,location);
+       //    case location^.loc of
+       //      LOC_REGISTER,LOC_CREGISTER:
+       //        a_load_ref_reg(list,location^.size,location^.size,tmpref,location^.register);
+       //      LOC_REFERENCE:
+       //        begin
+       //          reference_reset_base(ref,location^.reference.index,location^.reference.offset,paraloc.alignment);
+       //          { doubles in softemu mode have a strange order of registers and references }
+       //          if location^.size=OS_32 then
+       //            g_concatcopy(list,tmpref,ref,4)
+       //          else
+       //            begin
+       //              g_concatcopy(list,tmpref,ref,sizeleft);
+       //              if assigned(location^.next) then
+       //                internalerror(2005010710);
+       //            end;
+       //        end;
+       //      LOC_FPUREGISTER,LOC_CFPUREGISTER:
+       //        case location^.size of
+       //           OS_F32, OS_F64:
+       //             a_loadfpu_ref_reg(list,location^.size,location^.size,tmpref,location^.register);
+       //           else
+       //             internalerror(2002072801);
+       //        end;
+       //      LOC_VOID:
+       //        begin
+       //          // nothing to do
+       //        end;
+       //      else
+       //        internalerror(2002081103);
+       //    end;
+       //    inc(tmpref.offset,tcgsize2size[location^.size]);
+       //    dec(sizeleft,tcgsize2size[location^.size]);
+       //    location := location^.next;
+       //  end;
+     end;
+
+
+    procedure tcgllvm.a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : TCGPara);
+     var
+       ref: treference;
+       tmpreg: tregister;
+     begin
+       { TODO }
+       internalerror(2010081316);
+       //paraloc.check_simple_location;
+       //paramanager.allocparaloc(list,paraloc.location);
+       //case paraloc.location^.loc of
+       //  LOC_REGISTER,LOC_CREGISTER:
+       //    a_loadaddr_ref_reg(list,r,paraloc.location^.register);
+       //  LOC_REFERENCE:
+       //    begin
+       //      reference_reset(ref,paraloc.alignment);
+       //      ref.base := paraloc.location^.reference.index;
+       //      ref.offset := paraloc.location^.reference.offset;
+       //      tmpreg := getintregister(list,OS_ADDR);
+       //      a_loadaddr_ref_reg(list,r,tmpreg);
+       //      a_load_reg_ref(list,OS_ADDR,OS_ADDR,tmpreg,ref);
+       //    end;
+       //  else
+       //    internalerror(2002080701);
+       //end;
+     end;
+
+
+    procedure tcgllvm.a_call_name(list : TAsmList;const s : string; weak: boolean);
+      begin
+        { Not possible like this in LLVM, needs type info }
+        internalerror(2010081315);
+      end;
+
+
+    procedure tcgllvm.a_call_reg(list : TAsmList;reg: tregister);
+      begin
+        { Not possible like this in LLVM, needs type info }
+        internalerror(2010081313);
+      end;
+
+
+    procedure tcgllvm.a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: aint; reg: TRegister);
+      begin
+        { not SSA-safe! }
+        internalerror(2010081312);
+      end;
+
+
+    procedure tcgllvm.a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister);
+      begin
+        case op of
+          OP_NEG,
+          OP_NOT:
+            a_op_reg_reg_reg(list,op,size,src,src,dst)
+          else
+            { not SSA-safe! }
+            internalerror(2010081311);
+        end;
+      end;
+
+
+    const
+      topcg2llvmop: array[topcg] of tllvmop =
+       { OP_NONE  OP_MOVE     OP_ADD  OP_AND  OP_DIV   OP_IDIV  OP_IMUL OP_MUL }
+        (la_none, la_bitcast, la_add, la_and, la_udiv, la_sdiv, la_mul, la_mul,
+       { OP_NEG   OP_NOT   OP_OR  OP_SAR   OP_SHL  OP_SHR   OP_SUB  OP_XOR }
+         la_none, la_none, la_or, la_ashr, la_shl, la_lshr, la_sub, la_xor,
+       { OP_ROL   OP_ROR }
+         la_none, la_none);
+
+    procedure tcgllvm.a_op_const_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; a: aint; src, dst: tregister);
+      var
+        tmpreg: tregister;
+      begin
+        { default tcg implementation is not SSA-safe }
+        tmpreg:=getintregister(list,size);
+        a_load_const_reg(list,size,a,tmpreg);
+        a_op_reg_reg_reg(list,op,size,tmpreg,src,dst);
+      end;
+
+
+    procedure tcgllvm.a_op_reg_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister);
+     var
+       orgdst,
+       tmpreg1,
+       tmpreg2,
+       tmpreg3: tregister;
+       llsize: tllvmopsize;
+       tmpref: treference;
+     begin
+       llsize:=cgsize2llvmopsize[size];
+       orgdst:=dst;
+       if isaddressregister(src1) or
+          isaddressregister(src2) or
+          isaddressregister(dst) then
+         begin
+           { use getelementptr for address registers if possible, it helps with
+             LLVM optimisations }
+           if (op=OP_SUB) and
+              (isaddressregister(src1)<>isaddressregister(src2)) then
+             begin
+               { since getelementptr can only add, convert the sub into an add }
+               tmpreg1:=getintregister(list,OS_ADDR);
+               if isaddressregister(src1) then
+                 begin
+                   a_op_reg_reg_reg(list,OP_NEG,size,src2,NR_NO,tmpreg1);
+                   src2:=tmpreg2;
+                 end
+               else
+                 begin
+                   a_op_reg_reg_reg(list,OP_NEG,size,src1,NR_NO,tmpreg1);
+                   src1:=tmpreg2;
+                 end;
+               op:=OP_ADD;
+             end;
+           if (op=OP_ADD) and
+              (isaddressregister(src1)<>isaddressregister(src2)) then
+             begin
+               reference_reset_base(tmpref,NR_NO,0,1);
+               if isaddressregister(src1) then
+                 begin
+                   tmpref.base:=src1;
+                   tmpref.index:=src2;
+                 end
+               else
+                 begin
+                   tmpref.base:=src2;
+                   tmpref.index:=src1;
+                 end;
+               if isaddressregister(dst) then
+                 tmpreg1:=dst
+               else
+                 tmpreg1:=getaddressregister(list);
+               a_loadaddr_ref_reg(list,tmpref,tmpreg1);
+               if tmpreg1<>dst then
+                 a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpreg1,dst);
+               exit;
+             end
+           else
+             begin
+               { move everything to integer registers }
+               if isaddressregister(src1) then
+                 begin
+                   tmpreg1:=getintregister(list,OS_ADDR);
+                   a_load_reg_reg(list,OS_ADDR,OS_ADDR,src1,tmpreg1);
+                   src1:=tmpreg1;
+                 end;
+               if isaddressregister(src2) then
+                 begin
+                   tmpreg1:=getintregister(list,OS_ADDR);
+                   a_load_reg_reg(list,OS_ADDR,OS_ADDR,src2,tmpreg1);
+                   src2:=tmpreg1;
+                 end;
+               if isaddressregister(dst) then
+                 begin
+                   tmpreg1:=getintregister(list,OS_ADDR);
+                   dst:=tmpreg1;
+                 end
+             end;
+         end;
+       if topcg2llvmop[op]<>la_none then
+         list.concat(taillvm.op_reg_size_reg_reg(topcg2llvmop[op],dst,llsize,src1,src2))
+       else
+         begin
+           case op of
+             OP_NEG:
+               { %dst = sub size 0, %src1 }
+               list.concat(taillvm.op_reg_size_const_reg(la_sub,dst,llsize,0,src1));
+             OP_NOT:
+               { %dst = xor size -1, %src1 }
+               list.concat(taillvm.op_reg_size_const_reg(la_xor,dst,llsize,-1,src1));
+             OP_ROL:
+               begin
+                 tmpreg1:=getintregister(list,size);
+                 tmpreg2:=getintregister(list,size);
+                 tmpreg3:=getintregister(list,size);
+                 { tmpreg1 := tcgsize2size[size] - src1 }
+                 list.concat(taillvm.op_reg_size_const_reg(la_sub,tmpreg1,llsize,tcgsize2size[size],src1));
+                 { tmpreg2 := src2 shr tmpreg1 }
+                 a_op_reg_reg_reg(list,OP_SHR,size,tmpreg1,src2,tmpreg2);
+                 { tmpreg3 := src2 shl src1 }
+                 a_op_reg_reg_reg(list,OP_SHL,size,src1,src2,tmpreg3);
+                 { dst := tmpreg2 or tmpreg3 }
+                 a_op_reg_reg_reg(list,OP_OR,size,tmpreg2,tmpreg3,dst);
+               end;
+             OP_ROR:
+               begin
+                 tmpreg1:=getintregister(list,size);
+                 tmpreg2:=getintregister(list,size);
+                 tmpreg3:=getintregister(list,size);
+                 { tmpreg1 := tcgsize2size[size] - src1 }
+                 list.concat(taillvm.op_reg_size_const_reg(la_sub,tmpreg1,llsize,tcgsize2size[size],src1));
+                 { tmpreg2 := src2 shl tmpreg1 }
+                 a_op_reg_reg_reg(list,OP_SHL,size,tmpreg1,src2,tmpreg2);
+                 { tmpreg3 := src2 shr src1 }
+                 a_op_reg_reg_reg(list,OP_SHR,size,src1,src2,tmpreg3);
+                 { dst := tmpreg2 or tmpreg3 }
+                 a_op_reg_reg_reg(list,OP_OR,size,tmpreg2,tmpreg3,dst);
+               end;
+             else
+               internalerror(2010081310);
+           end;
+         end;
+       if dst<>orgdst then
+         a_load_reg_reg(list,OS_ADDR,OS_ADDR,dst,orgdst);
+     end;
+
+
+    procedure tcgllvm.a_op_const_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; a: aint; src, dst: tregister;setflags : boolean;var ovloc : tlocation);
+      begin
+        { TODO: call intrinsics }
+        internalerror(2010081314)
+      end;
+
+
+    procedure tcgllvm.a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister;setflags : boolean;var ovloc : tlocation);
+     begin
+        { TODO: call intrinsics }
+        internalerror(2010081315)
+     end;
+
+
+    { returns a reference that either only has the base set, or a symbol }
+    function tcgllvm.make_simple_ref(list: TAsmList; const ref: treference): treference;
+      var
+        tmpref: treference;
+        hreg: tregister;
+      begin
+        { base (if it's present) has to be an address register, index (if it's
+          present) an integer }
+        if (ref.index<>NR_NO) and
+           isaddressregister(ref.index) then
+          internalerror(2010081301);
+        { base address: either a symbol, a base register, or a direct
+          offset }
+        if assigned(ref.symbol) and
+           (ref.base<>NR_NO) then
+          internalerror(2010081302);
+        hreg:=NR_NO;
+        { the index consists of the index reg (if any) and the offset }
+        if (ref.index<>NR_NO) then
+          begin
+            { if we have both an index register and an offset, add them
+              together first }
+            if (ref.offset<>0) then
+              begin
+                hreg:=getintregister(list,OS_ADDR);
+                a_op_const_reg_reg(list,OP_ADD,OS_ADDR,ref.offset,ref.index,hreg);
+              end
+            else
+              { assume the index register has always OS_ADDR as size}
+              hreg:=ref.index;
+          end
+        else if (ref.offset<>0) or
+           (not assigned(ref.symbol) and
+           (ref.base=NR_NO)) then
+          begin
+            { if we have as symbol or base register, they are the base address;
+              if not, use the offset as "base" address (e.g. a null pointer) }
+            if assigned(ref.symbol) or
+               (ref.base<>NR_NO) then
+              hreg:=getintregister(list,OS_ADDR)
+            else
+              hreg:=getaddressregister(list);
+            a_load_const_reg(list,OS_ADDR,ref.offset,hreg);
+          end;
+        if hreg<>NR_NO then
+          begin
+            reference_reset_base(result,getaddressregister(list),0,ref.alignment);
+            if assigned(ref.symbol) or
+               (ref.base<>NR_NO) then
+              begin
+                { only one of the above conditions is true, checked at the
+                  start }
+                tmpref:=ref;
+                tmpref.index:=NR_NO;
+                tmpref.offset:=0;
+                list.concat(taillvm.getelementptr_reg_size_ref_size_reg(result.base,SL_I8P,tmpref,cgsize2llvmopsize[OS_ADDR],hreg))
+              end
+            else
+              a_load_reg_reg(list,OS_ADDR,OS_ADDR,hreg,result.base);
+          end
+        else
+          result:=ref;
+      end;
+
+
+    function tcgllvm.make_simple_ref_of_ptrsize(list: TAsmList; const ref: treference; tosize: tcgsize): treference;
+      var
+        newbase: tregister;
+      begin
+        result:=make_simple_ref(list,ref);
+        { convert to the desired size if <> SL_I8P }
+        if not(tosize in [OS_8,OS_S8]) then
+          begin
+            newbase:=cg.getaddressregister(list);
+            list.concat(taillvm.op_reg_size_ref_size(la_bitcast,newbase,SL_I8P,result,cgsize2llvmptropsize[tosize]));
+            result.symbol:=nil;
+            result.base:=newbase;
+          end;
+      end;
+
+
+    procedure tcgllvm.a_load_const_reg(list : TAsmList; size: tcgsize; a : aint;reg : tregister);
+      var
+        op: tllvmop;
+        fromsize,
+        tosize: tllvmopsize;
+      begin
+        fromsize:=cgsize2llvmopsize[size];
+        { bitcast only works amongst integers and vectors }
+        if not isaddressregister(reg) then
+          begin
+             op:=la_bitcast;
+             tosize:=fromsize;
+          end
+        else
+          begin
+            op:=la_inttoptr;
+            tosize:=cgsize2llvmptropsize[size];
+          end;
+        { reg = la_bitcast fromsize a to tosize }
+        list.concat(taillvm.op_reg_size_const_size(op,reg,fromsize,a,tosize));
+      end;
+
+
+    procedure tcgllvm.a_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);
+     var
+        tmpreg: tregister;
+        href: treference;
+      begin
+        href:=make_simple_ref_of_ptrsize(list,ref,tosize);
+        if tcgsize2size[fromsize]<>tcgsize2size[tosize] then
+          begin
+            tmpreg:=getintregister(list,tosize);
+            a_load_reg_reg(list,fromsize,tosize,reg,tmpreg);
+          end
+        else
+          tmpreg:=reg;
+        { store tosize tmpreg, tosize* href }
+        list.concat(taillvm.op_size_reg_size_ref(la_store,cgsize2llvmopsize[tosize],tmpreg,cgsize2llvmptropsize[tosize],href));
+      end;
+
+
+    procedure tcgllvm.a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;const ref : treference;reg : tregister);
+     var
+        tmpreg: tregister;
+        href: treference;
+      begin
+        href:=make_simple_ref_of_ptrsize(list,ref,fromsize);
+        if tcgsize2size[fromsize]<>tcgsize2size[tosize] then
+          tmpreg:=getintregister(list,fromsize)
+        else
+          tmpreg:=reg;
+        { %tmpreg = load size* %ref }
+        list.concat(taillvm.op_reg_size_ref(la_load,tmpreg,cgsize2llvmptropsize[fromsize],href));
+        if tmpreg<>reg then
+          a_load_reg_reg(list,fromsize,tosize,tmpreg,reg);
+      end;
+
+
+    procedure tcgllvm.a_load_reg_reg(list : TAsmList; fromsize, tosize : tcgsize;reg1, reg2 : tregister);
+      var
+        op: tllvmop;
+        fromllsize,
+        tollsize: tllvmopsize;
+      begin
+        if (fromsize=OS_NO) or (tosize=OS_NO) then
+          internalerror(2010081001);
+
+        { get llvm fromsize/tosize }
+        if not isaddressregister(reg1) then
+          fromllsize:=cgsize2llvmopsize[fromsize]
+        else
+          fromllsize:=cgsize2llvmptropsize[fromsize];
+        if not isaddressregister(reg2) then
+          tollsize:=cgsize2llvmopsize[tosize]
+        else
+          tollsize:=cgsize2llvmptropsize[tosize];
+        { int to pointer or vice versa }
+        if isaddressregister(reg1) and
+           not isaddressregister(reg2) then
+          op:=la_ptrtoint
+        else if not isaddressregister(reg1) and
+           isaddressregister(reg2) then
+          op:=la_inttoptr
+        { int to int or ptr to ptr: need zero/sign extension, or plain bitcast? }
+        else if tcgsize2size[tosize]<>tcgsize2size[fromsize] then
+          begin
+            if tcgsize2size[tosize]<tcgsize2size[fromsize] then
+              op:=la_trunc
+            else if tcgsize2unsigned[fromsize]<>fromsize then
+              { fromsize is signed -> sign extension }
+              op:=la_sext
+            else
+              op:=la_zext;
+          end
+        else
+          op:=la_bitcast;
+        { reg2 = bitcast fromllsize reg1 to tollsize }
+        list.concat(taillvm.op_reg_size_reg_size(op,reg2,fromllsize,reg1,tollsize));
+      end;
+
+
+    procedure tcgllvm.a_loadfpu_ref_cgpara(list : TAsmList;size : tcgsize;const ref : treference;const paraloc : TCGPara);
+     //var
+     //   href,href2 : treference;
+     //   hloc : pcgparalocation;
+     begin
+       { TODO }
+       internalerror(2010081323);
+       //href:=ref;
+       //hloc:=paraloc.location;
+       //while assigned(hloc) do
+       //  begin
+       //    case hloc^.loc of
+       //      LOC_FPUREGISTER,LOC_CFPUREGISTER:
+       //        begin
+       //          paramanager.allocparaloc(list,paraloc.location);
+       //          a_loadfpu_ref_reg(list,size,size,ref,hloc^.register);
+       //        end;
+       //      LOC_REGISTER :
+       //        case hloc^.size of
+       //          OS_32,
+       //          OS_F32:
+       //            begin
+       //              paramanager.allocparaloc(list,paraloc.location);
+       //              a_load_ref_reg(list,OS_32,OS_32,href,hloc^.register);
+       //            end;
+       //          OS_64,
+       //          OS_F64:
+       //            cg64.a_load64_ref_cgpara(list,href,paraloc);
+       //          else
+       //            a_load_ref_reg(list,hloc^.size,hloc^.size,href,hloc^.register);
+       //        end;
+       //      LOC_REFERENCE :
+       //        begin
+       //          reference_reset_base(href2,hloc^.reference.index,hloc^.reference.offset,paraloc.alignment);
+       //          { concatcopy should choose the best way to copy the data }
+       //          g_concatcopy(list,href,href2,tcgsize2size[hloc^.size]);
+       //        end;
+       //      else
+       //        internalerror(200408241);
+       //   end;
+       //   inc(href.offset,tcgsize2size[hloc^.size]);
+       //   hloc:=hloc^.next;
+       // end;
+     end;
+
+
+    procedure tcgllvm.a_loadfpu_reg_reg(list: TAsmList; fromsize,tosize: tcgsize; reg1, reg2: tregister);
+      var
+        op: tllvmop;
+        fromllsize,
+        tollsize: tllvmopsize;
+      begin
+        if (fromsize=OS_NO) or (tosize=OS_NO) then
+          internalerror(2010081309);
+
+        { get llvm fromsize/tosize }
+        fromllsize:=cgsize2llvmopsize[fromsize];
+        tollsize:=cgsize2llvmopsize[tosize];
+        if fromllsize<tollsize then
+          op:=la_fptrunc
+         else if fromllsize>tollsize then
+          op:=la_fpext
+        else
+          op:=la_bitcast;
+        { reg2 = bitcast fromllsize reg1 to tollsize }
+        list.concat(taillvm.op_reg_size_reg_size(op,reg2,fromllsize,reg1,tollsize));
+      end;
+
+
+    procedure tcgllvm.a_loadfpu_ref_reg(list: TAsmList; fromsize,tosize: tcgsize; const ref: treference; reg: tregister);
+     var
+        tmpreg: tregister;
+        href: treference;
+      begin
+        href:=make_simple_ref_of_ptrsize(list,ref,fromsize);
+        if fromsize<>tosize then
+          tmpreg:=getfpuregister(list,fromsize)
+        else
+          tmpreg:=reg;
+        { %tmpreg = load size* %ref }
+        list.concat(taillvm.op_reg_size_ref(la_load,tmpreg,cgsize2llvmptropsize[fromsize],href));
+        if tmpreg<>reg then
+          a_loadfpu_reg_reg(list,fromsize,tosize,tmpreg,reg);
+      end;
+
+
+    procedure tcgllvm.a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference);
+     var
+        tmpreg: tregister;
+        href: treference;
+      begin
+        href:=make_simple_ref_of_ptrsize(list,ref,tosize);
+        if tcgsize2size[fromsize]<>tcgsize2size[tosize] then
+          begin
+            tmpreg:=getfpuregister(list,tosize);
+            a_loadfpu_reg_reg(list,fromsize,tosize,reg,tmpreg);
+          end
+        else
+          tmpreg:=reg;
+        { store tosize tmpreg, tosize* href }
+        list.concat(taillvm.op_size_reg_size_ref(la_store,cgsize2llvmopsize[tosize],tmpreg,cgsize2llvmptropsize[tosize],href));
+      end;
+
+
+    {  comparison operations }
+    procedure tcgllvm.a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : aint;reg : tregister;l : tasmlabel);
+     var
+       tmpreg : tregister;
+     begin
+       if not isaddressregister(reg) then
+         tmpreg:=getintregister(list,size)
+       else
+         tmpreg:=getaddressregister(list);
+       a_load_const_reg(list,size,a,tmpreg);
+       a_cmp_reg_reg_label(list,size,cmp_op,tmpreg,reg,l);
+     end;
+
+
+    procedure tcgllvm.a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
+      var
+        resreg,
+        tmpreg: tregister;
+        cmpsize: tllvmopsize;
+      begin
+        if isaddressregister(reg1)<>isaddressregister(reg2) then
+          begin
+            tmpreg:=getaddressregister(list);
+            if not isaddressregister(reg1) then
+              begin
+                a_load_reg_reg(list,size,size,reg1,tmpreg);
+                reg1:=tmpreg;
+              end
+            else
+              begin
+                a_load_reg_reg(list,size,size,reg2,tmpreg);
+                reg2:=tmpreg;
+              end;
+          end;
+        if isaddressregister(reg1) then
+          begin
+            if size<>OS_ADDR then
+              internalerror(2010081308);
+            cmpsize:=SL_I8P;
+          end
+        else
+          cmpsize:=cgsize2llvmopsize[size];
+        resreg:=getflagsregister(list);
+        list.concat(taillvm.op_reg_cond_size_reg_reg(la_icmp,resreg,cmp_op,cmpsize,reg1,reg2));
+{$ifdef using_llvm_tresflags}
+        a_jmp_flags(list,resreg,l);
+{$endif}
+      end;
+
+
+    procedure tcgllvm.a_jmp_name(list : TAsmList;const s : string);
+     begin
+       { it's not possible to jump between different functions in llvm }
+       internalerror(2010081307);
+     end;
+
+
+    procedure tcgllvm.a_jmp_always(list : TAsmList;l: tasmlabel);
+     var
+       ai : taillvm;
+     begin
+       ai:=taillvm.op_lab(la_br,l);
+       ai.is_jmp:=true;
+       list.concat(ai);
+     end;
+
+{$ifdef using_llvm_tresflags}
+    procedure tcgllvm.a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel);
+     var
+       ai : taicpu;
+       lab: tasmlabel;
+     begin
+       current_asmdata.getjumplabel(lab);
+       ai:=taillvm.op_size_reg_lab_lab(la_br,SL_I1,f,l,lab);
+       ai.is_jmp:=true;
+       list.concat(ai);
+       a_label(list,lab);
+     end;
+
+
+    procedure tcgllvm.g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister);
+      var
+        op: tllvmop;
+      begin
+        if not isaddressregister(reg) then
+          op:=la_zext
+        else
+          op:=la_inttoptr;
+        list.concat(taillvm.op_reg_size_reg_size(op,reg,SL_I1,f,cgsize2llvmopsize[size]));
+      end;
+{$endif using_llvm_tresflags}
+
+    procedure tcgllvm.g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);
+      begin
+        { nothing to do }
+      end;
+
+
+    procedure tcgllvm.g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean);
+      begin
+        if is_void(current_procinfo.procdef.returndef) or
+           (
+            (po_assembler in current_procinfo.procdef.procoptions) and
+            (not(assigned(current_procinfo.procdef.funcretsym)) or
+             (tabstractvarsym(current_procinfo.procdef.funcretsym).refs=0))
+           ) or
+           paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef.proccalloption) then
+          list.concat(taillvm.op_none(la_ret))
+        else
+          begin
+            { TODO: in case of a simple result, return location^.register,
+                otherwise define an undef and use insertvalue to insert the
+                fields
+            list.concat(taillvm.op_def_reg(la_ret,current_procinfo.procdef.returndef,current_procinfo.procdef.funcretloc[calleeside].location^.register)); }
+            internalerror(2010081401);
+          end;
+      end;
+
+
+    procedure tcgllvm.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
+      var
+        tmpref: treference;
+        hreg: tregister;
+      begin
+        if not isaddressregister(r) then
+          internalerror(2010081503);
+        tmpref:=make_simple_ref(list,ref);
+        list.concat(taillvm.op_reg_size_ref_size(la_bitcast,r,SL_I8P,tmpref,SL_I8P));
+      end;
+
+
+    procedure tcgllvm.g_concatcopy(list : TAsmList;const source,dest : treference;len : aint);
+      var
+        srcref,dstref: treference;
+        tmpreg : tregister;
+        copyalignment: longint;
+        copysize: tcgsize;
+
+      procedure create_loop(iterations: aint; copyalignment: longint);
+        var
+          tmpbasereg,
+          newbasereg: tregister;
+          lab: tasmlabel;
+          loopcntref,tmpref: treference;
+        begin
+          if iterations=0 then
+            exit;
+
+          if iterations<>1 then
+            begin
+              { init loop counter }
+              tg.gettemp(list,sizeof(pint),sizeof(pint),tt_normal,loopcntref);
+              a_load_const_ref(list,OS_ADDR,iterations,loopcntref);
+
+              { loop label }
+              current_asmdata.getjumplabel(lab);
+              a_label(list,lab);
+            end;
+
+          { load source value: first load source address pointer  }
+          tmpbasereg:=getaddressregister(list);
+          a_load_ref_reg(list,OS_ADDR,OS_ADDR,srcref,tmpbasereg);
+          reference_reset_base(tmpref,tmpbasereg,0,copyalignment);
+          { and then the value }
+          tmpreg:=getintregister(list,copysize);
+          a_load_ref_reg(list,copysize,copysize,tmpref,tmpreg);
+          if iterations<>1 then
+            begin
+              { update the source reference }
+              newbasereg:=getaddressregister(list);
+              a_op_const_reg_reg(list,OP_ADD,OS_ADDR,copyalignment,tmpbasereg,newbasereg);
+              a_load_reg_ref(list,OS_ADDR,OS_ADDR,newbasereg,srcref);
+            end;
+          { store the loaded value: first load the dest address pointer }
+          tmpbasereg:=getaddressregister(list);
+          a_load_ref_reg(list,OS_ADDR,OS_ADDR,dstref,tmpbasereg);
+          reference_reset_base(tmpref,tmpbasereg,0,copyalignment);
+          { and store the value }
+          a_load_reg_ref(list,copysize,copysize,tmpreg,tmpref);
+
+          if iterations<>1 then
+            begin
+              { update the dest reference }
+              newbasereg:=getaddressregister(list);
+              a_op_const_reg_reg(list,OP_ADD,OS_ADDR,copyalignment,tmpbasereg,newbasereg);
+              a_load_reg_ref(list,OS_ADDR,OS_ADDR,newbasereg,dstref);
+
+              { decrease the loop counter }
+              a_op_const_ref(list,OP_SUB,OS_ADDR,1,loopcntref);
+
+              { loop }
+              a_cmp_const_ref_label(list,OS_ADDR,OC_NE,0,loopcntref,lab);
+            end;
+        end;
+
+      begin { g_concatcopy }
+        if len=0 then
+          exit;
+        { determine maximum common copyalignment }
+        copyalignment:=min(source.alignment,dest.alignment);
+        { limit to 128 bits, since we don't support > 128 bit loads/stores }
+        if copyalignment>16 then
+          copyalignment:=16;
+        { don't load more per iteration than the total length }
+        while copyalignment>len do
+          copyalignment:=copyalignment div 2;
+        case copyalignment of
+          1  : copysize:=OS_8;
+          2  : copysize:=OS_16;
+          4  : copysize:=OS_32;
+          8  : copysize:=OS_64;
+          16 : copysize:=OS_128;
+        else
+          internalerror(2010081304);
+        end;
+        { keep reference addresses in memory so we don't have to insert phi
+          nodes; llvm will lower everything to registers, or replace it with
+          memcpy }
+        tmpreg:=getaddressregister(list);
+        a_loadaddr_ref_reg(list,source,tmpreg);
+        tg.gettemp(list,sizeof(pint),sizeof(pint),tt_normal,srcref);
+        a_load_reg_ref(list,OS_ADDR,OS_ADDR,tmpreg,srcref);
+
+        tmpreg:=getaddressregister(list);
+        a_loadaddr_ref_reg(list,dest,tmpreg);
+        tg.gettemp(list,sizeof(pint),sizeof(pint),tt_normal,dstref);
+        a_load_reg_ref(list,OS_ADDR,OS_ADDR,tmpreg,dstref);
+
+        { main loop (separately because alignment is propagated to LLVM) }
+        create_loop(len div copyalignment,copyalignment);
+
+        { leftovers }
+        create_loop(len mod copyalignment,1);
+      end;
+
+
+    procedure tcgllvm.g_overflowCheck(list : TAsmList;const l : tlocation;def : tdef);
+      begin
+        { overflow checking cannot be performed like that with LLVM }
+        internalerror(2010081322);
+      end;
+
+
+    procedure tcgllvm.g_overflowCheck_loc(List:TAsmList;const Loc:TLocation;def:TDef;ovloc : tlocation);
+     var
+       hl : tasmlabel;
+       ai:TAiCpu;
+       hflags : tresflags;
+     begin
+       if not(cs_check_overflow in current_settings.localswitches) then
+         exit;
+       current_asmdata.getjumplabel(hl);
+       case ovloc.loc of
+         LOC_FLAGS:
+           cg.a_jmp_flags(list,ovloc.resflags,hl);
+         else
+           internalerror(2010081321);
+       end;
+
+       a_call_name(list,'FPC_OVERFLOW',false);
+       a_label(list,hl);
+     end;
+
+
+    procedure tcgllvm.g_save_registers(list : TAsmList);
+      begin
+        { LLVM does that for us }
+      end;
+
+
+    procedure tcgllvm.g_restore_registers(list : TAsmList);
+      begin
+        { LLVM does that for us }
+      end;
+
+
+    procedure tcgllvm.g_stackpointer_alloc(list: TAsmList; size: longint);
+      begin
+       internalerror(2010081319);
+      end;
+
+
+    procedure tcgllvm.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);
+      begin
+       { TODO }
+       internalerror(2010081320);
+       //if not(procdef.proctypeoption in [potype_function,potype_procedure]) then
+       //  Internalerror(200006137);
+       //if not assigned(procdef._class) or
+       //   (procdef.procoptions*[po_classmethod, po_staticmethod,
+       //     po_methodpointer, po_interrupt, po_iocheck]<>[]) then
+       //  Internalerror(200006138);
+       //if procdef.owner.symtabletype<>ObjectSymtable then
+       //  Internalerror(200109191);
+       //
+       //make_global:=false;
+       //if (not current_module.is_unit) or
+       //   create_smartlink or
+       //   (procdef.owner.defowner.owner.symtabletype=globalsymtable) then
+       //  make_global:=true;
+       //
+       //if make_global then
+       //  list.concat(Tai_symbol.Createname_global(labelname,AT_FUNCTION,0))
+       //else
+       //  list.concat(Tai_symbol.Createname(labelname,AT_FUNCTION,0));
+       //
+       //{ the wrapper might need aktlocaldata for the additional data to
+       //  load the constant }
+       //current_procinfo:=cprocinfo.create(nil);
+       //
+       //{ set param1 interface to self  }
+       //g_adjust_self_value(list,procdef,ioffset);
+       //
+       //{ case 4 }
+       //if po_virtualmethod in procdef.procoptions then
+       //  begin
+       //    loadvmttor12;
+       //    op_onr12methodaddr;
+       //  end
+       //{ case 0 }
+       //else
+       //  list.concat(taicpu.op_sym(A_B,current_asmdata.RefAsmSymbol(procdef.mangledname)));
+       //list.concatlist(current_procinfo.aktlocaldata);
+       //
+       //current_procinfo.Free;
+       //current_procinfo:=nil;
+       //
+       //list.concat(Tai_symbol_end.Createname(labelname));
+     end;
+
+
+    procedure create_codegen;
+      begin
+        cg:=tcgllvm.create;
+     end;
+
+end.

+ 66 - 5
compiler/llvm/llvmbase.pas

@@ -39,15 +39,18 @@ uses
     type
     type
       tllvmop = (la_none,
       tllvmop = (la_none,
         { terminator instructions }
         { terminator instructions }
-        la_ret, la_br, la_switch, la_invoke, la_unwind, la_unreachable,
+        la_ret, la_br, la_switch, la_indirectbr,
+        la_invoke, la_unwind,
+        la_unreachable,
         { binary operations }
         { binary operations }
-        la_add, la_sub, la_mul, la_div, la_urem, la_srem, la_frem, 
+        la_add, la_fadd, la_sub, la_fsub, la_mul, la_fmul,
+        la_udiv,la_sdiv, la_fdiv, la_urem, la_srem, la_frem,
         { bitwise binary operations }
         { bitwise binary operations }
         la_shl, la_lshr, la_ashr, la_and, la_or, la_xor,
         la_shl, la_lshr, la_ashr, la_and, la_or, la_xor,
         { vector operations }
         { vector operations }
         la_extractelement, la_insertelement, la_shufflevector,
         la_extractelement, la_insertelement, la_shufflevector,
         { memory access and memory addressing operations }
         { memory access and memory addressing operations }
-        la_malloc, la_free, la_alloca,
+        la_alloca,
         la_load, la_store, la_getelementptr,
         la_load, la_store, la_getelementptr,
         { conversion operations }
         { conversion operations }
         la_trunc, la_zext, la_sext, la_fptrunc, la_fpext,
         la_trunc, la_zext, la_sext, la_fptrunc, la_fpext,
@@ -56,12 +59,70 @@ uses
         la_bitcast,
         la_bitcast,
         { other operations }
         { other operations }
         la_icmp, la_fcmp,
         la_icmp, la_fcmp,
-        la_phi, la_select, la_call, la_va_arg, la_getresult,
+        la_phi, la_select, la_call, la_va_arg,
         la_type);
         la_type);
 
 
+    type
+      tllvmopsize = (SL_NO,
+        { i1, i8, ... }
+        SL_I1, SL_I8, SL_I16, SL_I32, SL_I64, SL_I128,
+        { pointer to i1, ... }
+        SL_I1P, SL_I8P, SL_I16P, SL_I32P, SL_I64P, SL_I128P,
+        { single, double, extended, 128 bit float, 128 bit float composed of two doubles }
+        SL_FLOAT, SL_DOUBLE, SL_X86_FP80, SL_FP128, SL_PPC_FP128,
+        SL_FLOATP, SL_DOUBLEP, SL_X86_FP80P, SL_FP128P, SL_PPC_FP128P,
+        { vectors (number = elementsize; total size = native vector register size) }
+        SL_M8,SL_M16,SL_M32,SL_M64,SL_M128,
+        SL_M8P,SL_M16P,SL_M32P,SL_M64P,SL_M128P
+        );
+
+
       {# This should define the array of instructions as string }
       {# This should define the array of instructions as string }
       llvmop2strtable=array[tllvmop] of string[8];
       llvmop2strtable=array[tllvmop] of string[8];
 
 
-  implementation
+    const
+{$if defined(powerpc) or defined(powerpc64) or defined(sparc)}
+      LLVMFLOAT128=SL_PPC_FP128;
+      LLVMFLOAT128P=SL_PPC_FP128P;
+{$else}
+      LLVMFLOAT128=SL_FP128;
+      LLVMFLOAT128P=SL_FP128P;
+{$endif}
+      cgsize2llvmopsize: array[tcgsize] of tllvmopsize = (SL_NO,
+        { integer registers }
+        SL_I8,SL_I16,SL_I32,SL_I64,SL_I128,SL_I8,SL_I16,SL_I32,SL_I64,SL_I128,
+        { single,double,extended,comp,float128 }
+        SL_FLOAT,SL_DOUBLE,SL_X86_FP80,SL_NO,LLVMFLOAT128,
+        { multi-media sizes: split in byte, word, dword, ... }
+        SL_M8,SL_M16,SL_M32,SL_M64,SL_M128,
+        SL_M8,SL_M16,SL_M32,SL_M64,SL_M128);
+
+      cgsize2llvmptropsize: array[tcgsize] of tllvmopsize = (SL_NO,
+        { integer registers }
+        SL_I8P,SL_I16P,SL_I32P,SL_I64P,SL_I128P,SL_I8P,SL_I16P,SL_I32P,SL_I64P,SL_I128P,
+        { single,double,extended,comp,float128 }
+        SL_FLOATP,SL_DOUBLEP,SL_X86_FP80P,SL_NO,LLVMFLOAT128P,
+        { multi-media sizes: split in byte, word, dword, ... }
+        SL_M8P,SL_M16P,SL_M32P,SL_M64P,SL_M128P,
+        SL_M8P,SL_M16P,SL_M32P,SL_M64P,SL_M128P);
+
+      llvmpsize2ptropsize: array[tllvmopsize] of tllvmopsize = (SL_NO,
+        SL_I1P,SL_I8P,SL_I16P,SL_I32P,SL_I64P,SL_I128P,
+        SL_NO,SL_NO,SL_NO,SL_NO,SL_NO,SL_NO,
+        SL_FLOATP, SL_DOUBLEP, SL_X86_FP80P, SL_FP128P, SL_PPC_FP128P,
+        SL_NO,SL_NO,SL_NO,SL_NO,SL_NO,
+        SL_M8P,SL_M16P,SL_M32P,SL_M64P,SL_M128P,
+        SL_NO,SL_NO,SL_NO,SL_NO,SL_NO);
+
+(*
+  need to resolve conflicts with native tresflags: in case llvm is used, we
+  still use parts of the original code generator as well (e.g., to generate
+  the entry/exit code for pure assembler routines), so we can't just replace its
+  resflags
+    type
+      tresflags = type tregister;
+*)
+
+implementation
 
 
 end.
 end.