Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 45 additions & 2 deletions lib/Target/JSBackend/JSBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ namespace {
AlignedHeapStartMap AlignedHeapStarts, ZeroInitStarts;
GlobalAddressMap GlobalAddresses;
NameSet Externals; // vars
NameSet ExternalFuncs; // funcs
NameSet Declares; // funcs
StringMap Redirects; // library function redirects actually used, needed for wrapper funcs in tables
std::vector<std::string> Relocations;
Expand All @@ -265,9 +266,14 @@ namespace {
BlockAddressMap BlockAddresses;
std::map<std::string, AsmConstInfo> AsmConsts; // code => { index, list of seen sigs }
std::map<std::string, std::string> EmJsFunctions; // name => code
NameSet FuncRelocatableExterns; // which externals are accessed in this function; we load them once at the beginning (avoids a potential call in a heap access, and might be faster)
// which externals are accessed in this function; we load them once at the
// beginning (avoids a potential call in a heap access, and might be faster)
NameSet FuncRelocatableExterns;
NameSet FuncRelocatableExternFunctions;
std::vector<std::string> ExtraFunctions;
std::set<const Function*> DeclaresNeedingTypeDeclarations; // list of declared funcs whose type we must declare asm.js-style with a usage, as they may not have another usage
// list of declared funcs whose type we must declare asm.js-style with a
// usage, as they may not have another usage
std::set<const Function*> DeclaresNeedingTypeDeclarations;

struct {
// 0 is reserved for void type
Expand Down Expand Up @@ -1850,6 +1856,22 @@ std::string JSWriter::getConstant(const Constant* CV, AsmCast sign) {
if (isa<ConstantPointerNull>(CV)) return "0";

if (const Function *F = dyn_cast<Function>(CV)) {
if (Relocatable && !F->isDSOLocal() && !F->hasLocalLinkage()) {
std::string Name = getOpName(F) + '$' + getFunctionSignature(F->getFunctionType());
ExternalFuncs.insert(Name);
// We access linked function addresses through calls, which we load at the
// beginning of basic blocks. The first time we call this function the
// dynamic linker will assign a table index for this function and return
// it.
FuncRelocatableExternFunctions.insert(Name);
// If we also implement this function we need to export it so that the
// dynamic linker can assign it a table index.
if (!F->isDeclaration())
Exports.push_back(getJSName(F));
Name = "t$" + Name;
UsedVars[Name] = i32;
return Name;
}
return relocateFunctionPointer(utostr(getFunctionIndex(F)));
}

Expand Down Expand Up @@ -3558,6 +3580,14 @@ void JSWriter::printFunctionBody(const Function *F) {
}
FuncRelocatableExterns.clear();
}
if (FuncRelocatableExternFunctions.size() > 0) {
for (auto& RE : FuncRelocatableExternFunctions) {
std::string Temp = "t$" + RE;
std::string Call = "fp$" + RE;
Out << Temp + " = " + Call + "() | 0;\n";
}
FuncRelocatableExternFunctions.clear();
}
}

// Emit (relooped) code
Expand Down Expand Up @@ -3957,6 +3987,19 @@ void JSWriter::printModuleBody() {
}
Out << "],";

Out << "\"externFunctions\": [";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't externs enough for the purpose here - idn't externFunctions duplicating part of it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

externs is for external global data and we want to be able to handle the corresponding g$ and fp$ helpers separately.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't emscripten.py tell which of the externs are functions and which are globals? Then it could create the helpers there? Or is this just easier to do here?

Copy link
Collaborator Author

@sbc100 sbc100 Sep 4, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. IIUC emscripten.py gets all the info it has from the metadata so we need to encode this somehow.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could instead list them in the declares sections with the fp$ prefix so we would know which decleres we of this type.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good either way - you know this code the best at this point.

first = true;
for (NameSet::const_iterator I = ExternalFuncs.begin(), E = ExternalFuncs.end();
I != E; ++I) {
if (first) {
first = false;
} else {
Out << ", ";
}
Out << "\"" << *I << "\"";
}
Out << "],";

Out << "\"implementedFunctions\": [";
first = true;
for (Module::const_iterator I = TheModule->begin(), E = TheModule->end();
Expand Down