diff options
| -rw-r--r-- | lld/test/wasm/call-indirect.ll | 18 | ||||
| -rw-r--r-- | lld/test/wasm/gc-sections.ll | 37 | ||||
| -rw-r--r-- | lld/test/wasm/relocatable.ll | 14 | ||||
| -rw-r--r-- | lld/wasm/InputChunks.h | 8 | ||||
| -rw-r--r-- | lld/wasm/InputFiles.cpp | 4 | ||||
| -rw-r--r-- | lld/wasm/InputFiles.h | 1 | ||||
| -rw-r--r-- | lld/wasm/Writer.cpp | 53 |
7 files changed, 89 insertions, 46 deletions
diff --git a/lld/test/wasm/call-indirect.ll b/lld/test/wasm/call-indirect.ll index 45270f6ccbe..ea814dec0eb 100644 --- a/lld/test/wasm/call-indirect.ll +++ b/lld/test/wasm/call-indirect.ll @@ -43,21 +43,21 @@ define void @call_ptr(i64 (i64)* %arg) { ; CHECK-NEXT: ReturnType: I64 ; CHECK-NEXT: ParamTypes: ; CHECK-NEXT: - Index: 1 -; CHECK-NEXT: ReturnType: NORESULT +; CHECK-NEXT: ReturnType: I32 ; CHECK-NEXT: ParamTypes: ; CHECK-NEXT: - Index: 2 -; CHECK-NEXT: ReturnType: I32 +; CHECK-NEXT: ReturnType: I64 ; CHECK-NEXT: ParamTypes: +; CHECK-NEXT: - I64 ; CHECK-NEXT: - Index: 3 ; CHECK-NEXT: ReturnType: NORESULT ; CHECK-NEXT: ParamTypes: -; CHECK-NEXT: - I32 ; CHECK-NEXT: - Index: 4 -; CHECK-NEXT: ReturnType: I64 +; CHECK-NEXT: ReturnType: NORESULT ; CHECK-NEXT: ParamTypes: -; CHECK-NEXT: - I64 +; CHECK-NEXT: - I32 ; CHECK-NEXT: - Type: FUNCTION -; CHECK-NEXT: FunctionTypes: [ 0, 1, 2, 2, 3, 1 ] +; CHECK-NEXT: FunctionTypes: [ 0, 3, 1, 1, 4, 3 ] ; CHECK-NEXT: - Type: TABLE ; CHECK-NEXT: Tables: ; CHECK-NEXT: - ElemType: ANYFUNC @@ -120,16 +120,16 @@ define void @call_ptr(i64 (i64)* %arg) { ; CHECK-NEXT: Locals: ; CHECK-NEXT: - Type: I32 ; CHECK-NEXT: Count: 1 -; CHECK-NEXT: Body: 4100280284888080002100410028028088808000118080808000001A2000118280808000001A0B +; CHECK-NEXT: Body: 4100280284888080002100410028028088808000118080808000001A2000118180808000001A0B ; CHECK-NEXT: - Index: 2 ; CHECK-NEXT: Locals: ; CHECK-NEXT: Body: 41020B ; CHECK-NEXT: - Index: 3 ; CHECK-NEXT: Locals: -; CHECK-NEXT: Body: 410028028888808000118280808000001A41000B +; CHECK-NEXT: Body: 410028028888808000118180808000001A41000B ; CHECK-NEXT: - Index: 4 ; CHECK-NEXT: Locals: -; CHECK-NEXT: Body: 42012000118480808000001A0B +; CHECK-NEXT: Body: 42012000118280808000001A0B ; CHECK-NEXT: - Index: 5 ; CHECK-NEXT: Locals: ; CHECK-NEXT: Body: 0B diff --git a/lld/test/wasm/gc-sections.ll b/lld/test/wasm/gc-sections.ll index fa9888acb10..d632871629d 100644 --- a/lld/test/wasm/gc-sections.ll +++ b/lld/test/wasm/gc-sections.ll @@ -7,12 +7,12 @@ target triple = "wasm32-unknown-unknown-wasm" -@unused_data = hidden global i32 1, align 4 +@unused_data = hidden global i64 1, align 4 @used_data = hidden global i32 2, align 4 -define hidden i32 @unused_function() { - %1 = load i32, i32* @unused_data, align 4 - ret i32 %1 +define hidden i64 @unused_function() { + %1 = load i64, i64* @unused_data, align 4 + ret i64 %1 } define hidden i32 @used_function() { @@ -27,6 +27,17 @@ entry: } ; RUN: obj2yaml %t1.wasm | FileCheck %s + +; CHECK: - Type: TYPE +; CHECK-NEXT: Signatures: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: ReturnType: I32 +; CHECK-NEXT: ParamTypes: +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: ReturnType: NORESULT +; CHECK-NEXT: ParamTypes: +; CHECK-NEXT: - Type: FUNCTION + ; CHECK: - Type: DATA ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 7 @@ -51,6 +62,20 @@ entry: ; RUN: lld -flavor wasm -print-gc-sections --no-gc-sections -o %t1.no-gc.wasm %t.o ; RUN: obj2yaml %t1.no-gc.wasm | FileCheck %s -check-prefix=NO-GC + +; NO-GC: - Type: TYPE +; NO-GC-NEXT: Signatures: +; NO-GC-NEXT: - Index: 0 +; NO-GC-NEXT: ReturnType: I64 +; NO-GC-NEXT: ParamTypes: +; NO-GC-NEXT: - Index: 1 +; NO-GC-NEXT: ReturnType: I32 +; NO-GC-NEXT: ParamTypes: +; NO-GC-NEXT: - Index: 2 +; NO-GC-NEXT: ReturnType: NORESULT +; NO-GC-NEXT: ParamTypes: +; NO-GC-NEXT: - Type: FUNCTION + ; NO-GC: - Type: DATA ; NO-GC-NEXT: Segments: ; NO-GC-NEXT: - SectionOffset: 7 @@ -58,10 +83,10 @@ entry: ; NO-GC-NEXT: Offset: ; NO-GC-NEXT: Opcode: I32_CONST ; NO-GC-NEXT: Value: 1024 -; NO-GC-NEXT: Content: '0100000002000000' +; NO-GC-NEXT: Content: '010000000000000002000000' ; NO-GC-NEXT: - Type: CUSTOM ; NO-GC-NEXT: Name: linking -; NO-GC-NEXT: DataSize: 8 +; NO-GC-NEXT: DataSize: 12 ; NO-GC-NEXT: - Type: CUSTOM ; NO-GC-NEXT: Name: name ; NO-GC-NEXT: FunctionNames: diff --git a/lld/test/wasm/relocatable.ll b/lld/test/wasm/relocatable.ll index 64403175133..b543b5e47b4 100644 --- a/lld/test/wasm/relocatable.ll +++ b/lld/test/wasm/relocatable.ll @@ -38,34 +38,34 @@ entry: ; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: ReturnType: NORESULT ; CHECK-NEXT: ParamTypes: +; CHECK-NEXT: - I32 ; CHECK-NEXT: - Index: 1 -; CHECK-NEXT: ReturnType: NORESULT +; CHECK-NEXT: ReturnType: I32 ; CHECK-NEXT: ParamTypes: -; CHECK-NEXT: - I32 ; CHECK-NEXT: - Index: 2 -; CHECK-NEXT: ReturnType: I32 +; CHECK-NEXT: ReturnType: NORESULT ; CHECK-NEXT: ParamTypes: ; CHECK-NEXT: - Type: IMPORT ; CHECK-NEXT: Imports: ; CHECK-NEXT: - Module: env ; CHECK-NEXT: Field: puts ; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: SigIndex: 1 +; CHECK-NEXT: SigIndex: 0 ; CHECK-NEXT: - Module: env ; CHECK-NEXT: Field: foo_import ; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: SigIndex: 2 +; CHECK-NEXT: SigIndex: 1 ; CHECK-NEXT: - Module: env ; CHECK-NEXT: Field: bar_import ; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: SigIndex: 2 +; CHECK-NEXT: SigIndex: 1 ; CHECK-NEXT: - Module: env ; CHECK-NEXT: Field: data_import ; CHECK-NEXT: Kind: GLOBAL ; CHECK-NEXT: GlobalType: I32 ; CHECK-NEXT: GlobalMutable: false ; CHECK-NEXT: - Type: FUNCTION -; CHECK-NEXT: FunctionTypes: [ 0, 2, 2 ] +; CHECK-NEXT: FunctionTypes: [ 2, 1, 1 ] ; CHECK-NEXT: - Type: TABLE ; CHECK-NEXT: Tables: ; CHECK-NEXT: - ElemType: ANYFUNC diff --git a/lld/wasm/InputChunks.h b/lld/wasm/InputChunks.h index 434680a1a09..9ae201776c2 100644 --- a/lld/wasm/InputChunks.h +++ b/lld/wasm/InputChunks.h @@ -59,14 +59,14 @@ public: bool Discarded = false; std::vector<OutputRelocation> OutRelocations; - const ObjFile *File; + ObjFile *File; // The garbage collector sets sections' Live bits. // If GC is disabled, all sections are considered live by default. unsigned Live : 1; protected: - InputChunk(const ObjFile *F, Kind K) + InputChunk(ObjFile *F, Kind K) : File(F), Live(!Config->GcSections), SectionKind(K) {} virtual ~InputChunk() = default; void calcRelocations(); @@ -88,7 +88,7 @@ protected: // each global variable. class InputSegment : public InputChunk { public: - InputSegment(const WasmSegment &Seg, const ObjFile *F) + InputSegment(const WasmSegment &Seg, ObjFile *F) : InputChunk(F, InputChunk::DataSegment), Segment(Seg) {} static bool classof(const InputChunk *C) { return C->kind() == DataSegment; } @@ -127,7 +127,7 @@ protected: class InputFunction : public InputChunk { public: InputFunction(const WasmSignature &S, const WasmFunction *Func, - const ObjFile *F) + ObjFile *F) : InputChunk(F, InputChunk::Function), Signature(S), Function(Func) {} static bool classof(const InputChunk *C) { diff --git a/lld/wasm/InputFiles.cpp b/lld/wasm/InputFiles.cpp index bfb4786cad3..fb1b64dc751 100644 --- a/lld/wasm/InputFiles.cpp +++ b/lld/wasm/InputFiles.cpp @@ -63,6 +63,7 @@ uint32_t ObjFile::relocateFunctionIndex(uint32_t Original) const { } uint32_t ObjFile::relocateTypeIndex(uint32_t Original) const { + assert(TypeIsUsed[Original]); return TypeMap[Original]; } @@ -149,6 +150,9 @@ void ObjFile::parse() { DataSection = &Section; } + TypeMap.resize(getWasmObj()->types().size()); + TypeIsUsed.resize(getWasmObj()->types().size(), false); + initializeSymbols(); } diff --git a/lld/wasm/InputFiles.h b/lld/wasm/InputFiles.h index 39472312c47..7435e9a0c77 100644 --- a/lld/wasm/InputFiles.h +++ b/lld/wasm/InputFiles.h @@ -101,6 +101,7 @@ public: const WasmSection *DataSection = nullptr; std::vector<uint32_t> TypeMap; + std::vector<bool> TypeIsUsed; std::vector<InputSegment *> Segments; std::vector<InputFunction *> Functions; diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp index a45b6697379..e0680f6239c 100644 --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -689,15 +689,23 @@ uint32_t Writer::registerType(const WasmSignature &Sig) { } void Writer::calculateTypes() { + // The output type section is the union of the following sets: + // 1. Any signature used in the TYPE relocation + // 2. The signatures of all imported functions + // 3. The signatures of all defined functions + for (ObjFile *File : Symtab->ObjectFiles) { - File->TypeMap.reserve(File->getWasmObj()->types().size()); - for (const WasmSignature &Sig : File->getWasmObj()->types()) - File->TypeMap.push_back(registerType(Sig)); + ArrayRef<WasmSignature> Types = File->getWasmObj()->types(); + for (uint32_t I = 0; I < Types.size(); I++) + if (File->TypeIsUsed[I]) + File->TypeMap[I] = registerType(Types[I]); } - for (Symbol *Sym : Symtab->getSymbols()) - if (Sym->isFunction()) - registerType(Sym->getFunctionType()); + for (const Symbol *Sym : ImportedFunctions) + registerType(Sym->getFunctionType()); + + for (const InputFunction *F : DefinedFunctions) + registerType(F->Signature); } void Writer::assignIndexes() { @@ -746,25 +754,30 @@ void Writer::assignIndexes() { } for (ObjFile *File : Symtab->ObjectFiles) { - DEBUG(dbgs() << "Table Indexes: " << File->getName() << "\n"); - auto HandleTableRelocs = [&](InputChunk *Chunk) { + DEBUG(dbgs() << "Handle relocs: " << File->getName() << "\n"); + auto HandleRelocs = [&](InputChunk *Chunk) { if (Chunk->Discarded) return; + ArrayRef<WasmSignature> Types = File->getWasmObj()->types(); for (const WasmRelocation& Reloc : Chunk->getRelocations()) { - if (Reloc.Type != R_WEBASSEMBLY_TABLE_INDEX_I32 && - Reloc.Type != R_WEBASSEMBLY_TABLE_INDEX_SLEB) - continue; - Symbol *Sym = File->getFunctionSymbol(Reloc.Index); - if (Sym->hasTableIndex() || !Sym->hasOutputIndex()) - continue; - Sym->setTableIndex(TableIndex++); - IndirectFunctions.emplace_back(Sym); + if (Reloc.Type == R_WEBASSEMBLY_TABLE_INDEX_I32 || + Reloc.Type == R_WEBASSEMBLY_TABLE_INDEX_SLEB) { + Symbol *Sym = File->getFunctionSymbol(Reloc.Index); + if (Sym->hasTableIndex() || !Sym->hasOutputIndex()) + continue; + Sym->setTableIndex(TableIndex++); + IndirectFunctions.emplace_back(Sym); + } else if (Reloc.Type == R_WEBASSEMBLY_TYPE_INDEX_LEB) { + Chunk->File->TypeMap[Reloc.Index] = registerType(Types[Reloc.Index]); + Chunk->File->TypeIsUsed[Reloc.Index] = true; + } } }; + for (InputFunction* Function : File->Functions) - HandleTableRelocs(Function); + HandleRelocs(Function); for (InputSegment* Segment : File->Segments) - HandleTableRelocs(Segment); + HandleRelocs(Segment); } } @@ -858,8 +871,6 @@ void Writer::calculateInitFunctions() { } void Writer::run() { - log("-- calculateTypes"); - calculateTypes(); log("-- calculateImports"); calculateImports(); log("-- assignIndexes"); @@ -870,6 +881,8 @@ void Writer::run() { calculateInitFunctions(); if (!Config->Relocatable) createCtorFunction(); + log("-- calculateTypes"); + calculateTypes(); if (errorHandler().Verbose) { log("Defined Functions: " + Twine(DefinedFunctions.size())); |

