mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-11-01 14:10:57 +01:00
* 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:
parent
a29524800f
commit
9d2bba1917
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 }
|
||||
|
||||
@ -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';
|
||||
|
||||
Loading…
Reference in New Issue
Block a user