diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h --- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h @@ -65,6 +65,7 @@ void emitEndOfAsmFile(Module &M) override; void EmitProducerInfo(Module &M); void EmitTargetFeatures(Module &M); + void emitGlobalVariable(const GlobalVariable *GV) override; void emitJumpTableInfo() override; void emitConstantPool() override; void emitFunctionBodyStart() override; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp @@ -170,13 +170,51 @@ return WasmSym; } +void WebAssemblyAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) { + if (!WebAssembly::isObjectAddressSpace(GV->getAddressSpace())) { + AsmPrinter::emitGlobalVariable(GV); + return; + } + + assert(!GV->isThreadLocal()); + + MCSymbolWasm *Sym = cast(getSymbol(GV)); + + if (!Sym->getType()) { + const WebAssemblyTargetLowering &TLI = *Subtarget->getTargetLowering(); + SmallVector VTs; + ComputeValueVTs(TLI, GV->getParent()->getDataLayout(), GV->getValueType(), + VTs); + if (VTs.size() != 1 || + TLI.getNumRegisters(GV->getParent()->getContext(), VTs[0]) != 1) + report_fatal_error("Aggregate globals not yet implemented"); + MVT VT = TLI.getRegisterType(GV->getParent()->getContext(), VTs[0]); + bool Mutable = true; + wasm::ValType Type = WebAssembly::toValType(VT); + Sym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL); + Sym->setGlobalType(wasm::WasmGlobalType{uint8_t(Type), Mutable}); + } + + emitVisibility(Sym, GV->getVisibility(), !GV->isDeclaration()); + if (GV->hasInitializer()) { + assert(getSymbolPreferLocal(*GV) == Sym); + emitLinkage(GV, Sym); + getTargetStreamer()->emitGlobalType(Sym); + OutStreamer->emitLabel(Sym); + OutStreamer->AddBlankLine(); + } +} + void WebAssemblyAsmPrinter::emitEndOfAsmFile(Module &M) { for (auto &It : OutContext.getSymbols()) { // Emit .globaltype, .eventtype, or .tabletype declarations. auto Sym = cast(It.getValue()); - if (Sym->getType() == wasm::WASM_SYMBOL_TYPE_GLOBAL) - getTargetStreamer()->emitGlobalType(Sym); - else if (Sym->getType() == wasm::WASM_SYMBOL_TYPE_EVENT) + if (Sym->getType() == wasm::WASM_SYMBOL_TYPE_GLOBAL) { + // .globaltype already handled by emitGlobalVariable for defined + // variables. + if (Sym->isUndefined()) + getTargetStreamer()->emitGlobalType(Sym); + } else if (Sym->getType() == wasm::WASM_SYMBOL_TYPE_EVENT) getTargetStreamer()->emitEventType(Sym); else if (Sym->getType() == wasm::WASM_SYMBOL_TYPE_TABLE) getTargetStreamer()->emitTableType(Sym); @@ -262,12 +300,12 @@ } for (const auto &G : M.globals()) { - if (!G.hasInitializer() && G.hasExternalLinkage()) { - if (G.getValueType()->isSized()) { - uint16_t Size = M.getDataLayout().getTypeAllocSize(G.getValueType()); - OutStreamer->emitELFSize(getSymbol(&G), - MCConstantExpr::create(Size, OutContext)); - } + if (!G.hasInitializer() && G.hasExternalLinkage() && + !WebAssembly::isObjectAddressSpace(G.getAddressSpace()) && + G.getValueType()->isSized()) { + uint16_t Size = M.getDataLayout().getTypeAllocSize(G.getValueType()); + OutStreamer->emitELFSize(getSymbol(&G), + MCConstantExpr::create(Size, OutContext)); } } diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp @@ -15,6 +15,7 @@ #include "WebAssemblyMCInstLower.h" #include "TargetInfo/WebAssemblyTargetInfo.h" #include "Utils/WebAssemblyTypeUtilities.h" +#include "Utils/WebAssemblyUtilities.h" #include "WebAssemblyAsmPrinter.h" #include "WebAssemblyMachineFunctionInfo.h" #include "WebAssemblyRuntimeLibcallSignatures.h" @@ -46,8 +47,28 @@ MCSymbol * WebAssemblyMCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const { const GlobalValue *Global = MO.getGlobal(); - if (!isa(Global)) - return cast(Printer.getSymbol(Global)); + if (!isa(Global)) { + auto *WasmSym = cast(Printer.getSymbol(Global)); + // If the symbol doesn't have an explicit WasmSymbolType yet and the + // GlobalValue is actually a WebAssembly global, then ensure the symbol is a + // WASM_SYMBOL_TYPE_GLOBAL. + if (WebAssembly::isObjectAddressSpace(Global->getAddressSpace()) && + !WasmSym->getType()) { + const MachineFunction &MF = *MO.getParent()->getParent()->getParent(); + const TargetMachine &TM = MF.getTarget(); + const Function &CurrentFunc = MF.getFunction(); + SmallVector VTs; + computeLegalValueVTs(CurrentFunc, TM, Global->getValueType(), VTs); + if (VTs.size() != 1) + report_fatal_error("Aggregate globals not yet implemented"); + + bool Mutable = true; + wasm::ValType Type = WebAssembly::toValType(VTs[0]); + WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL); + WasmSym->setGlobalType(wasm::WasmGlobalType{uint8_t(Type), Mutable}); + } + return WasmSym; + } const auto *FuncTy = cast(Global->getValueType()); const MachineFunction &MF = *MO.getParent()->getParent()->getParent(); diff --git a/llvm/test/CodeGen/WebAssembly/global-get.ll b/llvm/test/CodeGen/WebAssembly/global-get.ll --- a/llvm/test/CodeGen/WebAssembly/global-get.ll +++ b/llvm/test/CodeGen/WebAssembly/global-get.ll @@ -5,6 +5,9 @@ @f32_global = local_unnamed_addr addrspace(1) global float undef @f64_global = local_unnamed_addr addrspace(1) global double undef +@i32_external_used = external addrspace(1) global i32 +@i32_external_unused = external addrspace(1) global i32 + define i32 @return_i32_global() { ; CHECK-LABEL: return_i32_global: ; CHECK-NEXT: functype return_i32_global () -> (i32) @@ -41,14 +44,36 @@ ret double %v } +define i32 @return_extern_i32_global() { +; CHECK-LABEL: return_extern_i32_global: +; CHECK-NEXT: functype return_extern_i32_global () -> (i32) +; CHECK-NEXT: global.get i32_external_used +; CHECK-NEXT: end_function + %v = load i32, i32 addrspace(1)* @i32_external_used + ret i32 %v +} + + +; CHECK: .globl i32_global +; CHECK: .globaltype i32_global, i32 +; CHECK-LABEL: i32_global: + +; CHECK: .globl i64_global +; CHECK: .globaltype i64_global, i64 +; CHECK-LABEL: i64_global: + +; CHECK: .globl f32_global +; CHECK: .globaltype f32_global, f32 +; CHECK-LABEL: f32_global: + +; CHECK: .globl f64_global +; CHECK: .globaltype f64_global, f64 +; CHECK-LABEL: f64_global: + +; CHECK-NOT: .global i32_external_used +; CHECK: .globaltype i32_external_used, i32 +; CHECK-NOT: i32_external_used: -;; LLVM doesn't yet declare proper WebAssembly globals for these values, -;; instead placing them in linear memory. To fix in a followup. -; FIXME-CHECK: .globl i32_global -; FIXME-CHECK: .globaltype i32_global, i32 -; FIXME-CHECK: .globl i64_global -; FIXME-CHECK: .globaltype i64_global, i64 -; FIXME-CHECK: .globl f32_global -; FIXME-CHECK: .globaltype f32_global, f32 -; FIXME-CHECK: .globl f64_global -; FIXME-CHECK: .globaltype f64_global, f64 +; CHECK-NOT: .global i32_external_unused +; CHECK: .globaltype i32_external_unused, i32 +; CHECK-NOT: i32_external_unused: diff --git a/llvm/test/CodeGen/WebAssembly/global-set.ll b/llvm/test/CodeGen/WebAssembly/global-set.ll --- a/llvm/test/CodeGen/WebAssembly/global-set.ll +++ b/llvm/test/CodeGen/WebAssembly/global-set.ll @@ -45,13 +45,18 @@ ret void } -;; LLVM doesn't yet declare proper WebAssembly globals for these values, -;; instead placing them in linear memory. To fix in a followup. -; FIXME-CHECK: .globl i32_global -; FIXME-CHECK: .globaltype i32_global, i32 -; FIXME-CHECK: .globl i64_global -; FIXME-CHECK: .globaltype i64_global, i64 -; FIXME-CHECK: .globl f32_global -; FIXME-CHECK: .globaltype f32_global, f32 -; FIXME-CHECK: .globl f64_global -; FIXME-CHECK: .globaltype f64_global, f64 +; CHECK: .globl i32_global +; CHECK: .globaltype i32_global, i32 +; CHECK-LABEL: i32_global: + +; CHECK: .globl i64_global +; CHECK: .globaltype i64_global, i64 +; CHECK-LABEL: i64_global: + +; CHECK: .globl f32_global +; CHECK: .globaltype f32_global, f32 +; CHECK-LABEL: f32_global: + +; CHECK: .globl f64_global +; CHECK: .globaltype f64_global, f64 +; CHECK-LABEL: f64_global: