* emit the correct declaration for procdefs used to force a procname in LLVM

o fixes lazarus startup on macOS/AArch64 when compiled with the LLVM cg

git-svn-id: trunk@46675 -
This commit is contained in:
Jonas Maebe 2020-08-23 21:11:09 +00:00
parent 27fbf8c91e
commit 453bfcd370
4 changed files with 46 additions and 39 deletions

View File

@ -600,10 +600,10 @@ implementation
result:=inherited pass_1;
if assigned(result) then
exit;
{ set fforcedprocname so that even virtual method calls will be
{ set foverrideprocnamedef so that even virtual method calls will be
name-based (instead of based on VMT entry numbers) }
if procdefinition.typ=procdef then
fforcedprocname:=tprocdef(procdefinition).mangledname
foverrideprocnamedef:=tprocdef(procdefinition)
end;
end;

View File

@ -39,6 +39,7 @@ interface
function paraneedsinlinetemp(para: tcallparanode; const pushconstaddr, complexpara: boolean): boolean; override;
function can_call_ref(var ref: treference): boolean; override;
procedure pushparas; override;
procedure pass_generate_code; override;
end;
@ -46,6 +47,7 @@ implementation
uses
verbose,
aasmbase,aasmdata,aasmllvm,
symconst,symdef;
{*****************************************************************************
@ -104,6 +106,30 @@ implementation
end;
end;
procedure tllvmcallnode.pass_generate_code;
var
asmsym: tasmsymbol;
begin
inherited;
if assigned(overrideprocnamedef) and
not overrideprocnamedef.in_currentunit then
begin
{ insert an llvm declaration for this def if it's not defined in
the current unit, because otherwise we will define it in the
LLVM IR using the def for which this procdef's name is used
first, which may be something completely different from the original
def. LLVM can take the original def into account to load certain
registers, so if we use a wrong def this can result in wrong code
generation. }
asmsym:=current_asmdata.RefAsmSymbol(overrideprocnamedef.mangledname,AT_FUNCTION);
if not asmsym.declared then
begin
current_asmdata.AsmLists[al_imports].Concat(taillvmdecl.createdecl(asmsym,overrideprocnamedef,nil,sec_code,overrideprocnamedef.alignment));
end;
end;
end;
begin
ccallnode:=tllvmcallnode;
end.

View File

@ -67,7 +67,7 @@ interface
private
{ number of parameters passed from the source, this does not include the hidden parameters }
paralength : smallint;
function getforcedprocname: TSymStr;
function getoverrideprocnamedef: tprocdef; inline;
function is_simple_para_load(p:tnode; may_be_in_reg: boolean):boolean;
procedure maybe_load_in_temp(var p:tnode);
function gen_high_tree(var p:tnode;paradef:tdef):tnode;
@ -90,6 +90,7 @@ interface
function pass1_normal:tnode;
procedure register_created_object_types;
function get_expect_loc: tcgloc;
protected
function safe_call_self_node: tnode;
procedure load_in_temp(var p:tnode);
@ -124,12 +125,8 @@ interface
to ppu, is set while processing the node). Also used on the JVM
target for calling virtual methods, as this is name-based and not
based on VMT entry locations }
{$ifdef symansistr}
fforcedprocname: TSymStr;
{$else symansistr}
fforcedprocname: pshortstring;
{$endif symansistr}
property forcedprocname: TSymStr read getforcedprocname;
foverrideprocnamedef: tprocdef;
property overrideprocnamedef: tprocdef read getoverrideprocnamedef;
public
{ the symbol containing the definition of the procedure }
{ to call }
@ -1656,9 +1653,6 @@ implementation
call_vmt_node.free;
vmt_entry.free;
spezcontext.free;
{$ifndef symansistr}
stringdispose(fforcedprocname);
{$endif symansistr}
inherited destroy;
end;
@ -1844,14 +1838,7 @@ implementation
end
else
n.varargsparas:=nil;
{$ifdef symansistr}
n.fforcedprocname:=fforcedprocname;
{$else symansistr}
if assigned(fforcedprocname) then
n.fforcedprocname:=stringdup(fforcedprocname^)
else
n.fforcedprocname:=nil;
{$endif symansistr}
n.foverrideprocnamedef:=foverrideprocnamedef;
result:=n;
end;
@ -2084,16 +2071,9 @@ implementation
end;
function tcallnode.getforcedprocname: TSymStr;
function tcallnode.getoverrideprocnamedef: tprocdef; inline;
begin
{$ifdef symansistr}
result:=fforcedprocname;
{$else}
if assigned(fforcedprocname) then
result:=fforcedprocname^
else
result:='';
{$endif}
result:=foverrideprocnamedef;
end;
@ -2670,7 +2650,7 @@ implementation
vmt_def: trecorddef;
begin
if not assigned(right) and
(forcedprocname='') and
not assigned(overrideprocnamedef) and
(po_virtualmethod in procdefinition.procoptions) and
not is_objectpascal_helper(tprocdef(procdefinition).struct) and
assigned(methodpointer) and
@ -2780,11 +2760,7 @@ implementation
(srsym.typ<>procsym) or
(tprocsym(srsym).ProcdefList.count<>1) then
Message1(cg_f_unknown_compilerproc,'objc.'+msgsendname);
{$ifdef symansistr}
fforcedprocname:=tprocdef(tprocsym(srsym).ProcdefList[0]).mangledname;
{$else symansistr}
fforcedprocname:=stringdup(tprocdef(tprocsym(srsym).ProcdefList[0]).mangledname);
{$endif symansistr}
foverrideprocnamedef:=tprocdef(tprocsym(srsym).ProcdefList[0]);
{ B) Handle self }
{ 1) in case of sending a message to a superclass, self is a pointer to

View File

@ -1067,10 +1067,10 @@ implementation
end;
{$endif vtentry}
name_to_call:=forcedprocname;
{ When methodpointer is typen we don't need (and can't) load
a pointer. We can directly call the correct procdef (PFV) }
if (name_to_call='') and
name_to_call:='';
if not assigned(overrideprocnamedef) and
(po_virtualmethod in procdefinition.procoptions) and
not is_objectpascal_helper(tprocdef(procdefinition).struct) and
assigned(methodpointer) and
@ -1164,8 +1164,13 @@ implementation
extra_interrupt_code;
extra_call_code;
retloc.resetiftemp;
if (name_to_call='') then
name_to_call:=tprocdef(procdefinition).mangledname;
if name_to_call='' then
begin
if not assigned(overrideprocnamedef) then
name_to_call:=tprocdef(procdefinition).mangledname
else
name_to_call:=overrideprocnamedef.mangledname;
end;
if cnf_inherited in callnodeflags then
retloc:=hlcg.a_call_name_inherited(current_asmdata.CurrAsmList,tprocdef(procdefinition),name_to_call,paralocs)
{ under certain conditions, a static call (i.e. without PIC) can be generated }