[WebAssembly] Simplify generation of "names" section

Simplify generation of "names" section by simply iterating
over the DefinedFunctions array.

This even fixes some bugs, judging by the test changes required.
Some tests are asserting that functions are named multiple times,
other tests are asserting that the "names" section contains the
function's alias rather than its original name

Patch by Nicholas Wilson!

Differential Revision: https://reviews.llvm.org/D42076

llvm-svn: 322751
This commit is contained in:
Sam Clegg 2018-01-17 20:19:04 +00:00
parent 6d83f34afd
commit 1963d71cb8
6 changed files with 37 additions and 57 deletions

View File

@ -77,7 +77,7 @@ entry:
; CHECK-NEXT: Name: name ; CHECK-NEXT: Name: name
; CHECK-NEXT: FunctionNames: ; CHECK-NEXT: FunctionNames:
; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: - Index: 0
; CHECK-NEXT: Name: start_alias ; CHECK-NEXT: Name: _start
; CHECK-NEXT: - Index: 1 ; CHECK-NEXT: - Index: 1
; CHECK-NEXT: Name: __wasm_call_ctors ; CHECK-NEXT: Name: __wasm_call_ctors
; CHECK-NEXT: ... ; CHECK-NEXT: ...

View File

@ -239,4 +239,6 @@ entry:
; CHECK-NEXT: Name: hello ; CHECK-NEXT: Name: hello
; CHECK-NEXT: - Index: 3 ; CHECK-NEXT: - Index: 3
; CHECK-NEXT: Name: my_func ; CHECK-NEXT: Name: my_func
; CHECK-NEXT: - Index: 4
; CHECK-NEXT: Name: func_comdat
; CHECK-NEXT: ... ; CHECK-NEXT: ...

View File

@ -114,8 +114,12 @@ entry:
; CHECK-NEXT: FunctionNames: ; CHECK-NEXT: FunctionNames:
; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: - Index: 0
; CHECK-NEXT: Name: _start ; CHECK-NEXT: Name: _start
; CHECK-NEXT: - Index: 1
; CHECK-NEXT: Name: weakFn
; CHECK-NEXT: - Index: 2 ; CHECK-NEXT: - Index: 2
; CHECK-NEXT: Name: exportWeak1 ; CHECK-NEXT: Name: exportWeak1
; CHECK-NEXT: - Index: 3
; CHECK-NEXT: Name: weakFn
; CHECK-NEXT: - Index: 4 ; CHECK-NEXT: - Index: 4
; CHECK-NEXT: Name: exportWeak2 ; CHECK-NEXT: Name: exportWeak2
; CHECK-NEXT: - Index: 5 ; CHECK-NEXT: - Index: 5

View File

@ -112,8 +112,9 @@ class InputFunction : public InputChunk {
public: public:
InputFunction(const WasmSignature &S, const WasmFunction *Func, InputFunction(const WasmSignature &S, const WasmFunction *Func,
const ObjFile *F) const ObjFile *F)
: InputChunk(F), Signature(S), WrittenToNameSec(false), Function(Func) {} : InputChunk(F), Signature(S), Function(Func) {}
virtual StringRef getName() const { return Function->Name; }
StringRef getComdat() const override { return Function->Comdat; } StringRef getComdat() const override { return Function->Comdat; }
uint32_t getOutputIndex() const { return OutputIndex.getValue(); } uint32_t getOutputIndex() const { return OutputIndex.getValue(); }
bool hasOutputIndex() const { return OutputIndex.hasValue(); } bool hasOutputIndex() const { return OutputIndex.hasValue(); }
@ -121,8 +122,6 @@ public:
const WasmSignature &Signature; const WasmSignature &Signature;
unsigned WrittenToNameSec : 1;
protected: protected:
ArrayRef<uint8_t> data() const override { ArrayRef<uint8_t> data() const override {
return File->CodeSection->Content.slice(getInputSectionOffset(), return File->CodeSection->Content.slice(getInputSectionOffset(),
@ -138,12 +137,16 @@ protected:
class SyntheticFunction : public InputFunction { class SyntheticFunction : public InputFunction {
public: public:
SyntheticFunction(const WasmSignature &S, ArrayRef<uint8_t> Body) SyntheticFunction(const WasmSignature &S, ArrayRef<uint8_t> Body,
: InputFunction(S, nullptr, nullptr), Body(Body) {} StringRef Name)
: InputFunction(S, nullptr, nullptr), Name(Name), Body(Body) {}
StringRef getName() const override { return Name; }
protected: protected:
ArrayRef<uint8_t> data() const override { return Body; } ArrayRef<uint8_t> data() const override { return Body; }
StringRef Name;
ArrayRef<uint8_t> Body; ArrayRef<uint8_t> Body;
}; };

View File

@ -38,8 +38,7 @@ public:
InvalidKind, InvalidKind,
}; };
Symbol(StringRef Name, uint32_t Flags) Symbol(StringRef Name, uint32_t Flags) : Flags(Flags), Name(Name) {}
: WrittenToNameSec(0), Flags(Flags), Name(Name) {}
Kind getKind() const { return SymbolKind; } Kind getKind() const { return SymbolKind; }
@ -100,10 +99,6 @@ public:
const Archive::Symbol &getArchiveSymbol() { return ArchiveSymbol; } const Archive::Symbol &getArchiveSymbol() { return ArchiveSymbol; }
InputFunction *getFunction() { return Function; } InputFunction *getFunction() { return Function; }
// This bit is used by Writer::writeNameSection() to prevent
// symbols from being written to the symbol table more than once.
unsigned WrittenToNameSec : 1;
protected: protected:
uint32_t Flags; uint32_t Flags;
uint32_t VirtualAddress = 0; uint32_t VirtualAddress = 0;

View File

@ -469,59 +469,33 @@ void Writer::createLinkingSection() {
// Create the custom "name" section containing debug symbol names. // Create the custom "name" section containing debug symbol names.
void Writer::createNameSection() { void Writer::createNameSection() {
// Create an array of all function sorted by function index space unsigned NumNames = ImportedFunctions.size();
std::vector<const Symbol *> Names; for (const InputFunction *F : DefinedFunctions)
if (!F->getName().empty())
++NumNames;
auto AddToNames = [&](Symbol* S) { if (NumNames == 0)
if (!S->isFunction() || S->WrittenToNameSec) return;
return;
// We also need to guard against two different symbols (two different
// names) for the same wasm function. While this is possible (aliases)
// it is not legal in the "name" section.
InputFunction *Function = S->getFunction();
if (Function) {
if (Function->WrittenToNameSec)
return;
Function->WrittenToNameSec = true;
}
S->WrittenToNameSec = true;
Names.emplace_back(S);
};
for (ObjFile *File : Symtab->ObjectFiles) {
Names.reserve(Names.size() + File->getSymbols().size());
DEBUG(dbgs() << "adding names from: " << File->getName() << "\n");
for (Symbol *S : File->getSymbols()) {
if (S->isWeak())
continue;
AddToNames(S);
}
}
DEBUG(dbgs() << "adding symtab names\n");
for (Symbol *S : Symtab->getSymbols()) {
DEBUG(dbgs() << "sym: " << S->getName() << "\n");
if (S->getFile())
continue;
AddToNames(S);
}
SyntheticSection *Section = createSyntheticSection(WASM_SEC_CUSTOM, "name"); SyntheticSection *Section = createSyntheticSection(WASM_SEC_CUSTOM, "name");
std::sort(Names.begin(), Names.end(), [](const Symbol *A, const Symbol *B) {
return A->getOutputIndex() < B->getOutputIndex();
});
SubSection FunctionSubsection(WASM_NAMES_FUNCTION); SubSection FunctionSubsection(WASM_NAMES_FUNCTION);
raw_ostream &OS = FunctionSubsection.getStream(); raw_ostream &OS = FunctionSubsection.getStream();
writeUleb128(OS, Names.size(), "name count"); writeUleb128(OS, NumNames, "name count");
// We have to iterate through the inputs twice so that all the imports // Names must appear in function index order. As it happens ImportedFunctions
// appear first before any of the local function names. // and DefinedFunctions are numbers in order with imported functions coming
for (const Symbol *S : Names) { // first.
writeUleb128(OS, S->getOutputIndex(), "func index"); for (const Symbol *S : ImportedFunctions) {
writeUleb128(OS, S->getOutputIndex(), "import index");
writeStr(OS, S->getName(), "symbol name"); writeStr(OS, S->getName(), "symbol name");
} }
for (const InputFunction *F : DefinedFunctions) {
if (!F->getName().empty()) {
writeUleb128(OS, F->getOutputIndex(), "func index");
writeStr(OS, F->getName(), "symbol name");
}
}
FunctionSubsection.finalizeContents(); FunctionSubsection.finalizeContents();
FunctionSubsection.writeToStream(Section->getStream()); FunctionSubsection.writeToStream(Section->getStream());
@ -784,7 +758,9 @@ void Writer::createCtorFunction() {
ArrayRef<uint8_t> BodyArray( ArrayRef<uint8_t> BodyArray(
reinterpret_cast<const uint8_t *>(CtorFunctionBody.data()), reinterpret_cast<const uint8_t *>(CtorFunctionBody.data()),
CtorFunctionBody.size()); CtorFunctionBody.size());
CtorFunction = llvm::make_unique<SyntheticFunction>(Signature, BodyArray); CtorFunction = llvm::make_unique<SyntheticFunction>(
Signature, BodyArray, Config->CtorSymbol->getName());
CtorFunction->setOutputIndex(FunctionIndex);
DefinedFunctions.emplace_back(CtorFunction.get()); DefinedFunctions.emplace_back(CtorFunction.get());
} }