Index: lib/MC/MCContext.cpp =================================================================== --- lib/MC/MCContext.cpp +++ lib/MC/MCContext.cpp @@ -516,8 +516,10 @@ StringRef CachedName = Entry.first.SectionName; MCSymbol *Begin = nullptr; - if (BeginSymName) - Begin = createTempSymbol(BeginSymName, false); + if (BeginSymName) { + Begin = createSymbol(BeginSymName, false, false); + cast(Begin)->setType(wasm::WASM_SYMBOL_TYPE_SECTION); + } MCSectionWasm *Result = new (WasmAllocator.Allocate()) MCSectionWasm(CachedName, Kind, GroupSym, UniqueID, Begin); Index: lib/MC/MCObjectFileInfo.cpp =================================================================== --- lib/MC/MCObjectFileInfo.cpp +++ lib/MC/MCObjectFileInfo.cpp @@ -866,19 +866,19 @@ DataSection = Ctx->getWasmSection(".data", SectionKind::getData()); // TODO: Set the section types and flags. - DwarfLineSection = Ctx->getWasmSection(".debug_line", SectionKind::getMetadata()); + DwarfLineSection = Ctx->getWasmSection(".debug_line", SectionKind::getMetadata(), ".debug_line"); DwarfLineStrSection = Ctx->getWasmSection(".debug_line_str", SectionKind::getMetadata()); - DwarfStrSection = Ctx->getWasmSection(".debug_str", SectionKind::getMetadata()); + DwarfStrSection = Ctx->getWasmSection(".debug_str", SectionKind::getMetadata(), ".debug_str"); DwarfLocSection = Ctx->getWasmSection(".debug_loc", SectionKind::getMetadata()); - DwarfAbbrevSection = Ctx->getWasmSection(".debug_abbrev", SectionKind::getMetadata(), "section_abbrev"); + DwarfAbbrevSection = Ctx->getWasmSection(".debug_abbrev", SectionKind::getMetadata(), ".section_abbrev"); DwarfARangesSection = Ctx->getWasmSection(".debug_aranges", SectionKind::getMetadata()); - DwarfRangesSection = Ctx->getWasmSection(".debug_ranges", SectionKind::getMetadata(), "debug_range"); - DwarfMacinfoSection = Ctx->getWasmSection(".debug_macinfo", SectionKind::getMetadata(), "debug_macinfo"); + DwarfRangesSection = Ctx->getWasmSection(".debug_ranges", SectionKind::getMetadata(), ".debug_range"); + DwarfMacinfoSection = Ctx->getWasmSection(".debug_macinfo", SectionKind::getMetadata(), ".debug_macinfo"); DwarfAddrSection = Ctx->getWasmSection(".debug_addr", SectionKind::getMetadata()); DwarfCUIndexSection = Ctx->getWasmSection(".debug_cu_index", SectionKind::getMetadata()); DwarfTUIndexSection = Ctx->getWasmSection(".debug_tu_index", SectionKind::getMetadata()); - DwarfInfoSection = Ctx->getWasmSection(".debug_info", SectionKind::getMetadata(), "section_info"); + DwarfInfoSection = Ctx->getWasmSection(".debug_info", SectionKind::getMetadata(), ".section_info"); DwarfFrameSection = Ctx->getWasmSection(".debug_frame", SectionKind::getMetadata()); DwarfPubNamesSection = Ctx->getWasmSection(".debug_pubnames", SectionKind::getMetadata()); DwarfPubTypesSection = Ctx->getWasmSection(".debug_pubtypes", SectionKind::getMetadata()); Index: lib/MC/MCWasmStreamer.cpp =================================================================== --- lib/MC/MCWasmStreamer.cpp +++ lib/MC/MCWasmStreamer.cpp @@ -156,17 +156,8 @@ } void MCWasmStreamer::EmitIdent(StringRef IdentString) { - MCSection *Comment = getAssembler().getContext().getWasmSection( - ".comment", SectionKind::getMetadata()); - PushSection(); - SwitchSection(Comment); - if (!SeenIdent) { - EmitIntValue(0, 1); - SeenIdent = true; - } - EmitBytes(IdentString); - EmitIntValue(0, 1); - PopSection(); + // TODO(sbc): Add the ident section once we support mergable strings + // sections in the object format } void MCWasmStreamer::EmitInstToFragment(const MCInst &Inst, Index: lib/MC/WasmObjectWriter.cpp =================================================================== --- lib/MC/WasmObjectWriter.cpp +++ lib/MC/WasmObjectWriter.cpp @@ -244,8 +244,6 @@ DenseMap WasmIndices; // Maps data symbols to the Wasm segment and offset/size with the segment. DenseMap DataLocations; - // Maps section symbols to the section. - DenseMap CustomSectionSymbols; // Stores output data (index, relocations, content offset) for custom // section. @@ -295,7 +293,6 @@ FunctionTypes.clear(); Globals.clear(); DataSegments.clear(); - CustomSectionSymbols.clear(); MCObjectWriter::reset(); NumFunctionImports = 0; NumGlobalImports = 0; @@ -433,11 +430,6 @@ if (FixupSection.getSectionName().startswith(".init_array")) return; - // TODO: Add support for non-debug metadata sections? - if (FixupSection.getKind().isMetadata() && - !FixupSection.getSectionName().startswith(".debug_")) - return; - if (const MCSymbolRefExpr *RefB = Target.getSymB()) { assert(RefB->getKind() == MCSymbolRefExpr::VK_None && "Should not have constructed this"); @@ -495,36 +487,55 @@ // be negative and don't wrap. FixedValue = 0; - if (SymA) - SymA->setUsedInReloc(); - + unsigned Type = getRelocType(Target, Fixup); assert(!IsPCRel); assert(SymA); - unsigned Type = getRelocType(Target, Fixup); + // Absolute offset within a section or a function. + // Currently only supported for for metadata sections. + // See: test/MC/WebAssembly/blockaddress.ll + if (Type == wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32 || + Type == wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32) { + if (!FixupSection.getKind().isMetadata()) + report_fatal_error("relocations for function or section offsets are " + "only supported for metadata sections"); + + const MCSymbolWasm *SectionSymbol = nullptr; + const MCSection &SecA = SymA->getSection(); + if (SecA.getKind().isText()) { + const MCFragment &Frag = *SecA.begin(); + SectionSymbol = cast(Frag.getAtom()); + } else { + SectionSymbol = cast_or_null(SecA.getBeginSymbol()); + } + + SectionSymbol->setUsedInReloc(); + C += Layout.getSymbolOffset(*SymA); + WasmRelocationEntry Rec(FixupOffset, SectionSymbol, C, Type, &FixupSection); + DEBUG(dbgs() << "WasmRelocX: " << Rec << "\n"); + assert(FixupSection.getKind().isMetadata()); + CustomSectionsRelocations[&FixupSection].push_back(Rec); + return; + } + + // Relocation other than R_WEBASSEMBLY_TYPE_INDEX_LEB are required to be + // against a named symbol. + if (Type != wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB) { + if (SymA->getName().empty()) + report_fatal_error("relocations against un-named temporaries are not yet " + "supported by wasm"); + + SymA->setUsedInReloc(); + } WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection); DEBUG(dbgs() << "WasmReloc: " << Rec << "\n"); - // Relocation other than R_WEBASSEMBLY_TYPE_INDEX_LEB, - // R_WEBASSEMBLY_SECTION_OFFSET_I32 or R_WEBASSEMBLY_FUNCTION_OFFSET_I32 - // are currently required to be against a named symbol. - // TODO(sbc): Add support for relocations against unnamed temporaries such - // as those generated by llvm's `blockaddress`. - // See: test/MC/WebAssembly/blockaddress.ll - if (SymA->getName().empty() && - !(Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB || - Type == wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32 || - Type == wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32)) - report_fatal_error("relocations against un-named temporaries are not yet " - "supported by wasm"); - if (FixupSection.isWasmData()) { DataRelocations.push_back(Rec); } else if (FixupSection.getKind().isText()) { CodeRelocations.push_back(Rec); } else if (FixupSection.getKind().isMetadata()) { - assert(FixupSection.getSectionName().startswith(".debug_")); CustomSectionsRelocations[&FixupSection].push_back(Rec); } else { llvm_unreachable("unexpected section type"); @@ -591,15 +602,12 @@ report_fatal_error("symbol not found in wasm index space: " + RelEntry.Symbol->getName()); return WasmIndices[RelEntry.Symbol]; - case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32: { + case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32: + case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32: { const auto &Section = static_cast(RelEntry.Symbol->getSection()); return Section.getSectionOffset() + RelEntry.Addend; } - case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32: { - const auto &Section = *CustomSectionSymbols.find(RelEntry.Symbol)->second; - return Section.getSectionOffset() + RelEntry.Addend; - } case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB: case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32: case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: { @@ -1033,49 +1041,10 @@ CustomSection.OutputIndex = Section.Index; endSection(Section); - } -} - -void WasmObjectWriter::updateCustomSectionRelocations( - const SmallVector &Functions, const MCAsmLayout &Layout) { - std::map SectionSymbols; - for (const auto &P : CustomSectionSymbols) - SectionSymbols[P.second] = P.first; - std::map FuncSymbols; - for (const auto &FuncInfo : Functions) - FuncSymbols[&FuncInfo.Sym->getSection()] = FuncInfo.Sym; - - // Patch relocation records for R_WEBASSEMBLY_FUNCTION_OFFSET_I32 and - // R_WEBASSEMBLY_SECTION_OFFSET_I32. The Addend is stuffed the offset from - // the beginning of the function or custom section -- all such relocations - // target the function or custom section starts. - for (auto &Section : CustomSections) { - auto &Relocations = CustomSectionsRelocations[Section.Section]; - for (WasmRelocationEntry &RelEntry : Relocations) { - switch (RelEntry.Type) { - case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32: { - assert(RelEntry.hasAddend()); - auto &Section = - static_cast(RelEntry.Symbol->getSection()); - RelEntry.Addend += Layout.getSymbolOffset(*RelEntry.Symbol); - RelEntry.Symbol = FuncSymbols[&Section]; - break; - } - case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32: { - assert(RelEntry.hasAddend()); - auto &Section = - static_cast(RelEntry.Symbol->getSection()); - RelEntry.Addend += Layout.getSymbolOffset(*RelEntry.Symbol); - RelEntry.Symbol = SectionSymbols[&Section]; - break; - } - default: - break; - } - } // Apply fixups. - applyRelocations(Relocations, Section.OutputContentsOffset); + auto &Relocations = CustomSectionsRelocations[CustomSection.Section]; + applyRelocations(Relocations, CustomSection.OutputContentsOffset); } } @@ -1104,6 +1073,25 @@ return Pair.first->second; } +static bool isInSymtab(const MCSymbolWasm &Sym) { + if (Sym.isUsedInReloc()) + return true; + + if (Sym.isComdat() && !Sym.isDefined()) + return false; + + if (Sym.isTemporary() && Sym.getName().empty()) + return false; + + if (Sym.isTemporary() && Sym.isData() && !Sym.getSize()) + return false; + + if (Sym.isSection()) + return false; + + return true; +} + void WasmObjectWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) { DEBUG(dbgs() << "WasmObjectWriter::writeObject\n"); @@ -1181,76 +1169,53 @@ } } - // Populate DataSegments, which must be done before populating DataLocations. + // Populate DataSegments and CustomSections, which must be done before + // populating DataLocations. for (MCSection &Sec : Asm) { auto &Section = static_cast(Sec); - - if (Section.getSectionName().startswith(".custom_section.")) { - if (Section.getFragmentList().empty()) - continue; - if (Section.getFragmentList().size() != 1) - report_fatal_error( - "only one .custom_section section fragment supported"); - const MCFragment &Frag = *Section.begin(); - if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data) - report_fatal_error("only data supported in .custom_section section"); - const auto &DataFrag = cast(Frag); - if (!DataFrag.getFixups().empty()) - report_fatal_error("fixups not supported in .custom_section section"); - StringRef UserName = Section.getSectionName().substr(16); - CustomSections.emplace_back(UserName, &Section); - continue; - } - - if (!Section.isWasmData()) - continue; + StringRef SectionName = Section.getSectionName(); // .init_array sections are handled specially elsewhere. - if (cast(Sec).getSectionName().startswith(".init_array")) + if (SectionName.startswith(".init_array")) continue; - uint32_t SegmentIndex = DataSegments.size(); - DataSize = alignTo(DataSize, Section.getAlignment()); - DataSegments.emplace_back(); - WasmDataSegment &Segment = DataSegments.back(); - Segment.Name = Section.getSectionName(); - Segment.Offset = DataSize; - Segment.Section = &Section; - addData(Segment.Data, Section); - Segment.Alignment = Section.getAlignment(); - Segment.Flags = 0; - DataSize += Segment.Data.size(); - Section.setSegmentIndex(SegmentIndex); - - if (const MCSymbolWasm *C = Section.getGroup()) { - Comdats[C->getName()].emplace_back( - WasmComdatEntry{wasm::WASM_COMDAT_DATA, SegmentIndex}); - } - } - - // Create symbols for debug/custom sections. - for (MCSection &Sec : Asm) { - auto &DebugSection = static_cast(Sec); - StringRef SectionName = DebugSection.getSectionName(); - - // TODO: Add support for non-debug metadata sections? - if (!Sec.getKind().isMetadata() || !SectionName.startswith(".debug_")) + // Code is handled separately + if (Section.getKind().isText()) continue; - uint32_t ElementIndex = CustomSections.size(); - CustomSections.emplace_back(SectionName, &DebugSection); + if (Section.isWasmData()) { + uint32_t SegmentIndex = DataSegments.size(); + DataSize = alignTo(DataSize, Section.getAlignment()); + DataSegments.emplace_back(); + WasmDataSegment &Segment = DataSegments.back(); + Segment.Name = SectionName; + Segment.Offset = DataSize; + Segment.Section = &Section; + addData(Segment.Data, Section); + Segment.Alignment = Section.getAlignment(); + Segment.Flags = 0; + DataSize += Segment.Data.size(); + Section.setSegmentIndex(SegmentIndex); + + if (const MCSymbolWasm *C = Section.getGroup()) { + Comdats[C->getName()].emplace_back( + WasmComdatEntry{wasm::WASM_COMDAT_DATA, SegmentIndex}); + } + } else { + // Create custom sections + assert(Sec.getKind().isMetadata()); - MCSymbolWasm *SectionSym = - cast(Ctx.getOrCreateSymbol(SectionName)); - CustomSectionSymbols[SectionSym] = &DebugSection; + StringRef Name = SectionName; - wasm::WasmSymbolInfo Info; - Info.Name = SectionSym->getName(); - Info.Kind = wasm::WASM_SYMBOL_TYPE_SECTION; - Info.Flags = wasm::WASM_SYMBOL_BINDING_LOCAL; - Info.ElementIndex = ElementIndex; - SymbolIndices[SectionSym] = SymbolInfos.size(); - SymbolInfos.emplace_back(Info); + // For user-defined custom sections, strip the prefix + if (Name.startswith(".custom_section.")) + Name = Name.substr(strlen(".custom_section.")); + + MCSymbol* Begin = Sec.getBeginSymbol(); + if (Begin) + WasmIndices[cast(Begin)] = CustomSections.size(); + CustomSections.emplace_back(Name, &Section); + } } // Populate WasmIndices and DataLocations for defined symbols. @@ -1380,12 +1345,9 @@ // Finally, populate the symbol table itself, in its "natural" order. for (const MCSymbol &S : Asm.symbols()) { const auto &WS = static_cast(S); - if (WS.isTemporary() && WS.getName().empty()) - continue; - if (WS.isComdat() && !WS.isDefined()) - continue; - if (WS.isTemporary() && WS.isData() && !WS.getSize()) + if (!isInSymtab(WS)) continue; + DEBUG(dbgs() << "adding to symtab: " << WS << "\n"); uint32_t Flags = 0; if (WS.isWeak()) @@ -1401,10 +1363,13 @@ Info.Name = WS.getName(); Info.Kind = WS.getType(); Info.Flags = Flags; - if (!WS.isData()) + if (!WS.isData()) { + assert(WasmIndices.count(&WS) > 0); Info.ElementIndex = WasmIndices.find(&WS)->second; - else if (WS.isDefined()) + } else if (WS.isDefined()) { + assert(DataLocations.count(&WS) > 0); Info.DataRef = DataLocations.find(&WS)->second; + } SymbolIndices[&WS] = SymbolInfos.size(); SymbolInfos.emplace_back(Info); } @@ -1455,10 +1420,13 @@ if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data) report_fatal_error("only data supported in .init_array section"); uint16_t Priority = UINT16_MAX; - if (WS.getSectionName().size() != 11) { - if (WS.getSectionName()[11] != '.') + unsigned PrefixLength = strlen(".init_array"); + if (WS.getSectionName().size() > PrefixLength) { + if (WS.getSectionName()[PrefixLength] != '.') report_fatal_error(".init_array section priority should start with '.'"); - if (WS.getSectionName().substr(12).getAsInteger(10, Priority)) + if (WS.getSectionName() + .substr(PrefixLength + 1) + .getAsInteger(10, Priority)) report_fatal_error("invalid .init_array section priority"); } const auto &DataFrag = cast(Frag); @@ -1499,7 +1467,6 @@ writeCodeSection(Asm, Layout, Functions); writeDataSection(); writeCustomSections(Asm, Layout); - updateCustomSectionRelocations(Functions, Layout); writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats); writeRelocSection(CodeSectionIndex, "CODE", CodeRelocations); writeRelocSection(DataSectionIndex, "DATA", DataRelocations); Index: test/MC/WebAssembly/blockaddress.ll =================================================================== --- test/MC/WebAssembly/blockaddress.ll +++ test/MC/WebAssembly/blockaddress.ll @@ -1,6 +1,6 @@ ; TODO(sbc): Make this test pass by adding support for unnamed tempoaries ; in wasm relocations. -; RUN: not llc -filetype=obj %s +; RUN: not llc -filetype=obj %s 2>&1 | FileCheck %s target triple = "wasm32-unknown-unknown-wasm" @@ -13,3 +13,6 @@ addr: ret i32 0 } + +; CHECK: LLVM ERROR: relocations for function or section offsets are only supported for metadata sections + Index: test/MC/WebAssembly/debug-info.ll =================================================================== --- test/MC/WebAssembly/debug-info.ll +++ test/MC/WebAssembly/debug-info.ll @@ -96,38 +96,38 @@ ; CHECK-NEXT: } ; CHECK-NEXT: Section { ; CHECK-NEXT: Type: CUSTOM (0x0) -; CHECK-NEXT: Size: 100 +; CHECK-NEXT: Size: 88 ; CHECK-NEXT: Offset: 733 ; CHECK-NEXT: Name: linking ; CHECK-NEXT: } ; CHECK-NEXT: Section { ; CHECK-NEXT: Type: CUSTOM (0x0) ; CHECK-NEXT: Size: 9 -; CHECK-NEXT: Offset: 847 +; CHECK-NEXT: Offset: 835 ; CHECK-NEXT: Name: reloc.DATA ; CHECK-NEXT: } ; CHECK-NEXT: Section { ; CHECK-NEXT: Type: CUSTOM (0x0) ; CHECK-NEXT: Size: 58 -; CHECK-NEXT: Offset: 873 +; CHECK-NEXT: Offset: 861 ; CHECK-NEXT: Name: reloc..debug_info ; CHECK-NEXT: } ; CHECK-NEXT: Section { ; CHECK-NEXT: Type: CUSTOM (0x0) ; CHECK-NEXT: Size: 6 -; CHECK-NEXT: Offset: 955 +; CHECK-NEXT: Offset: 943 ; CHECK-NEXT: Name: reloc..debug_pubnames ; CHECK-NEXT: } ; CHECK-NEXT: Section { ; CHECK-NEXT: Type: CUSTOM (0x0) ; CHECK-NEXT: Size: 6 -; CHECK-NEXT: Offset: 989 +; CHECK-NEXT: Offset: 977 ; CHECK-NEXT: Name: reloc..debug_pubtypes ; CHECK-NEXT: } ; CHECK-NEXT: Section { ; CHECK-NEXT: Type: CUSTOM (0x0) ; CHECK-NEXT: Size: 6 -; CHECK-NEXT: Offset: 1023 +; CHECK-NEXT: Offset: 1011 ; CHECK-NEXT: Name: reloc..debug_line ; CHECK-NEXT: } ; CHECK-NEXT:] @@ -163,37 +163,37 @@ ; CHECK-NEXT:] ; CHECK-NEXT:Symbols [ ; CHECK-NEXT: Symbol { -; CHECK-NEXT: Name: .debug_str -; CHECK-NEXT: Type: SECTION (0x3) -; CHECK-NEXT: Flags: 0x2 +; CHECK-NEXT: Name: f2 +; CHECK-NEXT: Type: FUNCTION (0x0) +; CHECK-NEXT: Flags: 0x4 ; CHECK-NEXT: } ; CHECK-NEXT: Symbol { -; CHECK-NEXT: Name: .debug_abbrev -; CHECK-NEXT: Type: SECTION (0x3) -; CHECK-NEXT: Flags: 0x2 +; CHECK-NEXT: Name: foo +; CHECK-NEXT: Type: DATA (0x1) +; CHECK-NEXT: Flags: 0x4 ; CHECK-NEXT: } ; CHECK-NEXT: Symbol { -; CHECK-NEXT: Name: .debug_info -; CHECK-NEXT: Type: SECTION (0x3) -; CHECK-NEXT: Flags: 0x2 +; CHECK-NEXT: Name: myextern +; CHECK-NEXT: Type: DATA (0x1) +; CHECK-NEXT: Flags: 0x10 ; CHECK-NEXT: } ; CHECK-NEXT: Symbol { -; CHECK-NEXT: Name: .debug_ranges -; CHECK-NEXT: Type: SECTION (0x3) -; CHECK-NEXT: Flags: 0x2 +; CHECK-NEXT: Name: ptr2 +; CHECK-NEXT: Type: DATA (0x1) +; CHECK-NEXT: Flags: 0x4 ; CHECK-NEXT: } ; CHECK-NEXT: Symbol { -; CHECK-NEXT: Name: .debug_macinfo +; CHECK-NEXT: Name: .debug_str ; CHECK-NEXT: Type: SECTION (0x3) ; CHECK-NEXT: Flags: 0x2 ; CHECK-NEXT: } ; CHECK-NEXT: Symbol { -; CHECK-NEXT: Name: .debug_pubnames +; CHECK-NEXT: Name: .debug_abbrev ; CHECK-NEXT: Type: SECTION (0x3) ; CHECK-NEXT: Flags: 0x2 ; CHECK-NEXT: } ; CHECK-NEXT: Symbol { -; CHECK-NEXT: Name: .debug_pubtypes +; CHECK-NEXT: Name: .debug_info ; CHECK-NEXT: Type: SECTION (0x3) ; CHECK-NEXT: Flags: 0x2 ; CHECK-NEXT: } @@ -202,26 +202,6 @@ ; CHECK-NEXT: Type: SECTION (0x3) ; CHECK-NEXT: Flags: 0x2 ; CHECK-NEXT: } -; CHECK-NEXT: Symbol { -; CHECK-NEXT: Name: f2 -; CHECK-NEXT: Type: FUNCTION (0x0) -; CHECK-NEXT: Flags: 0x4 -; CHECK-NEXT: } -; CHECK-NEXT: Symbol { -; CHECK-NEXT: Name: foo -; CHECK-NEXT: Type: DATA (0x1) -; CHECK-NEXT: Flags: 0x4 -; CHECK-NEXT: } -; CHECK-NEXT: Symbol { -; CHECK-NEXT: Name: myextern -; CHECK-NEXT: Type: DATA (0x1) -; CHECK-NEXT: Flags: 0x10 -; CHECK-NEXT: } -; CHECK-NEXT: Symbol { -; CHECK-NEXT: Name: ptr2 -; CHECK-NEXT: Type: DATA (0x1) -; CHECK-NEXT: Flags: 0x4 -; CHECK-NEXT: } ; CHECK-NEXT:] target triple = "wasm32-unknown-unknown-wasm"