Index: include/llvm/MC/MCObjectStreamer.h =================================================================== --- include/llvm/MC/MCObjectStreamer.h +++ include/llvm/MC/MCObjectStreamer.h @@ -85,8 +85,6 @@ /// will be used as a symbol offset within the fragment. void flushPendingLabels(MCFragment *F, uint64_t FOffset = 0); - void addFragmentAtoms(); - public: void visitUsedSymbol(const MCSymbol &Sym) override; Index: lib/MC/MCMachOStreamer.cpp =================================================================== --- lib/MC/MCMachOStreamer.cpp +++ lib/MC/MCMachOStreamer.cpp @@ -455,7 +455,30 @@ // We have to set the fragment atom associations so we can relax properly for // Mach-O. - addFragmentAtoms(); + + // First, scan the symbol table to build a lookup table from fragments to + // defining symbols. + DenseMap DefiningSymbolMap; + for (const MCSymbol &Symbol : getAssembler().symbols()) { + if (getAssembler().isSymbolLinkerVisible(Symbol) && Symbol.isInSection() && + !Symbol.isVariable()) { + // An atom defining symbol should never be internal to a fragment. + assert(Symbol.getOffset() == 0 && + "Invalid offset in atom defining symbol!"); + DefiningSymbolMap[Symbol.getFragment()] = &Symbol; + } + } + + // Set the fragment atom associations by tracking the last seen atom defining + // symbol. + for (MCSection &Sec : getAssembler()) { + const MCSymbol *CurrentAtom = nullptr; + for (MCFragment &Frag : Sec) { + if (const MCSymbol *Symbol = DefiningSymbolMap.lookup(&Frag)) + CurrentAtom = Symbol; + Frag.setAtom(CurrentAtom); + } + } this->MCObjectStreamer::FinishImpl(); } Index: lib/MC/MCObjectStreamer.cpp =================================================================== --- lib/MC/MCObjectStreamer.cpp +++ lib/MC/MCObjectStreamer.cpp @@ -60,32 +60,6 @@ PendingLabels.clear(); } -void MCObjectStreamer::addFragmentAtoms() { - // First, scan the symbol table to build a lookup table from fragments to - // defining symbols. - DenseMap DefiningSymbolMap; - for (const MCSymbol &Symbol : getAssembler().symbols()) { - if (getAssembler().isSymbolLinkerVisible(Symbol) && Symbol.isInSection() && - !Symbol.isVariable()) { - // An atom defining symbol should never be internal to a fragment. - assert(Symbol.getOffset() == 0 && - "Invalid offset in atom defining symbol!"); - DefiningSymbolMap[Symbol.getFragment()] = &Symbol; - } - } - - // Set the fragment atom associations by tracking the last seen atom defining - // symbol. - for (MCSection &Sec : getAssembler()) { - const MCSymbol *CurrentAtom = nullptr; - for (MCFragment &Frag : Sec) { - if (const MCSymbol *Symbol = DefiningSymbolMap.lookup(&Frag)) - CurrentAtom = Symbol; - Frag.setAtom(CurrentAtom); - } - } -} - // As a compile-time optimization, avoid allocating and evaluating an MCExpr // tree for (Hi - Lo) when Hi and Lo are offsets into the same fragment. static Optional absoluteSymbolDiff(const MCSymbol *Hi, Index: lib/MC/MCWasmStreamer.cpp =================================================================== --- lib/MC/MCWasmStreamer.cpp +++ lib/MC/MCWasmStreamer.cpp @@ -190,9 +190,6 @@ void MCWasmStreamer::FinishImpl() { EmitFrames(nullptr); - // Set fragment atoms so we can map from code fragment to defining symbol - addFragmentAtoms(); - this->MCObjectStreamer::FinishImpl(); } Index: lib/MC/WasmObjectWriter.cpp =================================================================== --- lib/MC/WasmObjectWriter.cpp +++ lib/MC/WasmObjectWriter.cpp @@ -225,6 +225,9 @@ DenseMap> CustomSectionsRelocations; + // Map from section to fintining function. + DenseMap SectionFunctions; + DenseMap FunctionTypeIndices; SmallVector FunctionTypes; @@ -265,6 +268,7 @@ FunctionTypes.clear(); Globals.clear(); DataSegments.clear(); + SectionFunctions.clear(); MCObjectWriter::reset(); NumFunctionImports = 0; NumGlobalImports = 0; @@ -383,6 +387,18 @@ void WasmObjectWriter::executePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) { + // Build a map of sections to the function that defines them, for use + // in recordRelocation. + for (const MCSymbol &S : Asm.symbols()) { + const auto &WS = static_cast(S); + if (WS.isDefined() && WS.isFunction() && !WS.isVariable()) { + const auto &Sec = static_cast(S.getSection()); + auto Pair = SectionFunctions.insert(std::make_pair(&Sec, &S)); + if (!Pair.second) + report_fatal_error("section already has a defining function: " + + Sec.getSectionName()); + } + } } void WasmObjectWriter::recordRelocation(MCAssembler &Asm, @@ -468,14 +484,17 @@ // See: test/MC/WebAssembly/blockaddress.ll if (Type == wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32 || Type == wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32) { + LLVM_DEBUG(dbgs() << "dbgs begin sym: " << *SymA << "\n"); + LLVM_DEBUG(dbgs() << "isSymbolLinkerVisible: " << Asm.isSymbolLinkerVisible(*SymA) << "\n"); if (!FixupSection.getKind().isMetadata()) report_fatal_error("relocations for function or section offsets are " "only supported in metadata sections"); const MCSymbol *SectionSymbol = nullptr; const MCSection &SecA = SymA->getSection(); + LLVM_DEBUG(dbgs() << "isText: " << SecA.getKind().isText() << "\n"); if (SecA.getKind().isText()) - SectionSymbol = SecA.begin()->getAtom(); + SectionSymbol = SectionFunctions.find(&SecA)->second; else SectionSymbol = SecA.getBeginSymbol(); if (!SectionSymbol) Index: test/MC/WebAssembly/debug-info.ll =================================================================== --- test/MC/WebAssembly/debug-info.ll +++ test/MC/WebAssembly/debug-info.ll @@ -204,6 +204,13 @@ ; CHECK-NEXT: } ; CHECK-NEXT:] +; generated from the following C code using: clang --target=wasm32 -g -O0 -S -emit-llvm test.c +; extern int myextern; +; void f2(void) { return; } +; +; int* foo = &myextern; +; void (*ptr2)(void) = f2; + target triple = "wasm32-unknown-unknown" source_filename = "test.c" @@ -226,7 +233,7 @@ !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = distinct !DIGlobalVariable(name: "foo", scope: !2, file: !3, line: 4, type: !11, isLocal: false, isDefinition: true) -!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 6.0.0 (trunk 315924) (llvm/trunk 315960)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 7.0.0 (trunk 332303) (llvm/trunk 332406)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5) !3 = !DIFile(filename: "test.c", directory: "/usr/local/google/home/sbc/dev/wasm/simple") !4 = !{} !5 = !{!0, !6} @@ -240,6 +247,6 @@ !13 = !{i32 2, !"Dwarf Version", i32 4} !14 = !{i32 2, !"Debug Info Version", i32 3} !15 = !{i32 1, !"wchar_size", i32 4} -!16 = !{!"clang version 6.0.0 (trunk 315924) (llvm/trunk 315960)"} +!16 = !{!"clang version 7.0.0 (trunk 332303) (llvm/trunk 332406)"} !17 = distinct !DISubprogram(name: "f2", scope: !3, file: !3, line: 2, type: !9, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !2, retainedNodes: !4) -!18 = !DILocation(line: 2, column: 16, scope: !17) +!18 = !DILocation(line: 2, column: 17, scope: !17)