Index: lld/trunk/test/wasm/Inputs/globals.yaml =================================================================== --- lld/trunk/test/wasm/Inputs/globals.yaml +++ lld/trunk/test/wasm/Inputs/globals.yaml @@ -0,0 +1,53 @@ +--- !WASM +FileHeader: + Version: 0x00000001 +Sections: + - Type: TYPE + Signatures: + - Index: 0 + ReturnType: I64 + ParamTypes: + - Type: FUNCTION + FunctionTypes: [ 0 ] + - Type: GLOBAL + Globals: + - Index: 0 + Type: I64 + Mutable: true + InitExpr: + Opcode: I64_CONST + Value: 123 + - Index: 1 + Type: I64 + Mutable: true + InitExpr: + Opcode: I64_CONST + Value: 456 + - Type: CODE + Functions: + - Index: 0 + Locals: + Body: 2381808080000B + Relocations: + - Type: R_WEBASSEMBLY_GLOBAL_INDEX_LEB + Index: 1 + Offset: 0x00000004 + - Type: CUSTOM + Name: linking + SymbolTable: + - Index: 0 + Kind: GLOBAL + Name: unused_global + Flags: [ VISIBILITY_HIDDEN ] + Global: 0 + - Index: 1 + Kind: GLOBAL + Name: used_global + Flags: [ VISIBILITY_HIDDEN ] + Global: 1 + - Index: 2 + Kind: FUNCTION + Name: use_global + Flags: [ VISIBILITY_HIDDEN ] + Function: 0 +... Index: lld/trunk/test/wasm/gc-sections.ll =================================================================== --- lld/trunk/test/wasm/gc-sections.ll +++ lld/trunk/test/wasm/gc-sections.ll @@ -1,16 +1,20 @@ ; RUN: llc -filetype=obj %s -o %t.o -; RUN: wasm-ld -print-gc-sections -o %t1.wasm %t.o | FileCheck %s -check-prefix=PRINT-GC +; RUN: yaml2obj %S/Inputs/globals.yaml -o %t_globals.o +; RUN: wasm-ld -print-gc-sections -o %t1.wasm %t.o %t_globals.o | \ +; RUN: FileCheck %s -check-prefix=PRINT-GC ; PRINT-GC: removing unused section {{.*}}:(unused_function) ; PRINT-GC-NOT: removing unused section {{.*}}:(used_function) ; PRINT-GC: removing unused section {{.*}}:(.data.unused_data) ; PRINT-GC-NOT: removing unused section {{.*}}:(.data.used_data) +; PRINT-GC: removing unused section {{.*}}:(unused_global) +; PRINT-GC-NOT: removing unused section {{.*}}:(used_global) target triple = "wasm32-unknown-unknown-wasm" @unused_data = hidden global i64 1, align 4 @used_data = hidden global i32 2, align 4 -define hidden i64 @unused_function() { +define hidden i64 @unused_function(i64 %arg) { %1 = load i64, i64* @unused_data, align 4 ret i64 %1 } @@ -20,24 +24,45 @@ ret i32 %1 } +declare i64 @use_global() + define hidden void @_start() { entry: call i32 @used_function() + call i64 @use_global() ret void } ; RUN: obj2yaml %t1.wasm | FileCheck %s ; CHECK: - Type: TYPE -; CHECK-NEXT: Signatures: +; CHECK-NEXT: Signatures: ; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: ReturnType: NORESULT -; CHECK-NEXT: ParamTypes: +; CHECK-NEXT: ParamTypes: ; CHECK-NEXT: - Index: 1 ; CHECK-NEXT: ReturnType: I32 -; CHECK-NEXT: ParamTypes: +; CHECK-NEXT: ParamTypes: +; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: ReturnType: I64 +; CHECK-NEXT: ParamTypes: ; CHECK-NEXT: - Type: FUNCTION +; CHECK: - Type: GLOBAL +; CHECK-NEXT: Globals: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Type: I32 +; CHECK-NEXT: Mutable: true +; CHECK-NEXT: InitExpr: +; CHECK-NEXT: Opcode: I32_CONST +; CHECK-NEXT: Value: 66576 +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: Type: I64 +; CHECK-NEXT: Mutable: true +; CHECK-NEXT: InitExpr: +; CHECK-NEXT: Opcode: I64_CONST +; CHECK-NEXT: Value: 456 + ; CHECK: - Type: DATA ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 7 @@ -55,24 +80,52 @@ ; CHECK-NEXT: Name: used_function ; CHECK-NEXT: - Index: 2 ; CHECK-NEXT: Name: _start +; CHECK-NEXT: - Index: 3 +; CHECK-NEXT: Name: use_global ; CHECK-NEXT: ... -; RUN: wasm-ld -print-gc-sections --no-gc-sections -o %t1.no-gc.wasm %t.o +; RUN: wasm-ld -print-gc-sections --no-gc-sections -o %t1.no-gc.wasm \ +; RUN: %t.o %t_globals.o ; RUN: obj2yaml %t1.no-gc.wasm | FileCheck %s -check-prefix=NO-GC ; NO-GC: - Type: TYPE -; NO-GC-NEXT: Signatures: +; NO-GC-NEXT: Signatures: ; NO-GC-NEXT: - Index: 0 ; NO-GC-NEXT: ReturnType: NORESULT ; NO-GC-NEXT: ParamTypes: ; NO-GC-NEXT: - Index: 1 ; NO-GC-NEXT: ReturnType: I64 -; NO-GC-NEXT: ParamTypes: +; NO-GC-NEXT: ParamTypes: +; NO-GC-NEXT: - I64 ; NO-GC-NEXT: - Index: 2 ; NO-GC-NEXT: ReturnType: I32 -; NO-GC-NEXT: ParamTypes: +; NO-GC-NEXT: ParamTypes: +; NO-GC-NEXT: - Index: 3 +; NO-GC-NEXT: ReturnType: I64 +; NO-GC-NEXT: ParamTypes: ; NO-GC-NEXT: - Type: FUNCTION +; NO-GC: - Type: GLOBAL +; NO-GC-NEXT: Globals: +; NO-GC-NEXT: - Index: 0 +; NO-GC-NEXT: Type: I32 +; NO-GC-NEXT: Mutable: true +; NO-GC-NEXT: InitExpr: +; NO-GC-NEXT: Opcode: I32_CONST +; NO-GC-NEXT: Value: 66576 +; NO-GC-NEXT: - Index: 1 +; NO-GC-NEXT: Type: I64 +; NO-GC-NEXT: Mutable: true +; NO-GC-NEXT: InitExpr: +; NO-GC-NEXT: Opcode: I64_CONST +; NO-GC-NEXT: Value: 123 +; NO-GC-NEXT: - Index: 2 +; NO-GC-NEXT: Type: I64 +; NO-GC-NEXT: Mutable: true +; NO-GC-NEXT: InitExpr: +; NO-GC-NEXT: Opcode: I64_CONST +; NO-GC-NEXT: Value: 456 + ; NO-GC: - Type: DATA ; NO-GC-NEXT: Segments: ; NO-GC-NEXT: - SectionOffset: 7 @@ -92,6 +145,8 @@ ; NO-GC-NEXT: Name: used_function ; NO-GC-NEXT: - Index: 3 ; NO-GC-NEXT: Name: _start +; NO-GC-NEXT: - Index: 4 +; NO-GC-NEXT: Name: use_global ; NO-GC-NEXT: ... ; RUN: not wasm-ld --gc-sections --relocatable -o %t1.no-gc.wasm %t.o 2>&1 | FileCheck %s -check-prefix=CHECK-ERROR Index: lld/trunk/wasm/Driver.cpp =================================================================== --- lld/trunk/wasm/Driver.cpp +++ lld/trunk/wasm/Driver.cpp @@ -340,7 +340,8 @@ Global.Type = {WASM_TYPE_I32, true}; Global.InitExpr.Value.Int32 = 0; Global.InitExpr.Opcode = WASM_OPCODE_I32_CONST; - InputGlobal *StackPointer = make(Global); + Global.SymbolName = "__stack_pointer"; + InputGlobal *StackPointer = make(Global, nullptr); StackPointer->Live = true; static WasmSignature NullSignature = {{}, WASM_TYPE_NORESULT}; Index: lld/trunk/wasm/InputFiles.cpp =================================================================== --- lld/trunk/wasm/InputFiles.cpp +++ lld/trunk/wasm/InputFiles.cpp @@ -187,7 +187,7 @@ // Populate `Globals`. for (const WasmGlobal &G : WasmObj->globals()) - Globals.emplace_back(make(G)); + Globals.emplace_back(make(G, this)); // Populate `Symbols` based on the WasmSymbols in the object. Symbols.reserve(WasmObj->getNumberOfSymbols()); Index: lld/trunk/wasm/InputGlobal.h =================================================================== --- lld/trunk/wasm/InputGlobal.h +++ lld/trunk/wasm/InputGlobal.h @@ -26,8 +26,10 @@ // combined to form the final GLOBALS section. class InputGlobal { public: - InputGlobal(const WasmGlobal &G) : Global(G) {} + InputGlobal(const WasmGlobal &G, ObjFile *F) + : File(F), Global(G), Live(!Config->GcSections) {} + StringRef getName() const { return Global.SymbolName; } const WasmGlobalType &getType() const { return Global.Type; } uint32_t getGlobalIndex() const { return GlobalIndex.getValue(); } @@ -37,16 +39,21 @@ GlobalIndex = Index; } - bool Live = false; - + ObjFile *File; WasmGlobal Global; + bool Live = false; + protected: llvm::Optional GlobalIndex; }; } // namespace wasm +inline std::string toString(const wasm::InputGlobal *G) { + return (toString(G->File) + ":(" + G->getName() + ")").str(); +} + } // namespace lld #endif // LLD_WASM_INPUT_GLOBAL_H Index: lld/trunk/wasm/MarkLive.cpp =================================================================== --- lld/trunk/wasm/MarkLive.cpp +++ lld/trunk/wasm/MarkLive.cpp @@ -22,6 +22,7 @@ #include "MarkLive.h" #include "Config.h" #include "InputChunks.h" +#include "InputGlobal.h" #include "SymbolTable.h" #include "Symbols.h" @@ -102,9 +103,15 @@ for (InputChunk *C : Obj->Segments) if (!C->Live) message("removing unused section " + toString(C)); + for (InputGlobal *G : Obj->Globals) + if (!G->Live) + message("removing unused section " + toString(G)); } for (InputChunk *C : Symtab->SyntheticFunctions) if (!C->Live) message("removing unused section " + toString(C)); + for (InputGlobal *G : Symtab->SyntheticGlobals) + if (!G->Live) + message("removing unused section " + toString(G)); } }