forked from OSchip/llvm-project
[MC][WebAssembly] Avoid recalculating indexes in -gsplit-dwarf mode
Be consistent about asserting before setting WasmIndices. Adding these assertions revealed that we were duplicating a lot of work and setting these indexed twice when running in DWO mode. Differential Revision: https://reviews.llvm.org/D93650
This commit is contained in:
parent
e130dea92a
commit
30d314aae1
|
@ -1212,6 +1212,7 @@ static bool isInSymtab(const MCSymbolWasm &Sym) {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
void WasmObjectWriter::prepareImports(
|
||||
SmallVectorImpl<wasm::WasmImport> &Imports, MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout) {
|
||||
|
@ -1363,6 +1364,7 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
|
|||
if (Mode != DwoMode::DwoOnly) {
|
||||
prepareImports(Imports, Asm, Layout);
|
||||
}
|
||||
|
||||
// Populate DataSegments and CustomSections, which must be done before
|
||||
// populating DataLocations.
|
||||
for (MCSection &Sec : Asm) {
|
||||
|
@ -1417,6 +1419,7 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
|
|||
|
||||
MCSymbol *Begin = Sec.getBeginSymbol();
|
||||
if (Begin) {
|
||||
assert(WasmIndices.count(cast<MCSymbolWasm>(Begin)) == 0);
|
||||
WasmIndices[cast<MCSymbolWasm>(Begin)] = CustomSections.size();
|
||||
}
|
||||
|
||||
|
@ -1445,214 +1448,218 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
|
|||
}
|
||||
}
|
||||
|
||||
// Populate WasmIndices and DataLocations for defined symbols.
|
||||
for (const MCSymbol &S : Asm.symbols()) {
|
||||
// Ignore unnamed temporary symbols, which aren't ever exported, imported,
|
||||
// or used in relocations.
|
||||
if (S.isTemporary() && S.getName().empty())
|
||||
continue;
|
||||
|
||||
const auto &WS = static_cast<const MCSymbolWasm &>(S);
|
||||
LLVM_DEBUG(
|
||||
dbgs() << "MCSymbol: " << toString(WS.getType()) << " '" << S << "'"
|
||||
<< " isDefined=" << S.isDefined() << " isExternal="
|
||||
<< S.isExternal() << " isTemporary=" << S.isTemporary()
|
||||
<< " isWeak=" << WS.isWeak() << " isHidden=" << WS.isHidden()
|
||||
<< " isVariable=" << WS.isVariable() << "\n");
|
||||
|
||||
if (WS.isVariable())
|
||||
continue;
|
||||
if (WS.isComdat() && !WS.isDefined())
|
||||
continue;
|
||||
|
||||
if (WS.isFunction()) {
|
||||
unsigned Index;
|
||||
if (WS.isDefined()) {
|
||||
if (WS.getOffset() != 0)
|
||||
report_fatal_error(
|
||||
"function sections must contain one function each");
|
||||
|
||||
if (WS.getSize() == nullptr)
|
||||
report_fatal_error(
|
||||
"function symbols must have a size set with .size");
|
||||
|
||||
// A definition. Write out the function body.
|
||||
Index = NumFunctionImports + Functions.size();
|
||||
WasmFunction Func;
|
||||
Func.SigIndex = getFunctionType(WS);
|
||||
Func.Sym = &WS;
|
||||
WasmIndices[&WS] = Index;
|
||||
Functions.push_back(Func);
|
||||
|
||||
auto &Section = static_cast<MCSectionWasm &>(WS.getSection());
|
||||
if (const MCSymbolWasm *C = Section.getGroup()) {
|
||||
Comdats[C->getName()].emplace_back(
|
||||
WasmComdatEntry{wasm::WASM_COMDAT_FUNCTION, Index});
|
||||
}
|
||||
|
||||
if (WS.hasExportName()) {
|
||||
wasm::WasmExport Export;
|
||||
Export.Name = WS.getExportName();
|
||||
Export.Kind = wasm::WASM_EXTERNAL_FUNCTION;
|
||||
Export.Index = Index;
|
||||
Exports.push_back(Export);
|
||||
}
|
||||
} else {
|
||||
// An import; the index was assigned above.
|
||||
Index = WasmIndices.find(&WS)->second;
|
||||
}
|
||||
|
||||
LLVM_DEBUG(dbgs() << " -> function index: " << Index << "\n");
|
||||
|
||||
} else if (WS.isData()) {
|
||||
if (!isInSymtab(WS))
|
||||
if (Mode != DwoMode::DwoOnly) {
|
||||
// Populate WasmIndices and DataLocations for defined symbols.
|
||||
for (const MCSymbol &S : Asm.symbols()) {
|
||||
// Ignore unnamed temporary symbols, which aren't ever exported, imported,
|
||||
// or used in relocations.
|
||||
if (S.isTemporary() && S.getName().empty())
|
||||
continue;
|
||||
|
||||
if (!WS.isDefined()) {
|
||||
LLVM_DEBUG(dbgs() << " -> segment index: -1"
|
||||
<< "\n");
|
||||
const auto &WS = static_cast<const MCSymbolWasm &>(S);
|
||||
LLVM_DEBUG(
|
||||
dbgs() << "MCSymbol: " << toString(WS.getType()) << " '" << S << "'"
|
||||
<< " isDefined=" << S.isDefined() << " isExternal="
|
||||
<< S.isExternal() << " isTemporary=" << S.isTemporary()
|
||||
<< " isWeak=" << WS.isWeak() << " isHidden=" << WS.isHidden()
|
||||
<< " isVariable=" << WS.isVariable() << "\n");
|
||||
|
||||
if (WS.isVariable())
|
||||
continue;
|
||||
if (WS.isComdat() && !WS.isDefined())
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!WS.getSize())
|
||||
report_fatal_error("data symbols must have a size set with .size: " +
|
||||
WS.getName());
|
||||
if (WS.isFunction()) {
|
||||
unsigned Index;
|
||||
if (WS.isDefined()) {
|
||||
if (WS.getOffset() != 0)
|
||||
report_fatal_error(
|
||||
"function sections must contain one function each");
|
||||
|
||||
int64_t Size = 0;
|
||||
if (!WS.getSize()->evaluateAsAbsolute(Size, Layout))
|
||||
report_fatal_error(".size expression must be evaluatable");
|
||||
if (WS.getSize() == nullptr)
|
||||
report_fatal_error(
|
||||
"function symbols must have a size set with .size");
|
||||
|
||||
auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
|
||||
if (!DataSection.isWasmData())
|
||||
report_fatal_error("data symbols must live in a data section: " +
|
||||
WS.getName());
|
||||
// A definition. Write out the function body.
|
||||
Index = NumFunctionImports + Functions.size();
|
||||
WasmFunction Func;
|
||||
Func.SigIndex = getFunctionType(WS);
|
||||
Func.Sym = &WS;
|
||||
assert(WasmIndices.count(&WS) == 0);
|
||||
WasmIndices[&WS] = Index;
|
||||
Functions.push_back(Func);
|
||||
|
||||
// For each data symbol, export it in the symtab as a reference to the
|
||||
// corresponding Wasm data segment.
|
||||
wasm::WasmDataReference Ref = wasm::WasmDataReference{
|
||||
DataSection.getSegmentIndex(), Layout.getSymbolOffset(WS),
|
||||
static_cast<uint64_t>(Size)};
|
||||
DataLocations[&WS] = Ref;
|
||||
LLVM_DEBUG(dbgs() << " -> segment index: " << Ref.Segment << "\n");
|
||||
auto &Section = static_cast<MCSectionWasm &>(WS.getSection());
|
||||
if (const MCSymbolWasm *C = Section.getGroup()) {
|
||||
Comdats[C->getName()].emplace_back(
|
||||
WasmComdatEntry{wasm::WASM_COMDAT_FUNCTION, Index});
|
||||
}
|
||||
|
||||
} else if (WS.isGlobal()) {
|
||||
// A "true" Wasm global (currently just __stack_pointer)
|
||||
if (WS.isDefined()) {
|
||||
assert(WasmIndices.count(&WS) == 0);
|
||||
wasm::WasmGlobal Global;
|
||||
Global.Type = WS.getGlobalType();
|
||||
Global.Index = NumGlobalImports + Globals.size();
|
||||
switch (Global.Type.Type) {
|
||||
case wasm::WASM_TYPE_I32:
|
||||
Global.InitExpr.Opcode = wasm::WASM_OPCODE_I32_CONST;
|
||||
break;
|
||||
case wasm::WASM_TYPE_I64:
|
||||
Global.InitExpr.Opcode = wasm::WASM_OPCODE_I64_CONST;
|
||||
break;
|
||||
case wasm::WASM_TYPE_F32:
|
||||
Global.InitExpr.Opcode = wasm::WASM_OPCODE_F32_CONST;
|
||||
break;
|
||||
case wasm::WASM_TYPE_F64:
|
||||
Global.InitExpr.Opcode = wasm::WASM_OPCODE_F64_CONST;
|
||||
break;
|
||||
case wasm::WASM_TYPE_EXTERNREF:
|
||||
Global.InitExpr.Opcode = wasm::WASM_OPCODE_REF_NULL;
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("unexpected type");
|
||||
if (WS.hasExportName()) {
|
||||
wasm::WasmExport Export;
|
||||
Export.Name = WS.getExportName();
|
||||
Export.Kind = wasm::WASM_EXTERNAL_FUNCTION;
|
||||
Export.Index = Index;
|
||||
Exports.push_back(Export);
|
||||
}
|
||||
} else {
|
||||
// An import; the index was assigned above.
|
||||
Index = WasmIndices.find(&WS)->second;
|
||||
}
|
||||
WasmIndices[&WS] = Global.Index;
|
||||
Globals.push_back(Global);
|
||||
} else {
|
||||
// An import; the index was assigned above
|
||||
LLVM_DEBUG(dbgs() << " -> global index: "
|
||||
|
||||
LLVM_DEBUG(dbgs() << " -> function index: " << Index << "\n");
|
||||
|
||||
} else if (WS.isData()) {
|
||||
if (!isInSymtab(WS))
|
||||
continue;
|
||||
|
||||
if (!WS.isDefined()) {
|
||||
LLVM_DEBUG(dbgs() << " -> segment index: -1"
|
||||
<< "\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!WS.getSize())
|
||||
report_fatal_error("data symbols must have a size set with .size: " +
|
||||
WS.getName());
|
||||
|
||||
int64_t Size = 0;
|
||||
if (!WS.getSize()->evaluateAsAbsolute(Size, Layout))
|
||||
report_fatal_error(".size expression must be evaluatable");
|
||||
|
||||
auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
|
||||
if (!DataSection.isWasmData())
|
||||
report_fatal_error("data symbols must live in a data section: " +
|
||||
WS.getName());
|
||||
|
||||
// For each data symbol, export it in the symtab as a reference to the
|
||||
// corresponding Wasm data segment.
|
||||
wasm::WasmDataReference Ref = wasm::WasmDataReference{
|
||||
DataSection.getSegmentIndex(), Layout.getSymbolOffset(WS),
|
||||
static_cast<uint64_t>(Size)};
|
||||
assert(DataLocations.count(&WS) == 0);
|
||||
DataLocations[&WS] = Ref;
|
||||
LLVM_DEBUG(dbgs() << " -> segment index: " << Ref.Segment << "\n");
|
||||
|
||||
} else if (WS.isGlobal()) {
|
||||
// A "true" Wasm global (currently just __stack_pointer)
|
||||
if (WS.isDefined()) {
|
||||
wasm::WasmGlobal Global;
|
||||
Global.Type = WS.getGlobalType();
|
||||
Global.Index = NumGlobalImports + Globals.size();
|
||||
switch (Global.Type.Type) {
|
||||
case wasm::WASM_TYPE_I32:
|
||||
Global.InitExpr.Opcode = wasm::WASM_OPCODE_I32_CONST;
|
||||
break;
|
||||
case wasm::WASM_TYPE_I64:
|
||||
Global.InitExpr.Opcode = wasm::WASM_OPCODE_I64_CONST;
|
||||
break;
|
||||
case wasm::WASM_TYPE_F32:
|
||||
Global.InitExpr.Opcode = wasm::WASM_OPCODE_F32_CONST;
|
||||
break;
|
||||
case wasm::WASM_TYPE_F64:
|
||||
Global.InitExpr.Opcode = wasm::WASM_OPCODE_F64_CONST;
|
||||
break;
|
||||
case wasm::WASM_TYPE_EXTERNREF:
|
||||
Global.InitExpr.Opcode = wasm::WASM_OPCODE_REF_NULL;
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("unexpected type");
|
||||
}
|
||||
assert(WasmIndices.count(&WS) == 0);
|
||||
WasmIndices[&WS] = Global.Index;
|
||||
Globals.push_back(Global);
|
||||
} else {
|
||||
// An import; the index was assigned above
|
||||
LLVM_DEBUG(dbgs() << " -> global index: "
|
||||
<< WasmIndices.find(&WS)->second << "\n");
|
||||
}
|
||||
} else if (WS.isTable()) {
|
||||
if (WS.isDefined()) {
|
||||
wasm::WasmTable Table;
|
||||
Table.Index = NumTableImports + Tables.size();
|
||||
Table.Type.ElemType = static_cast<uint8_t>(WS.getTableType());
|
||||
// FIXME: Work on custom limits is ongoing
|
||||
Table.Type.Limits = {wasm::WASM_LIMITS_FLAG_NONE, 0, 0};
|
||||
assert(WasmIndices.count(&WS) == 0);
|
||||
WasmIndices[&WS] = Table.Index;
|
||||
Tables.push_back(Table);
|
||||
}
|
||||
LLVM_DEBUG(dbgs() << " -> table index: "
|
||||
<< WasmIndices.find(&WS)->second << "\n");
|
||||
} else if (WS.isEvent()) {
|
||||
// C++ exception symbol (__cpp_exception)
|
||||
unsigned Index;
|
||||
if (WS.isDefined()) {
|
||||
Index = NumEventImports + Events.size();
|
||||
wasm::WasmEventType Event;
|
||||
Event.SigIndex = getEventType(WS);
|
||||
Event.Attribute = wasm::WASM_EVENT_ATTRIBUTE_EXCEPTION;
|
||||
assert(WasmIndices.count(&WS) == 0);
|
||||
WasmIndices[&WS] = Index;
|
||||
Events.push_back(Event);
|
||||
} else {
|
||||
// An import; the index was assigned above.
|
||||
assert(WasmIndices.count(&WS) > 0);
|
||||
}
|
||||
LLVM_DEBUG(dbgs() << " -> event index: "
|
||||
<< WasmIndices.find(&WS)->second << "\n");
|
||||
}
|
||||
} else if (WS.isTable()) {
|
||||
if (WS.isDefined()) {
|
||||
assert(WasmIndices.count(&WS) == 0);
|
||||
wasm::WasmTable Table;
|
||||
Table.Index = NumTableImports + Tables.size();
|
||||
Table.Type.ElemType = static_cast<uint8_t>(WS.getTableType());
|
||||
// FIXME: Work on custom limits is ongoing
|
||||
Table.Type.Limits = {wasm::WASM_LIMITS_FLAG_NONE, 0, 0};
|
||||
|
||||
WasmIndices[&WS] = Table.Index;
|
||||
Tables.push_back(Table);
|
||||
}
|
||||
LLVM_DEBUG(dbgs() << " -> table index: " << WasmIndices.find(&WS)->second
|
||||
<< "\n");
|
||||
} else if (WS.isEvent()) {
|
||||
// C++ exception symbol (__cpp_exception)
|
||||
unsigned Index;
|
||||
if (WS.isDefined()) {
|
||||
assert(WasmIndices.count(&WS) == 0);
|
||||
Index = NumEventImports + Events.size();
|
||||
wasm::WasmEventType Event;
|
||||
Event.SigIndex = getEventType(WS);
|
||||
Event.Attribute = wasm::WASM_EVENT_ATTRIBUTE_EXCEPTION;
|
||||
WasmIndices[&WS] = Index;
|
||||
Events.push_back(Event);
|
||||
} else {
|
||||
// An import; the index was assigned above.
|
||||
assert(WasmIndices.count(&WS) > 0);
|
||||
assert(WS.isSection());
|
||||
}
|
||||
LLVM_DEBUG(dbgs() << " -> event index: " << WasmIndices.find(&WS)->second
|
||||
<< "\n");
|
||||
|
||||
} else {
|
||||
assert(WS.isSection());
|
||||
}
|
||||
}
|
||||
|
||||
// Populate WasmIndices and DataLocations for aliased symbols. We need to
|
||||
// process these in a separate pass because we need to have processed the
|
||||
// target of the alias before the alias itself and the symbols are not
|
||||
// necessarily ordered in this way.
|
||||
for (const MCSymbol &S : Asm.symbols()) {
|
||||
if (!S.isVariable())
|
||||
continue;
|
||||
// Populate WasmIndices and DataLocations for aliased symbols. We need to
|
||||
// process these in a separate pass because we need to have processed the
|
||||
// target of the alias before the alias itself and the symbols are not
|
||||
// necessarily ordered in this way.
|
||||
for (const MCSymbol &S : Asm.symbols()) {
|
||||
if (!S.isVariable())
|
||||
continue;
|
||||
|
||||
assert(S.isDefined());
|
||||
assert(S.isDefined());
|
||||
|
||||
const auto *BS = Layout.getBaseSymbol(S);
|
||||
if (!BS)
|
||||
report_fatal_error(Twine(S.getName()) +
|
||||
": absolute addressing not supported!");
|
||||
const MCSymbolWasm *Base = cast<MCSymbolWasm>(BS);
|
||||
const auto *BS = Layout.getBaseSymbol(S);
|
||||
if (!BS)
|
||||
report_fatal_error(Twine(S.getName()) +
|
||||
": absolute addressing not supported!");
|
||||
const MCSymbolWasm *Base = cast<MCSymbolWasm>(BS);
|
||||
|
||||
// Find the target symbol of this weak alias and export that index
|
||||
const auto &WS = static_cast<const MCSymbolWasm &>(S);
|
||||
LLVM_DEBUG(dbgs() << WS.getName() << ": weak alias of '" << *Base << "'\n");
|
||||
// Find the target symbol of this weak alias and export that index
|
||||
const auto &WS = static_cast<const MCSymbolWasm &>(S);
|
||||
LLVM_DEBUG(dbgs() << WS.getName() << ": weak alias of '" << *Base
|
||||
<< "'\n");
|
||||
|
||||
if (Base->isFunction()) {
|
||||
assert(WasmIndices.count(Base) > 0);
|
||||
uint32_t WasmIndex = WasmIndices.find(Base)->second;
|
||||
assert(WasmIndices.count(&WS) == 0);
|
||||
WasmIndices[&WS] = WasmIndex;
|
||||
LLVM_DEBUG(dbgs() << " -> index:" << WasmIndex << "\n");
|
||||
} else if (Base->isData()) {
|
||||
auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
|
||||
uint64_t Offset = Layout.getSymbolOffset(S);
|
||||
int64_t Size = 0;
|
||||
// For data symbol alias we use the size of the base symbol as the
|
||||
// size of the alias. When an offset from the base is involved this
|
||||
// can result in a offset + size goes past the end of the data section
|
||||
// which out object format doesn't support. So we must clamp it.
|
||||
if (!Base->getSize()->evaluateAsAbsolute(Size, Layout))
|
||||
report_fatal_error(".size expression must be evaluatable");
|
||||
const WasmDataSegment &Segment =
|
||||
DataSegments[DataSection.getSegmentIndex()];
|
||||
Size =
|
||||
std::min(static_cast<uint64_t>(Size), Segment.Data.size() - Offset);
|
||||
wasm::WasmDataReference Ref = wasm::WasmDataReference{
|
||||
DataSection.getSegmentIndex(),
|
||||
static_cast<uint32_t>(Layout.getSymbolOffset(S)),
|
||||
static_cast<uint32_t>(Size)};
|
||||
DataLocations[&WS] = Ref;
|
||||
LLVM_DEBUG(dbgs() << " -> index:" << Ref.Segment << "\n");
|
||||
} else {
|
||||
report_fatal_error("don't yet support global/event aliases");
|
||||
if (Base->isFunction()) {
|
||||
assert(WasmIndices.count(Base) > 0);
|
||||
uint32_t WasmIndex = WasmIndices.find(Base)->second;
|
||||
assert(WasmIndices.count(&WS) == 0);
|
||||
WasmIndices[&WS] = WasmIndex;
|
||||
LLVM_DEBUG(dbgs() << " -> index:" << WasmIndex << "\n");
|
||||
} else if (Base->isData()) {
|
||||
auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
|
||||
uint64_t Offset = Layout.getSymbolOffset(S);
|
||||
int64_t Size = 0;
|
||||
// For data symbol alias we use the size of the base symbol as the
|
||||
// size of the alias. When an offset from the base is involved this
|
||||
// can result in a offset + size goes past the end of the data section
|
||||
// which out object format doesn't support. So we must clamp it.
|
||||
if (!Base->getSize()->evaluateAsAbsolute(Size, Layout))
|
||||
report_fatal_error(".size expression must be evaluatable");
|
||||
const WasmDataSegment &Segment =
|
||||
DataSegments[DataSection.getSegmentIndex()];
|
||||
Size =
|
||||
std::min(static_cast<uint64_t>(Size), Segment.Data.size() - Offset);
|
||||
wasm::WasmDataReference Ref = wasm::WasmDataReference{
|
||||
DataSection.getSegmentIndex(),
|
||||
static_cast<uint32_t>(Layout.getSymbolOffset(S)),
|
||||
static_cast<uint32_t>(Size)};
|
||||
DataLocations[&WS] = Ref;
|
||||
LLVM_DEBUG(dbgs() << " -> index:" << Ref.Segment << "\n");
|
||||
} else {
|
||||
report_fatal_error("don't yet support global/event aliases");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue