; 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
; Check that calling an undefined weak function generates an appropriate stub
declare extern_weak void @weakFunc3(i32 %arg) ; different
declare extern_weak void @weakFunc4() ; should be GC'd as not called
+; CHECK-GC: removing unused section {{.*}}:(weakFunc4)
+
define i32 @callWeakFuncs() {
call void @weakFunc1()
call void @weakFunc2()
// Add a synthetic dummy for weak undefined functions. These dummies will
// be GC'd if not used as the target of any "call" instructions.
Optional<std::string> SymName = demangleItanium(Sym->getName());
- StringRef StubName =
+ StringRef DebugName =
Saver.save("undefined function " +
(SymName ? StringRef(*SymName) : Sym->getName()));
- SyntheticFunction *Func = make<SyntheticFunction>(Sig, StubName);
+ SyntheticFunction *Func =
+ make<SyntheticFunction>(Sig, Sym->getName(), DebugName);
Func->setBody(UnreachableFn);
// 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).
ArrayRef<WasmRelocation> getRelocations() const { return Relocations; }
virtual StringRef getName() const = 0;
+ virtual StringRef getDebugName() const = 0;
virtual uint32_t getComdat() const = 0;
StringRef getComdatName() const;
uint32_t getAlignment() const { return Segment.Data.Alignment; }
StringRef getName() const override { return Segment.Data.Name; }
+ StringRef getDebugName() const override { return StringRef(); }
uint32_t getComdat() const override { return Segment.Data.Comdat; }
const OutputSegment *OutputSeg = nullptr;
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 getFunctionIndex() const { return FunctionIndex.getValue(); }
bool hasFunctionIndex() const { return FunctionIndex.hasValue(); }
class SyntheticFunction : public InputFunction {
public:
- SyntheticFunction(const WasmSignature &S, StringRef Name)
- : InputFunction(S, nullptr, nullptr), Name(Name) {
+ SyntheticFunction(const WasmSignature &S, StringRef Name,
+ StringRef DebugName = {})
+ : InputFunction(S, nullptr, nullptr), Name(Name), DebugName(DebugName) {
SectionKind = InputChunk::SyntheticFunction;
}
}
StringRef getName() const override { return Name; }
+ StringRef getDebugName() const override { return DebugName; }
uint32_t getComdat() const override { return UINT32_MAX; }
void setBody(ArrayRef<uint8_t> Body_) { Body = Body_; }
ArrayRef<uint8_t> data() const override { return Body; }
StringRef Name;
+ StringRef DebugName;
ArrayRef<uint8_t> Body;
};
}
StringRef getName() const override { return Section.Name; }
+ StringRef getDebugName() const override { return StringRef(); }
uint32_t getComdat() const override { return UINT32_MAX; }
protected:
if (!C->Live)
message("removing unused section " + toString(C));
}
+ for (InputChunk *C : Symtab->SyntheticFunctions)
+ if (!C->Live)
+ message("removing unused section " + toString(C));
}
}
void Writer::createNameSection() {
unsigned NumNames = NumImportedFunctions;
for (const InputFunction *F : InputFunctions)
- if (!F->getName().empty())
+ if (!F->getName().empty() || !F->getDebugName().empty())
++NumNames;
if (NumNames == 0)
for (const InputFunction *F : InputFunctions) {
if (!F->getName().empty()) {
writeUleb128(Sub.OS, F->getFunctionIndex(), "func index");
- Optional<std::string> Name = demangleItanium(F->getName());
- writeStr(Sub.OS, Name ? StringRef(*Name) : F->getName(), "symbol name");
+ if (!F->getDebugName().empty()) {
+ 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");
+ }
}
}