* 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:
begin
case opnr of
0: result:=pasbool8type;
0: result:=llvmbool1type;
3,4: result:=oper[2]^.def;
else
internalerror(2013110801);

View File

@ -934,7 +934,7 @@ implementation
tmpsrc1:=getintregister(list,calcsize);
a_load_reg_reg(list,size,calcsize,dst,tmpsrc1);
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));
end;
@ -950,6 +950,9 @@ implementation
if (size=pasbool8type) and
(cmp_op in [OC_EQ,OC_NE]) then
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
OC_EQ:
invert:=a=0;
@ -967,7 +970,7 @@ implementation
l:=falselab;
falselab:=tmplab;
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);
exit;
end;
@ -984,13 +987,13 @@ implementation
begin
if getregtype(reg1)<>getregtype(reg2) then
internalerror(2012111105);
resreg:=getintregister(list,pasbool8type);
resreg:=getintregister(list,llvmbool1type);
current_asmdata.getjumplabel(falselab);
{ 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,
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_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);
end;
@ -1037,7 +1040,7 @@ implementation
a_load_const_cgpara(list,u32inttype,maxalign,alignpara);
{ we don't know anything about volatility here, should become an extra
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;
sourcepara.done;
destpara.done;
@ -1292,7 +1295,7 @@ implementation
if ovloc.size<>OS_8 then
internalerror(2015122504);
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);
a_label(list,hl);
end;

View File

@ -211,17 +211,23 @@ implementation
end;
end;
end
else if is_pasbool(fromsize) and
not is_pasbool(tosize) then
else if (fromsize=llvmbool1type) and
(tosize<>llvmbool1type) then
begin
if is_cbool(tosize) then
result:=la_sext
else
result:=la_zext
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
result:=la_bitcast;
end;
@ -308,10 +314,10 @@ implementation
if is_void(def) then
encodedstr:=encodedstr+'void'
{ 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'
else
encodedstr:=encodedstr+'i'+tostr(def.size*8);

View File

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

View File

@ -50,7 +50,7 @@ interface
{ procedure second_cord_to_pointer;override; }
procedure second_proc_to_procvar;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_load_smallset;override; }
{ procedure second_ansistring_to_pchar;override; }
@ -202,39 +202,6 @@ procedure tllvmtypeconvnode.second_nil_to_methodprocvar;
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;
var
truelabel,

View File

@ -96,16 +96,16 @@ procedure tllvmmoddivnode.pass_generate_code;
begin
current_asmdata.getjumplabel(hl);
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
current_asmdata.CurrAsmList.concat(taillvm.op_reg_cond_size_reg_const(la_icmp,ovloc.register,OC_EQ,resultdef,left.location.register,low(int64)))
else
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,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;
hlcg.g_overflowCheck_loc(current_asmdata.CurrAsmList,location,resultdef,ovloc);
end;

View File

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

View File

@ -1029,6 +1029,9 @@ interface
bool16type,
bool32type,
bool64type, { implement me }
{$ifdef llvm}
llvmbool1type, { LLVM i1 type }
{$endif llvm}
u8inttype, { 8-Bit unsigned integer }
s8inttype, { 8-Bit signed 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';