summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/test/wasm/call-indirect.ll18
-rw-r--r--lld/test/wasm/gc-sections.ll37
-rw-r--r--lld/test/wasm/relocatable.ll14
-rw-r--r--lld/wasm/InputChunks.h8
-rw-r--r--lld/wasm/InputFiles.cpp4
-rw-r--r--lld/wasm/InputFiles.h1
-rw-r--r--lld/wasm/Writer.cpp53
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()));
OpenPOWER on IntegriCloud