[llvm] r313395 - [WebAssembly] MC: Create wasm data segments based on MCSections
Sam Clegg via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 15 13:54:59 PDT 2017
Author: sbc
Date: Fri Sep 15 13:54:59 2017
New Revision: 313395
URL: http://llvm.org/viewvc/llvm-project?rev=313395&view=rev
Log:
[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
Added:
llvm/trunk/test/MC/WebAssembly/explicit-sections.ll
Modified:
llvm/trunk/include/llvm/MC/MCSectionWasm.h
llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
llvm/trunk/lib/MC/MCObjectFileInfo.cpp
llvm/trunk/lib/MC/MCWasmStreamer.cpp
llvm/trunk/lib/MC/WasmObjectWriter.cpp
Modified: llvm/trunk/include/llvm/MC/MCSectionWasm.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCSectionWasm.h?rev=313395&r1=313394&r2=313395&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCSectionWasm.h (original)
+++ llvm/trunk/include/llvm/MC/MCSectionWasm.h Fri Sep 15 13:54:59 2017
@@ -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; }
};
Modified: llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp?rev=313395&r1=313394&r2=313395&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp (original)
+++ llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp Fri Sep 15 13:54:59 2017
@@ -1248,8 +1248,8 @@ static const Comdat *getWasmComdat(const
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 *selectWasmSectionF
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 *selectWasmSectionF
UniqueID = *NextUniqueID;
(*NextUniqueID)++;
}
- return Ctx.getWasmSection(Name, /*Type=*/0, Group, UniqueID);
+ return Ctx.getWasmSection(Name, Type, Group, UniqueID);
}
MCSection *TargetLoweringObjectFileWasm::SelectSectionForGlobal(
Modified: llvm/trunk/lib/MC/MCObjectFileInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCObjectFileInfo.cpp?rev=313395&r1=313394&r2=313395&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCObjectFileInfo.cpp (original)
+++ llvm/trunk/lib/MC/MCObjectFileInfo.cpp Fri Sep 15 13:54:59 2017
@@ -820,24 +820,24 @@ void MCObjectFileInfo::initCOFFMCObjectF
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.
}
Modified: llvm/trunk/lib/MC/MCWasmStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCWasmStreamer.cpp?rev=313395&r1=313394&r2=313395&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCWasmStreamer.cpp (original)
+++ llvm/trunk/lib/MC/MCWasmStreamer.cpp Fri Sep 15 13:54:59 2017
@@ -156,7 +156,7 @@ void MCWasmStreamer::EmitValueToAlignmen
void MCWasmStreamer::EmitIdent(StringRef IdentString) {
MCSection *Comment = getAssembler().getContext().getWasmSection(
- ".comment", 0, 0);
+ ".comment", wasm::WASM_SEC_DATA);
PushSection();
SwitchSection(Comment);
if (!SeenIdent) {
Modified: llvm/trunk/lib/MC/WasmObjectWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/WasmObjectWriter.cpp?rev=313395&r1=313394&r2=313395&view=diff
==============================================================================
--- llvm/trunk/lib/MC/WasmObjectWriter.cpp (original)
+++ llvm/trunk/lib/MC/WasmObjectWriter.cpp Fri Sep 15 13:54:59 2017
@@ -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(co
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(
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(MCAss
// 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(MCAss
// 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(MCAss
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(MCAss
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(MCAss
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.
Added: llvm/trunk/test/MC/WebAssembly/explicit-sections.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/WebAssembly/explicit-sections.ll?rev=313395&view=auto
==============================================================================
--- llvm/trunk/test/MC/WebAssembly/explicit-sections.ll (added)
+++ llvm/trunk/test/MC/WebAssembly/explicit-sections.ll Fri Sep 15 13:54:59 2017
@@ -0,0 +1,65 @@
+; RUN: llc -mtriple wasm32-unknown-unknown-wasm -filetype=obj %s -o - | obj2yaml | FileCheck %s
+
+%struct.bd = type { i32, i8 }
+
+ at global0 = global i32 8, align 8
+ at global1 = global %struct.bd { i32 1, i8 3 }, align 8, section ".sec1"
+ at global2 = global i64 7, align 8, section ".sec1"
+ at 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'
More information about the llvm-commits
mailing list