aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp')
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp79
1 files changed, 44 insertions, 35 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
index bf326e51..4dc2c4c 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
@@ -180,26 +180,26 @@ void WebAssemblyAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
MCSymbolWasm *Sym = cast<MCSymbolWasm>(getSymbol(GV));
if (!Sym->getType()) {
- const WebAssemblyTargetLowering &TLI = *Subtarget->getTargetLowering();
SmallVector<MVT, 1> VTs;
Type *GlobalVT = GV->getValueType();
- computeLegalValueVTs(TLI, GV->getParent()->getContext(),
- GV->getParent()->getDataLayout(), GlobalVT, VTs);
+ if (Subtarget) {
+ // Subtarget is only set when a function is defined, because
+ // each function can declare a different subtarget. For example,
+ // on ARM a compilation unit might have a function on ARM and
+ // another on Thumb. Therefore only if Subtarget is non-null we
+ // can actually calculate the legal VTs.
+ const WebAssemblyTargetLowering &TLI = *Subtarget->getTargetLowering();
+ computeLegalValueVTs(TLI, GV->getParent()->getContext(),
+ GV->getParent()->getDataLayout(), GlobalVT, VTs);
+ }
WebAssembly::wasmSymbolSetType(Sym, GlobalVT, VTs);
}
- // If the GlobalVariable refers to a table, we handle it here instead of
- // in emitExternalDecls
- if (Sym->isTable()) {
- getTargetStreamer()->emitTableType(Sym);
- return;
- }
-
emitVisibility(Sym, GV->getVisibility(), !GV->isDeclaration());
+ emitSymbolType(Sym);
if (GV->hasInitializer()) {
assert(getSymbolPreferLocal(*GV) == Sym);
emitLinkage(GV, Sym);
- getTargetStreamer()->emitGlobalType(Sym);
OutStreamer->emitLabel(Sym);
// TODO: Actually emit the initializer value. Otherwise the global has the
// default value for its type (0, ref.null, etc).
@@ -271,31 +271,47 @@ MCSymbol *WebAssemblyAsmPrinter::getOrCreateWasmSymbol(StringRef Name) {
return WasmSym;
}
+void WebAssemblyAsmPrinter::emitSymbolType(const MCSymbolWasm *Sym) {
+ Optional<wasm::WasmSymbolType> WasmTy = Sym->getType();
+ if (!WasmTy)
+ return;
+
+ switch (WasmTy.getValue()) {
+ case wasm::WASM_SYMBOL_TYPE_GLOBAL:
+ getTargetStreamer()->emitGlobalType(Sym);
+ break;
+ case wasm::WASM_SYMBOL_TYPE_TAG:
+ getTargetStreamer()->emitTagType(Sym);
+ break;
+ case wasm::WASM_SYMBOL_TYPE_TABLE:
+ getTargetStreamer()->emitTableType(Sym);
+ break;
+ default:
+ break; // We only handle globals, tags and tables here
+ }
+}
+
void WebAssemblyAsmPrinter::emitExternalDecls(const Module &M) {
if (signaturesEmitted)
return;
signaturesEmitted = true;
// Normally symbols for globals get discovered as the MI gets lowered,
- // but we need to know about them ahead of time.
+ // but we need to know about them ahead of time. This will however,
+ // only find symbols that have been used. Unused symbols from globals will
+ // not be found here.
MachineModuleInfoWasm &MMIW = MMI->getObjFileInfo<MachineModuleInfoWasm>();
for (const auto &Name : MMIW.MachineSymbolsUsed) {
getOrCreateWasmSymbol(Name.getKey());
}
for (auto &It : OutContext.getSymbols()) {
- // Emit .globaltype, .tagtype, or .tabletype declarations.
+ // Emit .globaltype, .tagtype, or .tabletype declarations for extern
+ // declarations, i.e. those that have only been declared (but not defined)
+ // in the current module
auto Sym = cast<MCSymbolWasm>(It.getValue());
- if (Sym->getType() == wasm::WASM_SYMBOL_TYPE_GLOBAL) {
- // .globaltype already handled by emitGlobalVariable for defined
- // variables; here we make sure the types of external wasm globals get
- // written to the file.
- if (Sym->isUndefined())
- getTargetStreamer()->emitGlobalType(Sym);
- } else if (Sym->getType() == wasm::WASM_SYMBOL_TYPE_TAG)
- getTargetStreamer()->emitTagType(Sym);
- else if (Sym->getType() == wasm::WASM_SYMBOL_TYPE_TABLE)
- getTargetStreamer()->emitTableType(Sym);
+ if (!Sym->isDefined())
+ emitSymbolType(Sym);
}
DenseSet<MCSymbol *> InvokeSymbols;
@@ -362,8 +378,11 @@ void WebAssemblyAsmPrinter::emitExternalDecls(const Module &M) {
}
}
}
-
+
void WebAssemblyAsmPrinter::emitEndOfAsmFile(Module &M) {
+ // This is required to emit external declarations (like .functypes) when
+ // no functions are defined in the compilation unit and therefore,
+ // emitExternalDecls() is not called until now.
emitExternalDecls(M);
// When a function's address is taken, a TABLE_INDEX relocation is emitted
@@ -532,6 +551,7 @@ void WebAssemblyAsmPrinter::EmitTargetFeatures(Module &M) {
}
void WebAssemblyAsmPrinter::emitConstantPool() {
+ emitExternalDecls(*MMI->getModule());
assert(MF->getConstantPool()->getConstants().empty() &&
"WebAssembly disables constant pools");
}
@@ -540,17 +560,6 @@ void WebAssemblyAsmPrinter::emitJumpTableInfo() {
// Nothing to do; jump tables are incorporated into the instruction stream.
}
-void WebAssemblyAsmPrinter::emitLinkage(const GlobalValue *GV, MCSymbol *Sym)
- const {
- AsmPrinter::emitLinkage(GV, Sym);
- // This gets called before the function label and type are emitted.
- // We use it to emit signatures of external functions.
- // FIXME casts!
- const_cast<WebAssemblyAsmPrinter *>(this)
- ->emitExternalDecls(*MMI->getModule());
-}
-
-
void WebAssemblyAsmPrinter::emitFunctionBodyStart() {
const Function &F = MF->getFunction();
SmallVector<MVT, 1> ResultVTs;