Browse Source

LLVM: override thlcgobj.g_undefined_ok

Uses the freeze instruction available in LLVM 10.0+. If we don't freeze undef/
poison values before using them in a calculation (even if that calculation is
something like "and 0", which masks the result completely), the result will
still be undef/poison and will keep propagating.
Jonas Maebe 2 years ago
parent
commit
ab581c5c30

+ 15 - 1
compiler/llvm/aasmllvm.pas

@@ -57,6 +57,8 @@ interface
         { e.g. dst = alloca size }
         { e.g. dst = alloca size }
         constructor op_ref_size(op:tllvmop;const dst:treference;size:tdef);
         constructor op_ref_size(op:tllvmop;const dst:treference;size:tdef);
 
 
+        { e.g. dst = freeze size src }
+        constructor op_reg_size_reg(op:tllvmop;dst:tregister;size:tdef;src:tregister);
         { e.g. dst = add size src1, src2 }
         { e.g. dst = add size src1, src2 }
         constructor op_reg_size_reg_reg(op:tllvmop;dst:tregister;size:tdef;src1,src2:tregister);
         constructor op_reg_size_reg_reg(op:tllvmop;dst:tregister;size:tdef;src1,src2:tregister);
         { e.g. dst = shl size src1, 1 ( = src1 shl 1) }
         { e.g. dst = shl size src1, 1 ( = src1 shl 1) }
@@ -637,7 +639,8 @@ implementation
           la_load,
           la_load,
           la_icmp, la_fcmp,
           la_icmp, la_fcmp,
           la_phi, la_select,
           la_phi, la_select,
-          la_va_arg, la_landingpad:
+          la_va_arg, la_landingpad,
+          la_freeze:
             begin
             begin
               if opnr=0 then
               if opnr=0 then
                 result:=operand_write
                 result:=operand_write
@@ -855,6 +858,17 @@ implementation
       end;
       end;
 
 
 
 
+    { %dst = freeze i32 %src }
+    constructor taillvm.op_reg_size_reg(op: tllvmop; dst: tregister; size: tdef; src: tregister);
+      begin
+        create_llvm(op);
+        ops:=3;
+        loadreg(0,dst);
+        loaddef(1,size);
+        loadreg(2,src);
+      end;
+
+
     { %dst = add i32 %src1, %src2 }
     { %dst = add i32 %src1, %src2 }
     constructor taillvm.op_reg_size_reg_reg(op: tllvmop; dst: tregister;size: tdef; src1, src2: tregister);
     constructor taillvm.op_reg_size_reg_reg(op: tllvmop; dst: tregister;size: tdef; src1, src2: tregister);
       begin
       begin

+ 13 - 0
compiler/llvm/hlcgllvm.pas

@@ -98,6 +98,8 @@ uses
 
 
       procedure g_concatcopy(list : TAsmList;size: tdef; const source,dest : treference);override;
       procedure g_concatcopy(list : TAsmList;size: tdef; const source,dest : treference);override;
 
 
+      procedure g_undefined_ok(list: TAsmList; size: tdef; reg: tregister); override;
+
       procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; reg: tregister); override;
       procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; reg: tregister); override;
       procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tdef; reg: tregister; const ref: treference); override;
       procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tdef; reg: tregister; const ref: treference); override;
       procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tdef; reg1, reg2: tregister); override;
       procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tdef; reg1, reg2: tregister); override;
@@ -1319,6 +1321,17 @@ implementation
     end;
     end;
 
 
 
 
+  procedure thlcgllvm.g_undefined_ok(list: TAsmList; size: tdef; reg: tregister);
+    begin
+      if not(llvmflag_no_freeze in llvmversion_properties[current_settings.llvmversion]) then
+        begin
+          list.concat(taillvm.op_reg_size_reg(la_freeze,reg,size,reg));
+          exit;
+        end;
+      internalerror(2023010110);
+    end;
+
+
   procedure thlcgllvm.a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; reg: tregister);
   procedure thlcgllvm.a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; reg: tregister);
     var
     var
        tmpreg: tregister;
        tmpreg: tregister;

+ 1 - 0
compiler/llvm/itllvm.pas

@@ -58,6 +58,7 @@ interface
         'phi', 'select', 'call',
         'phi', 'select', 'call',
         'va_arg', 'landingpad',
         'va_arg', 'landingpad',
         'blockaddress',
         'blockaddress',
+        'freeze',
         { fpc pseudo opcodes }
         { fpc pseudo opcodes }
         'type', { type definition }
         'type', { type definition }
         'catch', { catch exception }
         'catch', { catch exception }

+ 1 - 0
compiler/llvm/llvmbase.pas

@@ -66,6 +66,7 @@ interface
       la_phi, la_select, la_call,
       la_phi, la_select, la_call,
       la_va_arg, la_landingpad,
       la_va_arg, la_landingpad,
       la_blockaddress,
       la_blockaddress,
+      la_freeze,
       { fpc pseudo opcodes }
       { fpc pseudo opcodes }
       la_type, { type definition }
       la_type, { type definition }
       la_catch, { catch clause of a landingpad }
       la_catch, { catch clause of a landingpad }

+ 8 - 7
compiler/llvm/llvminfo.pas

@@ -72,7 +72,8 @@ type
      llvmflag_para_attr_type,               { parameter attributes such as noalias and byval need to repeat the type }
      llvmflag_para_attr_type,               { parameter attributes such as noalias and byval need to repeat the type }
      llvmflag_opaque_ptr_transition,        { initial opaque pointer introduction, needs to some elementtype attributes }
      llvmflag_opaque_ptr_transition,        { initial opaque pointer introduction, needs to some elementtype attributes }
      llvmflag_opaque_ptr,                   { only opaque pointers }
      llvmflag_opaque_ptr,                   { only opaque pointers }
-     llvmflag_sanitizer_attributes          { can use attributes to exclude symbols from sanitizers }
+     llvmflag_sanitizer_attributes,         { can use attributes to exclude symbols from sanitizers }
+     llvmflag_no_freeze                     { lacks the freeze opcode to clear undefined/poison values }
    );
    );
    tllvmversionflags = set of tllvmversionflag;
    tllvmversionflags = set of tllvmversionflag;
 
 
@@ -124,12 +125,12 @@ Const
    llvmversion_properties: array[tllvmversion] of tllvmversionflags =
    llvmversion_properties: array[tllvmversion] of tllvmversionflags =
      (
      (
        { invalid         } [],
        { invalid         } [],
-       { llvmver_7_0     } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_NoDISPFlags],
-       { llvmver_7_1     } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_NoDISPFlags],
-       { llvmver_8_0     } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_NoDISPFlagMainSubprogram],
-       { llvmver_xc_11   } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_NoDISPFlagMainSubprogram],
-       { llvmver_9_0     } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_constrained_fptrunc_fpext],
-       { llvmver_xc_11_4 } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_constrained_fptrunc_fpext],
+       { llvmver_7_0     } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_NoDISPFlags,llvmflag_no_freeze],
+       { llvmver_7_1     } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_NoDISPFlags,llvmflag_no_freeze],
+       { llvmver_8_0     } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_NoDISPFlagMainSubprogram,llvmflag_no_freeze],
+       { llvmver_xc_11   } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_NoDISPFlagMainSubprogram,llvmflag_no_freeze],
+       { llvmver_9_0     } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_constrained_fptrunc_fpext,llvmflag_no_freeze],
+       { llvmver_xc_11_4 } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_constrained_fptrunc_fpext,llvmflag_no_freeze],
        { llvmver_10_0    } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_constrained_fptrunc_fpext,llvmflag_constrained_fptoi_itofp],
        { llvmver_10_0    } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_constrained_fptrunc_fpext,llvmflag_constrained_fptoi_itofp],
        { llvmver_xc_12_0 } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_constrained_fptrunc_fpext,llvmflag_constrained_fptoi_itofp],
        { llvmver_xc_12_0 } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid,llvmflag_constrained_fptrunc_fpext,llvmflag_constrained_fptoi_itofp],
        { llvmver_11_0    } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid_new,llvmflag_constrained_fptrunc_fpext,llvmflag_constrained_fptoi_itofp,llvmflag_array_datalocation],
        { llvmver_11_0    } [llvmflag_memcpy_indiv_align,llvmflag_null_pointer_valid_new,llvmflag_constrained_fptrunc_fpext,llvmflag_constrained_fptoi_itofp,llvmflag_array_datalocation],