mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-04 17:56:53 +00:00
[WebAssembly] Add data size and alignement to linking section
The overal size of the data section (including BSS) is otherwise not included in the wasm binary. Differential Revision: https://reviews.llvm.org/D34657 llvm-svn: 306459
This commit is contained in:
parent
6a67a4e40b
commit
d3b03d52bc
@ -112,6 +112,11 @@ struct WasmRelocation {
|
||||
int64_t Addend; // A value to add to the symbol.
|
||||
};
|
||||
|
||||
struct WasmLinkingData {
|
||||
uint32_t DataSize;
|
||||
uint32_t DataAlignment;
|
||||
};
|
||||
|
||||
enum : unsigned {
|
||||
WASM_SEC_CUSTOM = 0, // Custom / User-defined section
|
||||
WASM_SEC_TYPE = 1, // Function signature declarations
|
||||
@ -175,8 +180,10 @@ enum class ValType {
|
||||
|
||||
// Linking metadata kinds.
|
||||
enum : unsigned {
|
||||
WASM_STACK_POINTER = 0x1,
|
||||
WASM_SYMBOL_INFO = 0x2,
|
||||
WASM_STACK_POINTER = 0x1,
|
||||
WASM_SYMBOL_INFO = 0x2,
|
||||
WASM_DATA_SIZE = 0x3,
|
||||
WASM_DATA_ALIGNMENT = 0x4,
|
||||
};
|
||||
|
||||
enum : unsigned {
|
||||
|
@ -100,6 +100,7 @@ public:
|
||||
const std::vector<wasm::WasmLimits>& memories() const { return Memories; }
|
||||
const std::vector<wasm::WasmGlobal>& globals() const { return Globals; }
|
||||
const std::vector<wasm::WasmExport>& exports() const { return Exports; }
|
||||
const wasm::WasmLinkingData& linkingData() const { return LinkingData; }
|
||||
|
||||
uint32_t getNumberOfSymbols() const {
|
||||
return Symbols.size();
|
||||
@ -214,6 +215,7 @@ private:
|
||||
std::vector<WasmSymbol> Symbols;
|
||||
ArrayRef<uint8_t> CodeSection;
|
||||
uint32_t StartFunction = -1;
|
||||
wasm::WasmLinkingData LinkingData;
|
||||
|
||||
StringMap<uint32_t> SymbolMap;
|
||||
};
|
||||
|
@ -154,6 +154,8 @@ struct LinkingSection : CustomSection {
|
||||
}
|
||||
|
||||
std::vector<SymbolInfo> SymbolInfos;
|
||||
uint32_t DataSize;
|
||||
uint32_t DataAlignment;
|
||||
};
|
||||
|
||||
struct TypeSection : Section {
|
||||
|
@ -265,7 +265,8 @@ private:
|
||||
uint32_t NumFuncImports);
|
||||
void writeCodeRelocSection();
|
||||
void writeDataRelocSection(uint64_t DataSectionHeaderSize);
|
||||
void writeLinkingMetaDataSection(ArrayRef<StringRef> WeakSymbols,
|
||||
void writeLinkingMetaDataSection(uint32_t DataSize, uint32_t DataAlignment,
|
||||
ArrayRef<StringRef> WeakSymbols,
|
||||
bool HasStackPointer,
|
||||
uint32_t StackPointerGlobal);
|
||||
|
||||
@ -877,11 +878,8 @@ void WasmObjectWriter::writeDataRelocSection(uint64_t DataSectionHeaderSize) {
|
||||
}
|
||||
|
||||
void WasmObjectWriter::writeLinkingMetaDataSection(
|
||||
ArrayRef<StringRef> WeakSymbols, bool HasStackPointer,
|
||||
uint32_t StackPointerGlobal) {
|
||||
if (!HasStackPointer && WeakSymbols.empty())
|
||||
return;
|
||||
|
||||
uint32_t DataSize, uint32_t DataAlignment, ArrayRef<StringRef> WeakSymbols,
|
||||
bool HasStackPointer, uint32_t StackPointerGlobal) {
|
||||
SectionBookkeeping Section;
|
||||
startSection(Section, wasm::WASM_SEC_CUSTOM, "linking");
|
||||
SectionBookkeeping SubSection;
|
||||
@ -902,6 +900,16 @@ void WasmObjectWriter::writeLinkingMetaDataSection(
|
||||
endSection(SubSection);
|
||||
}
|
||||
|
||||
if (DataSize > 0) {
|
||||
startSection(SubSection, wasm::WASM_DATA_SIZE);
|
||||
encodeULEB128(DataSize, getStream());
|
||||
endSection(SubSection);
|
||||
|
||||
startSection(SubSection, wasm::WASM_DATA_ALIGNMENT);
|
||||
encodeULEB128(DataAlignment, getStream());
|
||||
endSection(SubSection);
|
||||
}
|
||||
|
||||
endSection(Section);
|
||||
}
|
||||
|
||||
@ -923,6 +931,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
|
||||
unsigned NumFuncImports = 0;
|
||||
unsigned NumGlobalImports = 0;
|
||||
SmallVector<char, 0> DataBytes;
|
||||
uint32_t DataAlignment = 1;
|
||||
uint32_t StackPointerGlobal = 0;
|
||||
bool HasStackPointer = false;
|
||||
|
||||
@ -1157,6 +1166,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
|
||||
report_fatal_error("data sections must contain at most one variable");
|
||||
|
||||
DataBytes.resize(alignTo(DataBytes.size(), DataSection.getAlignment()));
|
||||
DataAlignment = std::max(DataAlignment, DataSection.getAlignment());
|
||||
|
||||
DataSection.setSectionOffset(DataBytes.size());
|
||||
|
||||
@ -1272,7 +1282,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
|
||||
writeNameSection(Functions, Imports, NumFuncImports);
|
||||
writeCodeRelocSection();
|
||||
writeDataRelocSection(DataSectionHeaderSize);
|
||||
writeLinkingMetaDataSection(WeakSymbols, HasStackPointer, StackPointerGlobal);
|
||||
writeLinkingMetaDataSection(DataBytes.size(), DataAlignment, WeakSymbols, HasStackPointer, StackPointerGlobal);
|
||||
|
||||
// TODO: Translate the .comment section to the output.
|
||||
// TODO: Translate debug sections to the output.
|
||||
|
@ -193,6 +193,9 @@ static Error readSection(WasmSection &Section, const uint8_t *&Ptr,
|
||||
|
||||
WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
|
||||
: ObjectFile(Binary::ID_Wasm, Buffer) {
|
||||
LinkingData.DataAlignment = 0;
|
||||
LinkingData.DataSize = 0;
|
||||
|
||||
ErrorAsOutParameter ErrAsOutParam(&Err);
|
||||
Header.Magic = getData().substr(0, 4);
|
||||
if (Header.Magic != StringRef("\0asm", 4)) {
|
||||
@ -305,7 +308,7 @@ Error WasmObjectFile::parseLinkingSection(const uint8_t *Ptr,
|
||||
auto iter = SymbolMap.find(Symbol);
|
||||
if (iter == SymbolMap.end()) {
|
||||
return make_error<GenericBinaryError>(
|
||||
"Invalid symbol name in linking section",
|
||||
"Invalid symbol name in linking section: " + Symbol,
|
||||
object_error::parse_failed);
|
||||
}
|
||||
uint32_t SymIndex = iter->second;
|
||||
@ -318,6 +321,12 @@ Error WasmObjectFile::parseLinkingSection(const uint8_t *Ptr,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case wasm::WASM_DATA_SIZE:
|
||||
LinkingData.DataSize = readVaruint32(Ptr);
|
||||
break;
|
||||
case wasm::WASM_DATA_ALIGNMENT:
|
||||
LinkingData.DataAlignment = readVaruint32(Ptr);
|
||||
break;
|
||||
case wasm::WASM_STACK_POINTER:
|
||||
default:
|
||||
Ptr += Size;
|
||||
|
@ -56,6 +56,8 @@ static void sectionMapping(IO &IO, WasmYAML::NameSection &Section) {
|
||||
static void sectionMapping(IO &IO, WasmYAML::LinkingSection &Section) {
|
||||
commonSectionMapping(IO, Section);
|
||||
IO.mapRequired("Name", Section.Name);
|
||||
IO.mapRequired("DataSize", Section.DataSize);
|
||||
IO.mapRequired("DataAlignment", Section.DataAlignment);
|
||||
IO.mapRequired("SymbolInfo", Section.SymbolInfos);
|
||||
}
|
||||
|
||||
|
@ -7,47 +7,53 @@
|
||||
@b = global i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str2, i32 0, i32 0), align 8
|
||||
|
||||
|
||||
; CHECK: - Type: GLOBAL
|
||||
; CHECK: Globals:
|
||||
; CHECK: - Type: I32
|
||||
; CHECK: Mutable: false
|
||||
; CHECK: InitExpr:
|
||||
; CHECK: Opcode: I32_CONST
|
||||
; CHECK: Value: 0
|
||||
; CHECK: - Type: I32
|
||||
; CHECK: Mutable: false
|
||||
; CHECK: InitExpr:
|
||||
; CHECK: Opcode: I32_CONST
|
||||
; CHECK: Value: 6
|
||||
; CHECK: - Type: I32
|
||||
; CHECK: Mutable: false
|
||||
; CHECK: InitExpr:
|
||||
; CHECK: Opcode: I32_CONST
|
||||
; CHECK: Value: 16
|
||||
; CHECK: - Type: I32
|
||||
; CHECK: Mutable: false
|
||||
; CHECK: InitExpr:
|
||||
; CHECK: Opcode: I32_CONST
|
||||
; CHECK: Value: 24
|
||||
; CHECK: - Type: EXPORT
|
||||
; CHECK: Exports:
|
||||
; CHECK: - Name: a
|
||||
; CHECK: Kind: GLOBAL
|
||||
; CHECK: Index: 2
|
||||
; CHECK: - Name: b
|
||||
; CHECK: Kind: GLOBAL
|
||||
; CHECK: Index: 3
|
||||
; CHECK: - Type: DATA
|
||||
; CHECK: Relocations:
|
||||
; CHECK: - Type: R_WEBASSEMBLY_GLOBAL_ADDR_I32
|
||||
; CHECK: Index: 0
|
||||
; CHECK: Offset: 0x00000016
|
||||
; CHECK: - Type: R_WEBASSEMBLY_GLOBAL_ADDR_I32
|
||||
; CHECK: Index: 1
|
||||
; CHECK: Offset: 0x0000001E
|
||||
; CHECK: Segments:
|
||||
; CHECK: - Index: 0
|
||||
; CHECK: Offset:
|
||||
; CHECK: Opcode: I32_CONST
|
||||
; CHECK: Value: 0
|
||||
; CHECK: Content: 68656C6C6F00776F726C640000000000000000000000000006000000
|
||||
; 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: 6
|
||||
; 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: a
|
||||
; CHECK-NEXT: Kind: GLOBAL
|
||||
; CHECK-NEXT: Index: 2
|
||||
; CHECK-NEXT: - Name: b
|
||||
; CHECK-NEXT: Kind: GLOBAL
|
||||
; CHECK-NEXT: Index: 3
|
||||
; CHECK-NEXT: - Type: DATA
|
||||
; CHECK-NEXT: Relocations:
|
||||
; CHECK-NEXT: - Type: R_WEBASSEMBLY_GLOBAL_ADDR_I32
|
||||
; CHECK-NEXT: Index: 0
|
||||
; CHECK-NEXT: Offset: 0x00000016
|
||||
; CHECK-NEXT: - Type: R_WEBASSEMBLY_GLOBAL_ADDR_I32
|
||||
; CHECK-NEXT: Index: 1
|
||||
; CHECK-NEXT: Offset: 0x0000001E
|
||||
; CHECK-NEXT: Segments:
|
||||
; CHECK-NEXT: - Index: 0
|
||||
; CHECK-NEXT: Offset:
|
||||
; CHECK-NEXT: Opcode: I32_CONST
|
||||
; CHECK-NEXT: Value: 0
|
||||
; CHECK-NEXT: Content: 68656C6C6F00776F726C640000000000000000000000000006000000
|
||||
; CHECK-NEXT: - Type: CUSTOM
|
||||
; CHECK-NEXT: Name: linking
|
||||
; CHECK-NEXT: DataSize: 28
|
||||
; CHECK-NEXT: DataAlignment: 8
|
||||
; CHECK-NEXT: SymbolInfo:
|
||||
; CHECK-NEXT: ...
|
||||
|
@ -27,6 +27,8 @@ entry:
|
||||
; CHECK-NEXT: Name: foo
|
||||
; CHECK-NEXT: - Type: CUSTOM
|
||||
; CHECK-NEXT: Name: linking
|
||||
; CHECK-NEXT: DataSize: 0
|
||||
; CHECK-NEXT: DataAlignment: 0
|
||||
; CHECK-NEXT: SymbolInfo:
|
||||
; CHECK-NEXT: - Name: foo_alias
|
||||
; CHECK-NEXT: Flags: 1
|
||||
|
@ -26,6 +26,8 @@ entry:
|
||||
; CHECK-NEXT: Name: weak_function
|
||||
; CHECK-NEXT: - Type: CUSTOM
|
||||
; CHECK-NEXT: Name: linking
|
||||
; CHECK-NEXT: DataSize: 0
|
||||
; CHECK-NEXT: DataAlignment: 0
|
||||
; CHECK-NEXT: SymbolInfo:
|
||||
; CHECK-NEXT: - Name: weak_external_data
|
||||
; CHECK-NEXT: Flags: 1
|
||||
|
@ -3,6 +3,19 @@
|
||||
FileHeader:
|
||||
Version: 0x00000001
|
||||
Sections:
|
||||
- Type: TYPE
|
||||
Signatures:
|
||||
- ReturnType: I32
|
||||
ParamTypes:
|
||||
- Type: FUNCTION
|
||||
FunctionTypes: [ 0, 0 ]
|
||||
- Type: GLOBAL
|
||||
Globals:
|
||||
- Type: I32
|
||||
Mutable: false
|
||||
InitExpr:
|
||||
Opcode: I32_CONST
|
||||
Value: 1
|
||||
- Type: EXPORT
|
||||
Exports:
|
||||
- Name: function_export
|
||||
@ -10,9 +23,11 @@ Sections:
|
||||
Index: 1
|
||||
- Name: global_export
|
||||
Kind: GLOBAL
|
||||
Index: 2
|
||||
Index: 0
|
||||
- Type: CUSTOM
|
||||
Name: linking
|
||||
DataSize: 10
|
||||
DataAlignment: 2
|
||||
SymbolInfo:
|
||||
- Name: function_export
|
||||
Flags: 1
|
||||
@ -30,9 +45,11 @@ Sections:
|
||||
# CHECK: Index: 1
|
||||
# CHECK: - Name: global_export
|
||||
# CHECK: Kind: GLOBAL
|
||||
# CHECK: Index: 2
|
||||
# CHECK: Index: 0
|
||||
# CHECK: - Type: CUSTOM
|
||||
# CHECK: Name: linking
|
||||
# CHECK: DataSize: 10
|
||||
# CHECK: DataAlignment: 2
|
||||
# CHECK: SymbolInfo:
|
||||
# CHECK: - Name: function_export
|
||||
# CHECK: Flags: 1
|
||||
|
@ -33,6 +33,8 @@ Sections:
|
||||
Index: 0x00000002
|
||||
- Type: CUSTOM
|
||||
Name: linking
|
||||
DataSize: 0
|
||||
DataAlignment: 2
|
||||
SymbolInfo:
|
||||
- Name: weak_global_func
|
||||
Flags: 1
|
||||
|
@ -77,6 +77,8 @@ std::unique_ptr<WasmYAML::CustomSection> WasmDumper::dumpCustomSection(const Was
|
||||
LinkingSec->SymbolInfos.push_back(Info);
|
||||
}
|
||||
}
|
||||
LinkingSec->DataSize = Obj.linkingData().DataSize;
|
||||
LinkingSec->DataAlignment = Obj.linkingData().DataAlignment;
|
||||
CustomSec = std::move(LinkingSec);
|
||||
} else {
|
||||
CustomSec = make_unique<WasmYAML::CustomSection>(WasmSec.Name);
|
||||
|
@ -110,22 +110,52 @@ static int writeInitExpr(const wasm::WasmInitExpr &InitExpr, raw_ostream &OS) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section) {
|
||||
writeStringRef(Section.Name, OS);
|
||||
if (Section.SymbolInfos.size()) {
|
||||
encodeULEB128(wasm::WASM_SYMBOL_INFO, OS);
|
||||
std::string OutString;
|
||||
raw_string_ostream StringStream(OutString);
|
||||
class SubSectionWriter {
|
||||
raw_ostream &OS;
|
||||
std::string OutString;
|
||||
raw_string_ostream StringStream;
|
||||
|
||||
encodeULEB128(Section.SymbolInfos.size(), StringStream);
|
||||
for (const WasmYAML::SymbolInfo &Info : Section.SymbolInfos) {
|
||||
writeStringRef(Info.Name, StringStream);
|
||||
encodeULEB128(Info.Flags, StringStream);
|
||||
}
|
||||
public:
|
||||
SubSectionWriter(raw_ostream &OS) : OS(OS), StringStream(OutString) {}
|
||||
|
||||
void Done() {
|
||||
StringStream.flush();
|
||||
encodeULEB128(OutString.size(), OS);
|
||||
OS << OutString;
|
||||
OutString.clear();
|
||||
}
|
||||
|
||||
raw_ostream& GetStream() {
|
||||
return StringStream;
|
||||
}
|
||||
};
|
||||
|
||||
int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section) {
|
||||
writeStringRef(Section.Name, OS);
|
||||
|
||||
SubSectionWriter SubSection(OS);
|
||||
|
||||
// DATA_SIZE subsection
|
||||
encodeULEB128(wasm::WASM_DATA_SIZE, OS);
|
||||
encodeULEB128(Section.DataSize, SubSection.GetStream());
|
||||
SubSection.Done();
|
||||
|
||||
// DATA_ALIGNMENT subsection
|
||||
encodeULEB128(wasm::WASM_DATA_ALIGNMENT, OS);
|
||||
encodeULEB128(Section.DataAlignment, SubSection.GetStream());
|
||||
SubSection.Done();
|
||||
|
||||
// SYMBOL_INFO subsection
|
||||
if (Section.SymbolInfos.size()) {
|
||||
encodeULEB128(wasm::WASM_SYMBOL_INFO, OS);
|
||||
|
||||
encodeULEB128(Section.SymbolInfos.size(), SubSection.GetStream());
|
||||
for (const WasmYAML::SymbolInfo &Info : Section.SymbolInfos) {
|
||||
writeStringRef(Info.Name, SubSection.GetStream());
|
||||
encodeULEB128(Info.Flags, SubSection.GetStream());
|
||||
}
|
||||
|
||||
SubSection.Done();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -134,18 +164,16 @@ int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Sect
|
||||
writeStringRef(Section.Name, OS);
|
||||
if (Section.FunctionNames.size()) {
|
||||
encodeULEB128(wasm::WASM_NAMES_FUNCTION, OS);
|
||||
std::string OutString;
|
||||
raw_string_ostream StringStream(OutString);
|
||||
|
||||
encodeULEB128(Section.FunctionNames.size(), StringStream);
|
||||
SubSectionWriter SubSection(OS);
|
||||
|
||||
encodeULEB128(Section.FunctionNames.size(), SubSection.GetStream());
|
||||
for (const WasmYAML::NameEntry &NameEntry : Section.FunctionNames) {
|
||||
encodeULEB128(NameEntry.Index, StringStream);
|
||||
writeStringRef(NameEntry.Name, StringStream);
|
||||
encodeULEB128(NameEntry.Index, SubSection.GetStream());
|
||||
writeStringRef(NameEntry.Name, SubSection.GetStream());
|
||||
}
|
||||
|
||||
StringStream.flush();
|
||||
encodeULEB128(OutString.size(), OS);
|
||||
OS << OutString;
|
||||
SubSection.Done();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user