mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-11 21:45:16 +00:00
[WebAssembly] MC: Create wasm data segments based on MCSections
This means that we can honor -fdata-sections rather than always creating a segment for each symbol. It also allows for a followup change to add .init_array and friends. Differential Revision: https://reviews.llvm.org/D37876 llvm-svn: 313395
This commit is contained in:
parent
d75c714e9b
commit
91f177ea59
@ -43,11 +43,17 @@ private:
|
||||
// itself and does not include the size of the section header.
|
||||
uint64_t SectionOffset;
|
||||
|
||||
// For data sections, this is the offset of the corresponding wasm data
|
||||
// segment
|
||||
uint64_t MemoryOffset;
|
||||
|
||||
friend class MCContext;
|
||||
MCSectionWasm(StringRef Section, unsigned type, SectionKind K,
|
||||
const MCSymbolWasm *group, unsigned UniqueID, MCSymbol *Begin)
|
||||
: MCSection(SV_Wasm, K, Begin), SectionName(Section), Type(type),
|
||||
UniqueID(UniqueID), Group(group), SectionOffset(0) {}
|
||||
UniqueID(UniqueID), Group(group), SectionOffset(0) {
|
||||
assert(type == wasm::WASM_SEC_CODE || type == wasm::WASM_SEC_DATA);
|
||||
}
|
||||
|
||||
void setSectionName(StringRef Name) { SectionName = Name; }
|
||||
|
||||
@ -74,6 +80,9 @@ public:
|
||||
uint64_t getSectionOffset() const { return SectionOffset; }
|
||||
void setSectionOffset(uint64_t Offset) { SectionOffset = Offset; }
|
||||
|
||||
uint32_t getMemoryOffset() const { return MemoryOffset; }
|
||||
void setMemoryOffset(uint32_t Offset) { MemoryOffset = Offset; }
|
||||
|
||||
static bool classof(const MCSection *S) { return S->getVariant() == SV_Wasm; }
|
||||
};
|
||||
|
||||
|
@ -1248,8 +1248,8 @@ static const Comdat *getWasmComdat(const GlobalValue *GV) {
|
||||
|
||||
MCSection *TargetLoweringObjectFileWasm::getExplicitSectionGlobal(
|
||||
const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
|
||||
llvm_unreachable("getExplicitSectionGlobal not yet implemented");
|
||||
return nullptr;
|
||||
StringRef Name = GO->getSection();
|
||||
return getContext().getWasmSection(Name, wasm::WASM_SEC_DATA);
|
||||
}
|
||||
|
||||
static MCSectionWasm *selectWasmSectionForGlobal(
|
||||
@ -1262,10 +1262,12 @@ static MCSectionWasm *selectWasmSectionForGlobal(
|
||||
bool UniqueSectionNames = TM.getUniqueSectionNames();
|
||||
SmallString<128> Name = getSectionPrefixForGlobal(Kind);
|
||||
|
||||
uint32_t Type = wasm::WASM_SEC_DATA;
|
||||
if (const auto *F = dyn_cast<Function>(GO)) {
|
||||
const auto &OptionalPrefix = F->getSectionPrefix();
|
||||
if (OptionalPrefix)
|
||||
Name += *OptionalPrefix;
|
||||
Type = wasm::WASM_SEC_CODE;
|
||||
}
|
||||
|
||||
if (EmitUniqueSection && UniqueSectionNames) {
|
||||
@ -1277,7 +1279,7 @@ static MCSectionWasm *selectWasmSectionForGlobal(
|
||||
UniqueID = *NextUniqueID;
|
||||
(*NextUniqueID)++;
|
||||
}
|
||||
return Ctx.getWasmSection(Name, /*Type=*/0, Group, UniqueID);
|
||||
return Ctx.getWasmSection(Name, Type, Group, UniqueID);
|
||||
}
|
||||
|
||||
MCSection *TargetLoweringObjectFileWasm::SelectSectionForGlobal(
|
||||
|
@ -820,24 +820,24 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
|
||||
|
||||
void MCObjectFileInfo::initWasmMCObjectFileInfo(const Triple &T) {
|
||||
// TODO: Set the section types and flags.
|
||||
TextSection = Ctx->getWasmSection(".text", 0);
|
||||
DataSection = Ctx->getWasmSection(".data", 0);
|
||||
TextSection = Ctx->getWasmSection(".text", wasm::WASM_SEC_CODE);
|
||||
DataSection = Ctx->getWasmSection(".data", wasm::WASM_SEC_DATA);
|
||||
|
||||
// TODO: Set the section types and flags.
|
||||
DwarfLineSection = Ctx->getWasmSection(".debug_line", 0);
|
||||
DwarfStrSection = Ctx->getWasmSection(".debug_str", 0);
|
||||
DwarfLocSection = Ctx->getWasmSection(".debug_loc", 0);
|
||||
DwarfAbbrevSection = Ctx->getWasmSection(".debug_abbrev", 0, "section_abbrev");
|
||||
DwarfARangesSection = Ctx->getWasmSection(".debug_aranges", 0);
|
||||
DwarfRangesSection = Ctx->getWasmSection(".debug_ranges", 0, "debug_range");
|
||||
DwarfMacinfoSection = Ctx->getWasmSection(".debug_macinfo", 0, "debug_macinfo");
|
||||
DwarfAddrSection = Ctx->getWasmSection(".debug_addr", 0);
|
||||
DwarfCUIndexSection = Ctx->getWasmSection(".debug_cu_index", 0);
|
||||
DwarfTUIndexSection = Ctx->getWasmSection(".debug_tu_index", 0);
|
||||
DwarfInfoSection = Ctx->getWasmSection(".debug_info", 0, "section_info");
|
||||
DwarfFrameSection = Ctx->getWasmSection(".debug_frame", 0);
|
||||
DwarfPubNamesSection = Ctx->getWasmSection(".debug_pubnames", 0);
|
||||
DwarfPubTypesSection = Ctx->getWasmSection(".debug_pubtypes", 0);
|
||||
DwarfLineSection = Ctx->getWasmSection(".debug_line", wasm::WASM_SEC_DATA);
|
||||
DwarfStrSection = Ctx->getWasmSection(".debug_str", wasm::WASM_SEC_DATA);
|
||||
DwarfLocSection = Ctx->getWasmSection(".debug_loc", wasm::WASM_SEC_DATA);
|
||||
DwarfAbbrevSection = Ctx->getWasmSection(".debug_abbrev", wasm::WASM_SEC_DATA, "section_abbrev");
|
||||
DwarfARangesSection = Ctx->getWasmSection(".debug_aranges", wasm::WASM_SEC_DATA);
|
||||
DwarfRangesSection = Ctx->getWasmSection(".debug_ranges", wasm::WASM_SEC_DATA, "debug_range");
|
||||
DwarfMacinfoSection = Ctx->getWasmSection(".debug_macinfo", wasm::WASM_SEC_DATA, "debug_macinfo");
|
||||
DwarfAddrSection = Ctx->getWasmSection(".debug_addr", wasm::WASM_SEC_DATA);
|
||||
DwarfCUIndexSection = Ctx->getWasmSection(".debug_cu_index", wasm::WASM_SEC_DATA);
|
||||
DwarfTUIndexSection = Ctx->getWasmSection(".debug_tu_index", wasm::WASM_SEC_DATA);
|
||||
DwarfInfoSection = Ctx->getWasmSection(".debug_info", wasm::WASM_SEC_DATA, "section_info");
|
||||
DwarfFrameSection = Ctx->getWasmSection(".debug_frame", wasm::WASM_SEC_DATA);
|
||||
DwarfPubNamesSection = Ctx->getWasmSection(".debug_pubnames", wasm::WASM_SEC_DATA);
|
||||
DwarfPubTypesSection = Ctx->getWasmSection(".debug_pubtypes", wasm::WASM_SEC_DATA);
|
||||
|
||||
// TODO: Define more sections.
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ void MCWasmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
|
||||
|
||||
void MCWasmStreamer::EmitIdent(StringRef IdentString) {
|
||||
MCSection *Comment = getAssembler().getContext().getWasmSection(
|
||||
".comment", 0, 0);
|
||||
".comment", wasm::WASM_SEC_DATA);
|
||||
PushSection();
|
||||
SwitchSection(Comment);
|
||||
if (!SeenIdent) {
|
||||
|
@ -163,7 +163,8 @@ struct WasmRelocationEntry {
|
||||
|
||||
void print(raw_ostream &Out) const {
|
||||
Out << "Off=" << Offset << ", Sym=" << *Symbol << ", Addend=" << Addend
|
||||
<< ", Type=" << Type << ", FixupSection=" << FixupSection;
|
||||
<< ", Type=" << Type
|
||||
<< ", FixupSection=" << FixupSection->getSectionName();
|
||||
}
|
||||
|
||||
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
||||
@ -495,6 +496,39 @@ WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry) {
|
||||
return Value;
|
||||
}
|
||||
|
||||
static void addData(SmallVectorImpl<char> &DataBytes,
|
||||
MCSectionWasm &DataSection, uint32_t &DataAlignment) {
|
||||
DataBytes.resize(alignTo(DataBytes.size(), DataSection.getAlignment()));
|
||||
DataAlignment = std::max(DataAlignment, DataSection.getAlignment());
|
||||
DEBUG(errs() << "addData: " << DataSection.getSectionName() << "\n");
|
||||
|
||||
for (const MCFragment &Frag : DataSection) {
|
||||
if (Frag.hasInstructions())
|
||||
report_fatal_error("only data supported in data sections");
|
||||
|
||||
if (auto *Align = dyn_cast<MCAlignFragment>(&Frag)) {
|
||||
if (Align->getValueSize() != 1)
|
||||
report_fatal_error("only byte values supported for alignment");
|
||||
// If nops are requested, use zeros, as this is the data section.
|
||||
uint8_t Value = Align->hasEmitNops() ? 0 : Align->getValue();
|
||||
uint64_t Size = std::min<uint64_t>(alignTo(DataBytes.size(),
|
||||
Align->getAlignment()),
|
||||
DataBytes.size() +
|
||||
Align->getMaxBytesToEmit());
|
||||
DataBytes.resize(Size, Value);
|
||||
} else if (auto *Fill = dyn_cast<MCFillFragment>(&Frag)) {
|
||||
DataBytes.insert(DataBytes.end(), Fill->getSize(), Fill->getValue());
|
||||
} else {
|
||||
const auto &DataFrag = cast<MCDataFragment>(Frag);
|
||||
const SmallVectorImpl<char> &Contents = DataFrag.getContents();
|
||||
|
||||
DataBytes.insert(DataBytes.end(), Contents.begin(), Contents.end());
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG(dbgs() << "addData -> " << DataBytes.size() << "\n");
|
||||
}
|
||||
|
||||
uint32_t WasmObjectWriter::getRelocationIndexValue(
|
||||
const WasmRelocationEntry &RelEntry) {
|
||||
switch (RelEntry.Type) {
|
||||
@ -773,9 +807,7 @@ void WasmObjectWriter::writeCodeSection(const MCAssembler &Asm,
|
||||
report_fatal_error(".size expression must be evaluatable");
|
||||
|
||||
encodeULEB128(Size, getStream());
|
||||
|
||||
FuncSection.setSectionOffset(getStream().tell() - Section.ContentsOffset);
|
||||
|
||||
Asm.writeSectionData(&FuncSection, Layout);
|
||||
}
|
||||
|
||||
@ -1016,7 +1048,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
|
||||
// In the special .global_variables section, we've encoded global
|
||||
// variables used by the function. Translate them into the Globals
|
||||
// list.
|
||||
MCSectionWasm *GlobalVars = Ctx.getWasmSection(".global_variables", 0, 0);
|
||||
MCSectionWasm *GlobalVars = Ctx.getWasmSection(".global_variables", wasm::WASM_SEC_DATA);
|
||||
if (!GlobalVars->getFragmentList().empty()) {
|
||||
if (GlobalVars->getFragmentList().size() != 1)
|
||||
report_fatal_error("only one .global_variables fragment supported");
|
||||
@ -1072,7 +1104,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
|
||||
|
||||
// In the special .stack_pointer section, we've encoded the stack pointer
|
||||
// index.
|
||||
MCSectionWasm *StackPtr = Ctx.getWasmSection(".stack_pointer", 0, 0);
|
||||
MCSectionWasm *StackPtr = Ctx.getWasmSection(".stack_pointer", wasm::WASM_SEC_DATA);
|
||||
if (!StackPtr->getFragmentList().empty()) {
|
||||
if (StackPtr->getFragmentList().size() != 1)
|
||||
report_fatal_error("only one .stack_pointer fragment supported");
|
||||
@ -1089,6 +1121,21 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
|
||||
StackPointerGlobal = NumGlobalImports + *(const int32_t *)Contents.data();
|
||||
}
|
||||
|
||||
for (MCSection &Sec : Asm) {
|
||||
auto &Section = static_cast<MCSectionWasm &>(Sec);
|
||||
if (Section.getType() != wasm::WASM_SEC_DATA)
|
||||
continue;
|
||||
|
||||
DataSize = alignTo(DataSize, Section.getAlignment());
|
||||
DataSegments.emplace_back();
|
||||
WasmDataSegment &Segment = DataSegments.back();
|
||||
Segment.Offset = DataSize;
|
||||
Segment.Section = &Section;
|
||||
addData(Segment.Data, Section, DataAlignment);
|
||||
DataSize += Segment.Data.size();
|
||||
Section.setMemoryOffset(Segment.Offset);
|
||||
}
|
||||
|
||||
// Handle regular defined and undefined symbols.
|
||||
for (const MCSymbol &S : Asm.symbols()) {
|
||||
// Ignore unnamed temporary symbols, which aren't ever exported, imported,
|
||||
@ -1151,9 +1198,6 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
|
||||
if (!WS.isDefined(/*SetUsed=*/false))
|
||||
continue;
|
||||
|
||||
if (WS.getOffset() != 0)
|
||||
report_fatal_error("data sections must contain one variable each: " +
|
||||
WS.getName());
|
||||
if (!WS.getSize())
|
||||
report_fatal_error("data symbols must have a size set with .size: " +
|
||||
WS.getName());
|
||||
@ -1162,58 +1206,20 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
|
||||
if (!WS.getSize()->evaluateAsAbsolute(Size, Layout))
|
||||
report_fatal_error(".size expression must be evaluatable");
|
||||
|
||||
auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
|
||||
|
||||
if (uint64_t(Size) != Layout.getSectionFileSize(&DataSection))
|
||||
report_fatal_error("data sections must contain at most one variable");
|
||||
|
||||
DataAlignment = std::max(DataAlignment, DataSection.getAlignment());
|
||||
|
||||
DataSegments.emplace_back();
|
||||
WasmDataSegment &Segment = DataSegments.back();
|
||||
|
||||
DataSize = alignTo(DataSize, DataSection.getAlignment());
|
||||
Segment.Offset = DataSize;
|
||||
Segment.Section = &DataSection;
|
||||
|
||||
// For each global, prepare a corresponding wasm global holding its
|
||||
// address. For externals these will also be named exports.
|
||||
Index = NumGlobalImports + Globals.size();
|
||||
auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
|
||||
|
||||
WasmGlobal Global;
|
||||
Global.Type = PtrType;
|
||||
Global.IsMutable = false;
|
||||
Global.HasImport = false;
|
||||
Global.InitialValue = DataSize;
|
||||
Global.InitialValue = DataSection.getMemoryOffset() + Layout.getSymbolOffset(WS);
|
||||
Global.ImportIndex = 0;
|
||||
SymbolIndices[&WS] = Index;
|
||||
DEBUG(dbgs() << " -> global index: " << Index << "\n");
|
||||
Globals.push_back(Global);
|
||||
|
||||
for (const MCFragment &Frag : DataSection) {
|
||||
if (Frag.hasInstructions())
|
||||
report_fatal_error("only data supported in data sections");
|
||||
|
||||
if (auto *Align = dyn_cast<MCAlignFragment>(&Frag)) {
|
||||
if (Align->getValueSize() != 1)
|
||||
report_fatal_error("only byte values supported for alignment");
|
||||
// If nops are requested, use zeros, as this is the data section.
|
||||
uint8_t Value = Align->hasEmitNops() ? 0 : Align->getValue();
|
||||
uint64_t Size = std::min<uint64_t>(
|
||||
alignTo(Segment.Data.size(), Align->getAlignment()),
|
||||
Segment.Data.size() + Align->getMaxBytesToEmit());
|
||||
Segment.Data.resize(Size, Value);
|
||||
} else if (auto *Fill = dyn_cast<MCFillFragment>(&Frag)) {
|
||||
Segment.Data.insert(Segment.Data.end(), Fill->getSize(), Fill->getValue());
|
||||
} else {
|
||||
const auto &DataFrag = cast<MCDataFragment>(Frag);
|
||||
const SmallVectorImpl<char> &Contents = DataFrag.getContents();
|
||||
|
||||
Segment.Data.insert(Segment.Data.end(), Contents.begin(),
|
||||
Contents.end());
|
||||
}
|
||||
}
|
||||
DataSize += Segment.Data.size();
|
||||
}
|
||||
|
||||
// If the symbol is visible outside this translation unit, export it.
|
||||
|
65
test/MC/WebAssembly/explicit-sections.ll
Normal file
65
test/MC/WebAssembly/explicit-sections.ll
Normal file
@ -0,0 +1,65 @@
|
||||
; RUN: llc -mtriple wasm32-unknown-unknown-wasm -filetype=obj %s -o - | obj2yaml | FileCheck %s
|
||||
|
||||
%struct.bd = type { i32, i8 }
|
||||
|
||||
@global0 = global i32 8, align 8
|
||||
@global1 = global %struct.bd { i32 1, i8 3 }, align 8, section ".sec1"
|
||||
@global2 = global i64 7, align 8, section ".sec1"
|
||||
@global3 = global i32 8, align 8, section ".sec2"
|
||||
|
||||
; 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: 8
|
||||
; CHECK-NEXT: - Type: I32
|
||||
; CHECK-NEXT: Mutable: false
|
||||
; CHECK-NEXT: InitExpr:
|
||||
; CHECK-NEXT: Opcode: I32_CONST
|
||||
; CHECK-NEXT: Value: 16
|
||||
; CHECK-NEXT: - Type: I32
|
||||
; CHECK-NEXT: Mutable: false
|
||||
; CHECK-NEXT: InitExpr:
|
||||
; CHECK-NEXT: Opcode: I32_CONST
|
||||
; CHECK-NEXT: Value: 24
|
||||
; CHECK-NEXT: - Type: EXPORT
|
||||
; CHECK-NEXT: Exports:
|
||||
; CHECK-NEXT: - Name: global0
|
||||
; CHECK-NEXT: Kind: GLOBAL
|
||||
; CHECK-NEXT: Index: 0
|
||||
; CHECK-NEXT: - Name: global1
|
||||
; CHECK-NEXT: Kind: GLOBAL
|
||||
; CHECK-NEXT: Index: 1
|
||||
; CHECK-NEXT: - Name: global2
|
||||
; CHECK-NEXT: Kind: GLOBAL
|
||||
; CHECK-NEXT: Index: 2
|
||||
; CHECK-NEXT: - Name: global3
|
||||
; CHECK-NEXT: Kind: GLOBAL
|
||||
; CHECK-NEXT: Index: 3
|
||||
; CHECK-NEXT: - Type: DATA
|
||||
; CHECK-NEXT: Segments:
|
||||
; CHECK-NEXT: - SectionOffset: 6
|
||||
; CHECK-NEXT: MemoryIndex: 0
|
||||
; CHECK-NEXT: Offset:
|
||||
; CHECK-NEXT: Opcode: I32_CONST
|
||||
; CHECK-NEXT: Value: 0
|
||||
; CHECK-NEXT: Content: '08000000'
|
||||
; CHECK-NEXT: - SectionOffset: 15
|
||||
; CHECK-NEXT: MemoryIndex: 0
|
||||
; CHECK-NEXT: Offset:
|
||||
; CHECK-NEXT: Opcode: I32_CONST
|
||||
; CHECK-NEXT: Value: 8
|
||||
; CHECK-NEXT: Content: '01000000030000000700000000000000'
|
||||
; CHECK-NEXT: - SectionOffset: 36
|
||||
; CHECK-NEXT: MemoryIndex: 0
|
||||
; CHECK-NEXT: Offset:
|
||||
; CHECK-NEXT: Opcode: I32_CONST
|
||||
; CHECK-NEXT: Value: 24
|
||||
; CHECK-NEXT: Content: '08000000'
|
Loading…
Reference in New Issue
Block a user