// 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; }
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; }
};
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(
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) {
UniqueID = *NextUniqueID;
(*NextUniqueID)++;
}
- return Ctx.getWasmSection(Name, /*Type=*/0, Group, UniqueID);
+ return Ctx.getWasmSection(Name, Type, Group, UniqueID);
}
MCSection *TargetLoweringObjectFileWasm::SelectSectionForGlobal(
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.
}
void MCWasmStreamer::EmitIdent(StringRef IdentString) {
MCSection *Comment = getAssembler().getContext().getWasmSection(
- ".comment", 0, 0);
+ ".comment", wasm::WASM_SEC_DATA);
PushSection();
SwitchSection(Comment);
if (!SeenIdent) {
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)
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) {
report_fatal_error(".size expression must be evaluatable");
encodeULEB128(Size, getStream());
-
FuncSection.setSectionOffset(getStream().tell() - Section.ContentsOffset);
-
Asm.writeSectionData(&FuncSection, Layout);
}
// 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");
// 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");
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,
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());
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.
--- /dev/null
+; 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'