mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-28 22:40:30 +02:00
* Split load_ppu for clarity
This commit is contained in:
parent
8aa9ac99a6
commit
a5caf91f74
@ -64,6 +64,7 @@ interface
|
|||||||
constructor create(LoadedFrom:TModule;const amodulename: string; const afilename:TPathStr;_is_unit:boolean);
|
constructor create(LoadedFrom:TModule;const amodulename: string; const afilename:TPathStr;_is_unit:boolean);
|
||||||
destructor destroy;override;
|
destructor destroy;override;
|
||||||
procedure reset;override;
|
procedure reset;override;
|
||||||
|
procedure re_resolve(loadfrom: tmodule);
|
||||||
function openppufile:boolean;
|
function openppufile:boolean;
|
||||||
function openppustream(strm:TCStream):boolean;
|
function openppustream(strm:TCStream):boolean;
|
||||||
procedure getppucrc;
|
procedure getppucrc;
|
||||||
@ -83,7 +84,12 @@ interface
|
|||||||
avoid endless resolving loops in case of cyclic dependencies. }
|
avoid endless resolving loops in case of cyclic dependencies. }
|
||||||
defsgeneration : longint;
|
defsgeneration : longint;
|
||||||
|
|
||||||
|
function check_loadfrompackage: boolean;
|
||||||
|
procedure check_reload(from_module: tmodule; var do_load: boolean);
|
||||||
function openppu(ppufiletime:longint):boolean;
|
function openppu(ppufiletime:longint):boolean;
|
||||||
|
procedure post_load_or_compile(second_time: boolean);
|
||||||
|
procedure prepare_second_load(from_module: tmodule);
|
||||||
|
procedure recompile_from_sources(from_module: tmodule);
|
||||||
function search_unit_files(loaded_from : tmodule; onlysource:boolean):boolean;
|
function search_unit_files(loaded_from : tmodule; onlysource:boolean):boolean;
|
||||||
function search_unit(loaded_from : tmodule; onlysource,shortname:boolean):boolean;
|
function search_unit(loaded_from : tmodule; onlysource,shortname:boolean):boolean;
|
||||||
function loadfrompackage:boolean;
|
function loadfrompackage:boolean;
|
||||||
@ -95,6 +101,7 @@ interface
|
|||||||
procedure buildderefunitimportsyms;
|
procedure buildderefunitimportsyms;
|
||||||
procedure derefunitimportsyms;
|
procedure derefunitimportsyms;
|
||||||
procedure freederefunitimportsyms;
|
procedure freederefunitimportsyms;
|
||||||
|
procedure try_load_ppufile(from_module: tmodule);
|
||||||
procedure writesourcefiles;
|
procedure writesourcefiles;
|
||||||
procedure writeusedunit(intf:boolean);
|
procedure writeusedunit(intf:boolean);
|
||||||
procedure writelinkcontainer(var p:tlinkcontainer;id:byte;strippath:boolean);
|
procedure writelinkcontainer(var p:tlinkcontainer;id:byte;strippath:boolean);
|
||||||
@ -183,6 +190,39 @@ var
|
|||||||
inherited reset;
|
inherited reset;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure tppumodule.re_resolve(loadfrom: tmodule);
|
||||||
|
|
||||||
|
begin
|
||||||
|
Message1(unit_u_reresolving_unit,modulename^);
|
||||||
|
tstoredsymtable(globalsymtable).deref(false);
|
||||||
|
tstoredsymtable(globalsymtable).derefimpl(false);
|
||||||
|
if assigned(localsymtable) then
|
||||||
|
begin
|
||||||
|
{ we have only builderef(impl)'d the registered symbols of
|
||||||
|
the localsymtable -> also only deref those again }
|
||||||
|
tstoredsymtable(localsymtable).deref(true);
|
||||||
|
tstoredsymtable(localsymtable).derefimpl(true);
|
||||||
|
end;
|
||||||
|
if assigned(wpoinfo) then
|
||||||
|
begin
|
||||||
|
tunitwpoinfo(wpoinfo).deref;
|
||||||
|
tunitwpoinfo(wpoinfo).derefimpl;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ We have to flag the units that depend on this unit even
|
||||||
|
though it didn't change, because they might also
|
||||||
|
indirectly depend on the unit that did change (e.g.,
|
||||||
|
in case rgobj, rgx86 and rgcpu have been compiled
|
||||||
|
already, and then rgobj is recompiled for some reason
|
||||||
|
-> rgx86 is re-reresolved, but the vmtentries of trgcpu
|
||||||
|
must also be re-resolved, because they will also contain
|
||||||
|
pointers to procdefs in the old trgobj (in case of a
|
||||||
|
recompile, all old defs are freed) }
|
||||||
|
flagdependent(loadfrom);
|
||||||
|
reload_flagged_units;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure tppumodule.queuecomment(const s:TMsgStr;v,w:longint);
|
procedure tppumodule.queuecomment(const s:TMsgStr;v,w:longint);
|
||||||
begin
|
begin
|
||||||
if comments = nil then
|
if comments = nil then
|
||||||
@ -2076,6 +2116,164 @@ var
|
|||||||
inherited end_of_parsing;
|
inherited end_of_parsing;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure tppumodule.check_reload(from_module : tmodule; var do_load : boolean);
|
||||||
|
|
||||||
|
begin
|
||||||
|
{ A force reload }
|
||||||
|
if not do_reload then
|
||||||
|
exit;
|
||||||
|
Message(unit_u_forced_reload);
|
||||||
|
do_reload:=false;
|
||||||
|
{ When the unit is already loaded or being loaded
|
||||||
|
we can maybe skip a complete reload/recompile }
|
||||||
|
if assigned(globalsymtable) and
|
||||||
|
(not needrecompile) then
|
||||||
|
begin
|
||||||
|
{ When we don't have any data stored yet there
|
||||||
|
is nothing to resolve }
|
||||||
|
if interface_compiled and
|
||||||
|
{ it makes no sense to re-resolve the unit if it is already finally compiled }
|
||||||
|
not(state=ms_compiled) then
|
||||||
|
begin
|
||||||
|
re_resolve(from_module);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
Message1(unit_u_skipping_reresolving_unit,modulename^);
|
||||||
|
do_load:=false;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ Returns true if the module was loaded from package }
|
||||||
|
function tppumodule.check_loadfrompackage : boolean;
|
||||||
|
|
||||||
|
begin
|
||||||
|
{ try to load it as a package unit first }
|
||||||
|
Result:=(packagelist.count>0) and loadfrompackage;
|
||||||
|
if Result then
|
||||||
|
begin
|
||||||
|
do_reload:=false;
|
||||||
|
state:=ms_compiled;
|
||||||
|
{ PPU is not needed anymore }
|
||||||
|
if assigned(ppufile) then
|
||||||
|
begin
|
||||||
|
discardppu;
|
||||||
|
end;
|
||||||
|
{ add the unit to the used units list of the program }
|
||||||
|
usedunits.concat(tused_unit.create(self,true,false,nil));
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure tppumodule.prepare_second_load(from_module: tmodule);
|
||||||
|
|
||||||
|
begin
|
||||||
|
{ try to load the unit a second time first }
|
||||||
|
Message1(unit_u_second_load_unit,modulename^);
|
||||||
|
Message2(unit_u_previous_state,modulename^,ModuleStateStr[state]);
|
||||||
|
{ Flag modules to reload }
|
||||||
|
flagdependent(from_module);
|
||||||
|
{ Reset the module }
|
||||||
|
reset;
|
||||||
|
if state in [ms_compile,ms_second_compile] then
|
||||||
|
begin
|
||||||
|
Message1(unit_u_second_compile_unit,modulename^);
|
||||||
|
state:=ms_second_compile;
|
||||||
|
do_compile:=true;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
state:=ms_second_load;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure tppumodule.try_load_ppufile(from_module : tmodule);
|
||||||
|
|
||||||
|
begin
|
||||||
|
Message1(unit_u_loading_unit,modulename^);
|
||||||
|
search_unit_files(from_module,false);
|
||||||
|
if not do_compile then
|
||||||
|
begin
|
||||||
|
load_interface;
|
||||||
|
setdefgeneration;
|
||||||
|
if not do_compile then
|
||||||
|
begin
|
||||||
|
load_usedunits;
|
||||||
|
if not do_compile then
|
||||||
|
Message1(unit_u_finished_loading_unit,modulename^);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
{ PPU is not needed anymore }
|
||||||
|
if assigned(ppufile) then
|
||||||
|
discardppu;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure tppumodule.recompile_from_sources(from_module : tmodule);
|
||||||
|
|
||||||
|
var
|
||||||
|
pu : tused_unit;
|
||||||
|
begin
|
||||||
|
{ recompile the unit or give a fatal error if sources not available }
|
||||||
|
if not(sources_avail) then
|
||||||
|
begin
|
||||||
|
search_unit_files(from_module,true);
|
||||||
|
if not(sources_avail) then
|
||||||
|
begin
|
||||||
|
printcomments;
|
||||||
|
if recompile_reason=rr_noppu then
|
||||||
|
begin
|
||||||
|
pu:=tused_unit(from_module.used_units.first);
|
||||||
|
while assigned(pu) do
|
||||||
|
begin
|
||||||
|
if pu.u=self then
|
||||||
|
break;
|
||||||
|
pu:=tused_unit(pu.next);
|
||||||
|
end;
|
||||||
|
if assigned(pu) and assigned(pu.unitsym) then
|
||||||
|
MessagePos2(pu.unitsym.fileinfo,unit_f_cant_find_ppu,realmodulename^,from_module.realmodulename^)
|
||||||
|
else
|
||||||
|
Message2(unit_f_cant_find_ppu,realmodulename^,from_module.realmodulename^);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
Message1(unit_f_cant_compile_unit,realmodulename^);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
{ we found the sources, we do not need the verbose messages anymore }
|
||||||
|
if comments <> nil then
|
||||||
|
begin
|
||||||
|
comments.free;
|
||||||
|
comments:=nil;
|
||||||
|
end;
|
||||||
|
{ Flag modules to reload }
|
||||||
|
flagdependent(from_module);
|
||||||
|
{ Reset the module }
|
||||||
|
reset;
|
||||||
|
{ compile this module }
|
||||||
|
if not(state in [ms_compile,ms_second_compile]) then
|
||||||
|
state:=ms_compile;
|
||||||
|
compile_module(self);
|
||||||
|
setdefgeneration;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure tppumodule.post_load_or_compile(second_time : boolean);
|
||||||
|
|
||||||
|
begin
|
||||||
|
if current_module<>self then
|
||||||
|
internalerror(200212282);
|
||||||
|
|
||||||
|
if in_interface then
|
||||||
|
internalerror(200212283);
|
||||||
|
|
||||||
|
{ for a second_time recompile reload all dependent units,
|
||||||
|
for a first time compile register the unit _once_ }
|
||||||
|
if second_time then
|
||||||
|
reload_flagged_units
|
||||||
|
else
|
||||||
|
usedunits.concat(tused_unit.create(self,true,false,nil));
|
||||||
|
|
||||||
|
{ reopen the old module }
|
||||||
|
{$ifdef SHORT_ON_FILE_HANDLES}
|
||||||
|
if old_current_module.is_unit and
|
||||||
|
assigned(tppumodule(old_current_module).ppufile) then
|
||||||
|
tppumodule(old_current_module).ppufile.tempopen;
|
||||||
|
{$endif SHORT_ON_FILE_HANDLES}
|
||||||
|
end;
|
||||||
|
|
||||||
procedure tppumodule.loadppu(from_module : tmodule);
|
procedure tppumodule.loadppu(from_module : tmodule);
|
||||||
const
|
const
|
||||||
@ -2083,14 +2281,12 @@ var
|
|||||||
var
|
var
|
||||||
do_load,
|
do_load,
|
||||||
second_time : boolean;
|
second_time : boolean;
|
||||||
pu : tused_unit;
|
|
||||||
begin
|
begin
|
||||||
Message3(unit_u_load_unit,from_module.modulename^,
|
Message3(unit_u_load_unit,from_module.modulename^,
|
||||||
ImplIntf[from_module.in_interface],
|
ImplIntf[from_module.in_interface],
|
||||||
modulename^);
|
modulename^);
|
||||||
|
|
||||||
{ Update loaded_from to detect cycles }
|
|
||||||
|
|
||||||
{ check if the globalsymtable is already available, but
|
{ check if the globalsymtable is already available, but
|
||||||
we must reload when the do_reload flag is set }
|
we must reload when the do_reload flag is set }
|
||||||
if (not do_reload) and
|
if (not do_reload) and
|
||||||
@ -2102,198 +2298,48 @@ var
|
|||||||
second_time:=false;
|
second_time:=false;
|
||||||
set_current_module(self);
|
set_current_module(self);
|
||||||
|
|
||||||
{ try to load it as a package unit first }
|
do_load:=not check_loadfrompackage;
|
||||||
if (packagelist.count>0) and loadfrompackage then
|
|
||||||
begin
|
|
||||||
do_load:=false;
|
|
||||||
do_reload:=false;
|
|
||||||
state:=ms_compiled;
|
|
||||||
{ PPU is not needed anymore }
|
|
||||||
if assigned(ppufile) then
|
|
||||||
begin
|
|
||||||
discardppu;
|
|
||||||
end;
|
|
||||||
{ add the unit to the used units list of the program }
|
|
||||||
usedunits.concat(tused_unit.create(self,true,false,nil));
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ A force reload }
|
{ A force reload }
|
||||||
if do_reload then
|
check_reload(from_module, do_load);
|
||||||
begin
|
|
||||||
Message(unit_u_forced_reload);
|
|
||||||
do_reload:=false;
|
|
||||||
{ When the unit is already loaded or being loaded
|
|
||||||
we can maybe skip a complete reload/recompile }
|
|
||||||
if assigned(globalsymtable) and
|
|
||||||
(not needrecompile) then
|
|
||||||
begin
|
|
||||||
{ When we don't have any data stored yet there
|
|
||||||
is nothing to resolve }
|
|
||||||
if interface_compiled and
|
|
||||||
{ it makes no sense to re-resolve the unit if it is already finally compiled }
|
|
||||||
not(state=ms_compiled) then
|
|
||||||
begin
|
|
||||||
Message1(unit_u_reresolving_unit,modulename^);
|
|
||||||
tstoredsymtable(globalsymtable).deref(false);
|
|
||||||
tstoredsymtable(globalsymtable).derefimpl(false);
|
|
||||||
if assigned(localsymtable) then
|
|
||||||
begin
|
|
||||||
{ we have only builderef(impl)'d the registered symbols of
|
|
||||||
the localsymtable -> also only deref those again }
|
|
||||||
tstoredsymtable(localsymtable).deref(true);
|
|
||||||
tstoredsymtable(localsymtable).derefimpl(true);
|
|
||||||
end;
|
|
||||||
if assigned(wpoinfo) then
|
|
||||||
begin
|
|
||||||
tunitwpoinfo(wpoinfo).deref;
|
|
||||||
tunitwpoinfo(wpoinfo).derefimpl;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ We have to flag the units that depend on this unit even
|
if not do_load then
|
||||||
though it didn't change, because they might also
|
begin
|
||||||
indirectly depend on the unit that did change (e.g.,
|
// No need to do anything, restore situation and exit.
|
||||||
in case rgobj, rgx86 and rgcpu have been compiled
|
set_current_module(from_module);
|
||||||
already, and then rgobj is recompiled for some reason
|
exit;
|
||||||
-> rgx86 is re-reresolved, but the vmtentries of trgcpu
|
end;
|
||||||
must also be re-resolved, because they will also contain
|
|
||||||
pointers to procdefs in the old trgobj (in case of a
|
|
||||||
recompile, all old defs are freed) }
|
|
||||||
flagdependent(from_module);
|
|
||||||
reload_flagged_units;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
Message1(unit_u_skipping_reresolving_unit,modulename^);
|
|
||||||
do_load:=false;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if do_load then
|
{ loading the unit for a second time? }
|
||||||
begin
|
if state=ms_registered then
|
||||||
{ loading the unit for a second time? }
|
state:=ms_load
|
||||||
if state=ms_registered then
|
else
|
||||||
state:=ms_load
|
begin
|
||||||
else
|
second_time:=true;
|
||||||
begin
|
prepare_second_load(from_module);
|
||||||
{ try to load the unit a second time first }
|
end;
|
||||||
Message1(unit_u_second_load_unit,modulename^);
|
{ close old_current_ppu on system that are
|
||||||
Message2(unit_u_previous_state,modulename^,ModuleStateStr[state]);
|
short on file handles like DOS PM }
|
||||||
{ Flag modules to reload }
|
|
||||||
flagdependent(from_module);
|
|
||||||
{ Reset the module }
|
|
||||||
reset;
|
|
||||||
if state in [ms_compile,ms_second_compile] then
|
|
||||||
begin
|
|
||||||
Message1(unit_u_second_compile_unit,modulename^);
|
|
||||||
state:=ms_second_compile;
|
|
||||||
do_compile:=true;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
state:=ms_second_load;
|
|
||||||
second_time:=true;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ close old_current_ppu on system that are
|
|
||||||
short on file handles like DOS PM }
|
|
||||||
{$ifdef SHORT_ON_FILE_HANDLES}
|
{$ifdef SHORT_ON_FILE_HANDLES}
|
||||||
if old_current_module.is_unit and
|
if old_current_module.is_unit and
|
||||||
assigned(tppumodule(old_current_module).ppufile) then
|
assigned(tppumodule(old_current_module).ppufile) then
|
||||||
tppumodule(old_current_module).ppufile.tempclose;
|
tppumodule(old_current_module).ppufile.tempclose;
|
||||||
{$endif SHORT_ON_FILE_HANDLES}
|
{$endif SHORT_ON_FILE_HANDLES}
|
||||||
|
|
||||||
{ try to opening ppu, skip this when we already
|
{ try to opening ppu, skip this when we already
|
||||||
know that we need to compile the unit }
|
know that we need to compile the unit }
|
||||||
if not do_compile then
|
if not do_compile then
|
||||||
begin
|
try_load_ppufile(from_module);
|
||||||
Message1(unit_u_loading_unit,modulename^);
|
|
||||||
search_unit_files(from_module,false);
|
|
||||||
if not do_compile then
|
|
||||||
begin
|
|
||||||
load_interface;
|
|
||||||
setdefgeneration;
|
|
||||||
if not do_compile then
|
|
||||||
begin
|
|
||||||
load_usedunits;
|
|
||||||
if not do_compile then
|
|
||||||
Message1(unit_u_finished_loading_unit,modulename^);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
{ PPU is not needed anymore }
|
|
||||||
if assigned(ppufile) then
|
|
||||||
begin
|
|
||||||
discardppu;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ Do we need to recompile the unit }
|
{ Do we need to recompile the unit }
|
||||||
if do_compile then
|
if do_compile then
|
||||||
begin
|
recompile_from_sources(from_module)
|
||||||
{ recompile the unit or give a fatal error if sources not available }
|
else
|
||||||
if not(sources_avail) then
|
state:=ms_compiled;
|
||||||
begin
|
|
||||||
search_unit_files(from_module,true);
|
|
||||||
if not(sources_avail) then
|
|
||||||
begin
|
|
||||||
printcomments;
|
|
||||||
if recompile_reason=rr_noppu then
|
|
||||||
begin
|
|
||||||
pu:=tused_unit(from_module.used_units.first);
|
|
||||||
while assigned(pu) do
|
|
||||||
begin
|
|
||||||
if pu.u=self then
|
|
||||||
break;
|
|
||||||
pu:=tused_unit(pu.next);
|
|
||||||
end;
|
|
||||||
if assigned(pu) and assigned(pu.unitsym) then
|
|
||||||
MessagePos2(pu.unitsym.fileinfo,unit_f_cant_find_ppu,realmodulename^,from_module.realmodulename^)
|
|
||||||
else
|
|
||||||
Message2(unit_f_cant_find_ppu,realmodulename^,from_module.realmodulename^);
|
|
||||||
end
|
|
||||||
else
|
|
||||||
Message1(unit_f_cant_compile_unit,realmodulename^);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
{ we found the sources, we do not need the verbose messages anymore }
|
|
||||||
if comments <> nil then
|
|
||||||
begin
|
|
||||||
comments.free;
|
|
||||||
comments:=nil;
|
|
||||||
end;
|
|
||||||
{ Flag modules to reload }
|
|
||||||
flagdependent(from_module);
|
|
||||||
{ Reset the module }
|
|
||||||
reset;
|
|
||||||
{ compile this module }
|
|
||||||
if not(state in [ms_compile,ms_second_compile]) then
|
|
||||||
state:=ms_compile;
|
|
||||||
compile_module(self);
|
|
||||||
setdefgeneration;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
state:=ms_compiled;
|
|
||||||
|
|
||||||
if current_module<>self then
|
post_load_or_compile(second_time);
|
||||||
internalerror(200212282);
|
|
||||||
|
|
||||||
if in_interface then
|
|
||||||
internalerror(200212283);
|
|
||||||
|
|
||||||
{ for a second_time recompile reload all dependent units,
|
|
||||||
for a first time compile register the unit _once_ }
|
|
||||||
if second_time then
|
|
||||||
reload_flagged_units
|
|
||||||
else
|
|
||||||
usedunits.concat(tused_unit.create(self,true,false,nil));
|
|
||||||
|
|
||||||
{ reopen the old module }
|
|
||||||
{$ifdef SHORT_ON_FILE_HANDLES}
|
|
||||||
if old_current_module.is_unit and
|
|
||||||
assigned(tppumodule(old_current_module).ppufile) then
|
|
||||||
tppumodule(old_current_module).ppufile.tempopen;
|
|
||||||
{$endif SHORT_ON_FILE_HANDLES}
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ we are back, restore current_module }
|
{ we are back, restore current_module }
|
||||||
|
|
||||||
set_current_module(from_module);
|
set_current_module(from_module);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user