quantum created this revision.
quantum added reviewers: tlively, aheejin, sbc100, sunfish, alexcrichton.
Herald added subscribers: llvm-commits, cfe-commits, hiraditya, 
jgravelle-google, dschuff.
Herald added projects: clang, LLVM.

Add immutable WASM global `__tls_align` which stores the alignment
requirements of the TLS segment.

Add `__builtin_wasm_tls_align()` intrinsic to get this alignment in Clang.

The expected usage has now changed to:

  __wasm_init_tls(memalign(__builtin_wasm_tls_align(),
                           __builtin_wasm_tls_size()));


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D65028

Files:
  clang/include/clang/Basic/BuiltinsWebAssembly.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/test/CodeGen/builtins-wasm.c
  lld/test/wasm/tls-align.ll
  lld/test/wasm/tls.ll
  lld/wasm/Driver.cpp
  lld/wasm/Symbols.cpp
  lld/wasm/Symbols.h
  lld/wasm/Writer.cpp
  llvm/include/llvm/IR/IntrinsicsWebAssembly.td
  llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
  llvm/test/CodeGen/WebAssembly/tls-general-dynamic.ll

Index: llvm/test/CodeGen/WebAssembly/tls-general-dynamic.ll
===================================================================
--- llvm/test/CodeGen/WebAssembly/tls-general-dynamic.ll
+++ llvm/test/CodeGen/WebAssembly/tls-general-dynamic.ll
@@ -75,6 +75,15 @@
   ret i32 %1
 }
 
+; CHECK-LABEL: tls_align:
+; CHECK-NEXT: .functype tls_align () -> (i32)
+define i32 @tls_align() {
+; CHECK-NEXT: global.get __tls_align
+; CHECK-NEXT: return
+  %1 = call i32 @llvm.wasm.tls.align.i32()
+  ret i32 %1
+}
+
 ; CHECK-LABEL: tls_base:
 ; CHECK-NEXT: .functype tls_base () -> (i32)
 define i8* @tls_base() {
@@ -104,4 +113,5 @@
 @tls = internal thread_local global i32 0
 
 declare i32 @llvm.wasm.tls.size.i32()
+declare i32 @llvm.wasm.tls.align.i32()
 declare i8* @llvm.wasm.tls.base()
Index: llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
===================================================================
--- llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
+++ llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
@@ -79,7 +79,7 @@
   // Clang-provided symbols.
   if (strcmp(Name, "__stack_pointer") == 0 || strcmp(Name, "__tls_base") == 0 ||
       strcmp(Name, "__memory_base") == 0 || strcmp(Name, "__table_base") == 0 ||
-      strcmp(Name, "__tls_size") == 0) {
+      strcmp(Name, "__tls_size") == 0 || strcmp(Name, "__tls_align") == 0) {
     bool Mutable =
         strcmp(Name, "__stack_pointer") == 0 || strcmp(Name, "__tls_base") == 0;
     WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL);
Index: llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
===================================================================
--- llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
+++ llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
@@ -224,6 +224,16 @@
       ReplaceNode(Node, TLSSize);
       return;
     }
+    case Intrinsic::wasm_tls_align: {
+      MVT PtrVT = TLI->getPointerTy(CurDAG->getDataLayout());
+      assert(PtrVT == MVT::i32 && "only wasm32 is supported for now");
+
+      MachineSDNode *TLSAlign = CurDAG->getMachineNode(
+          WebAssembly::GLOBAL_GET_I32, DL, PtrVT,
+          CurDAG->getTargetExternalSymbol("__tls_align", MVT::i32));
+      ReplaceNode(Node, TLSAlign);
+      return;
+    }
     }
     break;
   }
Index: llvm/include/llvm/IR/IntrinsicsWebAssembly.td
===================================================================
--- llvm/include/llvm/IR/IntrinsicsWebAssembly.td
+++ llvm/include/llvm/IR/IntrinsicsWebAssembly.td
@@ -133,6 +133,11 @@
             [],
             [IntrNoMem, IntrSpeculatable]>;
 
+def int_wasm_tls_align :
+  Intrinsic<[llvm_anyint_ty],
+            [],
+            [IntrNoMem, IntrSpeculatable]>;
+
 def int_wasm_tls_base :
   Intrinsic<[llvm_ptr_ty],
             [],
Index: lld/wasm/Writer.cpp
===================================================================
--- lld/wasm/Writer.cpp
+++ lld/wasm/Writer.cpp
@@ -247,6 +247,9 @@
     if (WasmSym::tlsSize && seg->name == ".tdata") {
       auto *tlsSize = cast<DefinedGlobal>(WasmSym::tlsSize);
       tlsSize->global->global.InitExpr.Value.Int32 = seg->size;
+
+      auto *tlsAlign = cast<DefinedGlobal>(WasmSym::tlsAlign);
+      tlsAlign->global->global.InitExpr.Value.Int32 = 1U << seg->alignment;
     }
   }
 
Index: lld/wasm/Symbols.h
===================================================================
--- lld/wasm/Symbols.h
+++ lld/wasm/Symbols.h
@@ -435,6 +435,10 @@
   // Symbol whose value is the size of the TLS block.
   static GlobalSymbol *tlsSize;
 
+  // __tls_size
+  // Symbol whose value is the alignment of the TLS block.
+  static GlobalSymbol *tlsAlign;
+
   // __data_end
   // Symbol marking the end of the data and bss.
   static DefinedData *dataEnd;
Index: lld/wasm/Symbols.cpp
===================================================================
--- lld/wasm/Symbols.cpp
+++ lld/wasm/Symbols.cpp
@@ -35,6 +35,7 @@
 GlobalSymbol *WasmSym::stackPointer;
 GlobalSymbol *WasmSym::tlsBase;
 GlobalSymbol *WasmSym::tlsSize;
+GlobalSymbol *WasmSym::tlsAlign;
 UndefinedGlobal *WasmSym::tableBase;
 UndefinedGlobal *WasmSym::memoryBase;
 
Index: lld/wasm/Driver.cpp
===================================================================
--- lld/wasm/Driver.cpp
+++ lld/wasm/Driver.cpp
@@ -450,6 +450,16 @@
   return sym;
 }
 
+static GlobalSymbol *createGlobalVariable(StringRef name, bool isMutable) {
+  llvm::wasm::WasmGlobal wasmGlobal;
+  wasmGlobal.Type = {WASM_TYPE_I32, isMutable};
+  wasmGlobal.InitExpr.Value.Int32 = 0;
+  wasmGlobal.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
+  wasmGlobal.SymbolName = name;
+  return symtab->addSyntheticGlobal(name, WASM_SYMBOL_VISIBILITY_HIDDEN,
+                                    make<InputGlobal>(wasmGlobal, nullptr));
+}
+
 // Create ABI-defined synthetic symbols
 static void createSyntheticSymbols() {
   static WasmSignature nullSignature = {{}, {}};
@@ -517,24 +527,9 @@
   }
 
   if (config->sharedMemory && !config->shared) {
-    llvm::wasm::WasmGlobal tlsBaseGlobal;
-    tlsBaseGlobal.Type = {WASM_TYPE_I32, true};
-    tlsBaseGlobal.InitExpr.Value.Int32 = 0;
-    tlsBaseGlobal.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
-    tlsBaseGlobal.SymbolName = "__tls_base";
-    WasmSym::tlsBase =
-        symtab->addSyntheticGlobal("__tls_base", WASM_SYMBOL_VISIBILITY_HIDDEN,
-                                   make<InputGlobal>(tlsBaseGlobal, nullptr));
-
-    llvm::wasm::WasmGlobal tlsSizeGlobal;
-    tlsSizeGlobal.Type = {WASM_TYPE_I32, false};
-    tlsSizeGlobal.InitExpr.Value.Int32 = 0;
-    tlsSizeGlobal.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
-    tlsSizeGlobal.SymbolName = "__tls_size";
-    WasmSym::tlsSize =
-        symtab->addSyntheticGlobal("__tls_size", WASM_SYMBOL_VISIBILITY_HIDDEN,
-                                   make<InputGlobal>(tlsSizeGlobal, nullptr));
-
+    WasmSym::tlsBase = createGlobalVariable("__tls_base", true);
+    WasmSym::tlsSize = createGlobalVariable("__tls_size", false);
+    WasmSym::tlsAlign = createGlobalVariable("__tls_align", false);
     WasmSym::initTLS = symtab->addSyntheticFunction(
         "__wasm_init_tls", WASM_SYMBOL_VISIBILITY_HIDDEN,
         make<SyntheticFunction>(i32ArgSignature, "__wasm_init_tls"));
Index: lld/test/wasm/tls.ll
===================================================================
--- lld/test/wasm/tls.ll
+++ lld/test/wasm/tls.ll
@@ -14,6 +14,13 @@
   ret i32* @tls2
 }
 
+define i32 @tls_align() {
+  %1 = call i32 @llvm.wasm.tls.align.i32()
+  ret i32 %1
+}
+
+declare i32 @llvm.wasm.tls.align.i32()
+
 ; RUN: wasm-ld -no-gc-sections --shared-memory --max-memory=131072 --no-entry -o %t.wasm %t.o
 ; RUN: obj2yaml %t.wasm | FileCheck %s
 
@@ -28,12 +35,16 @@
 ; CHECK-NEXT:       InitExpr:
 ; CHECK-NEXT:         Opcode:          I32_CONST
 ; CHECK-NEXT:         Value:           66576
+
+; __tls_base
 ; CHECK-NEXT:     - Index:           1
 ; CHECK-NEXT:       Type:            I32
 ; CHECK-NEXT:       Mutable:         true
 ; CHECK-NEXT:       InitExpr:
 ; CHECK-NEXT:         Opcode:          I32_CONST
 ; CHECK-NEXT:         Value:           0
+
+; __tls_size
 ; CHECK-NEXT:     - Index:           2
 ; CHECK-NEXT:       Type:            I32
 ; CHECK-NEXT:       Mutable:         false
@@ -41,6 +52,14 @@
 ; CHECK-NEXT:         Opcode:          I32_CONST
 ; CHECK-NEXT:         Value:           8
 
+; __tls_align
+; CHECK-NEXT:     - Index:           3
+; CHECK-NEXT:       Type:            I32
+; CHECK-NEXT:       Mutable:         false
+; CHECK-NEXT:       InitExpr:
+; CHECK-NEXT:         Opcode:          I32_CONST
+; CHECK-NEXT:         Value:           4
+
 
 ; CHECK:      - Type:            CODE
 ; CHECK-NEXT:   Functions:
@@ -77,3 +96,11 @@
 ;   i32.const 4
 ;   i32.add
 ;   end
+
+; CHECK-NEXT:     - Index:           5
+; CHECK-NEXT:       Locals:          []
+; CHECK-NEXT:       Body:            2383808080000B
+
+; Expected body of tls1_addr:
+;   global.get 3
+;   end
Index: lld/test/wasm/tls-align.ll
===================================================================
--- lld/test/wasm/tls-align.ll
+++ lld/test/wasm/tls-align.ll
@@ -4,7 +4,7 @@
 
 @no_tls = global i32 0, align 4
 @tls1 = thread_local(localexec) global i32 1, align 4
-@tls2 = thread_local(localexec) global i32 1, align 4
+@tls2 = thread_local(localexec) global i32 1, align 16
 
 define i32* @tls1_addr() {
   ret i32* @tls1
@@ -17,9 +17,6 @@
 ; RUN: wasm-ld -no-gc-sections --shared-memory --max-memory=131072 --no-entry -o %t.wasm %t.o
 ; RUN: obj2yaml %t.wasm | FileCheck %s
 
-; RUN: wasm-ld -no-gc-sections --shared-memory --max-memory=131072 --no-merge-data-segments --no-entry -o %t.wasm %t.o
-; RUN: obj2yaml %t.wasm | FileCheck %s
-
 ; CHECK:      - Type:            GLOBAL
 ; CHECK-NEXT:   Globals:
 ; CHECK-NEXT:     - Index:           0
@@ -27,53 +24,28 @@
 ; CHECK-NEXT:       Mutable:         true
 ; CHECK-NEXT:       InitExpr:
 ; CHECK-NEXT:         Opcode:          I32_CONST
-; CHECK-NEXT:         Value:           66576
+; CHECK-NEXT:         Value:           66608
+
+; __tls_base
 ; CHECK-NEXT:     - Index:           1
 ; CHECK-NEXT:       Type:            I32
 ; CHECK-NEXT:       Mutable:         true
 ; CHECK-NEXT:       InitExpr:
 ; CHECK-NEXT:         Opcode:          I32_CONST
 ; CHECK-NEXT:         Value:           0
+
+; __tls_size
 ; CHECK-NEXT:     - Index:           2
 ; CHECK-NEXT:       Type:            I32
 ; CHECK-NEXT:       Mutable:         false
 ; CHECK-NEXT:       InitExpr:
 ; CHECK-NEXT:         Opcode:          I32_CONST
-; CHECK-NEXT:         Value:           8
-
-
-; CHECK:      - Type:            CODE
-; CHECK-NEXT:   Functions:
-; Skip __wasm_call_ctors and __wasm_init_memory
-; CHECK:          - Index:           2
-; CHECK-NEXT:       Locals:          []
-; CHECK-NEXT:       Body:            20002401200041004108FC0801000B
-
-; Expected body of __wasm_init_tls:
-;   local.get 0
-;   global.set  1
-;   local.get 0
-;   i32.const 0
-;   i32.const 8
-;   memory.init 1, 0
-;   end
+; CHECK-NEXT:         Value:           20
 
+; __tls_align
 ; CHECK-NEXT:     - Index:           3
-; CHECK-NEXT:       Locals:          []
-; CHECK-NEXT:       Body:            2381808080004180808080006A0B
-
-; Expected body of tls1_addr:
-;   global.get 1
-;   i32.const 0
-;   i32.add
-;   end
-
-; CHECK-NEXT:     - Index:           4
-; CHECK-NEXT:       Locals:          []
-; CHECK-NEXT:       Body:            2381808080004184808080006A0B
-
-; Expected body of tls1_addr:
-;   global.get 1
-;   i32.const 4
-;   i32.add
-;   end
+; CHECK-NEXT:       Type:            I32
+; CHECK-NEXT:       Mutable:         false
+; CHECK-NEXT:       InitExpr:
+; CHECK-NEXT:         Opcode:          I32_CONST
+; CHECK-NEXT:         Value:           16
Index: clang/test/CodeGen/builtins-wasm.c
===================================================================
--- clang/test/CodeGen/builtins-wasm.c
+++ clang/test/CodeGen/builtins-wasm.c
@@ -44,6 +44,12 @@
   // WEBASSEMBLY64: call i64 @llvm.wasm.tls.size.i64()
 }
 
+__SIZE_TYPE__ tls_align() {
+  return __builtin_wasm_tls_align();
+  // WEBASSEMBLY32: call i32 @llvm.wasm.tls.align.i32()
+  // WEBASSEMBLY64: call i64 @llvm.wasm.tls.align.i64()
+}
+
 void *tls_base() {
   return __builtin_wasm_tls_base();
   // WEBASSEMBLY: call i8* @llvm.wasm.tls.base()
Index: clang/lib/CodeGen/CGBuiltin.cpp
===================================================================
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -13924,6 +13924,11 @@
     Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_tls_size, ResultType);
     return Builder.CreateCall(Callee);
   }
+  case WebAssembly::BI__builtin_wasm_tls_align: {
+    llvm::Type *ResultType = ConvertType(E->getType());
+    Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_tls_align, ResultType);
+    return Builder.CreateCall(Callee);
+  }
   case WebAssembly::BI__builtin_wasm_tls_base: {
     Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_tls_base);
     return Builder.CreateCall(Callee);
Index: clang/include/clang/Basic/BuiltinsWebAssembly.def
===================================================================
--- clang/include/clang/Basic/BuiltinsWebAssembly.def
+++ clang/include/clang/Basic/BuiltinsWebAssembly.def
@@ -31,6 +31,7 @@
 
 // Thread-local storage
 TARGET_BUILTIN(__builtin_wasm_tls_size, "z", "nc", "bulk-memory")
+TARGET_BUILTIN(__builtin_wasm_tls_align, "z", "nc", "bulk-memory")
 TARGET_BUILTIN(__builtin_wasm_tls_base, "v*", "nU", "bulk-memory")
 
 // Floating point min/max
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to