Browse Source

* create a separate type and def for the LLVM "i1" type, because reusing
pasbool8type for this results in too much trouble (we mustn't use i1
for parameters, because then LLVM will try to apply the ABI convention
for passing "1 bit" values, or in records because then this may
result in unwanted bitpacking). Downside: the new LLVMBool1 type is
also exposed in the system unit, because we need it to define LLVM
intrinsics...

git-svn-id: trunk@33726 -

Jonas Maebe 9 years ago
parent
commit
9d2bba1917

+ 1 - 1
compiler/llvm/aasmllvm.pas

@@ -582,7 +582,7 @@ uses
           la_icmp, la_fcmp:
           la_icmp, la_fcmp:
             begin
             begin
               case opnr of
               case opnr of
-                0: result:=pasbool8type;
+                0: result:=llvmbool1type;
                 3,4: result:=oper[2]^.def;
                 3,4: result:=oper[2]^.def;
                 else
                 else
                   internalerror(2013110801);
                   internalerror(2013110801);

+ 9 - 6
compiler/llvm/hlcgllvm.pas

@@ -934,7 +934,7 @@ implementation
       tmpsrc1:=getintregister(list,calcsize);
       tmpsrc1:=getintregister(list,calcsize);
       a_load_reg_reg(list,size,calcsize,dst,tmpsrc1);
       a_load_reg_reg(list,size,calcsize,dst,tmpsrc1);
       location_reset(ovloc,LOC_REGISTER,OS_8);
       location_reset(ovloc,LOC_REGISTER,OS_8);
-      ovloc.register:=getintregister(list,pasbool8type);
+      ovloc.register:=getintregister(list,llvmbool1type);
       list.concat(taillvm.op_reg_cond_size_reg_reg(la_icmp,ovloc.register,OC_NE,calcsize,tmpsrc1,tmpdst));
       list.concat(taillvm.op_reg_cond_size_reg_reg(la_icmp,ovloc.register,OC_NE,calcsize,tmpsrc1,tmpdst));
     end;
     end;
 
 
@@ -950,6 +950,9 @@ implementation
       if (size=pasbool8type) and
       if (size=pasbool8type) and
          (cmp_op in [OC_EQ,OC_NE]) then
          (cmp_op in [OC_EQ,OC_NE]) then
         begin
         begin
+          { convert to an llvmbool1type and use directly }
+          tmpreg:=getintregister(list,llvmbool1type);
+          a_load_reg_reg(list,size,llvmbool1type,reg,tmpreg);
           case cmp_op of
           case cmp_op of
             OC_EQ:
             OC_EQ:
               invert:=a=0;
               invert:=a=0;
@@ -967,7 +970,7 @@ implementation
               l:=falselab;
               l:=falselab;
               falselab:=tmplab;
               falselab:=tmplab;
             end;
             end;
-          list.concat(taillvm.op_size_reg_lab_lab(la_br,pasbool8type,reg,l,falselab));
+          list.concat(taillvm.op_size_reg_lab_lab(la_br,llvmbool1type,tmpreg,l,falselab));
           a_label(list,fallthroughlab);
           a_label(list,fallthroughlab);
           exit;
           exit;
         end;
         end;
@@ -984,13 +987,13 @@ implementation
     begin
     begin
       if getregtype(reg1)<>getregtype(reg2) then
       if getregtype(reg1)<>getregtype(reg2) then
         internalerror(2012111105);
         internalerror(2012111105);
-      resreg:=getintregister(list,pasbool8type);
+      resreg:=getintregister(list,llvmbool1type);
       current_asmdata.getjumplabel(falselab);
       current_asmdata.getjumplabel(falselab);
       { invert order of registers. In FPC, cmp_reg_reg(reg1,reg2) means that
       { invert order of registers. In FPC, cmp_reg_reg(reg1,reg2) means that
         e.g. OC_GT is true if "subl %reg1,%reg2" in x86 AT&T is >0. In LLVM,
         e.g. OC_GT is true if "subl %reg1,%reg2" in x86 AT&T is >0. In LLVM,
         OC_GT is true if op1>op2 }
         OC_GT is true if op1>op2 }
       list.concat(taillvm.op_reg_cond_size_reg_reg(la_icmp,resreg,cmp_op,size,reg2,reg1));
       list.concat(taillvm.op_reg_cond_size_reg_reg(la_icmp,resreg,cmp_op,size,reg2,reg1));
-      list.concat(taillvm.op_size_reg_lab_lab(la_br,pasbool8type,resreg,l,falselab));
+      list.concat(taillvm.op_size_reg_lab_lab(la_br,llvmbool1type,resreg,l,falselab));
       a_label(list,falselab);
       a_label(list,falselab);
     end;
     end;
 
 
@@ -1037,7 +1040,7 @@ implementation
       a_load_const_cgpara(list,u32inttype,maxalign,alignpara);
       a_load_const_cgpara(list,u32inttype,maxalign,alignpara);
       { we don't know anything about volatility here, should become an extra
       { we don't know anything about volatility here, should become an extra
         parameter to g_concatcopy }
         parameter to g_concatcopy }
-      a_load_const_cgpara(list,pasbool8type,0,volatilepara);
+      a_load_const_cgpara(list,llvmbool1type,0,volatilepara);
       g_call_system_proc(list,pd,[@destpara,@sourcepara,@sizepara,@alignpara,@volatilepara],nil).resetiftemp;
       g_call_system_proc(list,pd,[@destpara,@sourcepara,@sizepara,@alignpara,@volatilepara],nil).resetiftemp;
       sourcepara.done;
       sourcepara.done;
       destpara.done;
       destpara.done;
@@ -1292,7 +1295,7 @@ implementation
       if ovloc.size<>OS_8 then
       if ovloc.size<>OS_8 then
         internalerror(2015122504);
         internalerror(2015122504);
       current_asmdata.getjumplabel(hl);
       current_asmdata.getjumplabel(hl);
-      a_cmp_const_loc_label(list,pasbool8type,OC_EQ,0,ovloc,hl);
+      a_cmp_const_loc_label(list,llvmbool1type,OC_EQ,0,ovloc,hl);
       g_call_system_proc(list,'fpc_overflow',[],nil);
       g_call_system_proc(list,'fpc_overflow',[],nil);
       a_label(list,hl);
       a_label(list,hl);
     end;
     end;

+ 15 - 9
compiler/llvm/llvmdef.pas

@@ -211,17 +211,23 @@ implementation
                   end;
                   end;
               end;
               end;
             end
             end
-          else if is_pasbool(fromsize) and
-                  not is_pasbool(tosize) then
+          else if (fromsize=llvmbool1type) and
+                  (tosize<>llvmbool1type) then
             begin
             begin
               if is_cbool(tosize) then
               if is_cbool(tosize) then
                 result:=la_sext
                 result:=la_sext
               else
               else
                 result:=la_zext
                 result:=la_zext
             end
             end
-          else if is_pasbool(tosize) and
-                  not is_pasbool(fromsize) then
-            result:=la_trunc
+          else if (tosize=llvmbool1type) and
+                  (fromsize<>llvmbool1type) then
+            begin
+              { would have to compare with 0, can't just take the lowest bit }
+              if is_cbool(fromsize) then
+                internalerror(2016052001)
+              else
+                result:=la_trunc
+            end
           else
           else
             result:=la_bitcast;
             result:=la_bitcast;
         end;
         end;
@@ -308,10 +314,10 @@ implementation
               if is_void(def) then
               if is_void(def) then
                 encodedstr:=encodedstr+'void'
                 encodedstr:=encodedstr+'void'
               { mainly required because comparison operations return i1, and
               { mainly required because comparison operations return i1, and
-                otherwise we always have to immediatel extend them to i8 for
-                no good reason; besides, Pascal booleans can only contain 0
-                or 1 in valid code anyway (famous last words...) }
-              else if torddef(def).ordtype=pasbool8 then
+                we need a way to represent the i1 type in Pascal. We don't
+                reuse pasbool8type, because putting an i1 in a record or
+                passing it as a parameter may result in unexpected behaviour }
+              else if def=llvmbool1type then
                 encodedstr:=encodedstr+'i1'
                 encodedstr:=encodedstr+'i1'
               else
               else
                 encodedstr:=encodedstr+'i'+tostr(def.size*8);
                 encodedstr:=encodedstr+'i'+tostr(def.size*8);

+ 16 - 4
compiler/llvm/nllvmadd.pas

@@ -109,7 +109,7 @@ implementation
       pass_left_right;
       pass_left_right;
 
 
       location_reset(location,LOC_REGISTER,OS_8);
       location_reset(location,LOC_REGISTER,OS_8);
-      location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,pasbool8type);
+      location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,llvmbool1type);
 
 
       force_reg_left_right(false,false);
       force_reg_left_right(false,false);
 
 
@@ -143,11 +143,15 @@ implementation
         else
         else
           internalerror(2012042701);
           internalerror(2012042701);
       end;
       end;
+      tmpreg:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
+      hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,llvmbool1type,resultdef,location.register,tmpreg);
+      location.register:=tmpreg;
     end;
     end;
 
 
 
 
   procedure tllvmaddnode.second_cmpordinal;
   procedure tllvmaddnode.second_cmpordinal;
     var
     var
+      tmpreg: tregister;
       cmpop: topcmp;
       cmpop: topcmp;
       unsigned : boolean;
       unsigned : boolean;
     begin
     begin
@@ -189,7 +193,7 @@ implementation
         cmpop:=swap_opcmp(cmpop);
         cmpop:=swap_opcmp(cmpop);
 
 
       location_reset(location,LOC_REGISTER,OS_8);
       location_reset(location,LOC_REGISTER,OS_8);
-      location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
+      location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,llvmbool1type);
 
 
       if right.location.loc=LOC_CONSTANT then
       if right.location.loc=LOC_CONSTANT then
         current_asmdata.CurrAsmList.concat(taillvm.op_reg_cond_size_reg_const(la_icmp,
         current_asmdata.CurrAsmList.concat(taillvm.op_reg_cond_size_reg_const(la_icmp,
@@ -197,6 +201,10 @@ implementation
       else
       else
         current_asmdata.CurrAsmList.concat(taillvm.op_reg_cond_size_reg_reg(la_icmp,
         current_asmdata.CurrAsmList.concat(taillvm.op_reg_cond_size_reg_reg(la_icmp,
           location.register,cmpop,left.resultdef,left.location.register,right.location.register));
           location.register,cmpop,left.resultdef,left.location.register,right.location.register));
+
+      tmpreg:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
+      hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,llvmbool1type,resultdef,location.register,tmpreg);
+      location.register:=tmpreg;
     end;
     end;
 
 
 
 
@@ -214,6 +222,7 @@ implementation
 
 
   procedure tllvmaddnode.second_addfloat;
   procedure tllvmaddnode.second_addfloat;
     var
     var
+      tmpreg: tregister;
       op    : tllvmop;
       op    : tllvmop;
       llvmfpcmp : tllvmfpcmp;
       llvmfpcmp : tllvmfpcmp;
       size : tdef;
       size : tdef;
@@ -279,7 +288,7 @@ implementation
       else
       else
         begin
         begin
           location_reset(location,LOC_REGISTER,OS_8);
           location_reset(location,LOC_REGISTER,OS_8);
-          location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
+          location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,llvmbool1type);
         end;
         end;
 
 
       { see comment in thlcgllvm.a_loadfpu_ref_reg }
       { see comment in thlcgllvm.a_loadfpu_ref_reg }
@@ -297,7 +306,10 @@ implementation
       else
       else
         begin
         begin
           current_asmdata.CurrAsmList.concat(taillvm.op_reg_fpcond_size_reg_reg(op,
           current_asmdata.CurrAsmList.concat(taillvm.op_reg_fpcond_size_reg_reg(op,
-            location.register,llvmfpcmp,size,left.location.register,right.location.register))
+            location.register,llvmfpcmp,size,left.location.register,right.location.register));
+          tmpreg:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
+          hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,llvmbool1type,resultdef,location.register,tmpreg);
+          location.register:=tmpreg;
         end;
         end;
     end;
     end;
 
 

+ 1 - 34
compiler/llvm/nllvmcnv.pas

@@ -50,7 +50,7 @@ interface
          { procedure second_cord_to_pointer;override; }
          { procedure second_cord_to_pointer;override; }
          procedure second_proc_to_procvar;override;
          procedure second_proc_to_procvar;override;
          procedure second_nil_to_methodprocvar; override;
          procedure second_nil_to_methodprocvar; override;
-         procedure second_bool_to_int;override;
+         { procedure second_bool_to_int;override; }
          procedure second_int_to_bool;override;
          procedure second_int_to_bool;override;
          { procedure second_load_smallset;override;  }
          { procedure second_load_smallset;override;  }
          { procedure second_ansistring_to_pchar;override; }
          { procedure second_ansistring_to_pchar;override; }
@@ -202,39 +202,6 @@ procedure tllvmtypeconvnode.second_nil_to_methodprocvar;
   end;
   end;
 
 
 
 
-procedure tllvmtypeconvnode.second_bool_to_int;
-  var
-    pdef: tdef;
-    hreg: tregister;
-  begin
-    inherited;
-    { all boolean/integer of the same size are represented using the same type
-      by FPC in LLVM, except for Pascal booleans, which are i1 -> convert
-      the type if necessary. This never has to be done for registers on the
-      assignment side, because we make everything that's explicitly typecasted
-      on the assignment side non regable for llvm }
-    if is_pasbool(left.resultdef) and
-       (nf_explicit in flags) and
-       not(left.location.loc in [LOC_FLAGS,LOC_JUMP]) and
-       (resultdef.size=1) then
-      case location.loc of
-        LOC_REFERENCE,LOC_CREFERENCE:
-          begin
-            pdef:=cpointerdef.getreusable(resultdef);
-            hreg:=hlcg.getaddressregister(current_asmdata.CurrAsmList,pdef);
-            hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.resultdef,pdef,location.reference,hreg);
-            hlcg.reference_reset_base(location.reference,pdef,hreg,0,location.reference.alignment);
-          end;
-        LOC_REGISTER,LOC_CREGISTER:
-          begin
-            hreg:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
-            hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,left.resultdef,resultdef,location.register,hreg);
-            location.register:=hreg;
-          end;
-      end;
-  end;
-
-
 procedure tllvmtypeconvnode.second_int_to_bool;
 procedure tllvmtypeconvnode.second_int_to_bool;
   var
   var
     truelabel,
     truelabel,

+ 4 - 4
compiler/llvm/nllvmmat.pas

@@ -96,16 +96,16 @@ procedure tllvmmoddivnode.pass_generate_code;
       begin
       begin
         current_asmdata.getjumplabel(hl);
         current_asmdata.getjumplabel(hl);
         location_reset(ovloc,LOC_REGISTER,OS_8);
         location_reset(ovloc,LOC_REGISTER,OS_8);
-        ovloc.register:=hlcg.getintregister(current_asmdata.CurrAsmList,pasbool8type);
+        ovloc.register:=hlcg.getintregister(current_asmdata.CurrAsmList,llvmbool1type);
         if right.nodetype=ordconstn then
         if right.nodetype=ordconstn then
           current_asmdata.CurrAsmList.concat(taillvm.op_reg_cond_size_reg_const(la_icmp,ovloc.register,OC_EQ,resultdef,left.location.register,low(int64)))
           current_asmdata.CurrAsmList.concat(taillvm.op_reg_cond_size_reg_const(la_icmp,ovloc.register,OC_EQ,resultdef,left.location.register,low(int64)))
         else
         else
           begin
           begin
-            tmpovreg1:=hlcg.getintregister(current_asmdata.CurrAsmList,pasbool8type);
-            tmpovreg2:=hlcg.getintregister(current_asmdata.CurrAsmList,pasbool8type);
+            tmpovreg1:=hlcg.getintregister(current_asmdata.CurrAsmList,llvmbool1type);
+            tmpovreg2:=hlcg.getintregister(current_asmdata.CurrAsmList,llvmbool1type);
             current_asmdata.CurrAsmList.concat(taillvm.op_reg_cond_size_reg_const(la_icmp,tmpovreg1,OC_EQ,resultdef,left.location.register,low(int64)));
             current_asmdata.CurrAsmList.concat(taillvm.op_reg_cond_size_reg_const(la_icmp,tmpovreg1,OC_EQ,resultdef,left.location.register,low(int64)));
             current_asmdata.CurrAsmList.concat(taillvm.op_reg_cond_size_reg_const(la_icmp,tmpovreg2,OC_EQ,resultdef,right.location.register,-1));
             current_asmdata.CurrAsmList.concat(taillvm.op_reg_cond_size_reg_const(la_icmp,tmpovreg2,OC_EQ,resultdef,right.location.register,-1));
-            hlcg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_AND,pasbool8type,tmpovreg1,tmpovreg2,ovloc.register);
+            hlcg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_AND,llvmbool1type,tmpovreg1,tmpovreg2,ovloc.register);
           end;
           end;
         hlcg.g_overflowCheck_loc(current_asmdata.CurrAsmList,location,resultdef,ovloc);
         hlcg.g_overflowCheck_loc(current_asmdata.CurrAsmList,location,resultdef,ovloc);
       end;
       end;

+ 12 - 0
compiler/psystem.pas

@@ -243,6 +243,9 @@ implementation
         bool16type:=corddef.create(bool16bit,low(int64),high(int64),true);
         bool16type:=corddef.create(bool16bit,low(int64),high(int64),true);
         bool32type:=corddef.create(bool32bit,low(int64),high(int64),true);
         bool32type:=corddef.create(bool32bit,low(int64),high(int64),true);
         bool64type:=corddef.create(bool64bit,low(int64),high(int64),true);
         bool64type:=corddef.create(bool64bit,low(int64),high(int64),true);
+{$ifdef llvm}
+        llvmbool1type:=corddef.create(pasbool8,0,1,true);
+{$endif llvm}
         cansichartype:=corddef.create(uchar,0,255,true);
         cansichartype:=corddef.create(uchar,0,255,true);
         cwidechartype:=corddef.create(uwidechar,0,65535,true);
         cwidechartype:=corddef.create(uwidechar,0,65535,true);
         cshortstringtype:=cstringdef.createshort(255,true);
         cshortstringtype:=cstringdef.createshort(255,true);
@@ -413,6 +416,9 @@ implementation
         addtype('WordBool',bool16type);
         addtype('WordBool',bool16type);
         addtype('LongBool',bool32type);
         addtype('LongBool',bool32type);
         addtype('QWordBool',bool64type);
         addtype('QWordBool',bool64type);
+{$ifdef llvm}
+        addtype('LLVMBool1',llvmbool1type);
+{$endif llvm}
         addtype('Byte',u8inttype);
         addtype('Byte',u8inttype);
         addtype('ShortInt',s8inttype);
         addtype('ShortInt',s8inttype);
         addtype('Word',u16inttype);
         addtype('Word',u16inttype);
@@ -459,6 +465,9 @@ implementation
         addtype('$wordbool',bool16type);
         addtype('$wordbool',bool16type);
         addtype('$longbool',bool32type);
         addtype('$longbool',bool32type);
         addtype('$qwordbool',bool64type);
         addtype('$qwordbool',bool64type);
+{$ifdef llvm}
+        addtype('$llvmbool1',llvmbool1type);
+{$endif llvm}
         addtype('$char_pointer',charpointertype);
         addtype('$char_pointer',charpointertype);
         addtype('$widechar_pointer',widecharpointertype);
         addtype('$widechar_pointer',widecharpointertype);
         addtype('$parentfp_void_pointer',parentfpvoidpointertype);
         addtype('$parentfp_void_pointer',parentfpvoidpointertype);
@@ -621,6 +630,9 @@ implementation
         loadtype('longint_farpointer',longintfarpointertype);
         loadtype('longint_farpointer',longintfarpointertype);
   {$endif i8086}
   {$endif i8086}
 {$endif x86}
 {$endif x86}
+{$ifdef llvm}
+        loadtype('llvmbool1',llvmbool1type);
+{$endif llvm}
         loadtype('file',cfiletype);
         loadtype('file',cfiletype);
         if not(target_info.system in systems_managed_vm) then
         if not(target_info.system in systems_managed_vm) then
           begin
           begin

+ 3 - 0
compiler/symdef.pas

@@ -1029,6 +1029,9 @@ interface
        bool16type,
        bool16type,
        bool32type,
        bool32type,
        bool64type,                { implement me }
        bool64type,                { implement me }
+{$ifdef llvm}
+       llvmbool1type,             { LLVM i1 type }
+{$endif llvm}
        u8inttype,                 { 8-Bit unsigned integer }
        u8inttype,                 { 8-Bit unsigned integer }
        s8inttype,                 { 8-Bit signed integer }
        s8inttype,                 { 8-Bit signed integer }
        u16inttype,                { 16-Bit unsigned integer }
        u16inttype,                { 16-Bit unsigned integer }

+ 1 - 1
rtl/inc/llvmintr.inc

@@ -14,6 +14,6 @@
  **********************************************************************}
  **********************************************************************}
 
 
 
 
-procedure llvm_memcpy64(dest, source: pointer; len: qword; align: cardinal; isvolatile: boolean); compilerproc; external name 'llvm.memcpy.p0i8.p0i8.i64';
+procedure llvm_memcpy64(dest, source: pointer; len: qword; align: cardinal; isvolatile: LLVMBool1); compilerproc; external name 'llvm.memcpy.p0i8.p0i8.i64';
 
 
 function llvm_frameaddress(level: longint): pointer; compilerproc; external name 'llvm.frameaddress';
 function llvm_frameaddress(level: longint): pointer; compilerproc; external name 'llvm.frameaddress';