* 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 -
This commit is contained in:
Jonas Maebe 2016-05-20 20:51:44 +00:00
parent a29524800f
commit 9d2bba1917
9 changed files with 62 additions and 59 deletions

View File

@ -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);

View File

@ -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;

View File

@ -211,17 +211,23 @@ implementation
end; end;
end; end;
end end
else if is_pasbool(fromsize) and else if (fromsize=llvmbool1type) and
not is_pasbool(tosize) then (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 else if (tosize=llvmbool1type) and
not is_pasbool(fromsize) then (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 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 we need a way to represent the i1 type in Pascal. We don't
no good reason; besides, Pascal booleans can only contain 0 reuse pasbool8type, because putting an i1 in a record or
or 1 in valid code anyway (famous last words...) } passing it as a parameter may result in unexpected behaviour }
else if torddef(def).ordtype=pasbool8 then 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);

View File

@ -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;

View File

@ -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,

View File

@ -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); tmpovreg1:=hlcg.getintregister(current_asmdata.CurrAsmList,llvmbool1type);
tmpovreg2:=hlcg.getintregister(current_asmdata.CurrAsmList,pasbool8type); 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;

View File

@ -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

View File

@ -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 }

View File

@ -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';