[llvm] b2f21b1 - [CodeGen][WebAssembly] Better lowering for WASM_SYMBOL_TYPE_GLOBAL symbols

Andy Wingo via llvm-commits llvm-commits at lists.llvm.org
Tue May 11 02:48:39 PDT 2021


Author: Andy Wingo
Date: 2021-05-11T11:47:40+02:00
New Revision: b2f21b145aecbf5bc1af63b79de395897fc2e6f4

URL: https://github.com/llvm/llvm-project/commit/b2f21b145aecbf5bc1af63b79de395897fc2e6f4
DIFF: https://github.com/llvm/llvm-project/commit/b2f21b145aecbf5bc1af63b79de395897fc2e6f4.diff

LOG: [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

Added: 
    

Modified: 
    llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
    llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h
    llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
    llvm/test/CodeGen/WebAssembly/global-get.ll
    llvm/test/CodeGen/WebAssembly/global-set.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
index 1391f2eee17a..d9e56e9dceeb 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
@@ -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));
     }
   }
 

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h
index 7a6a3247a19f..99b6e1077f1d 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h
@@ -65,6 +65,7 @@ class LLVM_LIBRARY_VISIBILITY WebAssemblyAsmPrinter final : public AsmPrinter {
   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/WebAssemblyMCInstLower.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
index 84b459b6997d..2383416d8a92 100644
--- 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 @@ 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();

diff  --git a/llvm/test/CodeGen/WebAssembly/global-get.ll b/llvm/test/CodeGen/WebAssembly/global-get.ll
index d683fe677864..a9b07657fbf5 100644
--- 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
 
+ at i32_external_used = external addrspace(1) global i32
+ at 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
+}
+
+
+; 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
index 741fda632afd..54034e476fd6 100644
--- a/llvm/test/CodeGen/WebAssembly/global-set.ll
+++ b/llvm/test/CodeGen/WebAssembly/global-set.ll
@@ -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:


        


More information about the llvm-commits mailing list