* Split load_ppu for clarity

This commit is contained in:
Michaël Van Canneyt 2024-02-01 14:51:16 +01:00 committed by Michael Van Canneyt
parent 8aa9ac99a6
commit a5caf91f74

View File

@ -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;