+ 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:
Jonas Maebe 2014-07-01 16:30:34 +00:00
parent bf617cb389
commit a8b2b576ca
4 changed files with 105 additions and 27 deletions

View File

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

View File

@ -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 = ('',

View File

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

View File

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