* use the extern and public assembler symbol lists stored in the units to resolve those symbols to a used package that don't have a corresponding Pascal symbol

git-svn-id: trunk@34179 -
This commit is contained in:
svenbarth 2016-07-22 13:42:13 +00:00
parent 6cc7539208
commit 022df814c2

View File

@ -45,8 +45,10 @@ implementation
globtype,systems,
cutils,
globals,verbose,
aasmbase,aasmdata,
symtype,symconst,symsym,symdef,symbase,symtable,
psub,
psub,pdecsub,
ncgutil,
ppu,entfile,fpcp,
export;
@ -540,10 +542,149 @@ implementation
procedure createimportlibfromexternals;
type
tcacheentry=record
pkg:tpackage;
sym:tasmsymbol;
end;
pcacheentry=^tcacheentry;
var
cache : tfphashlist;
alreadyloaded : tfpobjectlist;
function findpackagewithsym(symname:tsymstr):tcacheentry;
var
i,j : longint;
pkgentry : ppackageentry;
unitentry : pcontainedunit;
begin
for i:=0 to packagelist.count-1 do
begin
pkgentry:=ppackageentry(packagelist[i]);
for j:=0 to pkgentry^.package.containedmodules.count-1 do
begin
unitentry:=pcontainedunit(pkgentry^.package.containedmodules[j]);
if not assigned(unitentry^.module) then
{ the unit is not loaded }
continue;
result.sym:=tasmsymbol(tmodule(unitentry^.module).publicasmsyms.find(symname));
if assigned(result.sym) then
begin
{ completely ignore other external symbols }
if result.sym.bind in [ab_external,ab_weak_external] then
begin
result.sym:=nil;
continue;
end;
{ only accept global symbols of the used unit }
if result.sym.bind<>ab_global then
begin
result.sym:=nil;
result.pkg:=nil;
end
else
result.pkg:=pkgentry^.package;
exit;
end;
end;
end;
result.sym:=nil;
result.pkg:=nil;
end;
procedure processasmsyms(symlist:tfphashobjectlist);
var
i,j,k : longint;
sym : tasmsymbol;
cacheentry : pcacheentry;
list : TAsmList;
labind : tasmsymbol;
psym : tsymentry;
pd : tprocdef;
found : boolean;
impname,symname : TSymStr;
suffixidx : longint;
begin
for i:=0 to symlist.count-1 do
begin
sym:=tasmsymbol(symlist[i]);
if not (sym.bind in [ab_external,ab_external_indirect]) then
continue;
{ remove the indirect suffix }
symname:=sym.name;
if sym.bind=ab_external_indirect then
begin
suffixidx:=pos(suffix_indirect,symname);
if suffixidx=length(symname)-length(suffix_indirect)+1 then
symname:=copy(symname,1,suffixidx-1)
else
internalerror(2016062401);
end;
{ did we already import the symbol? }
cacheentry:=pcacheentry(cache.find(symname));
if assigned(cacheentry) then
continue;
{ was the symbol already imported in the previous pass? }
found:=false;
for j:=0 to alreadyloaded.count-1 do
begin
psym:=tsymentry(alreadyloaded[j]);
case psym.typ of
procsym:
for k:=0 to tprocsym(psym).procdeflist.count-1 do
begin
pd:=tprocdef(tprocsym(psym).procdeflist[k]);
if has_alias_name(pd,symname) or
(
([po_external,po_has_importdll]*pd.procoptions=[po_external,po_has_importdll]) and
(symname=proc_get_importname(pd))
) then
begin
found:=true;
break;
end;
end;
staticvarsym:
if tstaticvarsym(psym).mangledname=symname then
found:=true;
else
internalerror(2014101005);
end;
if found then
break;
end;
if found then begin
{ add a dummy entry }
new(cacheentry);
cacheentry^.pkg:=nil;
cacheentry^.sym:=sym;
cache.add(symname,cacheentry);
continue;
end;
new(cacheentry);
cacheentry^:=findpackagewithsym(symname);
cache.add(symname,cacheentry);
{ use cacheentry^.sym instead of sym, because for the later typ
is always at_none in case of an external symbol }
if assigned(cacheentry^.pkg) then
begin
impname:=symname;
if cacheentry^.sym.typ=AT_DATA then
{ import as the $indirect symbol if it as a variable }
impname:=symname+suffix_indirect;
current_module.addexternalimport(cacheentry^.pkg.pplfilename,symname,impname,0,cacheentry^.sym.typ=at_data,false);
end;
end;
end;
procedure import_proc_symbol(pd:tprocdef;pkg:tpackage);
var
item : TCmdStrListItem;
@ -636,7 +777,9 @@ implementation
var
unitentry : pcontainedunit;
module : tmodule;
i : longint;
begin
cache:=tfphashlist.create;
{ check each external asm symbol of each unit of the package whether it is
contained in the unit of a loaded package (and thus an import entry
is needed) }
@ -651,7 +794,19 @@ implementation
module:=tmodule(module.next);
end;
{ second pass to find all symbols that were loaded by asm name }
module:=tmodule(loaded_units.first);
while assigned(module) do
begin
if not assigned(module.package) then
processasmsyms(module.externasmsyms);
module:=tmodule(module.next);
end;
alreadyloaded.free;
for i:=0 to cache.count-1 do
dispose(pcacheentry(cache[i]));
cache.free;
end;