mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-16 05:59:28 +02:00
* 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:
parent
c1fd3bc0de
commit
c0ff55e95a
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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.
|
@ -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.
|
||||
|
@ -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) }
|
||||
|
@ -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);
|
||||
|
@ -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)]
|
||||
|
Loading…
Reference in New Issue
Block a user