mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-21 20:29:32 +02:00
* also support non-pointerdefs as first argument for g_ptrtypecast_ref()
via internal restructuring of the llvm code generator (so we can typecast e.g. a procvardef to a pointerdef) git-svn-id: trunk@32550 -
This commit is contained in:
parent
6735def16f
commit
4f4d4d9456
@ -542,7 +542,7 @@ unit hlcgobj;
|
||||
reference if necessary. fromdef needs to be a pointerdef because
|
||||
it may have to be passed as fromdef to a_loadaddr_ref_reg, which
|
||||
needs the "pointeddef" of fromdef }
|
||||
procedure g_ptrtypecast_ref(list: TAsmList; fromdef: tpointerdef; todef: tdef; var ref: treference); virtual;
|
||||
procedure g_ptrtypecast_ref(list: TAsmList; fromdef, todef: tdef; var ref: treference); virtual;
|
||||
|
||||
{ update a reference pointing to the start address of a record/object/
|
||||
class (contents) so it refers to the indicated field }
|
||||
@ -3844,7 +3844,7 @@ implementation
|
||||
{ nothing to do }
|
||||
end;
|
||||
|
||||
procedure thlcgobj.g_ptrtypecast_ref(list: TAsmList; fromdef: tpointerdef; todef: tdef; var ref: treference);
|
||||
procedure thlcgobj.g_ptrtypecast_ref(list: TAsmList; fromdef, todef: tdef; var ref: treference);
|
||||
begin
|
||||
{ nothing to do }
|
||||
end;
|
||||
|
@ -62,6 +62,9 @@ uses
|
||||
procedure a_load_reg_reg(list : TAsmList;fromsize, tosize : tdef;reg1,reg2 : tregister);override;
|
||||
procedure a_load_ref_reg(list : TAsmList;fromsize, tosize : tdef;const ref : treference;register : tregister);override;
|
||||
procedure a_load_ref_ref(list: TAsmList; fromsize, tosize: tdef; const sref: treference; const dref: treference); override;
|
||||
protected
|
||||
procedure a_loadaddr_ref_reg_intern(list : TAsmList;fromsize, tosize : tdef;const ref : treference;r : tregister; makefromsizepointer: boolean);
|
||||
public
|
||||
procedure a_loadaddr_ref_reg(list : TAsmList;fromsize, tosize : tdef;const ref : treference;r : tregister);override;
|
||||
|
||||
procedure a_op_const_reg(list: TAsmList; Op: TOpCG; size: tdef; a: tcgint; reg: TRegister); override;
|
||||
@ -95,7 +98,7 @@ uses
|
||||
procedure g_overflowCheck_loc(List:TAsmList;const Loc:TLocation;def:TDef;var ovloc : tlocation); override;
|
||||
|
||||
procedure g_ptrtypecast_reg(list: TAsmList; fromdef, todef: tdef; var reg: tregister); override;
|
||||
procedure g_ptrtypecast_ref(list: TAsmList; fromdef: tpointerdef; todef: tdef; var ref: treference); override;
|
||||
procedure g_ptrtypecast_ref(list: TAsmList; fromdef, todef: tdef; var ref: treference); override;
|
||||
|
||||
procedure g_set_addr_nonbitpacked_field_ref(list: TAsmList; recdef: tabstractrecorddef; field: tfieldvarsym; var recref: treference); override;
|
||||
|
||||
@ -133,6 +136,9 @@ uses
|
||||
|
||||
procedure g_external_wrapper(list: TAsmList; procdef: tprocdef; const externalname: string); override;
|
||||
|
||||
{ def is a pointerdef or implicit pointer type (class, classref, procvar,
|
||||
dynamic array, ...). }
|
||||
function make_simple_ref_ptr(list: TAsmList; const ref: treference; ptrdef: tdef): treference;
|
||||
{ def is the type of the data stored in memory pointed to by ref, not
|
||||
a pointer to this type }
|
||||
function make_simple_ref(list: TAsmList; const ref: treference; def: tdef): treference;
|
||||
@ -706,15 +712,23 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
procedure thlcgllvm.a_loadaddr_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; r: tregister);
|
||||
procedure thlcgllvm.a_loadaddr_ref_reg_intern(list: TAsmList; fromsize, tosize: tdef; const ref: treference; r: tregister; makefromsizepointer: boolean);
|
||||
var
|
||||
sref: treference;
|
||||
begin
|
||||
{ can't take the address of a 'named register' }
|
||||
if ref.refaddr=addr_full then
|
||||
internalerror(2013102306);
|
||||
sref:=make_simple_ref(list,ref,fromsize);
|
||||
list.concat(taillvm.op_reg_size_ref_size(la_bitcast,r,cpointerdef.getreusable(fromsize),sref,tosize));
|
||||
if makefromsizepointer then
|
||||
fromsize:=cpointerdef.getreusable(fromsize);
|
||||
sref:=make_simple_ref_ptr(list,ref,fromsize);
|
||||
list.concat(taillvm.op_reg_size_ref_size(la_bitcast,r,fromsize,sref,tosize));
|
||||
end;
|
||||
|
||||
|
||||
procedure thlcgllvm.a_loadaddr_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; r: tregister);
|
||||
begin
|
||||
a_loadaddr_ref_reg_intern(list,fromsize,tosize,ref,r,true);
|
||||
end;
|
||||
|
||||
|
||||
@ -1209,13 +1223,12 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
procedure thlcgllvm.g_ptrtypecast_ref(list: TAsmList; fromdef: tpointerdef; todef: tdef; var ref: treference);
|
||||
procedure thlcgllvm.g_ptrtypecast_ref(list: TAsmList; fromdef, todef: tdef; var ref: treference);
|
||||
var
|
||||
sref: treference;
|
||||
hreg: tregister;
|
||||
begin
|
||||
hreg:=getaddressregister(list,todef);
|
||||
a_loadaddr_ref_reg(list,fromdef.pointeddef,todef,ref,hreg);
|
||||
a_loadaddr_ref_reg_intern(list,fromdef,todef,ref,hreg,false);
|
||||
reference_reset_base(ref,todef,hreg,0,ref.alignment);
|
||||
end;
|
||||
|
||||
@ -1569,12 +1582,18 @@ implementation
|
||||
|
||||
|
||||
function thlcgllvm.make_simple_ref(list: TAsmList; const ref: treference; def: tdef): treference;
|
||||
begin
|
||||
result:=make_simple_ref_ptr(list,ref,cpointerdef.create(def));
|
||||
end;
|
||||
|
||||
|
||||
function thlcgllvm.make_simple_ref_ptr(list: TAsmList; const ref: treference; ptrdef: tdef): treference;
|
||||
var
|
||||
ptrindex: tcgint;
|
||||
hreg1,
|
||||
hreg2: tregister;
|
||||
tmpref: treference;
|
||||
defsize: asizeint;
|
||||
pointedsize: asizeint;
|
||||
begin
|
||||
{ already simple? }
|
||||
if (not assigned(ref.symbol) or
|
||||
@ -1585,24 +1604,36 @@ implementation
|
||||
result:=ref;
|
||||
exit;
|
||||
end;
|
||||
|
||||
hreg2:=getaddressregister(list,cpointerdef.getreusable(def));
|
||||
defsize:=def.size;
|
||||
{ for voiddef/formaldef }
|
||||
if defsize=0 then
|
||||
defsize:=1;
|
||||
case ptrdef.typ of
|
||||
pointerdef:
|
||||
begin
|
||||
pointedsize:=tpointerdef(ptrdef).pointeddef.size;
|
||||
{ void, formaldef }
|
||||
if pointedsize=0 then
|
||||
pointedsize:=1;
|
||||
end;
|
||||
else
|
||||
begin
|
||||
{ pointedsize is only used if the offset <> 0, to see whether we
|
||||
can use getelementptr if it's an exact multiple -> set pointedsize
|
||||
to a value that will never be a multiple as we can't "index" other
|
||||
types }
|
||||
pointedsize:=ref.offset+1;
|
||||
end;
|
||||
end;
|
||||
hreg2:=getaddressregister(list,ptrdef);
|
||||
{ symbol+offset or base+offset with offset a multiple of the size ->
|
||||
use getelementptr }
|
||||
if (ref.index=NR_NO) and
|
||||
(ref.offset mod defsize=0) then
|
||||
(ref.offset mod pointedsize=0) then
|
||||
begin
|
||||
ptrindex:=ref.offset div defsize;
|
||||
ptrindex:=ref.offset div pointedsize;
|
||||
if assigned(ref.symbol) then
|
||||
reference_reset_symbol(tmpref,ref.symbol,0,ref.alignment)
|
||||
else
|
||||
reference_reset_base(tmpref,cpointerdef.getreusable(def),ref.base,0,ref.alignment);
|
||||
list.concat(taillvm.getelementptr_reg_size_ref_size_const(hreg2,cpointerdef.getreusable(def),tmpref,ptruinttype,ptrindex,assigned(ref.symbol)));
|
||||
reference_reset_base(result,cpointerdef.getreusable(def),hreg2,0,ref.alignment);
|
||||
reference_reset_base(tmpref,ptrdef,ref.base,0,ref.alignment);
|
||||
list.concat(taillvm.getelementptr_reg_size_ref_size_const(hreg2,ptrdef,tmpref,ptruinttype,ptrindex,assigned(ref.symbol)));
|
||||
reference_reset_base(result,ptrdef,hreg2,0,ref.alignment);
|
||||
exit;
|
||||
end;
|
||||
{ for now, perform all calculations using plain pointer arithmetic. Later
|
||||
@ -1610,7 +1641,7 @@ implementation
|
||||
accesses (if only to prevent running out of virtual registers).
|
||||
|
||||
Assumptions:
|
||||
* symbol/base register: always type "def*"
|
||||
* symbol/base register: always type "ptrdef"
|
||||
* index/offset: always type "ptruinttype" (llvm bitcode has no sign information, so sign doesn't matter) }
|
||||
hreg1:=getintregister(list,ptruinttype);
|
||||
if assigned(ref.symbol) then
|
||||
@ -1618,11 +1649,11 @@ implementation
|
||||
if ref.base<>NR_NO then
|
||||
internalerror(2012111301);
|
||||
reference_reset_symbol(tmpref,ref.symbol,0,ref.alignment);
|
||||
list.concat(taillvm.getelementptr_reg_size_ref_size_const(hreg1,cpointerdef.getreusable(def),tmpref,ptruinttype,0,true));
|
||||
list.concat(taillvm.getelementptr_reg_size_ref_size_const(hreg1,ptrdef,tmpref,ptruinttype,0,true));
|
||||
end
|
||||
else if ref.base<>NR_NO then
|
||||
begin
|
||||
a_load_reg_reg(list,cpointerdef.getreusable(def),ptruinttype,ref.base,hreg1);
|
||||
a_load_reg_reg(list,ptrdef,ptruinttype,ref.base,hreg1);
|
||||
end
|
||||
else
|
||||
{ todo: support for absolute addresses on embedded platforms }
|
||||
@ -1640,9 +1671,9 @@ implementation
|
||||
a_op_const_reg_reg(list,OP_ADD,ptruinttype,ref.offset,hreg1,hreg2);
|
||||
hreg1:=hreg2;
|
||||
end;
|
||||
hreg2:=getaddressregister(list,cpointerdef.getreusable(def));
|
||||
a_load_reg_reg(list,ptruinttype,cpointerdef.getreusable(def),hreg1,hreg2);
|
||||
reference_reset_base(result,cpointerdef.getreusable(def),hreg2,0,ref.alignment);
|
||||
hreg2:=getaddressregister(list,ptrdef);
|
||||
a_load_reg_reg(list,ptruinttype,ptrdef,hreg1,hreg2);
|
||||
reference_reset_base(result,ptrdef,hreg2,0,ref.alignment);
|
||||
end;
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user