forked from OSchip/llvm-project
[WebAssembly] Implement --print-gc-sections for synthetic functions
Enables cleaning up confusion between which name variables are mangled and which are unmangled, and --print-gc-sections then excersises and tests that. Differential Revision: https://reviews.llvm.org/D44440 llvm-svn: 330449
This commit is contained in:
parent
ef90ff36da
commit
6c7fe30a1c
|
@ -1,5 +1,6 @@
|
||||||
; RUN: llc -filetype=obj %s -o %t.o
|
; RUN: llc -filetype=obj %s -o %t.o
|
||||||
; RUN: wasm-ld --check-signatures --no-entry %t.o -o %t.wasm
|
; RUN: wasm-ld --check-signatures --no-entry --print-gc-sections %t.o \
|
||||||
|
; RUN: -o %t.wasm 2>&1 | FileCheck -check-prefix=CHECK-GC %s
|
||||||
; RUN: obj2yaml %t.wasm | FileCheck %s
|
; RUN: obj2yaml %t.wasm | FileCheck %s
|
||||||
|
|
||||||
; Check that calling an undefined weak function generates an appropriate stub
|
; Check that calling an undefined weak function generates an appropriate stub
|
||||||
|
@ -12,6 +13,8 @@ declare extern_weak void @weakFunc2() ; same signature
|
||||||
declare extern_weak void @weakFunc3(i32 %arg) ; different
|
declare extern_weak void @weakFunc3(i32 %arg) ; different
|
||||||
declare extern_weak void @weakFunc4() ; should be GC'd as not called
|
declare extern_weak void @weakFunc4() ; should be GC'd as not called
|
||||||
|
|
||||||
|
; CHECK-GC: removing unused section {{.*}}:(weakFunc4)
|
||||||
|
|
||||||
define i32 @callWeakFuncs() {
|
define i32 @callWeakFuncs() {
|
||||||
call void @weakFunc1()
|
call void @weakFunc1()
|
||||||
call void @weakFunc2()
|
call void @weakFunc2()
|
||||||
|
|
|
@ -240,10 +240,11 @@ static void handleWeakUndefines() {
|
||||||
// Add a synthetic dummy for weak undefined functions. These dummies will
|
// Add a synthetic dummy for weak undefined functions. These dummies will
|
||||||
// be GC'd if not used as the target of any "call" instructions.
|
// be GC'd if not used as the target of any "call" instructions.
|
||||||
Optional<std::string> SymName = demangleItanium(Sym->getName());
|
Optional<std::string> SymName = demangleItanium(Sym->getName());
|
||||||
StringRef StubName =
|
StringRef DebugName =
|
||||||
Saver.save("undefined function " +
|
Saver.save("undefined function " +
|
||||||
(SymName ? StringRef(*SymName) : Sym->getName()));
|
(SymName ? StringRef(*SymName) : Sym->getName()));
|
||||||
SyntheticFunction *Func = make<SyntheticFunction>(Sig, StubName);
|
SyntheticFunction *Func =
|
||||||
|
make<SyntheticFunction>(Sig, Sym->getName(), DebugName);
|
||||||
Func->setBody(UnreachableFn);
|
Func->setBody(UnreachableFn);
|
||||||
// Ensure it compares equal to the null pointer, and so that table relocs
|
// Ensure it compares equal to the null pointer, and so that table relocs
|
||||||
// don't pull in the stub body (only call-operand relocs should do that).
|
// don't pull in the stub body (only call-operand relocs should do that).
|
||||||
|
|
|
@ -57,6 +57,7 @@ public:
|
||||||
ArrayRef<WasmRelocation> getRelocations() const { return Relocations; }
|
ArrayRef<WasmRelocation> getRelocations() const { return Relocations; }
|
||||||
|
|
||||||
virtual StringRef getName() const = 0;
|
virtual StringRef getName() const = 0;
|
||||||
|
virtual StringRef getDebugName() const = 0;
|
||||||
virtual uint32_t getComdat() const = 0;
|
virtual uint32_t getComdat() const = 0;
|
||||||
StringRef getComdatName() const;
|
StringRef getComdatName() const;
|
||||||
|
|
||||||
|
@ -99,6 +100,7 @@ public:
|
||||||
|
|
||||||
uint32_t getAlignment() const { return Segment.Data.Alignment; }
|
uint32_t getAlignment() const { return Segment.Data.Alignment; }
|
||||||
StringRef getName() const override { return Segment.Data.Name; }
|
StringRef getName() const override { return Segment.Data.Name; }
|
||||||
|
StringRef getDebugName() const override { return StringRef(); }
|
||||||
uint32_t getComdat() const override { return Segment.Data.Comdat; }
|
uint32_t getComdat() const override { return Segment.Data.Comdat; }
|
||||||
|
|
||||||
const OutputSegment *OutputSeg = nullptr;
|
const OutputSegment *OutputSeg = nullptr;
|
||||||
|
@ -125,7 +127,8 @@ public:
|
||||||
C->kind() == InputChunk::SyntheticFunction;
|
C->kind() == InputChunk::SyntheticFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringRef getName() const override { return Function->Name; }
|
StringRef getName() const override { return Function->SymbolName; }
|
||||||
|
StringRef getDebugName() const override { return Function->DebugName; }
|
||||||
uint32_t getComdat() const override { return Function->Comdat; }
|
uint32_t getComdat() const override { return Function->Comdat; }
|
||||||
uint32_t getFunctionIndex() const { return FunctionIndex.getValue(); }
|
uint32_t getFunctionIndex() const { return FunctionIndex.getValue(); }
|
||||||
bool hasFunctionIndex() const { return FunctionIndex.hasValue(); }
|
bool hasFunctionIndex() const { return FunctionIndex.hasValue(); }
|
||||||
|
@ -152,8 +155,9 @@ protected:
|
||||||
|
|
||||||
class SyntheticFunction : public InputFunction {
|
class SyntheticFunction : public InputFunction {
|
||||||
public:
|
public:
|
||||||
SyntheticFunction(const WasmSignature &S, StringRef Name)
|
SyntheticFunction(const WasmSignature &S, StringRef Name,
|
||||||
: InputFunction(S, nullptr, nullptr), Name(Name) {
|
StringRef DebugName = {})
|
||||||
|
: InputFunction(S, nullptr, nullptr), Name(Name), DebugName(DebugName) {
|
||||||
SectionKind = InputChunk::SyntheticFunction;
|
SectionKind = InputChunk::SyntheticFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,6 +166,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
StringRef getName() const override { return Name; }
|
StringRef getName() const override { return Name; }
|
||||||
|
StringRef getDebugName() const override { return DebugName; }
|
||||||
uint32_t getComdat() const override { return UINT32_MAX; }
|
uint32_t getComdat() const override { return UINT32_MAX; }
|
||||||
|
|
||||||
void setBody(ArrayRef<uint8_t> Body_) { Body = Body_; }
|
void setBody(ArrayRef<uint8_t> Body_) { Body = Body_; }
|
||||||
|
@ -170,6 +175,7 @@ protected:
|
||||||
ArrayRef<uint8_t> data() const override { return Body; }
|
ArrayRef<uint8_t> data() const override { return Body; }
|
||||||
|
|
||||||
StringRef Name;
|
StringRef Name;
|
||||||
|
StringRef DebugName;
|
||||||
ArrayRef<uint8_t> Body;
|
ArrayRef<uint8_t> Body;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -182,6 +188,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
StringRef getName() const override { return Section.Name; }
|
StringRef getName() const override { return Section.Name; }
|
||||||
|
StringRef getDebugName() const override { return StringRef(); }
|
||||||
uint32_t getComdat() const override { return UINT32_MAX; }
|
uint32_t getComdat() const override { return UINT32_MAX; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -105,5 +105,8 @@ void lld::wasm::markLive() {
|
||||||
if (!C->Live)
|
if (!C->Live)
|
||||||
message("removing unused section " + toString(C));
|
message("removing unused section " + toString(C));
|
||||||
}
|
}
|
||||||
|
for (InputChunk *C : Symtab->SyntheticFunctions)
|
||||||
|
if (!C->Live)
|
||||||
|
message("removing unused section " + toString(C));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -534,7 +534,7 @@ void Writer::createLinkingSection() {
|
||||||
void Writer::createNameSection() {
|
void Writer::createNameSection() {
|
||||||
unsigned NumNames = NumImportedFunctions;
|
unsigned NumNames = NumImportedFunctions;
|
||||||
for (const InputFunction *F : InputFunctions)
|
for (const InputFunction *F : InputFunctions)
|
||||||
if (!F->getName().empty())
|
if (!F->getName().empty() || !F->getDebugName().empty())
|
||||||
++NumNames;
|
++NumNames;
|
||||||
|
|
||||||
if (NumNames == 0)
|
if (NumNames == 0)
|
||||||
|
@ -558,8 +558,12 @@ void Writer::createNameSection() {
|
||||||
for (const InputFunction *F : InputFunctions) {
|
for (const InputFunction *F : InputFunctions) {
|
||||||
if (!F->getName().empty()) {
|
if (!F->getName().empty()) {
|
||||||
writeUleb128(Sub.OS, F->getFunctionIndex(), "func index");
|
writeUleb128(Sub.OS, F->getFunctionIndex(), "func index");
|
||||||
Optional<std::string> Name = demangleItanium(F->getName());
|
if (!F->getDebugName().empty()) {
|
||||||
writeStr(Sub.OS, Name ? StringRef(*Name) : F->getName(), "symbol name");
|
writeStr(Sub.OS, F->getDebugName(), "symbol name");
|
||||||
|
} else {
|
||||||
|
Optional<std::string> Name = demangleItanium(F->getName());
|
||||||
|
writeStr(Sub.OS, Name ? StringRef(*Name) : F->getName(), "symbol name");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue