forked from OSchip/llvm-project
[CodeGen][WebAssembly] Better lowering for WASM_SYMBOL_TYPE_GLOBAL symbols
As we have been missing support for WebAssembly globals on the IR level, the lowering of WASM_SYMBOL_TYPE_GLOBAL to IR was incomplete. This commit fleshes out the lowering support, lowering references to and definitions of addrspace(1) values to correctly typed WASM_SYMBOL_TYPE_GLOBAL symbols. Depends on D101608. Differential Revision: https://reviews.llvm.org/D101913
This commit is contained in:
parent
b159987054
commit
b2f21b145a
|
@ -170,13 +170,54 @@ MCSymbolWasm *WebAssemblyAsmPrinter::getMCSymbolForFunction(
|
|||
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);
|
||||
|
@ -262,12 +303,12 @@ void WebAssemblyAsmPrinter::emitEndOfAsmFile(Module &M) {
|
|||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@ public:
|
|||
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;
|
||||
|
|
|
@ -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 @@ static void removeRegisterOperands(const MachineInstr *MI, MCInst &OutMI);
|
|||
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();
|
||||
|
|
|
@ -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 @@ define double @return_f64_global() {
|
|||
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
|
||||
}
|
||||
|
||||
;; 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:
|
||||
|
||||
; CHECK-NOT: .global i32_external_used
|
||||
; CHECK: .globaltype i32_external_used, i32
|
||||
; CHECK-NOT: i32_external_used:
|
||||
|
||||
; CHECK-NOT: .global i32_external_unused
|
||||
; CHECK: .globaltype i32_external_unused, i32
|
||||
; CHECK-NOT: i32_external_unused:
|
||||
|
|
|
@ -45,13 +45,18 @@ define void @set_f64_global(double %v) {
|
|||
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:
|
||||
|
|
Loading…
Reference in New Issue