summaryrefslogtreecommitdiffstats
path: root/llvm/lib/MC/WasmObjectWriter.cpp
diff options
context:
space:
mode:
authorSam Clegg <sbc@chromium.org>2019-03-26 19:46:15 +0000
committerSam Clegg <sbc@chromium.org>2019-03-26 19:46:15 +0000
commit492f752969ff3a37138372e8e973317dc63ef2d3 (patch)
treedb63368f472fbb77026751650cc85ecc6c114f07 /llvm/lib/MC/WasmObjectWriter.cpp
parent6f4c45e9fc70473e2e176608657c02beb122973b (diff)
downloadbcm5719-llvm-492f752969ff3a37138372e8e973317dc63ef2d3.tar.gz
bcm5719-llvm-492f752969ff3a37138372e8e973317dc63ef2d3.zip
[WebAssembly] Initial implementation of PIC code generation
This change implements lowering of references global symbols in PIC mode. This change implements lowering of global references in PIC mode using a new @GOT reference type. @GOT references can be used with function or data symbol names combined with the get_global instruction. In this case the linker will insert the wasm global that stores the address of the symbol (either in memory for data symbols or in the wasm table for function symbols). For now I'm continuing to use the R_WASM_GLOBAL_INDEX_LEB relocation type for this type of reference which means that this relocation type can refer to either a global or a function or data symbol. We could choose to introduce specific relocation types for GOT entries in the future. See the current dynamic linking proposal: https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md Differential Revision: https://reviews.llvm.org/D54647 llvm-svn: 357022
Diffstat (limited to 'llvm/lib/MC/WasmObjectWriter.cpp')
-rw-r--r--llvm/lib/MC/WasmObjectWriter.cpp64
1 files changed, 36 insertions, 28 deletions
diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp
index 0014b695b90..adf0aef1202 100644
--- a/llvm/lib/MC/WasmObjectWriter.cpp
+++ b/llvm/lib/MC/WasmObjectWriter.cpp
@@ -243,6 +243,7 @@ class WasmObjectWriter : public MCObjectWriter {
// Maps function/global symbols to the function/global/event/section index
// space.
DenseMap<const MCSymbolWasm *, uint32_t> WasmIndices;
+ DenseMap<const MCSymbolWasm *, uint32_t> GOTIndices;
// Maps data symbols to the Wasm segment and offset/size with the segment.
DenseMap<const MCSymbolWasm *, wasm::WasmDataReference> DataLocations;
@@ -260,7 +261,6 @@ class WasmObjectWriter : public MCObjectWriter {
DenseMap<WasmSignature, uint32_t, WasmSignatureDenseMapInfo> SignatureIndices;
SmallVector<WasmSignature, 4> Signatures;
- SmallVector<WasmGlobal, 4> Globals;
SmallVector<WasmDataSegment, 4> DataSegments;
unsigned NumFunctionImports = 0;
unsigned NumGlobalImports = 0;
@@ -288,6 +288,7 @@ private:
DataRelocations.clear();
TypeIndices.clear();
WasmIndices.clear();
+ GOTIndices.clear();
TableIndices.clear();
DataLocations.clear();
CustomSections.clear();
@@ -296,7 +297,6 @@ private:
CustomSectionsRelocations.clear();
SignatureIndices.clear();
Signatures.clear();
- Globals.clear();
DataSegments.clear();
SectionFunctions.clear();
NumFunctionImports = 0;
@@ -326,7 +326,6 @@ private:
void writeImportSection(ArrayRef<wasm::WasmImport> Imports, uint32_t DataSize,
uint32_t NumElements);
void writeFunctionSection(ArrayRef<WasmFunction> Functions);
- void writeGlobalSection();
void writeExportSection(ArrayRef<wasm::WasmExport> Exports);
void writeElemSection(ArrayRef<uint32_t> TableElems);
void writeCodeSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
@@ -545,6 +544,9 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
SymA->setUsedInReloc();
}
+ if (RefA->getKind() == MCSymbolRefExpr::VK_GOT)
+ SymA->setUsedInGOT();
+
WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection);
LLVM_DEBUG(dbgs() << "WasmReloc: " << Rec << "\n");
@@ -575,6 +577,11 @@ static const MCSymbolWasm *resolveSymbol(const MCSymbolWasm &Symbol) {
// useable.
uint32_t
WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry) {
+ if (RelEntry.Type == wasm::R_WASM_GLOBAL_INDEX_LEB && !RelEntry.Symbol->isGlobal()) {
+ assert(GOTIndices.count(RelEntry.Symbol) > 0 && "symbol not found in GOT index space");
+ return GOTIndices[RelEntry.Symbol];
+ }
+
switch (RelEntry.Type) {
case wasm::R_WASM_TABLE_INDEX_SLEB:
case wasm::R_WASM_TABLE_INDEX_I32: {
@@ -590,9 +597,7 @@ WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry) {
case wasm::R_WASM_GLOBAL_INDEX_LEB:
case wasm::R_WASM_EVENT_INDEX_LEB:
// Provisional value is function/global/event Wasm index
- if (!WasmIndices.count(RelEntry.Symbol))
- report_fatal_error("symbol not found in wasm index space: " +
- RelEntry.Symbol->getName());
+ assert(WasmIndices.count(RelEntry.Symbol) > 0 && "symbol not found in wasm index space");
return WasmIndices[RelEntry.Symbol];
case wasm::R_WASM_FUNCTION_OFFSET_I32:
case wasm::R_WASM_SECTION_OFFSET_I32: {
@@ -787,26 +792,6 @@ void WasmObjectWriter::writeFunctionSection(ArrayRef<WasmFunction> Functions) {
endSection(Section);
}
-void WasmObjectWriter::writeGlobalSection() {
- if (Globals.empty())
- return;
-
- SectionBookkeeping Section;
- startSection(Section, wasm::WASM_SEC_GLOBAL);
-
- encodeULEB128(Globals.size(), W.OS);
- for (const WasmGlobal &Global : Globals) {
- writeValueType(static_cast<wasm::ValType>(Global.Type.Type));
- W.OS << char(Global.Type.Mutable);
-
- W.OS << char(wasm::WASM_OPCODE_I32_CONST);
- encodeSLEB128(Global.InitialValue, W.OS);
- W.OS << char(wasm::WASM_OPCODE_END);
- }
-
- endSection(Section);
-}
-
void WasmObjectWriter::writeEventSection(ArrayRef<wasm::WasmEventType> Events) {
if (Events.empty())
return;
@@ -1208,17 +1193,19 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
Import.Kind = wasm::WASM_EXTERNAL_FUNCTION;
Import.SigIndex = getFunctionType(WS);
Imports.push_back(Import);
+ assert(WasmIndices.count(&WS) == 0);
WasmIndices[&WS] = NumFunctionImports++;
} else if (WS.isGlobal()) {
if (WS.isWeak())
report_fatal_error("undefined global symbol cannot be weak");
wasm::WasmImport Import;
- Import.Module = WS.getImportModule();
Import.Field = WS.getImportName();
Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
+ Import.Module = WS.getImportModule();
Import.Global = WS.getGlobalType();
Imports.push_back(Import);
+ assert(WasmIndices.count(&WS) == 0);
WasmIndices[&WS] = NumGlobalImports++;
} else if (WS.isEvent()) {
if (WS.isWeak())
@@ -1231,11 +1218,30 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
Import.Event.Attribute = wasm::WASM_EVENT_ATTRIBUTE_EXCEPTION;
Import.Event.SigIndex = getEventType(WS);
Imports.push_back(Import);
+ assert(WasmIndices.count(&WS) == 0);
WasmIndices[&WS] = NumEventImports++;
}
}
}
+ // Add imports for GOT globals
+ for (const MCSymbol &S : Asm.symbols()) {
+ const auto &WS = static_cast<const MCSymbolWasm &>(S);
+ if (WS.isUsedInGOT()) {
+ wasm::WasmImport Import;
+ if (WS.isFunction())
+ Import.Module = "GOT.func";
+ else
+ Import.Module = "GOT.mem";
+ Import.Field = WS.getName();
+ Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
+ Import.Global = {wasm::WASM_TYPE_I32, true};
+ Imports.push_back(Import);
+ assert(GOTIndices.count(&WS) == 0);
+ GOTIndices[&WS] = NumGlobalImports++;
+ }
+ }
+
// Populate DataSegments and CustomSections, which must be done before
// populating DataLocations.
for (MCSection &Sec : Asm) {
@@ -1401,10 +1407,12 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
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);
Index = WasmIndices.find(&WS)->second;
}
LLVM_DEBUG(dbgs() << " -> event index: " << WasmIndices.find(&WS)->second
@@ -1434,6 +1442,7 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
if (ResolvedSym->isFunction()) {
assert(WasmIndices.count(ResolvedSym) > 0);
uint32_t WasmIndex = WasmIndices.find(ResolvedSym)->second;
+ assert(WasmIndices.count(&WS) == 0);
WasmIndices[&WS] = WasmIndex;
LLVM_DEBUG(dbgs() << " -> index:" << WasmIndex << "\n");
} else if (ResolvedSym->isData()) {
@@ -1586,7 +1595,6 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
writeFunctionSection(Functions);
// Skip the "table" section; we import the table instead.
// Skip the "memory" section; we import the memory instead.
- writeGlobalSection();
writeEventSection(Events);
writeExportSection(Exports);
writeElemSection(TableElems);
OpenPOWER on IntegriCloud