return WasmSym;
}
+void WebAssemblyAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
+ if (!WebAssembly::isWasmVarAddressSpace(GV->getAddressSpace())) {
+ AsmPrinter::emitGlobalVariable(GV);
+ return;
+ }
+
+ assert(!GV->isThreadLocal());
+
+ MCSymbolWasm *Sym = cast<MCSymbolWasm>(getSymbol(GV));
+
+ if (!Sym->getType()) {
+ const WebAssemblyTargetLowering &TLI = *Subtarget->getTargetLowering();
+ SmallVector<EVT, 1> 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);
+ // TODO: Actually emit the initializer value. Otherwise the global has the
+ // default value for its type (0, ref.null, etc).
+ OutStreamer->AddBlankLine();
+ }
+}
+
void WebAssemblyAsmPrinter::emitEndOfAsmFile(Module &M) {
for (auto &It : OutContext.getSymbols()) {
// Emit .globaltype, .eventtype, or .tabletype declarations.
auto Sym = cast<MCSymbolWasm>(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; 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_EVENT)
getTargetStreamer()->emitEventType(Sym);
else if (Sym->getType() == wasm::WASM_SYMBOL_TYPE_TABLE)
getTargetStreamer()->emitTableType(Sym);
}
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::isWasmVarAddressSpace(G.getAddressSpace()) &&
+ G.getValueType()->isSized()) {
+ uint16_t Size = M.getDataLayout().getTypeAllocSize(G.getValueType());
+ OutStreamer->emitELFSize(getSymbol(&G),
+ MCConstantExpr::create(Size, OutContext));
}
}
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;
#include "WebAssemblyMCInstLower.h"
#include "TargetInfo/WebAssemblyTargetInfo.h"
#include "Utils/WebAssemblyTypeUtilities.h"
+#include "Utils/WebAssemblyUtilities.h"
#include "WebAssemblyAsmPrinter.h"
#include "WebAssemblyMachineFunctionInfo.h"
#include "WebAssemblyRuntimeLibcallSignatures.h"
MCSymbol *
WebAssemblyMCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const {
const GlobalValue *Global = MO.getGlobal();
- if (!isa<Function>(Global))
- return cast<MCSymbolWasm>(Printer.getSymbol(Global));
+ if (!isa<Function>(Global)) {
+ auto *WasmSym = cast<MCSymbolWasm>(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::isWasmVarAddressSpace(Global->getAddressSpace()) &&
+ !WasmSym->getType()) {
+ const MachineFunction &MF = *MO.getParent()->getParent()->getParent();
+ const TargetMachine &TM = MF.getTarget();
+ const Function &CurrentFunc = MF.getFunction();
+ SmallVector<MVT, 1> 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<FunctionType>(Global->getValueType());
const MachineFunction &MF = *MO.getParent()->getParent()->getParent();
@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)
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:
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: