mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2026-01-07 10:00:35 +01:00
+ new llvmconvop() routine that determines the conversion operation to
convert one def to another, including information regarding whether
it should be done via an intermediate integer typecast
* use this routine in hlcgllvm
git-svn-id: branches/hlcgllvm@28116 -
This commit is contained in:
parent
bf617cb389
commit
a8b2b576ca
@ -480,32 +480,35 @@ implementation
|
||||
|
||||
procedure thlcgllvm.a_load_reg_reg(list: TAsmList; fromsize, tosize: tdef; reg1, reg2: tregister);
|
||||
var
|
||||
fromregtyp,
|
||||
toregtyp: tregistertype;
|
||||
op: tllvmop;
|
||||
tmpreg: tregister;
|
||||
tmpintdef: tdef;
|
||||
begin
|
||||
fromregtyp:=def2regtyp(fromsize);
|
||||
toregtyp:=def2regtyp(tosize);
|
||||
{ int to pointer or vice versa }
|
||||
if (fromregtyp=R_ADDRESSREGISTER) and
|
||||
(toregtyp=R_INTREGISTER) then
|
||||
op:=la_ptrtoint
|
||||
else if (fromregtyp=R_INTREGISTER) and
|
||||
(toregtyp=R_ADDRESSREGISTER) then
|
||||
op:=la_inttoptr
|
||||
{ int to int or ptr to ptr: need zero/sign extension, or plain bitcast? }
|
||||
else if tosize.size<>fromsize.size then
|
||||
begin
|
||||
if tosize.size<fromsize.size then
|
||||
op:=la_trunc
|
||||
else if is_signed(fromsize) then
|
||||
{ fromsize is signed -> sign extension }
|
||||
op:=la_sext
|
||||
else
|
||||
op:=la_zext;
|
||||
end
|
||||
else
|
||||
op:=la_bitcast;
|
||||
op:=llvmconvop(fromsize,tosize);
|
||||
{ converting from pointer to something else and vice versa is only
|
||||
possible via an intermediate pass to integer. Same for "something else"
|
||||
to pointer. }
|
||||
case op of
|
||||
la_ptrtoint_to_x,
|
||||
la_x_to_inttoptr:
|
||||
begin
|
||||
{ convert via an integer with the same size as "x" }
|
||||
if op=la_ptrtoint_to_x then
|
||||
begin
|
||||
tmpintdef:=cgsize_orddef(def_cgsize(tosize));
|
||||
op:=la_bitcast
|
||||
end
|
||||
else
|
||||
begin
|
||||
tmpintdef:=cgsize_orddef(def_cgsize(fromsize));
|
||||
op:=la_inttoptr;
|
||||
end;
|
||||
tmpreg:=getintregister(list,tmpintdef);
|
||||
a_load_reg_reg(list,fromsize,tmpintdef,reg1,tmpreg);
|
||||
reg1:=tmpreg;
|
||||
fromsize:=tmpintdef;
|
||||
end;
|
||||
end;
|
||||
{ reg2 = bitcast fromsize reg1 to tosize }
|
||||
list.concat(taillvm.op_reg_size_reg_size(op,reg2,fromsize,reg1,tosize));
|
||||
end;
|
||||
|
||||
@ -58,7 +58,9 @@ interface
|
||||
'phi', 'select', 'call',
|
||||
'va_arg', 'landingpad',
|
||||
{ fpc pseudo opcodes }
|
||||
'type' { type definition }
|
||||
'type', { type definition }
|
||||
'invalid1', { la_x_to_inttoptr }
|
||||
'invalid2' { la_ptrtoint_to_x }
|
||||
);
|
||||
|
||||
llvm_cond2str : array[topcmp] of ansistring = ('',
|
||||
|
||||
@ -66,7 +66,9 @@ interface
|
||||
la_phi, la_select, la_call,
|
||||
la_va_arg, la_landingpad,
|
||||
{ fpc pseudo opcodes }
|
||||
la_type { type definition }
|
||||
la_type, { type definition }
|
||||
la_x_to_inttoptr, { have to convert something first to int before it can be converted to a pointer }
|
||||
la_ptrtoint_to_x { have to convert a pointer first to int before it can be converted to something else }
|
||||
);
|
||||
|
||||
tllvmvalueextension = (lve_none, lve_zeroext, lve_signext);
|
||||
|
||||
@ -94,6 +94,8 @@ interface
|
||||
(struct, array) }
|
||||
function llvmaggregatetype(def: tdef): boolean;
|
||||
|
||||
function llvmconvop(fromsize, tosize: tdef): tllvmop;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
@ -102,7 +104,7 @@ implementation
|
||||
verbose,systems,
|
||||
fmodule,
|
||||
symtable,symconst,symsym,
|
||||
llvmsym,
|
||||
llvmsym,hlcgobj,
|
||||
defutil,cgbase,paramgr;
|
||||
|
||||
|
||||
@ -125,6 +127,75 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
function llvmconvop(fromsize, tosize: tdef): tllvmop;
|
||||
var
|
||||
fromregtyp,
|
||||
toregtyp: tregistertype;
|
||||
frombytesize,
|
||||
tobytesize: asizeint;
|
||||
begin
|
||||
fromregtyp:=hlcg.def2regtyp(fromsize);
|
||||
toregtyp:=hlcg.def2regtyp(tosize);
|
||||
{ int to pointer or vice versa }
|
||||
if fromregtyp=R_ADDRESSREGISTER then
|
||||
begin
|
||||
case toregtyp of
|
||||
R_INTREGISTER:
|
||||
result:=la_ptrtoint;
|
||||
R_ADDRESSREGISTER:
|
||||
result:=la_bitcast;
|
||||
else
|
||||
result:=la_ptrtoint_to_x;
|
||||
end;
|
||||
end
|
||||
else if toregtyp=R_ADDRESSREGISTER then
|
||||
begin
|
||||
case fromregtyp of
|
||||
R_INTREGISTER:
|
||||
result:=la_inttoptr;
|
||||
R_ADDRESSREGISTER:
|
||||
result:=la_bitcast;
|
||||
else
|
||||
result:=la_x_to_inttoptr;
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
frombytesize:=fromsize.size;
|
||||
tobytesize:=tosize.size;
|
||||
{ need zero/sign extension, float truncation or plain bitcast? }
|
||||
if tobytesize<>frombytesize then
|
||||
begin
|
||||
case fromregtyp of
|
||||
R_FPUREGISTER,
|
||||
R_MMREGISTER:
|
||||
begin
|
||||
{ todo: update once we support vectors }
|
||||
if not(toregtyp in [R_FPUREGISTER,R_MMREGISTER]) then
|
||||
internalerror(2014062203);
|
||||
if tobytesize<frombytesize then
|
||||
result:=la_fptrunc
|
||||
else
|
||||
result:=la_fpext
|
||||
end;
|
||||
else
|
||||
begin
|
||||
if tobytesize<frombytesize then
|
||||
result:=la_trunc
|
||||
else if is_signed(fromsize) then
|
||||
{ fromsize is signed -> sign extension }
|
||||
result:=la_sext
|
||||
else
|
||||
result:=la_zext;
|
||||
end;
|
||||
end;
|
||||
end
|
||||
else
|
||||
result:=la_bitcast;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
function llvmbyvalparaloc(paraloc: pcgparalocation): boolean;
|
||||
begin
|
||||
{ "byval" is broken for register paras on several platforms in llvm
|
||||
|
||||
Loading…
Reference in New Issue
Block a user