Index: llvm/trunk/lib/MC/WasmObjectWriter.cpp =================================================================== --- llvm/trunk/lib/MC/WasmObjectWriter.cpp +++ llvm/trunk/lib/MC/WasmObjectWriter.cpp @@ -510,6 +510,7 @@ DataBytes.resize(alignTo(DataBytes.size(), DataSection.getAlignment())); + size_t LastFragmentSize = 0; for (const MCFragment &Frag : DataSection) { if (Frag.hasInstructions()) report_fatal_error("only data supported in data sections"); @@ -531,9 +532,16 @@ const SmallVectorImpl &Contents = DataFrag.getContents(); DataBytes.insert(DataBytes.end(), Contents.begin(), Contents.end()); + LastFragmentSize = Contents.size(); } } + // Don't allow empty segments, or segments that end with zero-sized + // fragment, otherwise the linker cannot map symbols to a unique + // data segment. This can be triggered by zero-sized structs + // See: test/MC/WebAssembly/bss.ll + if (LastFragmentSize == 0) + DataBytes.resize(DataBytes.size() + 1); DEBUG(dbgs() << "addData -> " << DataBytes.size() << "\n"); } Index: llvm/trunk/test/MC/WebAssembly/bss.ll =================================================================== --- llvm/trunk/test/MC/WebAssembly/bss.ll +++ llvm/trunk/test/MC/WebAssembly/bss.ll @@ -1,8 +1,49 @@ ; RUN: llc -mtriple wasm32-unknown-unknown-wasm -filetype=obj %s -o - | obj2yaml | FileCheck %s @g0 = global i8* null, align 4 +@g1 = global i32 0, align 4 -; CHECK: - Type: DATA +%union.u1 = type {} +@foo = global %union.u1 zeroinitializer, align 1 +@bar = global %union.u1 zeroinitializer, align 1 + +; CHECK: - Type: GLOBAL +; CHECK-NEXT: Globals: +; CHECK-NEXT: - Type: I32 +; CHECK-NEXT: Mutable: false +; CHECK-NEXT: InitExpr: +; CHECK-NEXT: Opcode: I32_CONST +; CHECK-NEXT: Value: 0 +; CHECK-NEXT: - Type: I32 +; CHECK-NEXT: Mutable: false +; CHECK-NEXT: InitExpr: +; CHECK-NEXT: Opcode: I32_CONST +; CHECK-NEXT: Value: 4 +; CHECK-NEXT: - Type: I32 +; CHECK-NEXT: Mutable: false +; CHECK-NEXT: InitExpr: +; CHECK-NEXT: Opcode: I32_CONST +; CHECK-NEXT: Value: 8 +; CHECK-NEXT: - Type: I32 +; CHECK-NEXT: Mutable: false +; CHECK-NEXT: InitExpr: +; CHECK-NEXT: Opcode: I32_CONST +; CHECK-NEXT: Value: 9 +; CHECK-NEXT: - Type: EXPORT +; CHECK-NEXT: Exports: +; CHECK-NEXT: - Name: g0 +; CHECK-NEXT: Kind: GLOBAL +; CHECK-NEXT: Index: 0 +; CHECK-NEXT: - Name: g1 +; CHECK-NEXT: Kind: GLOBAL +; CHECK-NEXT: Index: 1 +; CHECK-NEXT: - Name: foo +; CHECK-NEXT: Kind: GLOBAL +; CHECK-NEXT: Index: 2 +; CHECK-NEXT: - Name: bar +; CHECK-NEXT: Kind: GLOBAL +; CHECK-NEXT: Index: 3 +; CHECK-NEXT: - Type: DATA ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 6 ; CHECK-NEXT: MemoryIndex: 0 @@ -10,12 +51,42 @@ ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 0 ; CHECK-NEXT: Content: '00000000' +; CHECK-NEXT: - SectionOffset: 15 +; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Offset: +; CHECK-NEXT: Opcode: I32_CONST +; CHECK-NEXT: Value: 4 +; CHECK-NEXT: Content: '00000000' +; CHECK-NEXT: - SectionOffset: 24 +; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Offset: +; CHECK-NEXT: Opcode: I32_CONST +; CHECK-NEXT: Value: 8 +; CHECK-NEXT: Content: '00' +; CHECK-NEXT: - SectionOffset: 30 +; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Offset: +; CHECK-NEXT: Opcode: I32_CONST +; CHECK-NEXT: Value: 9 +; CHECK-NEXT: Content: '00' ; CHECK-NEXT: - Type: CUSTOM ; CHECK-NEXT: Name: linking -; CHECK-NEXT: DataSize: 4 +; CHECK-NEXT: DataSize: 10 ; CHECK-NEXT: SegmentInfo: ; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: Name: .bss.g0 ; CHECK-NEXT: Alignment: 4 ; CHECK-NEXT: Flags: 0 +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: Name: .bss.g1 +; CHECK-NEXT: Alignment: 4 +; CHECK-NEXT: Flags: 0 +; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: Name: .bss.foo +; CHECK-NEXT: Alignment: 1 +; CHECK-NEXT: Flags: 0 +; CHECK-NEXT: - Index: 3 +; CHECK-NEXT: Name: .bss.bar +; CHECK-NEXT: Alignment: 1 +; CHECK-NEXT: Flags: 0 ; CHECK-NEXT: ...