* changed the abstract method wrapper generation from thlcgobj to synthetic

methods. Implementing a fully functional g_external_wrapper() for llvm is
    quite hard, and the regular wrapper method that calls FPC_ABSTRACTERROR can
    in principle be optimized to a plain jump by tail call optimisation on other
    targets (to the extent that this matters, because most of them will be
    smartlinked away, and the ones that are executed will trigger an exception)
   o this means that the synthetic method generation needs to be run for all
     objectdefs on all platforms now, rather than only for Java classes

git-svn-id: trunk@34127 -
This commit is contained in:
Jonas Maebe 2016-07-14 15:24:13 +00:00
parent c1fd3bc0de
commit c0ff55e95a
7 changed files with 46 additions and 94 deletions

1
.gitattributes vendored
View File

@ -352,7 +352,6 @@ compiler/llvm/nllvmmat.pas svneol=native#text/plain
compiler/llvm/nllvmmem.pas svneol=native#text/plain
compiler/llvm/nllvmtcon.pas svneol=native#text/plain
compiler/llvm/nllvmutil.pas svneol=native#text/plain
compiler/llvm/nllvmvmt.pas svneol=native#text/plain
compiler/llvm/rgllvm.pas svneol=native#text/plain
compiler/llvm/symllvm.pas svneol=native#text/plain
compiler/llvm/tgllvm.pas svneol=native#text/plain

View File

@ -38,7 +38,7 @@ implementation
ncgadd,ncgcal,ncgmat,ncginl,
tgllvm,hlcgllvm,
nllvmadd,nllvmbas,nllvmcal,nllvmcnv,nllvmcon,nllvminl,nllvmld,nllvmmat,
nllvmmem,nllvmtcon,nllvmutil,nllvmvmt,
nllvmmem,nllvmtcon,nllvmutil,
llvmpara,
symllvm;

View File

@ -1,69 +0,0 @@
{
Copyright (c) 2015 by Jonas Maebe
Generate LLVM IR for VMT generation
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
****************************************************************************
}
unit nllvmvmt;
{$i fpcdefs.inc}
interface
uses
aasmdata,
ncgvmt,
symdef;
type
tllvmvmtwriter = class(TVMTWriter)
protected
procedure generate_abstract_stub(list:TAsmList;pd:tprocdef); override;
end;
implementation
uses
globtype,globals,
aasmbase,
symconst,
hlcgobj;
{*****************************************************************************
TLLVMVMTWRITER
*****************************************************************************}
procedure tllvmvmtwriter.generate_abstract_stub(list: TAsmList; pd: tprocdef);
var
sym: TAsmSymbol;
begin
if (po_global in pd.procoptions) and
(pd.owner.defowner<>self._class) then
exit;
sym:=current_asmdata.GetAsmSymbol(pd.mangledname);
if assigned(sym) and (sym.bind<>AB_EXTERNAL) then
exit;
hlcg.g_external_wrapper(list,pd,'FPC_ABSTRACTERROR');
end;
begin
CVMTWriter:=tllvmvmtwriter;
end.

View File

@ -117,7 +117,10 @@ implementation
aasmtai,
wpobase,
nobj,
cgbase,parabase,paramgr,cgobj,cgcpu,hlcgobj,hlcgcpu,
cgbase,parabase,paramgr,
{$ifndef cpuhighleveltarget}
cgobj,cgcpu,hlcgobj,hlcgcpu,
{$endif not cpuhighleveltarget}
ncgrtti;
@ -971,23 +974,13 @@ implementation
if (po_global in pd.procoptions) and
(pd.owner.defowner<>self._class) then
exit;
sym:=current_asmdata.GetAsmSymbol(pd.mangledname);
if assigned(sym) and (sym.bind<>AB_EXTERNAL) then
exit;
maybe_new_object_file(list);
new_section(list,sec_code,lower(pd.mangledname),target_info.alignment.procalign);
if (po_global in pd.procoptions) then
begin
sym:=current_asmdata.DefineAsmSymbol(pd.mangledname,AB_GLOBAL,AT_FUNCTION);
list.concat(Tai_symbol.Create_global(sym,0));
end
else
begin
sym:=current_asmdata.DefineAsmSymbol(pd.mangledname,AB_LOCAL,AT_FUNCTION);
list.concat(Tai_symbol.Create(sym,0));
end;
hlcg.g_external_wrapper(list,pd,'FPC_ABSTRACTERROR');
list.concat(Tai_symbol_end.Create(sym));
pd.synthetickind:=tsk_call_no_parameters;
pd.skpara:=search_system_proc('ABSTRACTERROR');
{ abstract methods are not marked as forwarddef, because otherwise
the compiler would accept implementations for them (and complain if
they were missing); we are now after parsing the user code, so we can
mark them again as forwarddef to indicate they need to be parsed }
pd.forwarddef:=true;
end;
@ -1348,9 +1341,13 @@ implementation
procedure write_vmts(st:tsymtable;is_global:boolean);
begin
{$ifndef cpuhighleveltarget}
create_hlcodegen;
{$endif}
do_write_vmts(st,is_global);
{$ifndef cpuhighleveltarget}
destroy_hlcodegen;
{$endif}
end;
end.

View File

@ -432,7 +432,8 @@ type
tsk_field_getter, // getter for a field (callthrough property is passed in skpara)
tsk_field_setter, // Setter for a field (callthrough property is passed in skpara)
tsk_block_invoke_procvar, // Call a procvar to invoke inside a block
tsk_interface_wrapper // Call through to a method from an interface wrapper
tsk_interface_wrapper, // Call through to a method from an interface wrapper
tsk_call_no_parameters // Call skpara procedure without passing any parameters nor returning a result
);
{ synthetic procdef supplementary information (tprocdef.skpara) }

View File

@ -977,6 +977,28 @@ implementation
pd.skpara:=nil;
end;
procedure implement_call_no_parameters(pd: tprocdef);
var
callpd: tprocdef;
str: ansistring;
isclassmethod: boolean;
begin
str:='begin ';
callpd:=tprocdef(pd.skpara);
str:=str+def_unit_name_prefix_if_toplevel(callpd)+callpd.procsym.realname+'; ';
{ avoid warnings about unset function results }
if (pd.proctypeoption<>potype_constructor) and
not is_void(pd.returndef) then
str:=str+'result:=system.default('+def_unit_name_prefix_if_toplevel(pd.returndef)+pd.returndef.typename+'); ';
str:=str+'end;';
isclassmethod:=
(po_classmethod in pd.procoptions) and
not(pd.proctypeoption in [potype_constructor,potype_destructor]);
str_parse_method_impl(str,pd,isclassmethod);
end;
procedure add_synthetic_method_implementations_for_st(st: tsymtable);
var
i : longint;
@ -1051,6 +1073,8 @@ implementation
implement_block_invoke_procvar(pd);
tsk_interface_wrapper:
implement_interface_wrapper(pd);
tsk_call_no_parameters:
implement_call_no_parameters(pd);
else
internalerror(2011032801);
end;
@ -1078,9 +1102,9 @@ implementation
{ not true for the "main" procedure, whose localsymtable is the staticsymtable }
(tprocdef(def).localst.symtabletype=localsymtable) then
add_synthetic_method_implementations(tprocdef(def).localst)
else if (is_javaclass(def) and
not(oo_is_external in tobjectdef(def).objectoptions)) or
(def.typ=recorddef) then
else if ((def.typ=objectdef) and
not(oo_is_external in tobjectdef(def).objectoptions)) or
(def.typ=recorddef) then
begin
{ also complete nested types }
add_synthetic_method_implementations(tabstractrecorddef(def).symtable);

View File

@ -542,7 +542,7 @@ const
'jvm enum bitset2set', 'jvm enum set2set',
'jvm procvar invoke', 'jvm procvar intf constructor',
'jvm virtual class method', 'jvm field getter', 'jvm field setter',
'block invoke','interface wrapper');
'block invoke','interface wrapper','call parameterless routine');
begin
if w<=ord(high(syntheticName)) then
result:=syntheticName[tsynthetickind(w)]