[WebAssembly] Implement -print-gc-sections, to better test GC of globals

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

llvm-svn: 330456
This commit is contained in:
Nicholas Wilson 2018-04-20 17:28:12 +00:00
parent 3a1b697d6e
commit 358af38d37
6 changed files with 137 additions and 14 deletions

View File

@ -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
...

View File

@ -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 @@ define hidden i32 @used_function() {
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 @@ entry:
; 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 @@ entry:
; 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

View File

@ -340,7 +340,8 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
Global.Type = {WASM_TYPE_I32, true};
Global.InitExpr.Value.Int32 = 0;
Global.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
InputGlobal *StackPointer = make<InputGlobal>(Global);
Global.SymbolName = "__stack_pointer";
InputGlobal *StackPointer = make<InputGlobal>(Global, nullptr);
StackPointer->Live = true;
static WasmSignature NullSignature = {{}, WASM_TYPE_NORESULT};

View File

@ -187,7 +187,7 @@ void ObjFile::parse() {
// Populate `Globals`.
for (const WasmGlobal &G : WasmObj->globals())
Globals.emplace_back(make<InputGlobal>(G));
Globals.emplace_back(make<InputGlobal>(G, this));
// Populate `Symbols` based on the WasmSymbols in the object.
Symbols.reserve(WasmObj->getNumberOfSymbols());

View File

@ -26,8 +26,10 @@ namespace wasm {
// 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 @@ public:
GlobalIndex = Index;
}
bool Live = false;
ObjFile *File;
WasmGlobal Global;
bool Live = false;
protected:
llvm::Optional<uint32_t> 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

View File

@ -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 @@ void lld::wasm::markLive() {
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));
}
}