Browse Source

+ llvm implementation of add nodes

git-svn-id: branches/hlcgllvm@26047 -
Jonas Maebe 11 years ago
parent
commit
8fa91ab73f
2 changed files with 261 additions and 0 deletions
  1. 1 0
      .gitattributes
  2. 260 0
      compiler/llvm/nllvmadd.pas

+ 1 - 0
.gitattributes

@@ -323,6 +323,7 @@ compiler/llvm/llvmdef.pas svneol=native#text/plain
 compiler/llvm/llvminfo.pas svneol=native#text/plain
 compiler/llvm/llvmpara.pas svneol=native#text/plain
 compiler/llvm/llvmsym.pas svneol=native#text/plain
+compiler/llvm/nllvmadd.pas svneol=native#text/plain
 compiler/llvm/nllvmcon.pas svneol=native#text/plain
 compiler/llvm/rgllvm.pas svneol=native#text/plain
 compiler/llvm/tgllvm.pas svneol=native#text/plain

+ 260 - 0
compiler/llvm/nllvmadd.pas

@@ -0,0 +1,260 @@
+{
+    Copyright (c) 2013 by Jonas Maebe
+
+    Generate LLVM bytecode for add nodes
+
+    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 nllvmadd;
+
+{$mode objfpc}
+
+interface
+
+    uses
+      node,
+      ncgadd;
+
+    type
+      tllvmaddnode = class(tcgaddnode)
+       public
+        function pass_1: tnode; override;
+       protected
+        procedure second_cmpsmallset; override;
+        procedure second_cmpordinal; override;
+        procedure second_add64bit; override;
+        procedure second_cmp64bit; override;
+        procedure second_addfloat; override;
+      end;
+
+
+implementation
+
+     uses
+       verbose,globtype,
+       aasmdata,
+       symdef,defutil,
+       llvmbase,aasmllvm,
+       cgbase,cgutils,
+       hlcgobj,
+       nadd
+       ;
+
+{ tllvmaddnode }
+
+  function tllvmaddnode.pass_1: tnode;
+    begin
+      result:=inherited pass_1;
+      { there are no flags in LLVM }
+      if expectloc=LOC_FLAGS then
+        expectloc:=LOC_REGISTER;
+    end;
+
+
+  procedure tllvmaddnode.second_cmpsmallset;
+    var
+      tmpreg,
+      tmpreg2: tregister;
+      cmpop : topcmp;
+    begin
+      pass_left_right;
+
+      location_reset(location,LOC_REGISTER,OS_8);
+      location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,pasbool8type);
+
+      force_reg_left_right(false,false);
+
+      case nodetype of
+        equaln,
+        unequaln:
+          begin
+            if nodetype=equaln then
+              cmpop:=OC_EQ
+            else
+              cmpop:=OC_NE;
+            current_asmdata.CurrAsmList.concat(taillvm.op_reg_cond_size_reg_reg(la_icmp,
+              location.register,cmpop,left.resultdef,left.location.register,right.location.register));
+          end;
+        lten,
+        gten:
+          begin
+            if (not(nf_swapped in flags) and
+                (nodetype = lten)) or
+               ((nf_swapped in flags) and
+                (nodetype = gten)) then
+              swapleftright;
+            { set1<=set2 <-> set2 and not(set1) = 0 }
+            tmpreg:=hlcg.getintregister(current_asmdata.CurrAsmList,left.resultdef);
+            hlcg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NOT,left.resultdef,left.location.register,tmpreg);
+            tmpreg2:=hlcg.getintregister(current_asmdata.CurrAsmList,left.resultdef);
+            hlcg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_AND,left.resultdef,right.location.register,tmpreg,tmpreg2);
+            current_asmdata.CurrAsmList.concat(taillvm.op_reg_cond_size_reg_const(la_icmp,
+              location.register,OC_EQ,left.resultdef,tmpreg2,0));
+          end;
+        else
+          internalerror(2012042701);
+      end;
+    end;
+
+
+  procedure tllvmaddnode.second_cmpordinal;
+    var
+      cmpop: topcmp;
+      unsigned : boolean;
+    begin
+      pass_left_right;
+      force_reg_left_right(true,true);
+
+      unsigned:=not(is_signed(left.resultdef)) or
+                not(is_signed(right.resultdef));
+
+      case nodetype of
+        ltn:
+          if unsigned then
+            cmpop:=OC_B
+          else
+            cmpop:=OC_LT;
+        lten:
+          if unsigned then
+            cmpop:=OC_BE
+          else
+            cmpop:=OC_LTE;
+        gtn:
+          if unsigned then
+            cmpop:=OC_A
+          else
+            cmpop:=OC_GT;
+        gten:
+          if unsigned then
+            cmpop:=OC_AE
+          else
+            cmpop:=OC_GTE;
+        equaln:
+          cmpop:=OC_EQ;
+        unequaln:
+          cmpop:=OC_NE;
+      end;
+      if nf_swapped in flags then
+        cmpop:=swap_opcmp(cmpop);
+
+      location_reset(location,LOC_REGISTER,OS_8);
+      location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
+
+      if right.location.loc=LOC_CONSTANT then
+        current_asmdata.CurrAsmList.concat(taillvm.op_reg_cond_size_reg_const(la_icmp,
+          location.register,cmpop,left.resultdef,left.location.register,right.location.value64))
+      else
+        current_asmdata.CurrAsmList.concat(taillvm.op_reg_cond_size_reg_reg(la_icmp,
+          location.register,cmpop,left.resultdef,left.location.register,right.location.register));
+    end;
+
+
+  procedure tllvmaddnode.second_add64bit;
+    begin
+      second_addordinal;
+    end;
+
+
+  procedure tllvmaddnode.second_cmp64bit;
+    begin
+      second_cmpordinal;
+    end;
+
+
+  procedure tllvmaddnode.second_addfloat;
+    var
+      op    : tllvmop;
+      llvmfpcmp : tllvmfpcmp;
+      cmpop,
+      singleprec : boolean;
+    begin
+      pass_left_right;
+
+      cmpop:=false;
+      singleprec:=tfloatdef(left.resultdef).floattype=s32real;
+      case nodetype of
+        addn :
+          op:=la_fadd;
+        muln :
+          op:=la_fmul;
+        subn :
+          op:=la_fsub;
+        slashn :
+          op:=la_fdiv;
+        ltn,lten,gtn,gten,
+        equaln,unequaln :
+          begin
+            op:=la_fcmp;
+            cmpop:=true;
+            case nodetype of
+              ltn:
+                llvmfpcmp:=lfc_olt;
+              lten:
+                llvmfpcmp:=lfc_ole;
+              gtn:
+                llvmfpcmp:=lfc_ogt;
+              gten:
+                llvmfpcmp:=lfc_oge;
+              equaln:
+                llvmfpcmp:=lfc_oeq;
+              unequaln:
+                llvmfpcmp:=lfc_one;
+            end;
+          end;
+        else
+          internalerror(2013102401);
+      end;
+
+      // get the operands in the correct order, there are no special cases
+      // here, everything is register-based
+      if nf_swapped in flags then
+        swapleftright;
+
+      // put both operands in a register
+      hlcg.location_force_fpureg(current_asmdata.CurrAsmList,right.location,right.resultdef,true);
+      hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
+
+      // initialize the result
+      if not cmpop then
+        begin
+          location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
+          location.register:=hlcg.getfpuregister(current_asmdata.CurrAsmList,resultdef);
+        end
+      else
+        begin
+          location_reset(location,LOC_REGISTER,OS_8);
+          location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
+        end;
+
+      // emit the actual operation
+      if not cmpop then
+        begin
+          current_asmdata.CurrAsmList.concat(taillvm.op_reg_size_reg_reg(op,location.register,resultdef,
+            left.location.register,right.location.register))
+        end
+      else
+        begin
+          current_asmdata.CurrAsmList.concat(taillvm.op_reg_fpcond_size_reg_reg(op,
+            location.register,llvmfpcmp,left.resultdef,left.location.register,right.location.register))
+        end;
+    end;
+
+
+begin
+  caddnode:=tllvmaddnode;
+end.
+