[PATCH] D66255: [WebAssembly] Correctly handle va_arg of zero-sized structures

2019-08-15 Thread Guanzhong Chen via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL369042: [WebAssembly] Correctly handle va_arg of zero-sized 
structures (authored by quantum, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D66255?vs=215272=215455#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66255/new/

https://reviews.llvm.org/D66255

Files:
  cfe/trunk/lib/CodeGen/TargetInfo.cpp
  cfe/trunk/test/CodeGen/wasm-varargs.c


Index: cfe/trunk/lib/CodeGen/TargetInfo.cpp
===
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp
@@ -833,8 +833,9 @@
 
 Address WebAssemblyABIInfo::EmitVAArg(CodeGenFunction , Address VAListAddr,
   QualType Ty) const {
-  bool IsIndirect =
-  isAggregateTypeForABI(Ty) && !isSingleElementStruct(Ty, getContext());
+  bool IsIndirect = isAggregateTypeForABI(Ty) &&
+!isEmptyRecord(getContext(), Ty, true) &&
+!isSingleElementStruct(Ty, getContext());
   return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect,
   getContext().getTypeInfoInChars(Ty),
   CharUnits::fromQuantity(4),
Index: cfe/trunk/test/CodeGen/wasm-varargs.c
===
--- cfe/trunk/test/CodeGen/wasm-varargs.c
+++ cfe/trunk/test/CodeGen/wasm-varargs.c
@@ -80,21 +80,61 @@
   return v;
 }
 
-// CHECK: define void @test_struct([[STRUCT_S:%[^,=]+]]*{{.*}} noalias sret 
[[AGG_RESULT:%.*]], i8*{{.*}} %fmt, ...) {{.*}} {
-// CHECK:   [[FMT_ADDR:%[^,=]+]] = alloca i8*, align 4
-// CHECK:   [[VA:%[^,=]+]] = alloca i8*, align 4
-// CHECK:   store i8* %fmt, i8** [[FMT_ADDR]], align 4
-// CHECK:   [[VA1:%[^,=]+]] = bitcast i8** [[VA]] to i8*
-// CHECK:   call void @llvm.va_start(i8* [[VA1]])
-// CHECK:   [[ARGP_CUR:%[^,=]+]] = load i8*, i8** [[VA]], align 4
-// CHECK:   [[ARGP_NEXT:%[^,=]+]] = getelementptr inbounds i8, i8* 
[[ARGP_CUR]], i32 4
-// CHECK:   store i8* [[ARGP_NEXT]], i8** [[VA]], align 4
-// CHECK:   [[R3:%[^,=]+]] = bitcast i8* [[ARGP_CUR]] to [[STRUCT_S]]**
-// CHECK:   [[R4:%[^,=]+]] = load [[STRUCT_S]]*, [[STRUCT_S]]** %0, align 4
-// CHECK:   [[R5:%[^,=]+]] = bitcast [[STRUCT_S]]* [[AGG_RESULT]] to i8*
-// CHECK:   [[R6:%[^,=]+]] = bitcast [[STRUCT_S]]* [[R4]] to i8*
-// CHECK:   call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 [[R5]], i8* align 
4 [[R6]], i32 12, i1 false)
-// CHECK:   [[VA2:%[^,=]+]] = bitcast i8** [[VA]] to i8*
-// CHECK:   call void @llvm.va_end(i8* [[VA2]])
-// CHECK:   ret void
-// CHECK: }
+// CHECK:  define void @test_struct([[STRUCT_S:%[^,=]+]]*{{.*}} noalias 
sret [[AGG_RESULT:%.*]], i8*{{.*}} %fmt, ...) {{.*}} {
+// CHECK:[[FMT_ADDR:%[^,=]+]] = alloca i8*, align 4
+// CHECK-NEXT:   [[VA:%[^,=]+]] = alloca i8*, align 4
+// CHECK-NEXT:   store i8* %fmt, i8** [[FMT_ADDR]], align 4
+// CHECK-NEXT:   [[VA1:%[^,=]+]] = bitcast i8** [[VA]] to i8*
+// CHECK-NEXT:   call void @llvm.va_start(i8* [[VA1]])
+// CHECK-NEXT:   [[ARGP_CUR:%[^,=]+]] = load i8*, i8** [[VA]], align 4
+// CHECK-NEXT:   [[ARGP_NEXT:%[^,=]+]] = getelementptr inbounds i8, i8* 
[[ARGP_CUR]], i32 4
+// CHECK-NEXT:   store i8* [[ARGP_NEXT]], i8** [[VA]], align 4
+// CHECK-NEXT:   [[R3:%[^,=]+]] = bitcast i8* [[ARGP_CUR]] to [[STRUCT_S]]**
+// CHECK-NEXT:   [[R4:%[^,=]+]] = load [[STRUCT_S]]*, [[STRUCT_S]]** [[R3]], 
align 4
+// CHECK-NEXT:   [[R5:%[^,=]+]] = bitcast [[STRUCT_S]]* [[AGG_RESULT]] to i8*
+// CHECK-NEXT:   [[R6:%[^,=]+]] = bitcast [[STRUCT_S]]* [[R4]] to i8*
+// CHECK-NEXT:   call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 [[R5]], i8* 
align 4 [[R6]], i32 12, i1 false)
+// CHECK-NEXT:   [[VA2:%[^,=]+]] = bitcast i8** [[VA]] to i8*
+// CHECK-NEXT:   call void @llvm.va_end(i8* [[VA2]])
+// CHECK-NEXT:   ret void
+// CHECK-NEXT: }
+
+struct Z {};
+
+struct S test_empty_struct(char *fmt, ...) {
+  va_list va;
+
+  va_start(va, fmt);
+  struct Z u = va_arg(va, struct Z);
+  struct S v = va_arg(va, struct S);
+  va_end(va);
+
+  return v;
+}
+
+// CHECK:  define void @test_empty_struct([[STRUCT_S:%[^,=]+]]*{{.*}} 
noalias sret [[AGG_RESULT:%.*]], i8*{{.*}} %fmt, ...) {{.*}} {
+// CHECK:[[FMT_ADDR:%[^,=]+]] = alloca i8*, align 4
+// CHECK-NEXT:   [[VA:%[^,=]+]] = alloca i8*, align 4
+// CHECK-NEXT:   [[U:%[^,=]+]] = alloca [[STRUCT_Z:%[^,=]+]], align 1
+// CHECK-NEXT:   store i8* %fmt, i8** [[FMT_ADDR]], align 4
+// CHECK-NEXT:   [[VA1:%[^,=]+]] = bitcast i8** [[VA]] to i8*
+// CHECK-NEXT:   call void @llvm.va_start(i8* [[VA1]])
+// CHECK-NEXT:   [[ARGP_CUR:%[^,=]+]] = load i8*, i8** [[VA]], align 4
+// CHECK-NEXT:   [[ARGP_NEXT:%[^,=]+]] = getelementptr inbounds i8, i8* 
[[ARGP_CUR]], i32 0
+// CHECK-NEXT:   store i8* [[ARGP_NEXT]], i8** [[VA]], align 4
+// CHECK-NEXT:   [[R0:%[^,=]+]] = 

[PATCH] D66255: [WebAssembly] Correctly handle va_arg of zero-sized structures

2019-08-14 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum added inline comments.



Comment at: clang/test/CodeGen/wasm-varargs.c:104
+
+struct S test_zero_size_struct(char *fmt, ...) {
+  va_list va;

dschuff wrote:
> This should maybe be called "test_empty_struct" since its size is actually 1 
> and not zero.
Done.



Comment at: clang/test/CodeGen/wasm-varargs.c:115
+
+// CHECK: define void @test_zero_size_struct([[STRUCT_S:%[^,=]+]]*{{.*}} 
noalias sret [[AGG_RESULT:%.*]], i8*{{.*}} %fmt, ...) {{.*}} {
+// CHECK:   [[FMT_ADDR:%[^,=]+]] = alloca i8*, align 4

dschuff wrote:
> could use CHECK_LABEL here and above.
Can't because the line has match patterns.



Comment at: clang/test/CodeGen/wasm-varargs.c:125
+// CHECK:   store i8* [[ARGP_NEXT]], i8** [[VA]], align 4
+// CHECK:   [[R0:%[^,=]+]] = bitcast i8* [[ARGP_CUR]] to [[STRUCT_Z]]*
+// CHECK:   [[R1:%[^,=]+]] = bitcast [[STRUCT_Z]]* [[U]] to i8*

dschuff wrote:
> It looks like most of the output (up to here) is boilerplate for va_arg setup 
> and duplicates the CHECKs above. It might be more clear if we just omitted 
> the duplicated stuff and only CHECK for the things that are different from 
> the above test.
We can't remove the duplicate checks for the second argument because the broken 
code resulted from the second argument being incorrectly read when the first 
argument is a blank structure.

Instead, I am changing the whole test to use `CHECK-NEXT` so we can be sure the 
exact generated code is correct.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66255/new/

https://reviews.llvm.org/D66255



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D66255: [WebAssembly] Correctly handle va_arg of zero-sized structures

2019-08-14 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum updated this revision to Diff 215272.
quantum marked 6 inline comments as done.
quantum added a comment.

Address review feedback.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66255/new/

https://reviews.llvm.org/D66255

Files:
  clang/lib/CodeGen/TargetInfo.cpp
  clang/test/CodeGen/wasm-varargs.c


Index: clang/test/CodeGen/wasm-varargs.c
===
--- clang/test/CodeGen/wasm-varargs.c
+++ clang/test/CodeGen/wasm-varargs.c
@@ -80,21 +80,61 @@
   return v;
 }
 
-// CHECK: define void @test_struct([[STRUCT_S:%[^,=]+]]*{{.*}} noalias sret 
[[AGG_RESULT:%.*]], i8*{{.*}} %fmt, ...) {{.*}} {
-// CHECK:   [[FMT_ADDR:%[^,=]+]] = alloca i8*, align 4
-// CHECK:   [[VA:%[^,=]+]] = alloca i8*, align 4
-// CHECK:   store i8* %fmt, i8** [[FMT_ADDR]], align 4
-// CHECK:   [[VA1:%[^,=]+]] = bitcast i8** [[VA]] to i8*
-// CHECK:   call void @llvm.va_start(i8* [[VA1]])
-// CHECK:   [[ARGP_CUR:%[^,=]+]] = load i8*, i8** [[VA]], align 4
-// CHECK:   [[ARGP_NEXT:%[^,=]+]] = getelementptr inbounds i8, i8* 
[[ARGP_CUR]], i32 4
-// CHECK:   store i8* [[ARGP_NEXT]], i8** [[VA]], align 4
-// CHECK:   [[R3:%[^,=]+]] = bitcast i8* [[ARGP_CUR]] to [[STRUCT_S]]**
-// CHECK:   [[R4:%[^,=]+]] = load [[STRUCT_S]]*, [[STRUCT_S]]** %0, align 4
-// CHECK:   [[R5:%[^,=]+]] = bitcast [[STRUCT_S]]* [[AGG_RESULT]] to i8*
-// CHECK:   [[R6:%[^,=]+]] = bitcast [[STRUCT_S]]* [[R4]] to i8*
-// CHECK:   call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 [[R5]], i8* align 
4 [[R6]], i32 12, i1 false)
-// CHECK:   [[VA2:%[^,=]+]] = bitcast i8** [[VA]] to i8*
-// CHECK:   call void @llvm.va_end(i8* [[VA2]])
-// CHECK:   ret void
-// CHECK: }
+// CHECK:  define void @test_struct([[STRUCT_S:%[^,=]+]]*{{.*}} noalias 
sret [[AGG_RESULT:%.*]], i8*{{.*}} %fmt, ...) {{.*}} {
+// CHECK:[[FMT_ADDR:%[^,=]+]] = alloca i8*, align 4
+// CHECK-NEXT:   [[VA:%[^,=]+]] = alloca i8*, align 4
+// CHECK-NEXT:   store i8* %fmt, i8** [[FMT_ADDR]], align 4
+// CHECK-NEXT:   [[VA1:%[^,=]+]] = bitcast i8** [[VA]] to i8*
+// CHECK-NEXT:   call void @llvm.va_start(i8* [[VA1]])
+// CHECK-NEXT:   [[ARGP_CUR:%[^,=]+]] = load i8*, i8** [[VA]], align 4
+// CHECK-NEXT:   [[ARGP_NEXT:%[^,=]+]] = getelementptr inbounds i8, i8* 
[[ARGP_CUR]], i32 4
+// CHECK-NEXT:   store i8* [[ARGP_NEXT]], i8** [[VA]], align 4
+// CHECK-NEXT:   [[R3:%[^,=]+]] = bitcast i8* [[ARGP_CUR]] to [[STRUCT_S]]**
+// CHECK-NEXT:   [[R4:%[^,=]+]] = load [[STRUCT_S]]*, [[STRUCT_S]]** [[R3]], 
align 4
+// CHECK-NEXT:   [[R5:%[^,=]+]] = bitcast [[STRUCT_S]]* [[AGG_RESULT]] to i8*
+// CHECK-NEXT:   [[R6:%[^,=]+]] = bitcast [[STRUCT_S]]* [[R4]] to i8*
+// CHECK-NEXT:   call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 [[R5]], i8* 
align 4 [[R6]], i32 12, i1 false)
+// CHECK-NEXT:   [[VA2:%[^,=]+]] = bitcast i8** [[VA]] to i8*
+// CHECK-NEXT:   call void @llvm.va_end(i8* [[VA2]])
+// CHECK-NEXT:   ret void
+// CHECK-NEXT: }
+
+struct Z {};
+
+struct S test_empty_struct(char *fmt, ...) {
+  va_list va;
+
+  va_start(va, fmt);
+  struct Z u = va_arg(va, struct Z);
+  struct S v = va_arg(va, struct S);
+  va_end(va);
+
+  return v;
+}
+
+// CHECK:  define void @test_empty_struct([[STRUCT_S:%[^,=]+]]*{{.*}} 
noalias sret [[AGG_RESULT:%.*]], i8*{{.*}} %fmt, ...) {{.*}} {
+// CHECK:[[FMT_ADDR:%[^,=]+]] = alloca i8*, align 4
+// CHECK-NEXT:   [[VA:%[^,=]+]] = alloca i8*, align 4
+// CHECK-NEXT:   [[U:%[^,=]+]] = alloca [[STRUCT_Z:%[^,=]+]], align 1
+// CHECK-NEXT:   store i8* %fmt, i8** [[FMT_ADDR]], align 4
+// CHECK-NEXT:   [[VA1:%[^,=]+]] = bitcast i8** [[VA]] to i8*
+// CHECK-NEXT:   call void @llvm.va_start(i8* [[VA1]])
+// CHECK-NEXT:   [[ARGP_CUR:%[^,=]+]] = load i8*, i8** [[VA]], align 4
+// CHECK-NEXT:   [[ARGP_NEXT:%[^,=]+]] = getelementptr inbounds i8, i8* 
[[ARGP_CUR]], i32 0
+// CHECK-NEXT:   store i8* [[ARGP_NEXT]], i8** [[VA]], align 4
+// CHECK-NEXT:   [[R0:%[^,=]+]] = bitcast i8* [[ARGP_CUR]] to [[STRUCT_Z]]*
+// CHECK-NEXT:   [[R1:%[^,=]+]] = bitcast [[STRUCT_Z]]* [[U]] to i8*
+// CHECK-NEXT:   [[R2:%[^,=]+]] = bitcast [[STRUCT_Z]]* [[R0]] to i8*
+// CHECK-NEXT:   call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 [[R1]], i8* 
align 4 [[R2]], i32 0, i1 false)
+// CHECK-NEXT:   [[ARGP_CUR2:%[^,=]+]] = load i8*, i8** [[VA]], align 4
+// CHECK-NEXT:   [[ARGP_NEXT2:%[^,=]+]] = getelementptr inbounds i8, i8* 
[[ARGP_CUR2]], i32 4
+// CHECK-NEXT:   store i8* [[ARGP_NEXT2]], i8** [[VA]], align 4
+// CHECK-NEXT:   [[R3:%[^,=]+]] = bitcast i8* [[ARGP_CUR2]] to [[STRUCT_S]]**
+// CHECK-NEXT:   [[R4:%[^,=]+]] = load [[STRUCT_S]]*, [[STRUCT_S]]** [[R3]], 
align 4
+// CHECK-NEXT:   [[R5:%[^,=]+]] = bitcast [[STRUCT_S]]* [[AGG_RESULT]] to i8*
+// CHECK-NEXT:   [[R6:%[^,=]+]] = bitcast [[STRUCT_S]]* [[R4]] to i8*
+// CHECK-NEXT:   call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 [[R5]], i8* 
align 4 [[R6]], i32 12, i1 false)
+// CHECK-NEXT:   [[VA2:%[^,=]+]] = bitcast i8** [[VA]] to i8*
+// 

[PATCH] D66255: [WebAssembly] Correctly handle va_arg of zero-sized structures

2019-08-14 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum created this revision.
quantum added reviewers: dschuff, tlively, sbc100.
Herald added subscribers: cfe-commits, sunfish, aheejin, jgravelle-google.
Herald added a project: clang.

D66168  passes size 0 structs indirectly, 
while the wasm backend expects it to
be passed directly. This causes subsequent variadic arguments to be read
incorrectly.

This diff changes it so that size 0 structs are passed directly.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D66255

Files:
  clang/lib/CodeGen/TargetInfo.cpp
  clang/test/CodeGen/wasm-varargs.c


Index: clang/test/CodeGen/wasm-varargs.c
===
--- clang/test/CodeGen/wasm-varargs.c
+++ clang/test/CodeGen/wasm-varargs.c
@@ -90,7 +90,47 @@
 // CHECK:   [[ARGP_NEXT:%[^,=]+]] = getelementptr inbounds i8, i8* 
[[ARGP_CUR]], i32 4
 // CHECK:   store i8* [[ARGP_NEXT]], i8** [[VA]], align 4
 // CHECK:   [[R3:%[^,=]+]] = bitcast i8* [[ARGP_CUR]] to [[STRUCT_S]]**
-// CHECK:   [[R4:%[^,=]+]] = load [[STRUCT_S]]*, [[STRUCT_S]]** %0, align 4
+// CHECK:   [[R4:%[^,=]+]] = load [[STRUCT_S]]*, [[STRUCT_S]]** [[R3]], align 4
+// CHECK:   [[R5:%[^,=]+]] = bitcast [[STRUCT_S]]* [[AGG_RESULT]] to i8*
+// CHECK:   [[R6:%[^,=]+]] = bitcast [[STRUCT_S]]* [[R4]] to i8*
+// CHECK:   call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 [[R5]], i8* align 
4 [[R6]], i32 12, i1 false)
+// CHECK:   [[VA2:%[^,=]+]] = bitcast i8** [[VA]] to i8*
+// CHECK:   call void @llvm.va_end(i8* [[VA2]])
+// CHECK:   ret void
+// CHECK: }
+
+struct Z {};
+
+struct S test_zero_size_struct(char *fmt, ...) {
+  va_list va;
+
+  va_start(va, fmt);
+  struct Z u = va_arg(va, struct Z);
+  struct S v = va_arg(va, struct S);
+  va_end(va);
+
+  return v;
+}
+
+// CHECK: define void @test_zero_size_struct([[STRUCT_S:%[^,=]+]]*{{.*}} 
noalias sret [[AGG_RESULT:%.*]], i8*{{.*}} %fmt, ...) {{.*}} {
+// CHECK:   [[FMT_ADDR:%[^,=]+]] = alloca i8*, align 4
+// CHECK:   [[VA:%[^,=]+]] = alloca i8*, align 4
+// CHECK:   [[U:%[^,=]+]] = alloca [[STRUCT_Z:%[^,=]+]], align 1
+// CHECK:   store i8* %fmt, i8** [[FMT_ADDR]], align 4
+// CHECK:   [[VA1:%[^,=]+]] = bitcast i8** [[VA]] to i8*
+// CHECK:   call void @llvm.va_start(i8* [[VA1]])
+// CHECK:   [[ARGP_CUR:%[^,=]+]] = load i8*, i8** [[VA]], align 4
+// CHECK:   [[ARGP_NEXT:%[^,=]+]] = getelementptr inbounds i8, i8* 
[[ARGP_CUR]], i32 0
+// CHECK:   store i8* [[ARGP_NEXT]], i8** [[VA]], align 4
+// CHECK:   [[R0:%[^,=]+]] = bitcast i8* [[ARGP_CUR]] to [[STRUCT_Z]]*
+// CHECK:   [[R1:%[^,=]+]] = bitcast [[STRUCT_Z]]* [[U]] to i8*
+// CHECK:   [[R2:%[^,=]+]] = bitcast [[STRUCT_Z]]* [[R0]] to i8*
+// CHECK:   call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 [[R1]], i8* align 
4 [[R2]], i32 0, i1 false)
+// CHECK:   [[ARGP_CUR2:%[^,=]+]] = load i8*, i8** [[VA]], align 4
+// CHECK:   [[ARGP_NEXT2:%[^,=]+]] = getelementptr inbounds i8, i8* 
[[ARGP_CUR2]], i32 4
+// CHECK:   store i8* [[ARGP_NEXT2]], i8** [[VA]], align 4
+// CHECK:   [[R3:%[^,=]+]] = bitcast i8* [[ARGP_CUR2]] to [[STRUCT_S]]**
+// CHECK:   [[R4:%[^,=]+]] = load [[STRUCT_S]]*, [[STRUCT_S]]** [[R3]], align 4
 // CHECK:   [[R5:%[^,=]+]] = bitcast [[STRUCT_S]]* [[AGG_RESULT]] to i8*
 // CHECK:   [[R6:%[^,=]+]] = bitcast [[STRUCT_S]]* [[R4]] to i8*
 // CHECK:   call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 [[R5]], i8* align 
4 [[R6]], i32 12, i1 false)
Index: clang/lib/CodeGen/TargetInfo.cpp
===
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -833,8 +833,9 @@
 
 Address WebAssemblyABIInfo::EmitVAArg(CodeGenFunction , Address VAListAddr,
   QualType Ty) const {
-  bool IsIndirect =
-  isAggregateTypeForABI(Ty) && !isSingleElementStruct(Ty, getContext());
+  bool IsIndirect = isAggregateTypeForABI(Ty) &&
+!isEmptyRecord(getContext(), Ty, true) &&
+!isSingleElementStruct(Ty, getContext());
   return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect,
   getContext().getTypeInfoInChars(Ty),
   CharUnits::fromQuantity(4),


Index: clang/test/CodeGen/wasm-varargs.c
===
--- clang/test/CodeGen/wasm-varargs.c
+++ clang/test/CodeGen/wasm-varargs.c
@@ -90,7 +90,47 @@
 // CHECK:   [[ARGP_NEXT:%[^,=]+]] = getelementptr inbounds i8, i8* [[ARGP_CUR]], i32 4
 // CHECK:   store i8* [[ARGP_NEXT]], i8** [[VA]], align 4
 // CHECK:   [[R3:%[^,=]+]] = bitcast i8* [[ARGP_CUR]] to [[STRUCT_S]]**
-// CHECK:   [[R4:%[^,=]+]] = load [[STRUCT_S]]*, [[STRUCT_S]]** %0, align 4
+// CHECK:   [[R4:%[^,=]+]] = load [[STRUCT_S]]*, [[STRUCT_S]]** [[R3]], align 4
+// CHECK:   [[R5:%[^,=]+]] = bitcast [[STRUCT_S]]* [[AGG_RESULT]] to i8*
+// CHECK:   [[R6:%[^,=]+]] = bitcast [[STRUCT_S]]* [[R4]] to i8*
+// CHECK:   call void @llvm.memcpy.p0i8.p0i8.i32(i8* 

[PATCH] D66168: [WebAssembly] Make clang emit correct va_arg code for structs

2019-08-13 Thread Guanzhong Chen via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL368750: [WebAssembly] Make clang emit correct va_arg code 
for structs (authored by quantum, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D66168?vs=214916=214927#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66168/new/

https://reviews.llvm.org/D66168

Files:
  cfe/trunk/lib/CodeGen/TargetInfo.cpp
  cfe/trunk/test/CodeGen/wasm-varargs.c


Index: cfe/trunk/test/CodeGen/wasm-varargs.c
===
--- cfe/trunk/test/CodeGen/wasm-varargs.c
+++ cfe/trunk/test/CodeGen/wasm-varargs.c
@@ -87,12 +87,13 @@
 // CHECK:   [[VA1:%[^,=]+]] = bitcast i8** [[VA]] to i8*
 // CHECK:   call void @llvm.va_start(i8* [[VA1]])
 // CHECK:   [[ARGP_CUR:%[^,=]+]] = load i8*, i8** [[VA]], align 4
-// CHECK:   [[ARGP_NEXT:%[^,=]+]] = getelementptr inbounds i8, i8* 
[[ARGP_CUR]], i32 12
+// CHECK:   [[ARGP_NEXT:%[^,=]+]] = getelementptr inbounds i8, i8* 
[[ARGP_CUR]], i32 4
 // CHECK:   store i8* [[ARGP_NEXT]], i8** [[VA]], align 4
-// CHECK:   [[R3:%[^,=]+]] = bitcast i8* [[ARGP_CUR]] to [[STRUCT_S]]*
-// CHECK:   [[R4:%[^,=]+]] = bitcast [[STRUCT_S]]* [[AGG_RESULT]] to i8*
-// CHECK:   [[R5:%[^,=]+]] = bitcast [[STRUCT_S]]* [[R3]] to i8*
-// CHECK:   call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 [[R4]], i8* align 
4 [[R5]], i32 12, i1 false)
+// CHECK:   [[R3:%[^,=]+]] = bitcast i8* [[ARGP_CUR]] to [[STRUCT_S]]**
+// CHECK:   [[R4:%[^,=]+]] = load [[STRUCT_S]]*, [[STRUCT_S]]** %0, align 4
+// CHECK:   [[R5:%[^,=]+]] = bitcast [[STRUCT_S]]* [[AGG_RESULT]] to i8*
+// CHECK:   [[R6:%[^,=]+]] = bitcast [[STRUCT_S]]* [[R4]] to i8*
+// CHECK:   call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 [[R5]], i8* align 
4 [[R6]], i32 12, i1 false)
 // CHECK:   [[VA2:%[^,=]+]] = bitcast i8** [[VA]] to i8*
 // CHECK:   call void @llvm.va_end(i8* [[VA2]])
 // CHECK:   ret void
Index: cfe/trunk/lib/CodeGen/TargetInfo.cpp
===
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp
@@ -833,10 +833,12 @@
 
 Address WebAssemblyABIInfo::EmitVAArg(CodeGenFunction , Address VAListAddr,
   QualType Ty) const {
-  return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*IsIndirect=*/ false,
+  bool IsIndirect =
+  isAggregateTypeForABI(Ty) && !isSingleElementStruct(Ty, getContext());
+  return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect,
   getContext().getTypeInfoInChars(Ty),
   CharUnits::fromQuantity(4),
-  /*AllowHigherAlign=*/ true);
+  /*AllowHigherAlign=*/true);
 }
 
 
//===--===//


Index: cfe/trunk/test/CodeGen/wasm-varargs.c
===
--- cfe/trunk/test/CodeGen/wasm-varargs.c
+++ cfe/trunk/test/CodeGen/wasm-varargs.c
@@ -87,12 +87,13 @@
 // CHECK:   [[VA1:%[^,=]+]] = bitcast i8** [[VA]] to i8*
 // CHECK:   call void @llvm.va_start(i8* [[VA1]])
 // CHECK:   [[ARGP_CUR:%[^,=]+]] = load i8*, i8** [[VA]], align 4
-// CHECK:   [[ARGP_NEXT:%[^,=]+]] = getelementptr inbounds i8, i8* [[ARGP_CUR]], i32 12
+// CHECK:   [[ARGP_NEXT:%[^,=]+]] = getelementptr inbounds i8, i8* [[ARGP_CUR]], i32 4
 // CHECK:   store i8* [[ARGP_NEXT]], i8** [[VA]], align 4
-// CHECK:   [[R3:%[^,=]+]] = bitcast i8* [[ARGP_CUR]] to [[STRUCT_S]]*
-// CHECK:   [[R4:%[^,=]+]] = bitcast [[STRUCT_S]]* [[AGG_RESULT]] to i8*
-// CHECK:   [[R5:%[^,=]+]] = bitcast [[STRUCT_S]]* [[R3]] to i8*
-// CHECK:   call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 [[R4]], i8* align 4 [[R5]], i32 12, i1 false)
+// CHECK:   [[R3:%[^,=]+]] = bitcast i8* [[ARGP_CUR]] to [[STRUCT_S]]**
+// CHECK:   [[R4:%[^,=]+]] = load [[STRUCT_S]]*, [[STRUCT_S]]** %0, align 4
+// CHECK:   [[R5:%[^,=]+]] = bitcast [[STRUCT_S]]* [[AGG_RESULT]] to i8*
+// CHECK:   [[R6:%[^,=]+]] = bitcast [[STRUCT_S]]* [[R4]] to i8*
+// CHECK:   call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 [[R5]], i8* align 4 [[R6]], i32 12, i1 false)
 // CHECK:   [[VA2:%[^,=]+]] = bitcast i8** [[VA]] to i8*
 // CHECK:   call void @llvm.va_end(i8* [[VA2]])
 // CHECK:   ret void
Index: cfe/trunk/lib/CodeGen/TargetInfo.cpp
===
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp
@@ -833,10 +833,12 @@
 
 Address WebAssemblyABIInfo::EmitVAArg(CodeGenFunction , Address VAListAddr,
   QualType Ty) const {
-  return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*IsIndirect=*/ false,
+  bool IsIndirect =
+  isAggregateTypeForABI(Ty) && !isSingleElementStruct(Ty, getContext());
+  return emitVoidPtrVAArg(CGF, VAListAddr, Ty, 

[PATCH] D66168: [WebAssembly] Make clang emit correct va_arg code for structs

2019-08-13 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum created this revision.
quantum added reviewers: tlively, sbc100, kripken, aheejin.
Herald added subscribers: cfe-commits, sunfish, jgravelle-google, dschuff.
Herald added a project: clang.

In the WebAssembly backend, when lowering variadic function calls, non-single
member aggregate type arguments are always passed by pointer.

However, when emitting va_arg code in clang, the arguments are instead read as
if they are passed directly. This results in the pointer being read as the
actual structure.

Fixes https://github.com/emscripten-core/emscripten/issues/9042.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D66168

Files:
  clang/lib/CodeGen/TargetInfo.cpp
  clang/test/CodeGen/wasm-varargs.c


Index: clang/test/CodeGen/wasm-varargs.c
===
--- clang/test/CodeGen/wasm-varargs.c
+++ clang/test/CodeGen/wasm-varargs.c
@@ -87,12 +87,13 @@
 // CHECK:   [[VA1:%[^,=]+]] = bitcast i8** [[VA]] to i8*
 // CHECK:   call void @llvm.va_start(i8* [[VA1]])
 // CHECK:   [[ARGP_CUR:%[^,=]+]] = load i8*, i8** [[VA]], align 4
-// CHECK:   [[ARGP_NEXT:%[^,=]+]] = getelementptr inbounds i8, i8* 
[[ARGP_CUR]], i32 12
+// CHECK:   [[ARGP_NEXT:%[^,=]+]] = getelementptr inbounds i8, i8* 
[[ARGP_CUR]], i32 4
 // CHECK:   store i8* [[ARGP_NEXT]], i8** [[VA]], align 4
-// CHECK:   [[R3:%[^,=]+]] = bitcast i8* [[ARGP_CUR]] to [[STRUCT_S]]*
-// CHECK:   [[R4:%[^,=]+]] = bitcast [[STRUCT_S]]* [[AGG_RESULT]] to i8*
-// CHECK:   [[R5:%[^,=]+]] = bitcast [[STRUCT_S]]* [[R3]] to i8*
-// CHECK:   call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 [[R4]], i8* align 
4 [[R5]], i32 12, i1 false)
+// CHECK:   [[R3:%[^,=]+]] = bitcast i8* [[ARGP_CUR]] to [[STRUCT_S]]**
+// CHECK:   [[R4:%[^,=]+]] = load [[STRUCT_S]]*, [[STRUCT_S]]** %0, align 4
+// CHECK:   [[R5:%[^,=]+]] = bitcast [[STRUCT_S]]* [[AGG_RESULT]] to i8*
+// CHECK:   [[R6:%[^,=]+]] = bitcast [[STRUCT_S]]* [[R4]] to i8*
+// CHECK:   call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 [[R5]], i8* align 
4 [[R6]], i32 12, i1 false)
 // CHECK:   [[VA2:%[^,=]+]] = bitcast i8** [[VA]] to i8*
 // CHECK:   call void @llvm.va_end(i8* [[VA2]])
 // CHECK:   ret void
Index: clang/lib/CodeGen/TargetInfo.cpp
===
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -833,10 +833,12 @@
 
 Address WebAssemblyABIInfo::EmitVAArg(CodeGenFunction , Address VAListAddr,
   QualType Ty) const {
-  return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*IsIndirect=*/ false,
+  bool IsIndirect =
+  isAggregateTypeForABI(Ty) && !isSingleElementStruct(Ty, getContext());
+  return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect,
   getContext().getTypeInfoInChars(Ty),
   CharUnits::fromQuantity(4),
-  /*AllowHigherAlign=*/ true);
+  /*AllowHigherAlign=*/true);
 }
 
 
//===--===//


Index: clang/test/CodeGen/wasm-varargs.c
===
--- clang/test/CodeGen/wasm-varargs.c
+++ clang/test/CodeGen/wasm-varargs.c
@@ -87,12 +87,13 @@
 // CHECK:   [[VA1:%[^,=]+]] = bitcast i8** [[VA]] to i8*
 // CHECK:   call void @llvm.va_start(i8* [[VA1]])
 // CHECK:   [[ARGP_CUR:%[^,=]+]] = load i8*, i8** [[VA]], align 4
-// CHECK:   [[ARGP_NEXT:%[^,=]+]] = getelementptr inbounds i8, i8* [[ARGP_CUR]], i32 12
+// CHECK:   [[ARGP_NEXT:%[^,=]+]] = getelementptr inbounds i8, i8* [[ARGP_CUR]], i32 4
 // CHECK:   store i8* [[ARGP_NEXT]], i8** [[VA]], align 4
-// CHECK:   [[R3:%[^,=]+]] = bitcast i8* [[ARGP_CUR]] to [[STRUCT_S]]*
-// CHECK:   [[R4:%[^,=]+]] = bitcast [[STRUCT_S]]* [[AGG_RESULT]] to i8*
-// CHECK:   [[R5:%[^,=]+]] = bitcast [[STRUCT_S]]* [[R3]] to i8*
-// CHECK:   call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 [[R4]], i8* align 4 [[R5]], i32 12, i1 false)
+// CHECK:   [[R3:%[^,=]+]] = bitcast i8* [[ARGP_CUR]] to [[STRUCT_S]]**
+// CHECK:   [[R4:%[^,=]+]] = load [[STRUCT_S]]*, [[STRUCT_S]]** %0, align 4
+// CHECK:   [[R5:%[^,=]+]] = bitcast [[STRUCT_S]]* [[AGG_RESULT]] to i8*
+// CHECK:   [[R6:%[^,=]+]] = bitcast [[STRUCT_S]]* [[R4]] to i8*
+// CHECK:   call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 [[R5]], i8* align 4 [[R6]], i32 12, i1 false)
 // CHECK:   [[VA2:%[^,=]+]] = bitcast i8** [[VA]] to i8*
 // CHECK:   call void @llvm.va_end(i8* [[VA2]])
 // CHECK:   ret void
Index: clang/lib/CodeGen/TargetInfo.cpp
===
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -833,10 +833,12 @@
 
 Address WebAssemblyABIInfo::EmitVAArg(CodeGenFunction , Address VAListAddr,
   QualType Ty) const {
-  return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*IsIndirect=*/ false,
+  bool IsIndirect =
+  

[PATCH] D65684: [WebAssembly] Lower ASan constructor priority on Emscripten

2019-08-06 Thread Guanzhong Chen via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL368101: [WebAssembly] Lower ASan constructor priority on 
Emscripten (authored by quantum, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D65684?vs=213720=213730#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65684/new/

https://reviews.llvm.org/D65684

Files:
  cfe/trunk/test/CodeGen/asan-constructor.c
  llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp


Index: cfe/trunk/test/CodeGen/asan-constructor.c
===
--- cfe/trunk/test/CodeGen/asan-constructor.c
+++ cfe/trunk/test/CodeGen/asan-constructor.c
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple wasm32-unknown-emscripten -fsanitize=address 
-emit-llvm -o - %s | FileCheck %s --check-prefix=EMSCRIPTEN
+
+// CHECK: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] 
[{ i32, void ()*, i8* } { i32 1, void ()* @asan.module_ctor, i8* null }]
+// EMSCRIPTEN: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* 
}] [{ i32, void ()*, i8* } { i32 50, void ()* @asan.module_ctor, i8* null }]
Index: llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp
===
--- llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -129,6 +129,8 @@
 static const char *const kAsanModuleCtorName = "asan.module_ctor";
 static const char *const kAsanModuleDtorName = "asan.module_dtor";
 static const uint64_t kAsanCtorAndDtorPriority = 1;
+// On Emscripten, the system needs more than one priorities for constructors.
+static const uint64_t kAsanEmscriptenCtorAndDtorPriority = 50;
 static const char *const kAsanReportErrorTemplate = "__asan_report_";
 static const char *const kAsanRegisterGlobalsName = "__asan_register_globals";
 static const char *const kAsanUnregisterGlobalsName =
@@ -530,6 +532,14 @@
   return std::max(32U, 1U << MappingScale);
 }
 
+static uint64_t GetCtorAndDtorPriority(Triple ) {
+  if (TargetTriple.isOSEmscripten()) {
+return kAsanEmscriptenCtorAndDtorPriority;
+  } else {
+return kAsanCtorAndDtorPriority;
+  }
+}
+
 namespace {
 
 /// Module analysis for getting various metadata about the module.
@@ -1777,7 +1787,8 @@
   if (F->getName() == kAsanModuleCtorName) continue;
   ConstantInt *Priority = dyn_cast(CS->getOperand(0));
   // Don't instrument CTORs that will run before asan.module_ctor.
-  if (Priority->getLimitedValue() <= kAsanCtorAndDtorPriority) continue;
+  if (Priority->getLimitedValue() <= GetCtorAndDtorPriority(TargetTriple))
+continue;
   poisonOneInitializer(*F, ModuleName);
 }
   }
@@ -2429,22 +2440,22 @@
 Changed |= InstrumentGlobals(IRB, M, );
   }
 
+  const uint64_t Priority = GetCtorAndDtorPriority(TargetTriple);
+
   // Put the constructor and destructor in comdat if both
   // (1) global instrumentation is not TU-specific
   // (2) target is ELF.
   if (UseCtorComdat && TargetTriple.isOSBinFormatELF() && CtorComdat) {
 AsanCtorFunction->setComdat(M.getOrInsertComdat(kAsanModuleCtorName));
-appendToGlobalCtors(M, AsanCtorFunction, kAsanCtorAndDtorPriority,
-AsanCtorFunction);
+appendToGlobalCtors(M, AsanCtorFunction, Priority, AsanCtorFunction);
 if (AsanDtorFunction) {
   AsanDtorFunction->setComdat(M.getOrInsertComdat(kAsanModuleDtorName));
-  appendToGlobalDtors(M, AsanDtorFunction, kAsanCtorAndDtorPriority,
-  AsanDtorFunction);
+  appendToGlobalDtors(M, AsanDtorFunction, Priority, AsanDtorFunction);
 }
   } else {
-appendToGlobalCtors(M, AsanCtorFunction, kAsanCtorAndDtorPriority);
+appendToGlobalCtors(M, AsanCtorFunction, Priority);
 if (AsanDtorFunction)
-  appendToGlobalDtors(M, AsanDtorFunction, kAsanCtorAndDtorPriority);
+  appendToGlobalDtors(M, AsanDtorFunction, Priority);
   }
 
   return Changed;


Index: cfe/trunk/test/CodeGen/asan-constructor.c
===
--- cfe/trunk/test/CodeGen/asan-constructor.c
+++ cfe/trunk/test/CodeGen/asan-constructor.c
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple wasm32-unknown-emscripten -fsanitize=address -emit-llvm -o - %s | FileCheck %s --check-prefix=EMSCRIPTEN
+
+// CHECK: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 1, void ()* @asan.module_ctor, i8* null }]
+// EMSCRIPTEN: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 50, void ()* @asan.module_ctor, i8* null }]
Index: llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp

[PATCH] D65684: [WebAssembly] Lower ASan constructor priority on Emscripten

2019-08-06 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum updated this revision to Diff 213720.
quantum added a comment.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Add constructor priority test


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65684/new/

https://reviews.llvm.org/D65684

Files:
  clang/test/CodeGen/asan-constructor.c
  llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp


Index: llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
===
--- llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -129,6 +129,8 @@
 static const char *const kAsanModuleCtorName = "asan.module_ctor";
 static const char *const kAsanModuleDtorName = "asan.module_dtor";
 static const uint64_t kAsanCtorAndDtorPriority = 1;
+// On Emscripten, the system needs more than one priorities for constructors.
+static const uint64_t kAsanEmscriptenCtorAndDtorPriority = 50;
 static const char *const kAsanReportErrorTemplate = "__asan_report_";
 static const char *const kAsanRegisterGlobalsName = "__asan_register_globals";
 static const char *const kAsanUnregisterGlobalsName =
@@ -530,6 +532,14 @@
   return std::max(32U, 1U << MappingScale);
 }
 
+static uint64_t GetCtorAndDtorPriority(Triple ) {
+  if (TargetTriple.isOSEmscripten()) {
+return kAsanEmscriptenCtorAndDtorPriority;
+  } else {
+return kAsanCtorAndDtorPriority;
+  }
+}
+
 namespace {
 
 /// Module analysis for getting various metadata about the module.
@@ -1777,7 +1787,8 @@
   if (F->getName() == kAsanModuleCtorName) continue;
   ConstantInt *Priority = dyn_cast(CS->getOperand(0));
   // Don't instrument CTORs that will run before asan.module_ctor.
-  if (Priority->getLimitedValue() <= kAsanCtorAndDtorPriority) continue;
+  if (Priority->getLimitedValue() <= GetCtorAndDtorPriority(TargetTriple))
+continue;
   poisonOneInitializer(*F, ModuleName);
 }
   }
@@ -2429,22 +2440,22 @@
 Changed |= InstrumentGlobals(IRB, M, );
   }
 
+  const uint64_t Priority = GetCtorAndDtorPriority(TargetTriple);
+
   // Put the constructor and destructor in comdat if both
   // (1) global instrumentation is not TU-specific
   // (2) target is ELF.
   if (UseCtorComdat && TargetTriple.isOSBinFormatELF() && CtorComdat) {
 AsanCtorFunction->setComdat(M.getOrInsertComdat(kAsanModuleCtorName));
-appendToGlobalCtors(M, AsanCtorFunction, kAsanCtorAndDtorPriority,
-AsanCtorFunction);
+appendToGlobalCtors(M, AsanCtorFunction, Priority, AsanCtorFunction);
 if (AsanDtorFunction) {
   AsanDtorFunction->setComdat(M.getOrInsertComdat(kAsanModuleDtorName));
-  appendToGlobalDtors(M, AsanDtorFunction, kAsanCtorAndDtorPriority,
-  AsanDtorFunction);
+  appendToGlobalDtors(M, AsanDtorFunction, Priority, AsanDtorFunction);
 }
   } else {
-appendToGlobalCtors(M, AsanCtorFunction, kAsanCtorAndDtorPriority);
+appendToGlobalCtors(M, AsanCtorFunction, Priority);
 if (AsanDtorFunction)
-  appendToGlobalDtors(M, AsanDtorFunction, kAsanCtorAndDtorPriority);
+  appendToGlobalDtors(M, AsanDtorFunction, Priority);
   }
 
   return Changed;
Index: clang/test/CodeGen/asan-constructor.c
===
--- /dev/null
+++ clang/test/CodeGen/asan-constructor.c
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple wasm32-unknown-emscripten -fsanitize=address 
-emit-llvm -o - %s | FileCheck %s --check-prefix=EMSCRIPTEN
+
+// CHECK: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] 
[{ i32, void ()*, i8* } { i32 1, void ()* @asan.module_ctor, i8* null }]
+// EMSCRIPTEN: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* 
}] [{ i32, void ()*, i8* } { i32 50, void ()* @asan.module_ctor, i8* null }]


Index: llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
===
--- llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -129,6 +129,8 @@
 static const char *const kAsanModuleCtorName = "asan.module_ctor";
 static const char *const kAsanModuleDtorName = "asan.module_dtor";
 static const uint64_t kAsanCtorAndDtorPriority = 1;
+// On Emscripten, the system needs more than one priorities for constructors.
+static const uint64_t kAsanEmscriptenCtorAndDtorPriority = 50;
 static const char *const kAsanReportErrorTemplate = "__asan_report_";
 static const char *const kAsanRegisterGlobalsName = "__asan_register_globals";
 static const char *const kAsanUnregisterGlobalsName =
@@ -530,6 +532,14 @@
   return std::max(32U, 1U << MappingScale);
 }
 
+static uint64_t GetCtorAndDtorPriority(Triple ) {
+  if (TargetTriple.isOSEmscripten()) {
+return 

[PATCH] D65028: [WebAssembly] Compute and export TLS block alignment

2019-07-19 Thread Guanzhong Chen via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL366624: [WebAssembly] Compute and export TLS block alignment 
(authored by quantum, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D65028?vs=210930=210934#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65028/new/

https://reviews.llvm.org/D65028

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

Index: lld/trunk/wasm/Symbols.cpp
===
--- lld/trunk/wasm/Symbols.cpp
+++ lld/trunk/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/trunk/wasm/Writer.cpp
===
--- lld/trunk/wasm/Writer.cpp
+++ lld/trunk/wasm/Writer.cpp
@@ -247,6 +247,9 @@
 if (WasmSym::tlsSize && seg->name == ".tdata") {
   auto *tlsSize = cast(WasmSym::tlsSize);
   tlsSize->global->global.InitExpr.Value.Int32 = seg->size;
+
+  auto *tlsAlign = cast(WasmSym::tlsAlign);
+  tlsAlign->global->global.InitExpr.Value.Int32 = 1U << seg->alignment;
 }
   }
 
Index: lld/trunk/wasm/Symbols.h
===
--- lld/trunk/wasm/Symbols.h
+++ lld/trunk/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/trunk/wasm/Driver.cpp
===
--- lld/trunk/wasm/Driver.cpp
+++ lld/trunk/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(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(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(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(i32ArgSignature, "__wasm_init_tls"));
Index: lld/trunk/test/wasm/tls-align.ll
===
--- lld/trunk/test/wasm/tls-align.ll
+++ lld/trunk/test/wasm/tls-align.ll
@@ -0,0 +1,51 @@
+; RUN: llc -mattr=+bulk-memory -filetype=obj %s -o %t.o
+
+target triple = "wasm32-unknown-unknown"
+
+@no_tls = global i32 0, align 4
+@tls1 = thread_local(localexec) global i32 1, align 4
+@tls2 = thread_local(localexec) global i32 1, align 16
+
+define i32* @tls1_addr() {
+  ret i32* @tls1
+}
+
+define i32* @tls2_addr() {
+  ret i32* @tls2
+}
+
+; RUN: wasm-ld -no-gc-sections --shared-memory --max-memory=131072 

[PATCH] D65028: [WebAssembly] Compute and export TLS block alignment

2019-07-19 Thread Guanzhong Chen via Phabricator via cfe-commits
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(WasmSym::tlsSize);
   tlsSize->global->global.InitExpr.Value.Int32 = seg->size;
+
+  auto *tlsAlign = cast(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 

[PATCH] D64949: [WebAssembly] Fix __builtin_wasm_tls_base intrinsic

2019-07-18 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum updated this revision to Diff 210675.
quantum added a comment.

Add a test with a memory dependency on __builtin_wasm_tls_base.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64949/new/

https://reviews.llvm.org/D64949

Files:
  clang/include/clang/Basic/BuiltinsWebAssembly.def
  llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.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
@@ -84,6 +84,17 @@
   ret i8* %1
 }
 
+; CHECK-LABEL: tls_base_write:
+; CHECK-NEXT: .functype tls_base_write (i32) -> ()
+define void @tls_base_write(i8** %output) {
+; CHECK-NEXT: global.get __tls_base
+; CHECK-NEXT: i32.store 0
+; CHECK-NEXT: return
+  %1 = call i8* @llvm.wasm.tls.base()
+  store i8* %1, i8** %output
+  ret void
+}
+
 ; CHECK: .type tls,@object
 ; TLS-NEXT: .section .tbss.tls,"",@
 ; NO-TLS-NEXT: .section .bss.tls,"",@
Index: llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
===
--- llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
+++ llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
@@ -235,7 +235,7 @@
   assert(PtrVT == MVT::i32 && "only wasm32 is supported for now");
 
   MachineSDNode *TLSBase = CurDAG->getMachineNode(
-  WebAssembly::GLOBAL_GET_I32, DL, MVT::i32,
+  WebAssembly::GLOBAL_GET_I32, DL, MVT::i32, MVT::Other,
   CurDAG->getTargetExternalSymbol("__tls_base", PtrVT),
   Node->getOperand(0));
   ReplaceNode(Node, TLSBase);
Index: clang/include/clang/Basic/BuiltinsWebAssembly.def
===
--- clang/include/clang/Basic/BuiltinsWebAssembly.def
+++ clang/include/clang/Basic/BuiltinsWebAssembly.def
@@ -31,7 +31,7 @@
 
 // Thread-local storage
 TARGET_BUILTIN(__builtin_wasm_tls_size, "z", "nc", "bulk-memory")
-TARGET_BUILTIN(__builtin_wasm_tls_base, "v*", "n", "bulk-memory")
+TARGET_BUILTIN(__builtin_wasm_tls_base, "v*", "nU", "bulk-memory")
 
 // Floating point min/max
 BUILTIN(__builtin_wasm_min_f32, "fff", "nc")


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
@@ -84,6 +84,17 @@
   ret i8* %1
 }
 
+; CHECK-LABEL: tls_base_write:
+; CHECK-NEXT: .functype tls_base_write (i32) -> ()
+define void @tls_base_write(i8** %output) {
+; CHECK-NEXT: global.get __tls_base
+; CHECK-NEXT: i32.store 0
+; CHECK-NEXT: return
+  %1 = call i8* @llvm.wasm.tls.base()
+  store i8* %1, i8** %output
+  ret void
+}
+
 ; CHECK: .type tls,@object
 ; TLS-NEXT: .section .tbss.tls,"",@
 ; NO-TLS-NEXT: .section .bss.tls,"",@
Index: llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
===
--- llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
+++ llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
@@ -235,7 +235,7 @@
   assert(PtrVT == MVT::i32 && "only wasm32 is supported for now");
 
   MachineSDNode *TLSBase = CurDAG->getMachineNode(
-  WebAssembly::GLOBAL_GET_I32, DL, MVT::i32,
+  WebAssembly::GLOBAL_GET_I32, DL, MVT::i32, MVT::Other,
   CurDAG->getTargetExternalSymbol("__tls_base", PtrVT),
   Node->getOperand(0));
   ReplaceNode(Node, TLSBase);
Index: clang/include/clang/Basic/BuiltinsWebAssembly.def
===
--- clang/include/clang/Basic/BuiltinsWebAssembly.def
+++ clang/include/clang/Basic/BuiltinsWebAssembly.def
@@ -31,7 +31,7 @@
 
 // Thread-local storage
 TARGET_BUILTIN(__builtin_wasm_tls_size, "z", "nc", "bulk-memory")
-TARGET_BUILTIN(__builtin_wasm_tls_base, "v*", "n", "bulk-memory")
+TARGET_BUILTIN(__builtin_wasm_tls_base, "v*", "nU", "bulk-memory")
 
 // Floating point min/max
 BUILTIN(__builtin_wasm_min_f32, "fff", "nc")
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64949: [WebAssembly] Fix __builtin_wasm_tls_base intrinsic

2019-07-18 Thread Guanzhong Chen via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL366499: [WebAssembly] Fix __builtin_wasm_tls_base intrinsic 
(authored by quantum, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D64949?vs=210675=210676#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64949/new/

https://reviews.llvm.org/D64949

Files:
  cfe/trunk/include/clang/Basic/BuiltinsWebAssembly.def
  llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
  llvm/trunk/test/CodeGen/WebAssembly/tls-general-dynamic.ll


Index: llvm/trunk/test/CodeGen/WebAssembly/tls-general-dynamic.ll
===
--- llvm/trunk/test/CodeGen/WebAssembly/tls-general-dynamic.ll
+++ llvm/trunk/test/CodeGen/WebAssembly/tls-general-dynamic.ll
@@ -84,6 +84,17 @@
   ret i8* %1
 }
 
+; CHECK-LABEL: tls_base_write:
+; CHECK-NEXT: .functype tls_base_write (i32) -> ()
+define void @tls_base_write(i8** %output) {
+; CHECK-NEXT: global.get __tls_base
+; CHECK-NEXT: i32.store 0
+; CHECK-NEXT: return
+  %1 = call i8* @llvm.wasm.tls.base()
+  store i8* %1, i8** %output
+  ret void
+}
+
 ; CHECK: .type tls,@object
 ; TLS-NEXT: .section .tbss.tls,"",@
 ; NO-TLS-NEXT: .section .bss.tls,"",@
Index: llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
===
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
@@ -235,7 +235,7 @@
   assert(PtrVT == MVT::i32 && "only wasm32 is supported for now");
 
   MachineSDNode *TLSBase = CurDAG->getMachineNode(
-  WebAssembly::GLOBAL_GET_I32, DL, MVT::i32,
+  WebAssembly::GLOBAL_GET_I32, DL, MVT::i32, MVT::Other,
   CurDAG->getTargetExternalSymbol("__tls_base", PtrVT),
   Node->getOperand(0));
   ReplaceNode(Node, TLSBase);
Index: cfe/trunk/include/clang/Basic/BuiltinsWebAssembly.def
===
--- cfe/trunk/include/clang/Basic/BuiltinsWebAssembly.def
+++ cfe/trunk/include/clang/Basic/BuiltinsWebAssembly.def
@@ -31,7 +31,7 @@
 
 // Thread-local storage
 TARGET_BUILTIN(__builtin_wasm_tls_size, "z", "nc", "bulk-memory")
-TARGET_BUILTIN(__builtin_wasm_tls_base, "v*", "n", "bulk-memory")
+TARGET_BUILTIN(__builtin_wasm_tls_base, "v*", "nU", "bulk-memory")
 
 // Floating point min/max
 BUILTIN(__builtin_wasm_min_f32, "fff", "nc")


Index: llvm/trunk/test/CodeGen/WebAssembly/tls-general-dynamic.ll
===
--- llvm/trunk/test/CodeGen/WebAssembly/tls-general-dynamic.ll
+++ llvm/trunk/test/CodeGen/WebAssembly/tls-general-dynamic.ll
@@ -84,6 +84,17 @@
   ret i8* %1
 }
 
+; CHECK-LABEL: tls_base_write:
+; CHECK-NEXT: .functype tls_base_write (i32) -> ()
+define void @tls_base_write(i8** %output) {
+; CHECK-NEXT: global.get __tls_base
+; CHECK-NEXT: i32.store 0
+; CHECK-NEXT: return
+  %1 = call i8* @llvm.wasm.tls.base()
+  store i8* %1, i8** %output
+  ret void
+}
+
 ; CHECK: .type tls,@object
 ; TLS-NEXT: .section .tbss.tls,"",@
 ; NO-TLS-NEXT: .section .bss.tls,"",@
Index: llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
===
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
@@ -235,7 +235,7 @@
   assert(PtrVT == MVT::i32 && "only wasm32 is supported for now");
 
   MachineSDNode *TLSBase = CurDAG->getMachineNode(
-  WebAssembly::GLOBAL_GET_I32, DL, MVT::i32,
+  WebAssembly::GLOBAL_GET_I32, DL, MVT::i32, MVT::Other,
   CurDAG->getTargetExternalSymbol("__tls_base", PtrVT),
   Node->getOperand(0));
   ReplaceNode(Node, TLSBase);
Index: cfe/trunk/include/clang/Basic/BuiltinsWebAssembly.def
===
--- cfe/trunk/include/clang/Basic/BuiltinsWebAssembly.def
+++ cfe/trunk/include/clang/Basic/BuiltinsWebAssembly.def
@@ -31,7 +31,7 @@
 
 // Thread-local storage
 TARGET_BUILTIN(__builtin_wasm_tls_size, "z", "nc", "bulk-memory")
-TARGET_BUILTIN(__builtin_wasm_tls_base, "v*", "n", "bulk-memory")
+TARGET_BUILTIN(__builtin_wasm_tls_base, "v*", "nU", "bulk-memory")
 
 // Floating point min/max
 BUILTIN(__builtin_wasm_min_f32, "fff", "nc")
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64949: [WebAssembly] Fix __builtin_wasm_tls_base intrinsic

2019-07-18 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum created this revision.
quantum added reviewers: tlively, aheejin, sbc100, sunfish.
Herald added subscribers: llvm-commits, cfe-commits, hiraditya, 
jgravelle-google, dschuff.
Herald added projects: clang, LLVM.

Properly generate the outchain for the `__builtin_wasm_tls_base` intrinsic.

Also marked the intrinsic pure, per @sunfish's suggestion.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D64949

Files:
  clang/include/clang/Basic/BuiltinsWebAssembly.def
  llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp


Index: llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
===
--- llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
+++ llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
@@ -235,7 +235,7 @@
   assert(PtrVT == MVT::i32 && "only wasm32 is supported for now");
 
   MachineSDNode *TLSBase = CurDAG->getMachineNode(
-  WebAssembly::GLOBAL_GET_I32, DL, MVT::i32,
+  WebAssembly::GLOBAL_GET_I32, DL, MVT::i32, MVT::Other,
   CurDAG->getTargetExternalSymbol("__tls_base", PtrVT),
   Node->getOperand(0));
   ReplaceNode(Node, TLSBase);
Index: clang/include/clang/Basic/BuiltinsWebAssembly.def
===
--- clang/include/clang/Basic/BuiltinsWebAssembly.def
+++ clang/include/clang/Basic/BuiltinsWebAssembly.def
@@ -31,7 +31,7 @@
 
 // Thread-local storage
 TARGET_BUILTIN(__builtin_wasm_tls_size, "z", "nc", "bulk-memory")
-TARGET_BUILTIN(__builtin_wasm_tls_base, "v*", "n", "bulk-memory")
+TARGET_BUILTIN(__builtin_wasm_tls_base, "v*", "nU", "bulk-memory")
 
 // Floating point min/max
 BUILTIN(__builtin_wasm_min_f32, "fff", "nc")


Index: llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
===
--- llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
+++ llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
@@ -235,7 +235,7 @@
   assert(PtrVT == MVT::i32 && "only wasm32 is supported for now");
 
   MachineSDNode *TLSBase = CurDAG->getMachineNode(
-  WebAssembly::GLOBAL_GET_I32, DL, MVT::i32,
+  WebAssembly::GLOBAL_GET_I32, DL, MVT::i32, MVT::Other,
   CurDAG->getTargetExternalSymbol("__tls_base", PtrVT),
   Node->getOperand(0));
   ReplaceNode(Node, TLSBase);
Index: clang/include/clang/Basic/BuiltinsWebAssembly.def
===
--- clang/include/clang/Basic/BuiltinsWebAssembly.def
+++ clang/include/clang/Basic/BuiltinsWebAssembly.def
@@ -31,7 +31,7 @@
 
 // Thread-local storage
 TARGET_BUILTIN(__builtin_wasm_tls_size, "z", "nc", "bulk-memory")
-TARGET_BUILTIN(__builtin_wasm_tls_base, "v*", "n", "bulk-memory")
+TARGET_BUILTIN(__builtin_wasm_tls_base, "v*", "nU", "bulk-memory")
 
 // Floating point min/max
 BUILTIN(__builtin_wasm_min_f32, "fff", "nc")
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64900: [WebAssembly] Implement __builtin_wasm_tls_base intrinsic

2019-07-18 Thread Guanzhong Chen via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL366475: [WebAssembly] Implement __builtin_wasm_tls_base 
intrinsic (authored by quantum, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D64900?vs=210469=210632#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64900/new/

https://reviews.llvm.org/D64900

Files:
  cfe/trunk/include/clang/Basic/BuiltinsWebAssembly.def
  cfe/trunk/lib/CodeGen/CGBuiltin.cpp
  cfe/trunk/test/CodeGen/builtins-wasm.c
  llvm/trunk/include/llvm/IR/IntrinsicsWebAssembly.td
  llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
  llvm/trunk/test/CodeGen/WebAssembly/tls-general-dynamic.ll

Index: llvm/trunk/include/llvm/IR/IntrinsicsWebAssembly.td
===
--- llvm/trunk/include/llvm/IR/IntrinsicsWebAssembly.td
+++ llvm/trunk/include/llvm/IR/IntrinsicsWebAssembly.td
@@ -133,4 +133,9 @@
 [],
 [IntrNoMem, IntrSpeculatable]>;
 
+def int_wasm_tls_base :
+  Intrinsic<[llvm_ptr_ty],
+[],
+[IntrReadMem]>;
+
 } // TargetPrefix = "wasm"
Index: llvm/trunk/test/CodeGen/WebAssembly/tls-general-dynamic.ll
===
--- llvm/trunk/test/CodeGen/WebAssembly/tls-general-dynamic.ll
+++ llvm/trunk/test/CodeGen/WebAssembly/tls-general-dynamic.ll
@@ -75,6 +75,15 @@
   ret i32 %1
 }
 
+; CHECK-LABEL: tls_base:
+; CHECK-NEXT: .functype tls_base () -> (i32)
+define i8* @tls_base() {
+; CHECK-NEXT: global.get __tls_base
+; CHECK-NEXT: return
+  %1 = call i8* @llvm.wasm.tls.base()
+  ret i8* %1
+}
+
 ; CHECK: .type tls,@object
 ; TLS-NEXT: .section .tbss.tls,"",@
 ; NO-TLS-NEXT: .section .bss.tls,"",@
@@ -84,3 +93,4 @@
 @tls = internal thread_local global i32 0
 
 declare i32 @llvm.wasm.tls.size.i32()
+declare i8* @llvm.wasm.tls.base()
Index: llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
===
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
@@ -227,6 +227,23 @@
 }
 break;
   }
+  case ISD::INTRINSIC_W_CHAIN: {
+unsigned IntNo = cast(Node->getOperand(1))->getZExtValue();
+switch (IntNo) {
+case Intrinsic::wasm_tls_base: {
+  MVT PtrVT = TLI->getPointerTy(CurDAG->getDataLayout());
+  assert(PtrVT == MVT::i32 && "only wasm32 is supported for now");
+
+  MachineSDNode *TLSBase = CurDAG->getMachineNode(
+  WebAssembly::GLOBAL_GET_I32, DL, MVT::i32,
+  CurDAG->getTargetExternalSymbol("__tls_base", PtrVT),
+  Node->getOperand(0));
+  ReplaceNode(Node, TLSBase);
+  return;
+}
+}
+break;
+  }
 
   default:
 break;
Index: cfe/trunk/include/clang/Basic/BuiltinsWebAssembly.def
===
--- cfe/trunk/include/clang/Basic/BuiltinsWebAssembly.def
+++ cfe/trunk/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_base, "v*", "n", "bulk-memory")
 
 // Floating point min/max
 BUILTIN(__builtin_wasm_min_f32, "fff", "nc")
Index: cfe/trunk/test/CodeGen/builtins-wasm.c
===
--- cfe/trunk/test/CodeGen/builtins-wasm.c
+++ cfe/trunk/test/CodeGen/builtins-wasm.c
@@ -44,6 +44,11 @@
   // WEBASSEMBLY64: call i64 @llvm.wasm.tls.size.i64()
 }
 
+void *tls_base() {
+  return __builtin_wasm_tls_base();
+  // WEBASSEMBLY: call i8* @llvm.wasm.tls.base()
+}
+
 void throw(void *obj) {
   return __builtin_wasm_throw(0, obj);
   // WEBASSEMBLY32: call void @llvm.wasm.throw(i32 0, i8* %{{.*}})
Index: cfe/trunk/lib/CodeGen/CGBuiltin.cpp
===
--- cfe/trunk/lib/CodeGen/CGBuiltin.cpp
+++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp
@@ -13924,6 +13924,10 @@
 Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_tls_size, ResultType);
 return Builder.CreateCall(Callee);
   }
+  case WebAssembly::BI__builtin_wasm_tls_base: {
+Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_tls_base);
+return Builder.CreateCall(Callee);
+  }
   case WebAssembly::BI__builtin_wasm_throw: {
 Value *Tag = EmitScalarExpr(E->getArg(0));
 Value *Obj = EmitScalarExpr(E->getArg(1));
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64900: [WebAssembly] Implement __builtin_wasm_tls_base intrinsic

2019-07-18 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum added a comment.

In D64900#1590715 , @aheejin wrote:

> What does this return when `__wasm_init_tls` has not been called?


It returns `0`, which I think is fine.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64900/new/

https://reviews.llvm.org/D64900



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64900: [WebAssembly] Implement __builtin_wasm_tls_base intrinsic

2019-07-17 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum created this revision.
quantum added reviewers: tlively, aheejin, sbc100.
Herald added subscribers: llvm-commits, cfe-commits, sunfish, hiraditya, 
jgravelle-google, dschuff.
Herald added projects: clang, LLVM.

Add `__builtin_wasm_tls_base` so that LeakSanitizer can find the thread-local
block and scan through it for memory leaks.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D64900

Files:
  clang/include/clang/Basic/BuiltinsWebAssembly.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/test/CodeGen/builtins-wasm.c
  llvm/include/llvm/IR/IntrinsicsWebAssembly.td
  llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.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_base:
+; CHECK-NEXT: .functype tls_base () -> (i32)
+define i8* @tls_base() {
+; CHECK-NEXT: global.get __tls_base
+; CHECK-NEXT: return
+  %1 = call i8* @llvm.wasm.tls.base()
+  ret i8* %1
+}
+
 ; CHECK: .type tls,@object
 ; TLS-NEXT: .section .tbss.tls,"",@
 ; NO-TLS-NEXT: .section .bss.tls,"",@
@@ -84,3 +93,4 @@
 @tls = internal thread_local global i32 0
 
 declare i32 @llvm.wasm.tls.size.i32()
+declare i8* @llvm.wasm.tls.base()
Index: llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
===
--- llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
+++ llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
@@ -227,6 +227,23 @@
 }
 break;
   }
+  case ISD::INTRINSIC_W_CHAIN: {
+unsigned IntNo = cast(Node->getOperand(1))->getZExtValue();
+switch (IntNo) {
+case Intrinsic::wasm_tls_base: {
+  MVT PtrVT = TLI->getPointerTy(CurDAG->getDataLayout());
+  assert(PtrVT == MVT::i32 && "only wasm32 is supported for now");
+
+  MachineSDNode *TLSBase = CurDAG->getMachineNode(
+  WebAssembly::GLOBAL_GET_I32, DL, MVT::i32,
+  CurDAG->getTargetExternalSymbol("__tls_base", PtrVT),
+  Node->getOperand(0));
+  ReplaceNode(Node, TLSBase);
+  return;
+}
+}
+break;
+  }
 
   default:
 break;
Index: llvm/include/llvm/IR/IntrinsicsWebAssembly.td
===
--- llvm/include/llvm/IR/IntrinsicsWebAssembly.td
+++ llvm/include/llvm/IR/IntrinsicsWebAssembly.td
@@ -133,4 +133,9 @@
 [],
 [IntrNoMem, IntrSpeculatable]>;
 
+def int_wasm_tls_base :
+  Intrinsic<[llvm_ptr_ty],
+[],
+[IntrReadMem]>;
+
 } // TargetPrefix = "wasm"
Index: clang/test/CodeGen/builtins-wasm.c
===
--- clang/test/CodeGen/builtins-wasm.c
+++ clang/test/CodeGen/builtins-wasm.c
@@ -44,6 +44,11 @@
   // WEBASSEMBLY64: call i64 @llvm.wasm.tls.size.i64()
 }
 
+void *tls_base() {
+  return __builtin_wasm_tls_base();
+  // WEBASSEMBLY: call i8* @llvm.wasm.tls.base()
+}
+
 void throw(void *obj) {
   return __builtin_wasm_throw(0, obj);
   // WEBASSEMBLY32: call void @llvm.wasm.throw(i32 0, i8* %{{.*}})
Index: clang/lib/CodeGen/CGBuiltin.cpp
===
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -13924,6 +13924,10 @@
 Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_tls_size, ResultType);
 return Builder.CreateCall(Callee);
   }
+  case WebAssembly::BI__builtin_wasm_tls_base: {
+Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_tls_base);
+return Builder.CreateCall(Callee);
+  }
   case WebAssembly::BI__builtin_wasm_throw: {
 Value *Tag = EmitScalarExpr(E->getArg(0));
 Value *Obj = EmitScalarExpr(E->getArg(1));
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_base, "v*", "n", "bulk-memory")
 
 // Floating point min/max
 BUILTIN(__builtin_wasm_min_f32, "fff", "nc")
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64537: [WebAssembly] Implement thread-local storage (local-exec model)

2019-07-16 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum added a comment.

In D64537#1588699 , @dschuff wrote:

> I had a reply that got eaten here, so I'm going to keep trolling you on your 
> CL since we don't have a design doc for this.
>  The `offset` field of a data segment initializer can be a `global.get` on an 
> imported global.  
> (https://webassembly.github.io/spec/core/valid/instructions.html#constant-expressions).
>  Since each thread is separately instantiated with separate JS, we could have 
> a global import like `__tls_base` which has a different value in each thread. 
> Then we wouldn't need to manually call the init code anywhere. Would there be 
> other advantages or disadvantages for that?


I already answered this one:

In D64537#1586614 , @quantum wrote:

> In D64537#1586556 , @dschuff wrote:
>
> > The `offset` field of a segment can be a constant expression 
> > 
> >  which can be a `global.get` of an imported global. So we could have an 
> > imported global `__tls_base` which is different for each thread, and have 
> > an active segment with that as its segment offset?
>
>
> I didn't know that it could have been a constant expression. I don't think 
> this would have worked very well on the main thread though, since we need to 
> run `malloc` before we can compute `__tls_base`. I think this requires the 
> global to be mutable, if only because we need to be able to initialize it on 
> the main thread.


The problem I found with the import approach is that the main thread cannot use 
`global.get` of an imported global to get the location of TLS, mainly because 
it needs to be `malloc`'d. To use `malloc`, the main thread needs to be 
initialized. This will result in a circular dependency.


Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64537: [WebAssembly] Implement thread-local storage (local-exec model)

2019-07-16 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum updated this revision to Diff 210188.
quantum added a comment.

Disable atomics when TLS is stripped


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537

Files:
  clang/include/clang/Basic/BuiltinsWebAssembly.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/test/CodeGen/builtins-wasm.c
  lld/test/wasm/data-segments.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/BinaryFormat/Wasm.h
  llvm/include/llvm/IR/IntrinsicsWebAssembly.td
  llvm/include/llvm/MC/MCSectionWasm.h
  llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
  llvm/test/CodeGen/WebAssembly/target-features-tls.ll
  llvm/test/CodeGen/WebAssembly/tls.ll

Index: llvm/test/CodeGen/WebAssembly/tls.ll
===
--- llvm/test/CodeGen/WebAssembly/tls.ll
+++ llvm/test/CodeGen/WebAssembly/tls.ll
@@ -1,17 +1,82 @@
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck --check-prefix=SINGLE %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+bulk-memory | FileCheck %s --check-prefixes=CHECK,TLS
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+bulk-memory -fast-isel | FileCheck %s --check-prefixes=CHECK,TLS
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=-bulk-memory | FileCheck %s --check-prefixes=CHECK,NO-TLS
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
-; SINGLE-LABEL: address_of_tls:
+; CHECK-LABEL: address_of_tls:
+; CHECK-NEXT: .functype  address_of_tls () -> (i32)
 define i32 @address_of_tls() {
-  ; SINGLE: i32.const $push0=, tls
-  ; SINGLE-NEXT: return $pop0
+  ; TLS-DAG: global.get __tls_base
+  ; TLS-DAG: i32.const tls
+  ; TLS-NEXT: i32.add
+  ; TLS-NEXT: return
+
+  ; NO-TLS-NEXT: i32.const tls
+  ; NO-TLS-NEXT: return
   ret i32 ptrtoint(i32* @tls to i32)
 }
 
-; SINGLE: .type	tls,@object
-; SINGLE-NEXT: .section	.bss.tls,"",@
-; SINGLE-NEXT: .p2align 2
-; SINGLE-NEXT: tls:
-; SINGLE-NEXT: .int32 0
-@tls = internal thread_local global i32 0
+; CHECK-LABEL: ptr_to_tls:
+; CHECK-NEXT: .functype ptr_to_tls () -> (i32)
+define i32* @ptr_to_tls() {
+  ; TLS-DAG: global.get __tls_base
+  ; TLS-DAG: i32.const tls
+  ; TLS-NEXT: i32.add
+  ; TLS-NEXT: return
+
+  ; NO-TLS-NEXT: i32.const tls
+  ; NO-TLS-NEXT: return
+  ret i32* @tls
+}
+
+; CHECK-LABEL: tls_load:
+; CHECK-NEXT: .functype tls_load () -> (i32)
+define i32 @tls_load() {
+  ; TLS-DAG: global.get __tls_base
+  ; TLS-DAG: i32.const tls
+  ; TLS-NEXT: i32.add
+  ; TLS-NEXT: i32.load 0
+  ; TLS-NEXT: return
+
+  ; NO-TLS-NEXT: i32.const 0
+  ; NO-TLS-NEXT: i32.load tls
+  ; NO-TLS-NEXT: return
+  %tmp = load i32, i32* @tls, align 4
+  ret i32 %tmp
+}
+
+; CHECK-LABEL: tls_store:
+; CHECK-NEXT: .functype tls_store (i32) -> ()
+define void @tls_store(i32 %x) {
+  ; TLS-DAG: global.get __tls_base
+  ; TLS-DAG: i32.const tls
+  ; TLS-NEXT: i32.add
+  ; TLS-NEXT: i32.store 0
+  ; TLS-NEXT: return
+
+  ; NO-TLS-NEXT: i32.const 0
+  ; NO-TLS-NEXT: i32.store tls
+  ; NO-TLS-NEXT: return
+  store i32 %x, i32* @tls, align 4
+  ret void
+}
+
+; CHECK-LABEL: tls_size:
+; CHECK-NEXT: .functype tls_size () -> (i32)
+define i32 @tls_size() {
+; CHECK-NEXT: global.get __tls_size
+; CHECK-NEXT: return
+  %1 = call i32 @llvm.wasm.tls.size.i32()
+  ret i32 %1
+}
+
+; CHECK: .type tls,@object
+; TLS-NEXT: .section .tbss.tls,"",@
+; NO-TLS-NEXT: .section .bss.tls,"",@
+; CHECK-NEXT: .p2align 2
+; CHECK-NEXT: tls:
+; CHECK-NEXT: .int32 0
+@tls = internal thread_local(localexec) global i32 0
+
+declare i32 @llvm.wasm.tls.size.i32()
Index: llvm/test/CodeGen/WebAssembly/target-features-tls.ll
===
--- llvm/test/CodeGen/WebAssembly/target-features-tls.ll
+++ llvm/test/CodeGen/WebAssembly/target-features-tls.ll
@@ -1,5 +1,5 @@
-; RUN: llc < %s -mattr=-atomics | FileCheck %s --check-prefixes CHECK,NO-ATOMICS
-; RUN: llc < %s -mattr=+atomics | FileCheck %s --check-prefixes CHECK,ATOMICS
+; RUN: llc < %s -mattr=-bulk-memory | FileCheck %s --check-prefixes NO-BULK-MEM
+; RUN: llc < %s -mattr=+bulk-memory | FileCheck %s --check-prefixes BULK-MEM
 
 ; Test that the target features section contains -atomics or +atomics
 ; for modules that have thread local storage in their source.
@@ -9,18 +9,18 @@
 
 @foo = internal thread_local global i32 0
 
-; CHECK-LABEL: .custom_section.target_features,"",@
+; -bulk-memory
+; NO-BULK-MEM-LABEL: 

[PATCH] D64537: [WebAssembly] Implement thread-local storage (local-exec model)

2019-07-16 Thread Guanzhong Chen via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL366272: [WebAssembly] Implement thread-local storage 
(local-exec model) (authored by quantum, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D64537?vs=210188=210191#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537

Files:
  cfe/trunk/include/clang/Basic/BuiltinsWebAssembly.def
  cfe/trunk/lib/CodeGen/CGBuiltin.cpp
  cfe/trunk/test/CodeGen/builtins-wasm.c
  lld/trunk/test/wasm/data-segments.ll
  lld/trunk/test/wasm/tls.ll
  lld/trunk/wasm/Driver.cpp
  lld/trunk/wasm/Symbols.cpp
  lld/trunk/wasm/Symbols.h
  lld/trunk/wasm/Writer.cpp
  llvm/trunk/include/llvm/BinaryFormat/Wasm.h
  llvm/trunk/include/llvm/IR/IntrinsicsWebAssembly.td
  llvm/trunk/include/llvm/MC/MCSectionWasm.h
  llvm/trunk/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
  llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
  llvm/trunk/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
  llvm/trunk/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
  llvm/trunk/test/CodeGen/WebAssembly/target-features-tls.ll
  llvm/trunk/test/CodeGen/WebAssembly/tls.ll

Index: lld/trunk/wasm/Symbols.h
===
--- lld/trunk/wasm/Symbols.h
+++ lld/trunk/wasm/Symbols.h
@@ -426,6 +426,15 @@
   // linear memory.
   static GlobalSymbol *stackPointer;
 
+  // __tls_base
+  // Global that holds the address of the base of the current thread's
+  // TLS block.
+  static GlobalSymbol *tlsBase;
+
+  // __tls_size
+  // Symbol whose value is the size of the TLS block.
+  static GlobalSymbol *tlsSize;
+
   // __data_end
   // Symbol marking the end of the data and bss.
   static DefinedData *dataEnd;
@@ -448,6 +457,10 @@
   // Function that applies relocations to data segment post-instantiation.
   static DefinedFunction *applyRelocs;
 
+  // __wasm_init_tls
+  // Function that allocates thread-local storage and initializes it.
+  static DefinedFunction *initTLS;
+
   // __dso_handle
   // Symbol used in calls to __cxa_atexit to determine current DLL
   static DefinedData *dsoHandle;
Index: lld/trunk/wasm/Driver.cpp
===
--- lld/trunk/wasm/Driver.cpp
+++ lld/trunk/wasm/Driver.cpp
@@ -454,6 +454,7 @@
 // Create ABI-defined synthetic symbols
 static void createSyntheticSymbols() {
   static WasmSignature nullSignature = {{}, {}};
+  static WasmSignature i32ArgSignature = {{}, {ValType::I32}};
   static llvm::wasm::WasmGlobalType globalTypeI32 = {WASM_TYPE_I32, false};
   static llvm::wasm::WasmGlobalType mutableGlobalTypeI32 = {WASM_TYPE_I32,
 true};
@@ -516,6 +517,30 @@
 WasmSym::heapBase = symtab->addOptionalDataSymbol("__heap_base");
   }
 
+  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(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(tlsSizeGlobal, nullptr));
+
+WasmSym::initTLS = symtab->addSyntheticFunction(
+"__wasm_init_tls", WASM_SYMBOL_VISIBILITY_HIDDEN,
+make(i32ArgSignature, "__wasm_init_tls"));
+  }
+
   WasmSym::dsoHandle = symtab->addSyntheticDataSymbol(
   "__dso_handle", WASM_SYMBOL_VISIBILITY_HIDDEN);
 }
Index: lld/trunk/wasm/Symbols.cpp
===
--- lld/trunk/wasm/Symbols.cpp
+++ lld/trunk/wasm/Symbols.cpp
@@ -27,11 +27,14 @@
 DefinedFunction *WasmSym::callCtors;
 DefinedFunction *WasmSym::initMemory;
 DefinedFunction *WasmSym::applyRelocs;
+DefinedFunction *WasmSym::initTLS;
 DefinedData *WasmSym::dsoHandle;
 DefinedData *WasmSym::dataEnd;
 DefinedData *WasmSym::globalBase;
 DefinedData *WasmSym::heapBase;
 GlobalSymbol *WasmSym::stackPointer;
+GlobalSymbol *WasmSym::tlsBase;
+GlobalSymbol *WasmSym::tlsSize;
 UndefinedGlobal *WasmSym::tableBase;
 UndefinedGlobal *WasmSym::memoryBase;
 
@@ -200,8 +203,14 @@
 
 uint32_t DefinedData::getVirtualAddress() const {
   LLVM_DEBUG(dbgs() << "getVirtualAddress: " << getName() << "\n");
-  if (segment)
+  if (segment) {
+// For thread local data, the symbol location is relative to the start of
+// 

[PATCH] D64537: [WebAssembly] Implement thread-local storage (local-exec model)

2019-07-16 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum updated this revision to Diff 210187.
quantum added a comment.

Remove extra braces


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537

Files:
  clang/include/clang/Basic/BuiltinsWebAssembly.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/test/CodeGen/builtins-wasm.c
  lld/test/wasm/data-segments.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/BinaryFormat/Wasm.h
  llvm/include/llvm/IR/IntrinsicsWebAssembly.td
  llvm/include/llvm/MC/MCSectionWasm.h
  llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
  llvm/test/CodeGen/WebAssembly/target-features-tls.ll
  llvm/test/CodeGen/WebAssembly/tls.ll

Index: llvm/test/CodeGen/WebAssembly/tls.ll
===
--- llvm/test/CodeGen/WebAssembly/tls.ll
+++ llvm/test/CodeGen/WebAssembly/tls.ll
@@ -1,17 +1,82 @@
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck --check-prefix=SINGLE %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+bulk-memory | FileCheck %s --check-prefixes=CHECK,TLS
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+bulk-memory -fast-isel | FileCheck %s --check-prefixes=CHECK,TLS
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=-bulk-memory | FileCheck %s --check-prefixes=CHECK,NO-TLS
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
-; SINGLE-LABEL: address_of_tls:
+; CHECK-LABEL: address_of_tls:
+; CHECK-NEXT: .functype  address_of_tls () -> (i32)
 define i32 @address_of_tls() {
-  ; SINGLE: i32.const $push0=, tls
-  ; SINGLE-NEXT: return $pop0
+  ; TLS-DAG: global.get __tls_base
+  ; TLS-DAG: i32.const tls
+  ; TLS-NEXT: i32.add
+  ; TLS-NEXT: return
+
+  ; NO-TLS-NEXT: i32.const tls
+  ; NO-TLS-NEXT: return
   ret i32 ptrtoint(i32* @tls to i32)
 }
 
-; SINGLE: .type	tls,@object
-; SINGLE-NEXT: .section	.bss.tls,"",@
-; SINGLE-NEXT: .p2align 2
-; SINGLE-NEXT: tls:
-; SINGLE-NEXT: .int32 0
-@tls = internal thread_local global i32 0
+; CHECK-LABEL: ptr_to_tls:
+; CHECK-NEXT: .functype ptr_to_tls () -> (i32)
+define i32* @ptr_to_tls() {
+  ; TLS-DAG: global.get __tls_base
+  ; TLS-DAG: i32.const tls
+  ; TLS-NEXT: i32.add
+  ; TLS-NEXT: return
+
+  ; NO-TLS-NEXT: i32.const tls
+  ; NO-TLS-NEXT: return
+  ret i32* @tls
+}
+
+; CHECK-LABEL: tls_load:
+; CHECK-NEXT: .functype tls_load () -> (i32)
+define i32 @tls_load() {
+  ; TLS-DAG: global.get __tls_base
+  ; TLS-DAG: i32.const tls
+  ; TLS-NEXT: i32.add
+  ; TLS-NEXT: i32.load 0
+  ; TLS-NEXT: return
+
+  ; NO-TLS-NEXT: i32.const 0
+  ; NO-TLS-NEXT: i32.load tls
+  ; NO-TLS-NEXT: return
+  %tmp = load i32, i32* @tls, align 4
+  ret i32 %tmp
+}
+
+; CHECK-LABEL: tls_store:
+; CHECK-NEXT: .functype tls_store (i32) -> ()
+define void @tls_store(i32 %x) {
+  ; TLS-DAG: global.get __tls_base
+  ; TLS-DAG: i32.const tls
+  ; TLS-NEXT: i32.add
+  ; TLS-NEXT: i32.store 0
+  ; TLS-NEXT: return
+
+  ; NO-TLS-NEXT: i32.const 0
+  ; NO-TLS-NEXT: i32.store tls
+  ; NO-TLS-NEXT: return
+  store i32 %x, i32* @tls, align 4
+  ret void
+}
+
+; CHECK-LABEL: tls_size:
+; CHECK-NEXT: .functype tls_size () -> (i32)
+define i32 @tls_size() {
+; CHECK-NEXT: global.get __tls_size
+; CHECK-NEXT: return
+  %1 = call i32 @llvm.wasm.tls.size.i32()
+  ret i32 %1
+}
+
+; CHECK: .type tls,@object
+; TLS-NEXT: .section .tbss.tls,"",@
+; NO-TLS-NEXT: .section .bss.tls,"",@
+; CHECK-NEXT: .p2align 2
+; CHECK-NEXT: tls:
+; CHECK-NEXT: .int32 0
+@tls = internal thread_local(localexec) global i32 0
+
+declare i32 @llvm.wasm.tls.size.i32()
Index: llvm/test/CodeGen/WebAssembly/target-features-tls.ll
===
--- llvm/test/CodeGen/WebAssembly/target-features-tls.ll
+++ llvm/test/CodeGen/WebAssembly/target-features-tls.ll
@@ -1,5 +1,5 @@
-; RUN: llc < %s -mattr=-atomics | FileCheck %s --check-prefixes CHECK,NO-ATOMICS
-; RUN: llc < %s -mattr=+atomics | FileCheck %s --check-prefixes CHECK,ATOMICS
+; RUN: llc < %s -mattr=-bulk-memory | FileCheck %s --check-prefixes NO-BULK-MEM
+; RUN: llc < %s -mattr=+bulk-memory | FileCheck %s --check-prefixes BULK-MEM
 
 ; Test that the target features section contains -atomics or +atomics
 ; for modules that have thread local storage in their source.
@@ -9,18 +9,18 @@
 
 @foo = internal thread_local global i32 0
 
-; CHECK-LABEL: .custom_section.target_features,"",@
+; -bulk-memory
+; NO-BULK-MEM-LABEL: 

[PATCH] D64537: [WebAssembly] Implement thread-local storage (local-exec model)

2019-07-16 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum updated this revision to Diff 210184.
quantum added a comment.

Removed the trailing `.`. I would add a test to make sure things work without 
`-fdata-sections`, but `this->Options.DataSections = true;` is hard-coded in 
`WebAssemblyTargetMachine.cpp`.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537

Files:
  clang/include/clang/Basic/BuiltinsWebAssembly.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/test/CodeGen/builtins-wasm.c
  lld/test/wasm/data-segments.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/BinaryFormat/Wasm.h
  llvm/include/llvm/IR/IntrinsicsWebAssembly.td
  llvm/include/llvm/MC/MCSectionWasm.h
  llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
  llvm/test/CodeGen/WebAssembly/target-features-tls.ll
  llvm/test/CodeGen/WebAssembly/tls.ll

Index: llvm/test/CodeGen/WebAssembly/tls.ll
===
--- llvm/test/CodeGen/WebAssembly/tls.ll
+++ llvm/test/CodeGen/WebAssembly/tls.ll
@@ -1,17 +1,82 @@
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck --check-prefix=SINGLE %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+bulk-memory | FileCheck %s --check-prefixes=CHECK,TLS
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+bulk-memory -fast-isel | FileCheck %s --check-prefixes=CHECK,TLS
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=-bulk-memory | FileCheck %s --check-prefixes=CHECK,NO-TLS
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
-; SINGLE-LABEL: address_of_tls:
+; CHECK-LABEL: address_of_tls:
+; CHECK-NEXT: .functype  address_of_tls () -> (i32)
 define i32 @address_of_tls() {
-  ; SINGLE: i32.const $push0=, tls
-  ; SINGLE-NEXT: return $pop0
+  ; TLS-DAG: global.get __tls_base
+  ; TLS-DAG: i32.const tls
+  ; TLS-NEXT: i32.add
+  ; TLS-NEXT: return
+
+  ; NO-TLS-NEXT: i32.const tls
+  ; NO-TLS-NEXT: return
   ret i32 ptrtoint(i32* @tls to i32)
 }
 
-; SINGLE: .type	tls,@object
-; SINGLE-NEXT: .section	.bss.tls,"",@
-; SINGLE-NEXT: .p2align 2
-; SINGLE-NEXT: tls:
-; SINGLE-NEXT: .int32 0
-@tls = internal thread_local global i32 0
+; CHECK-LABEL: ptr_to_tls:
+; CHECK-NEXT: .functype ptr_to_tls () -> (i32)
+define i32* @ptr_to_tls() {
+  ; TLS-DAG: global.get __tls_base
+  ; TLS-DAG: i32.const tls
+  ; TLS-NEXT: i32.add
+  ; TLS-NEXT: return
+
+  ; NO-TLS-NEXT: i32.const tls
+  ; NO-TLS-NEXT: return
+  ret i32* @tls
+}
+
+; CHECK-LABEL: tls_load:
+; CHECK-NEXT: .functype tls_load () -> (i32)
+define i32 @tls_load() {
+  ; TLS-DAG: global.get __tls_base
+  ; TLS-DAG: i32.const tls
+  ; TLS-NEXT: i32.add
+  ; TLS-NEXT: i32.load 0
+  ; TLS-NEXT: return
+
+  ; NO-TLS-NEXT: i32.const 0
+  ; NO-TLS-NEXT: i32.load tls
+  ; NO-TLS-NEXT: return
+  %tmp = load i32, i32* @tls, align 4
+  ret i32 %tmp
+}
+
+; CHECK-LABEL: tls_store:
+; CHECK-NEXT: .functype tls_store (i32) -> ()
+define void @tls_store(i32 %x) {
+  ; TLS-DAG: global.get __tls_base
+  ; TLS-DAG: i32.const tls
+  ; TLS-NEXT: i32.add
+  ; TLS-NEXT: i32.store 0
+  ; TLS-NEXT: return
+
+  ; NO-TLS-NEXT: i32.const 0
+  ; NO-TLS-NEXT: i32.store tls
+  ; NO-TLS-NEXT: return
+  store i32 %x, i32* @tls, align 4
+  ret void
+}
+
+; CHECK-LABEL: tls_size:
+; CHECK-NEXT: .functype tls_size () -> (i32)
+define i32 @tls_size() {
+; CHECK-NEXT: global.get __tls_size
+; CHECK-NEXT: return
+  %1 = call i32 @llvm.wasm.tls.size.i32()
+  ret i32 %1
+}
+
+; CHECK: .type tls,@object
+; TLS-NEXT: .section .tbss.tls,"",@
+; NO-TLS-NEXT: .section .bss.tls,"",@
+; CHECK-NEXT: .p2align 2
+; CHECK-NEXT: tls:
+; CHECK-NEXT: .int32 0
+@tls = internal thread_local(localexec) global i32 0
+
+declare i32 @llvm.wasm.tls.size.i32()
Index: llvm/test/CodeGen/WebAssembly/target-features-tls.ll
===
--- llvm/test/CodeGen/WebAssembly/target-features-tls.ll
+++ llvm/test/CodeGen/WebAssembly/target-features-tls.ll
@@ -1,5 +1,5 @@
-; RUN: llc < %s -mattr=-atomics | FileCheck %s --check-prefixes CHECK,NO-ATOMICS
-; RUN: llc < %s -mattr=+atomics | FileCheck %s --check-prefixes CHECK,ATOMICS
+; RUN: llc < %s -mattr=-bulk-memory | FileCheck %s --check-prefixes NO-BULK-MEM
+; RUN: llc < %s -mattr=+bulk-memory | FileCheck %s --check-prefixes BULK-MEM
 
 ; Test that the target features section contains -atomics or +atomics
 ; for modules that have thread local storage in their source.
@@ -9,18 +9,18 

[PATCH] D64537: [WebAssembly] Implement thread-local storage (local-exec model)

2019-07-16 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum updated this revision to Diff 210166.
quantum added a comment.

More fine-grainted stripping.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537

Files:
  clang/include/clang/Basic/BuiltinsWebAssembly.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/test/CodeGen/builtins-wasm.c
  lld/test/wasm/data-segments.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/BinaryFormat/Wasm.h
  llvm/include/llvm/IR/IntrinsicsWebAssembly.td
  llvm/include/llvm/MC/MCSectionWasm.h
  llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
  llvm/test/CodeGen/WebAssembly/target-features-tls.ll
  llvm/test/CodeGen/WebAssembly/tls.ll

Index: llvm/test/CodeGen/WebAssembly/tls.ll
===
--- llvm/test/CodeGen/WebAssembly/tls.ll
+++ llvm/test/CodeGen/WebAssembly/tls.ll
@@ -1,17 +1,82 @@
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck --check-prefix=SINGLE %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+bulk-memory | FileCheck %s --check-prefixes=CHECK,TLS
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+bulk-memory -fast-isel | FileCheck %s --check-prefixes=CHECK,TLS
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=-bulk-memory | FileCheck %s --check-prefixes=CHECK,NO-TLS
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
-; SINGLE-LABEL: address_of_tls:
+; CHECK-LABEL: address_of_tls:
+; CHECK-NEXT: .functype  address_of_tls () -> (i32)
 define i32 @address_of_tls() {
-  ; SINGLE: i32.const $push0=, tls
-  ; SINGLE-NEXT: return $pop0
+  ; TLS-DAG: global.get __tls_base
+  ; TLS-DAG: i32.const tls
+  ; TLS-NEXT: i32.add
+  ; TLS-NEXT: return
+
+  ; NO-TLS-NEXT: i32.const tls
+  ; NO-TLS-NEXT: return
   ret i32 ptrtoint(i32* @tls to i32)
 }
 
-; SINGLE: .type	tls,@object
-; SINGLE-NEXT: .section	.bss.tls,"",@
-; SINGLE-NEXT: .p2align 2
-; SINGLE-NEXT: tls:
-; SINGLE-NEXT: .int32 0
-@tls = internal thread_local global i32 0
+; CHECK-LABEL: ptr_to_tls:
+; CHECK-NEXT: .functype ptr_to_tls () -> (i32)
+define i32* @ptr_to_tls() {
+  ; TLS-DAG: global.get __tls_base
+  ; TLS-DAG: i32.const tls
+  ; TLS-NEXT: i32.add
+  ; TLS-NEXT: return
+
+  ; NO-TLS-NEXT: i32.const tls
+  ; NO-TLS-NEXT: return
+  ret i32* @tls
+}
+
+; CHECK-LABEL: tls_load:
+; CHECK-NEXT: .functype tls_load () -> (i32)
+define i32 @tls_load() {
+  ; TLS-DAG: global.get __tls_base
+  ; TLS-DAG: i32.const tls
+  ; TLS-NEXT: i32.add
+  ; TLS-NEXT: i32.load 0
+  ; TLS-NEXT: return
+
+  ; NO-TLS-NEXT: i32.const 0
+  ; NO-TLS-NEXT: i32.load tls
+  ; NO-TLS-NEXT: return
+  %tmp = load i32, i32* @tls, align 4
+  ret i32 %tmp
+}
+
+; CHECK-LABEL: tls_store:
+; CHECK-NEXT: .functype tls_store (i32) -> ()
+define void @tls_store(i32 %x) {
+  ; TLS-DAG: global.get __tls_base
+  ; TLS-DAG: i32.const tls
+  ; TLS-NEXT: i32.add
+  ; TLS-NEXT: i32.store 0
+  ; TLS-NEXT: return
+
+  ; NO-TLS-NEXT: i32.const 0
+  ; NO-TLS-NEXT: i32.store tls
+  ; NO-TLS-NEXT: return
+  store i32 %x, i32* @tls, align 4
+  ret void
+}
+
+; CHECK-LABEL: tls_size:
+; CHECK-NEXT: .functype tls_size () -> (i32)
+define i32 @tls_size() {
+; CHECK-NEXT: global.get __tls_size
+; CHECK-NEXT: return
+  %1 = call i32 @llvm.wasm.tls.size.i32()
+  ret i32 %1
+}
+
+; CHECK: .type tls,@object
+; TLS-NEXT: .section .tbss.tls,"",@
+; NO-TLS-NEXT: .section .bss.tls,"",@
+; CHECK-NEXT: .p2align 2
+; CHECK-NEXT: tls:
+; CHECK-NEXT: .int32 0
+@tls = internal thread_local(localexec) global i32 0
+
+declare i32 @llvm.wasm.tls.size.i32()
Index: llvm/test/CodeGen/WebAssembly/target-features-tls.ll
===
--- llvm/test/CodeGen/WebAssembly/target-features-tls.ll
+++ llvm/test/CodeGen/WebAssembly/target-features-tls.ll
@@ -1,5 +1,5 @@
-; RUN: llc < %s -mattr=-atomics | FileCheck %s --check-prefixes CHECK,NO-ATOMICS
-; RUN: llc < %s -mattr=+atomics | FileCheck %s --check-prefixes CHECK,ATOMICS
+; RUN: llc < %s -mattr=-bulk-memory | FileCheck %s --check-prefixes NO-BULK-MEM
+; RUN: llc < %s -mattr=+bulk-memory | FileCheck %s --check-prefixes BULK-MEM
 
 ; Test that the target features section contains -atomics or +atomics
 ; for modules that have thread local storage in their source.
@@ -9,18 +9,18 @@
 
 @foo = internal thread_local global i32 0
 
-; CHECK-LABEL: .custom_section.target_features,"",@
+; -bulk-memory
+; NO-BULK-MEM-LABEL: 

[PATCH] D64537: [WebAssembly] Implement thread-local storage (local-exec model)

2019-07-15 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum added a comment.

In D64537#1586809 , @aheejin wrote:

> Where should we call `__wasm_init_tls`, in case within a library?


Dynamic libraries are not supported by the local-exec TLS model. Support will 
be implemented later. The idea is that we'll have an `__ensure_tls_initialized` 
function that will `malloc` and `__wasm_init_tls` if `__tls_base == 0`.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64776: [WebAssembly] Compile all TLS on Emscripten as local-exec

2019-07-15 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum updated this revision to Diff 209996.
quantum added a comment.
Herald added subscribers: cfe-commits, jfb.
Herald added a project: clang.

Change to use TODO instead of XXX


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64776/new/

https://reviews.llvm.org/D64776

Files:
  clang/include/clang/Basic/BuiltinsWebAssembly.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/test/CodeGen/builtins-wasm.c
  lld/test/wasm/data-segments.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/BinaryFormat/Wasm.h
  llvm/include/llvm/IR/IntrinsicsWebAssembly.td
  llvm/include/llvm/MC/MCSectionWasm.h
  llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
  llvm/test/CodeGen/WebAssembly/atomic-fence.ll
  llvm/test/CodeGen/WebAssembly/atomic-mem-consistency.ll
  llvm/test/CodeGen/WebAssembly/atomic-rmw.ll
  llvm/test/CodeGen/WebAssembly/i32-load-store-alignment.ll
  llvm/test/CodeGen/WebAssembly/i64-load-store-alignment.ll
  llvm/test/CodeGen/WebAssembly/load-ext-atomic.ll
  llvm/test/CodeGen/WebAssembly/offset-atomics.ll
  llvm/test/CodeGen/WebAssembly/store-trunc-atomic.ll
  llvm/test/CodeGen/WebAssembly/target-features-tls.ll
  llvm/test/CodeGen/WebAssembly/target-features.ll
  llvm/test/CodeGen/WebAssembly/tls.ll

Index: llvm/test/CodeGen/WebAssembly/tls.ll
===
--- llvm/test/CodeGen/WebAssembly/tls.ll
+++ llvm/test/CodeGen/WebAssembly/tls.ll
@@ -1,17 +1,82 @@
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck --check-prefix=SINGLE %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+atomics,+bulk-memory | FileCheck %s --check-prefixes=CHECK,TLS
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+atomics,+bulk-memory -fast-isel | FileCheck %s --check-prefixes=CHECK,TLS
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+atomics,-bulk-memory | FileCheck %s --check-prefixes=CHECK,NO-TLS
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
-; SINGLE-LABEL: address_of_tls:
+; CHECK-LABEL: address_of_tls:
+; CHECK-NEXT: .functype  address_of_tls () -> (i32)
 define i32 @address_of_tls() {
-  ; SINGLE: i32.const $push0=, tls
-  ; SINGLE-NEXT: return $pop0
+  ; TLS-DAG: global.get __tls_base
+  ; TLS-DAG: i32.const tls
+  ; TLS-NEXT: i32.add
+  ; TLS-NEXT: return
+
+  ; NO-TLS-NEXT: i32.const tls
+  ; NO-TLS-NEXT: return
   ret i32 ptrtoint(i32* @tls to i32)
 }
 
-; SINGLE: .type	tls,@object
-; SINGLE-NEXT: .section	.bss.tls,"",@
-; SINGLE-NEXT: .p2align 2
-; SINGLE-NEXT: tls:
-; SINGLE-NEXT: .int32 0
-@tls = internal thread_local global i32 0
+; CHECK-LABEL: ptr_to_tls:
+; CHECK-NEXT: .functype ptr_to_tls () -> (i32)
+define i32* @ptr_to_tls() {
+  ; TLS-DAG: global.get __tls_base
+  ; TLS-DAG: i32.const tls
+  ; TLS-NEXT: i32.add
+  ; TLS-NEXT: return
+
+  ; NO-TLS-NEXT: i32.const tls
+  ; NO-TLS-NEXT: return
+  ret i32* @tls
+}
+
+; CHECK-LABEL: tls_load:
+; CHECK-NEXT: .functype tls_load () -> (i32)
+define i32 @tls_load() {
+  ; TLS-DAG: global.get __tls_base
+  ; TLS-DAG: i32.const tls
+  ; TLS-NEXT: i32.add
+  ; TLS-NEXT: i32.load 0
+  ; TLS-NEXT: return
+
+  ; NO-TLS-NEXT: i32.const 0
+  ; NO-TLS-NEXT: i32.load tls
+  ; NO-TLS-NEXT: return
+  %tmp = load i32, i32* @tls, align 4
+  ret i32 %tmp
+}
+
+; CHECK-LABEL: tls_store:
+; CHECK-NEXT: .functype tls_store (i32) -> ()
+define void @tls_store(i32 %x) {
+  ; TLS-DAG: global.get __tls_base
+  ; TLS-DAG: i32.const tls
+  ; TLS-NEXT: i32.add
+  ; TLS-NEXT: i32.store 0
+  ; TLS-NEXT: return
+
+  ; NO-TLS-NEXT: i32.const 0
+  ; NO-TLS-NEXT: i32.store tls
+  ; NO-TLS-NEXT: return
+  store i32 %x, i32* @tls, align 4
+  ret void
+}
+
+; CHECK-LABEL: tls_size:
+; CHECK-NEXT: .functype tls_size () -> (i32)
+define i32 @tls_size() {
+; CHECK-NEXT: global.get __tls_size
+; CHECK-NEXT: return
+  %1 = call i32 @llvm.wasm.tls.size.i32()
+  ret i32 %1
+}
+
+; CHECK: .type tls,@object
+; TLS-NEXT: .section .tbss.tls,"",@
+; NO-TLS-NEXT: .section .bss.tls,"",@
+; CHECK-NEXT: .p2align 2
+; CHECK-NEXT: tls:
+; CHECK-NEXT: .int32 0
+@tls = internal thread_local(localexec) global i32 0
+
+declare i32 @llvm.wasm.tls.size.i32()
Index: llvm/test/CodeGen/WebAssembly/target-features.ll
===
--- llvm/test/CodeGen/WebAssembly/target-features.ll
+++ llvm/test/CodeGen/WebAssembly/target-features.ll
@@ -23,7 +23,7 @@
   ret void
 }
 
-attributes #0 = { 

[PATCH] D64776: [WebAssembly] Compile all TLS on Emscripten as local-exec

2019-07-15 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum updated this revision to Diff 209997.
quantum added a comment.

Undo compressing the previous diff.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64776/new/

https://reviews.llvm.org/D64776

Files:
  llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp


Index: llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
===
--- llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
+++ llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
@@ -179,8 +179,14 @@
   report_fatal_error("cannot use thread-local storage without bulk memory",
  false);
 
+// Currently Emscripten does not support dynamic linking with threads.
+// Therefore, if we have thread-local storage, only the local-exec model
+// is possible.
+// TODO: remove this and implement proper TLS models once Emscripten
+// supports dynamic linking with threads.
 if (GA->getGlobal()->getThreadLocalMode() !=
-GlobalValue::LocalExecTLSModel) {
+GlobalValue::LocalExecTLSModel &&
+!Subtarget->getTargetTriple().isOSEmscripten()) {
   report_fatal_error("only -ftls-model=local-exec is supported for now",
  false);
 }


Index: llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
===
--- llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
+++ llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
@@ -179,8 +179,14 @@
   report_fatal_error("cannot use thread-local storage without bulk memory",
  false);
 
+// Currently Emscripten does not support dynamic linking with threads.
+// Therefore, if we have thread-local storage, only the local-exec model
+// is possible.
+// TODO: remove this and implement proper TLS models once Emscripten
+// supports dynamic linking with threads.
 if (GA->getGlobal()->getThreadLocalMode() !=
-GlobalValue::LocalExecTLSModel) {
+GlobalValue::LocalExecTLSModel &&
+!Subtarget->getTargetTriple().isOSEmscripten()) {
   report_fatal_error("only -ftls-model=local-exec is supported for now",
  false);
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64537: [WebAssembly] Implement thread-local storage (local-exec model)

2019-07-15 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum added a comment.

In D64537#1586577 , @dschuff wrote:

> Another high-level question (based just on reading the CL description): The 
> TLS-size intrinsic is per-function, does that mean that the tls-init function 
> is called for every function? are there just multiple TLS sections per object 
> file?


The TLS-size intrinsic returns the total size of TLS for the module it's called 
from. The initialization function initializes the TLS for the entire module.

In D64537#1586556 , @dschuff wrote:

> The `offset` field of a segment can be a constant expression 
> 
>  which can be a `global.get` of an imported global. So we could have an 
> imported global `__tls_base` which is different for each thread, and have an 
> active segment with that as its segment offset?


I didn't know that it could have been a constant expression. I don't think this 
would have worked very well on the main thread though, since we need to run 
`malloc` before we can compute `__tls_base`. I think this requires the global 
to be mutable, if only because we need to be able to initialize it on the main 
thread.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64537: [WebAssembly] Implement thread-local storage (local-exec model)

2019-07-15 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum updated this revision to Diff 209966.
quantum added a comment.

Fix duplicate end function


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537

Files:
  clang/include/clang/Basic/BuiltinsWebAssembly.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/test/CodeGen/builtins-wasm.c
  lld/test/wasm/data-segments.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/BinaryFormat/Wasm.h
  llvm/include/llvm/IR/IntrinsicsWebAssembly.td
  llvm/include/llvm/MC/MCSectionWasm.h
  llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
  llvm/test/CodeGen/WebAssembly/atomic-fence.ll
  llvm/test/CodeGen/WebAssembly/atomic-mem-consistency.ll
  llvm/test/CodeGen/WebAssembly/atomic-rmw.ll
  llvm/test/CodeGen/WebAssembly/i32-load-store-alignment.ll
  llvm/test/CodeGen/WebAssembly/i64-load-store-alignment.ll
  llvm/test/CodeGen/WebAssembly/load-ext-atomic.ll
  llvm/test/CodeGen/WebAssembly/offset-atomics.ll
  llvm/test/CodeGen/WebAssembly/store-trunc-atomic.ll
  llvm/test/CodeGen/WebAssembly/target-features-tls.ll
  llvm/test/CodeGen/WebAssembly/target-features.ll
  llvm/test/CodeGen/WebAssembly/tls.ll

Index: llvm/test/CodeGen/WebAssembly/tls.ll
===
--- llvm/test/CodeGen/WebAssembly/tls.ll
+++ llvm/test/CodeGen/WebAssembly/tls.ll
@@ -1,17 +1,82 @@
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck --check-prefix=SINGLE %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+atomics,+bulk-memory | FileCheck %s --check-prefixes=CHECK,TLS
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+atomics,+bulk-memory -fast-isel | FileCheck %s --check-prefixes=CHECK,TLS
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+atomics,-bulk-memory | FileCheck %s --check-prefixes=CHECK,NO-TLS
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
-; SINGLE-LABEL: address_of_tls:
+; CHECK-LABEL: address_of_tls:
+; CHECK-NEXT: .functype  address_of_tls () -> (i32)
 define i32 @address_of_tls() {
-  ; SINGLE: i32.const $push0=, tls
-  ; SINGLE-NEXT: return $pop0
+  ; TLS-DAG: global.get __tls_base
+  ; TLS-DAG: i32.const tls
+  ; TLS-NEXT: i32.add
+  ; TLS-NEXT: return
+
+  ; NO-TLS-NEXT: i32.const tls
+  ; NO-TLS-NEXT: return
   ret i32 ptrtoint(i32* @tls to i32)
 }
 
-; SINGLE: .type	tls,@object
-; SINGLE-NEXT: .section	.bss.tls,"",@
-; SINGLE-NEXT: .p2align 2
-; SINGLE-NEXT: tls:
-; SINGLE-NEXT: .int32 0
-@tls = internal thread_local global i32 0
+; CHECK-LABEL: ptr_to_tls:
+; CHECK-NEXT: .functype ptr_to_tls () -> (i32)
+define i32* @ptr_to_tls() {
+  ; TLS-DAG: global.get __tls_base
+  ; TLS-DAG: i32.const tls
+  ; TLS-NEXT: i32.add
+  ; TLS-NEXT: return
+
+  ; NO-TLS-NEXT: i32.const tls
+  ; NO-TLS-NEXT: return
+  ret i32* @tls
+}
+
+; CHECK-LABEL: tls_load:
+; CHECK-NEXT: .functype tls_load () -> (i32)
+define i32 @tls_load() {
+  ; TLS-DAG: global.get __tls_base
+  ; TLS-DAG: i32.const tls
+  ; TLS-NEXT: i32.add
+  ; TLS-NEXT: i32.load 0
+  ; TLS-NEXT: return
+
+  ; NO-TLS-NEXT: i32.const 0
+  ; NO-TLS-NEXT: i32.load tls
+  ; NO-TLS-NEXT: return
+  %tmp = load i32, i32* @tls, align 4
+  ret i32 %tmp
+}
+
+; CHECK-LABEL: tls_store:
+; CHECK-NEXT: .functype tls_store (i32) -> ()
+define void @tls_store(i32 %x) {
+  ; TLS-DAG: global.get __tls_base
+  ; TLS-DAG: i32.const tls
+  ; TLS-NEXT: i32.add
+  ; TLS-NEXT: i32.store 0
+  ; TLS-NEXT: return
+
+  ; NO-TLS-NEXT: i32.const 0
+  ; NO-TLS-NEXT: i32.store tls
+  ; NO-TLS-NEXT: return
+  store i32 %x, i32* @tls, align 4
+  ret void
+}
+
+; CHECK-LABEL: tls_size:
+; CHECK-NEXT: .functype tls_size () -> (i32)
+define i32 @tls_size() {
+; CHECK-NEXT: global.get __tls_size
+; CHECK-NEXT: return
+  %1 = call i32 @llvm.wasm.tls.size.i32()
+  ret i32 %1
+}
+
+; CHECK: .type tls,@object
+; TLS-NEXT: .section .tbss.tls,"",@
+; NO-TLS-NEXT: .section .bss.tls,"",@
+; CHECK-NEXT: .p2align 2
+; CHECK-NEXT: tls:
+; CHECK-NEXT: .int32 0
+@tls = internal thread_local(localexec) global i32 0
+
+declare i32 @llvm.wasm.tls.size.i32()
Index: llvm/test/CodeGen/WebAssembly/target-features.ll
===
--- llvm/test/CodeGen/WebAssembly/target-features.ll
+++ llvm/test/CodeGen/WebAssembly/target-features.ll
@@ -23,7 +23,7 @@
   ret void
 }
 
-attributes #0 = { "target-features"="+atomics" }
+attributes #0 = { "target-features"="+atomics,+bulk-memory" }
 

[PATCH] D64537: [WebAssembly] Implement thread-local storage (local-exec model)

2019-07-15 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum added inline comments.



Comment at: lld/test/wasm/data-segments.ll:7
 ; RUN: wasm-ld -no-gc-sections --no-entry --shared-memory --max-memory=131072 
%t.atomics.o -o %t.atomics.wasm
-; RUN: obj2yaml %t.atomics.wasm | FileCheck %s --check-prefix ACTIVE
+; RUN: obj2yaml %t.atomics.wasm | FileCheck %s --check-prefixes 
ACTIVE,ACTIVE-TLS
 

aheejin wrote:
> quantum wrote:
> > aheejin wrote:
> > > What is the difference between `ACTIVE` and `ACTIVE-TLS`? It looks we 
> > > don't have different build processes for them. And as what @sbc100 said, 
> > > can we exclude TLS from build?
> > `ACTIVE-TLS` is for builds with TLS enabled. Currently, we use 
> > `--shared-memory` to determine that, per @tlively's recommendation. The 
> > rationale is that we don't want even more flags that need to be passed in a 
> > proper threaded build.
> Then if we don't enable `--shared-memory`, we don't generate those globals? 
> Do we have a test for that?
Yes. In this file, the cases with `--check-prefix ACTIVE` will ensure that the 
fields are not generated.



Comment at: lld/wasm/Driver.cpp:543
+  "__wasm_init_tls", WASM_SYMBOL_VISIBILITY_HIDDEN,
+  make(I32ArgSignature, "__wasm_init_tls"));
+

tlively wrote:
> quantum wrote:
> > aheejin wrote:
> > > Does this TLS thing work when `Config->Shared == true`, i.e., do we 
> > > create TLS globals even when this is a library?
> > Since TLS is module specific (we can't allocate memory for other modules), 
> > we must in fact generate this symbol for every module. Shared library 
> > support will not be implemented in this diff, however.
> Until we do implement TLS for shared modules, would it make sense to omit 
> these globals and function from shared modules, since we can't use them in 
> that context anyway?
That would make sense for now.



Comment at: lld/wasm/Writer.cpp:638
+  if (Name.startswith(".tbss."))
+return ".tdata";
   return Name;

tlively wrote:
> quantum wrote:
> > tlively wrote:
> > > Does this mean we can't control whether .tdata or .tbss comes first? Is 
> > > that important for anything?
> > Yes, it does mean that. The only reason why .tbss is supposed to be 
> > separate is so that its memory can just be zeroed whereas .tdata has to 
> > have the bytes stored in the program image. Currently, we just explicitly 
> > store the zero bytes, so this won't be a problem.
> It would be really great if we could find a way to elide the .bss 0 bytes as 
> a code size optimization. Since we can't assume that the memory is already 
> zeroed the way we can with passive segments, perhaps we can use a memory.fill 
> instruction to zero the memory? Pursuing this in a follow-on CL should be 
> fine.
Yes, this is a good idea for a follow-on CL.



Comment at: lld/wasm/Writer.cpp:805
+  writeUleb128(os, 0, "num locals");
+  writeU8(os, WASM_OPCODE_END, "end function");
+}

tlively wrote:
> You could avoid duplicating these lines by making them unconditional.
Right.



Comment at: lld/wasm/Writer.cpp:905
+  if (config->sharedMemory)
+createInitTLSFunction();
+

tlively wrote:
> Can you remind me how the InitTLSFunction interacts with relocatable code? 
> I'm wondering if this should be called up in the condition with the other 
> synthetic functions.
I don't think it should. `__wasm_init_tls` initializes the TLS block for the 
current module only, so every shared library needs to have its own 
`__wasm_init_tls`.



Comment at: llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp:193
+
+if (!Features[WebAssembly::FeatureBulkMemory])
   Stripped |= stripThreadLocals(M);

tlively wrote:
> I just realized that if we have atomics but not bulk memory and TLS is 
> stripped, then we will be in the awkward situation of both using atomics and 
> disallowing atomics because the module is not thread safe. I think the best 
> solution would be to go back and forcibly strip both atomics and TLS if 
> either of them would be stripped.
Done.



Comment at: llvm/test/CodeGen/WebAssembly/tls.ll:2
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt 
-wasm-disable-explicit-locals -mattr=+bulk-memory | FileCheck %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt 
-wasm-disable-explicit-locals -mattr=+bulk-memory -fast-isel | FileCheck %s
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"

tlively wrote:
> It would be good to check the negative case, too, i.e with bulk-memory 
> disabled.
Done.



Comment at: llvm/test/CodeGen/WebAssembly/tls.ll:6
 
-; SINGLE-LABEL: address_of_tls:
+; CHECK-LABEL: address_of_tls:
 define i32 @address_of_tls() {

tlively wrote:
> Is `CHECK` still used as a prefix if it not listed in the invocation of 
> FileCheck?
Yes, 

[PATCH] D64537: [WebAssembly] Implement thread-local storage (local-exec model)

2019-07-15 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum updated this revision to Diff 209953.
quantum marked 16 inline comments as done.
quantum added a comment.

Deal with review comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537

Files:
  clang/include/clang/Basic/BuiltinsWebAssembly.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/test/CodeGen/builtins-wasm.c
  lld/test/wasm/data-segments.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/BinaryFormat/Wasm.h
  llvm/include/llvm/IR/IntrinsicsWebAssembly.td
  llvm/include/llvm/MC/MCSectionWasm.h
  llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
  llvm/test/CodeGen/WebAssembly/atomic-fence.ll
  llvm/test/CodeGen/WebAssembly/atomic-mem-consistency.ll
  llvm/test/CodeGen/WebAssembly/atomic-rmw.ll
  llvm/test/CodeGen/WebAssembly/i32-load-store-alignment.ll
  llvm/test/CodeGen/WebAssembly/i64-load-store-alignment.ll
  llvm/test/CodeGen/WebAssembly/load-ext-atomic.ll
  llvm/test/CodeGen/WebAssembly/offset-atomics.ll
  llvm/test/CodeGen/WebAssembly/store-trunc-atomic.ll
  llvm/test/CodeGen/WebAssembly/target-features-tls.ll
  llvm/test/CodeGen/WebAssembly/target-features.ll
  llvm/test/CodeGen/WebAssembly/tls.ll

Index: llvm/test/CodeGen/WebAssembly/tls.ll
===
--- llvm/test/CodeGen/WebAssembly/tls.ll
+++ llvm/test/CodeGen/WebAssembly/tls.ll
@@ -1,17 +1,82 @@
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck --check-prefix=SINGLE %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+atomics,+bulk-memory | FileCheck %s --check-prefixes=CHECK,TLS
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+atomics,+bulk-memory -fast-isel | FileCheck %s --check-prefixes=CHECK,TLS
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+atomics,-bulk-memory | FileCheck %s --check-prefixes=CHECK,NO-TLS
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
-; SINGLE-LABEL: address_of_tls:
+; CHECK-LABEL: address_of_tls:
+; CHECK-NEXT: .functype  address_of_tls () -> (i32)
 define i32 @address_of_tls() {
-  ; SINGLE: i32.const $push0=, tls
-  ; SINGLE-NEXT: return $pop0
+  ; TLS-DAG: global.get __tls_base
+  ; TLS-DAG: i32.const tls
+  ; TLS-NEXT: i32.add
+  ; TLS-NEXT: return
+
+  ; NO-TLS-NEXT: i32.const tls
+  ; NO-TLS-NEXT: return
   ret i32 ptrtoint(i32* @tls to i32)
 }
 
-; SINGLE: .type	tls,@object
-; SINGLE-NEXT: .section	.bss.tls,"",@
-; SINGLE-NEXT: .p2align 2
-; SINGLE-NEXT: tls:
-; SINGLE-NEXT: .int32 0
-@tls = internal thread_local global i32 0
+; CHECK-LABEL: ptr_to_tls:
+; CHECK-NEXT: .functype ptr_to_tls () -> (i32)
+define i32* @ptr_to_tls() {
+  ; TLS-DAG: global.get __tls_base
+  ; TLS-DAG: i32.const tls
+  ; TLS-NEXT: i32.add
+  ; TLS-NEXT: return
+
+  ; NO-TLS-NEXT: i32.const tls
+  ; NO-TLS-NEXT: return
+  ret i32* @tls
+}
+
+; CHECK-LABEL: tls_load:
+; CHECK-NEXT: .functype tls_load () -> (i32)
+define i32 @tls_load() {
+  ; TLS-DAG: global.get __tls_base
+  ; TLS-DAG: i32.const tls
+  ; TLS-NEXT: i32.add
+  ; TLS-NEXT: i32.load 0
+  ; TLS-NEXT: return
+
+  ; NO-TLS-NEXT: i32.const 0
+  ; NO-TLS-NEXT: i32.load tls
+  ; NO-TLS-NEXT: return
+  %tmp = load i32, i32* @tls, align 4
+  ret i32 %tmp
+}
+
+; CHECK-LABEL: tls_store:
+; CHECK-NEXT: .functype tls_store (i32) -> ()
+define void @tls_store(i32 %x) {
+  ; TLS-DAG: global.get __tls_base
+  ; TLS-DAG: i32.const tls
+  ; TLS-NEXT: i32.add
+  ; TLS-NEXT: i32.store 0
+  ; TLS-NEXT: return
+
+  ; NO-TLS-NEXT: i32.const 0
+  ; NO-TLS-NEXT: i32.store tls
+  ; NO-TLS-NEXT: return
+  store i32 %x, i32* @tls, align 4
+  ret void
+}
+
+; CHECK-LABEL: tls_size:
+; CHECK-NEXT: .functype tls_size () -> (i32)
+define i32 @tls_size() {
+; CHECK-NEXT: global.get __tls_size
+; CHECK-NEXT: return
+  %1 = call i32 @llvm.wasm.tls.size.i32()
+  ret i32 %1
+}
+
+; CHECK: .type tls,@object
+; TLS-NEXT: .section .tbss.tls,"",@
+; NO-TLS-NEXT: .section .bss.tls,"",@
+; CHECK-NEXT: .p2align 2
+; CHECK-NEXT: tls:
+; CHECK-NEXT: .int32 0
+@tls = internal thread_local(localexec) global i32 0
+
+declare i32 @llvm.wasm.tls.size.i32()
Index: llvm/test/CodeGen/WebAssembly/target-features.ll
===
--- llvm/test/CodeGen/WebAssembly/target-features.ll
+++ llvm/test/CodeGen/WebAssembly/target-features.ll
@@ -23,7 +23,7 @@
   ret void
 }
 
-attributes #0 = { "target-features"="+atomics" }
+attributes #0 = { 

[PATCH] D64537: [WebAssembly] Implement thread-local storage (local-exec model)

2019-07-12 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum added inline comments.



Comment at: lld/test/wasm/data-segments.ll:7
 ; RUN: wasm-ld -no-gc-sections --no-entry --shared-memory --max-memory=131072 
%t.atomics.o -o %t.atomics.wasm
-; RUN: obj2yaml %t.atomics.wasm | FileCheck %s --check-prefix ACTIVE
+; RUN: obj2yaml %t.atomics.wasm | FileCheck %s --check-prefixes 
ACTIVE,ACTIVE-TLS
 

aheejin wrote:
> What is the difference between `ACTIVE` and `ACTIVE-TLS`? It looks we don't 
> have different build processes for them. And as what @sbc100 said, can we 
> exclude TLS from build?
`ACTIVE-TLS` is for builds with TLS enabled. Currently, we use 
`--shared-memory` to determine that, per @tlively's recommendation. The 
rationale is that we don't want even more flags that need to be passed in a 
proper threaded build.



Comment at: lld/test/wasm/tls.ll:6
+@tls1 = thread_local(localexec) global i32 1, align 4
+@tls2 = thread_local(localexec) global i32 1, align 4
+

aheejin wrote:
> Can we possibly mix one non-tls global variable between `tls1` and `tls2`, 
> just to see they work together?
Done.



Comment at: lld/wasm/Writer.cpp:629
+  // Merge .tbss into .tdata so that they share the same offsets.
+  if (name.startswith(".tbss."))
+return ".tdata";

aheejin wrote:
> quantum wrote:
> > sbc100 wrote:
> > > Maybe write this as a single conditional so its clear even without this 
> > > comment?
> > Changed in latest diff.
> Has it been reflected? It says it has been changed but it doesn't look like 
> it has
I think you are commenting on an old version? It is a single condition on the 
latest version.



Comment at: lld/wasm/Writer.cpp:514
   if (G->getGlobalType()->Mutable) {
 // Only the __stack_pointer should ever be create as mutable.
+assert(G == WasmSym::StackPointer || G == WasmSym::TLSBase);

aheejin wrote:
> quantum wrote:
> > aheejin wrote:
> > > Now `__tls_base` is also mutable, I think we should fix the comment
> > Will do.
> PIng. It doesn't look like fixed yet
Looks like the fix got rebasing against the change that made everything 
lowerCamelCase. Going to do it again.



Comment at: llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp:203
+ReplaceUses(SDValue(Node, 0), SDValue(TLSAddress, 0));
+CurDAG->RemoveDeadNode(Node);
+return;

aheejin wrote:
> These two lines can be shortened to
> ```
> ReplaceNode(Node, TLSAddress);
> ```
> The same applies to the code below for `__tls_size` too.
Nice. I didn't know that was possible. Changing.



Comment at: llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp:208
+  case ISD::INTRINSIC_WO_CHAIN:
+switch (cast(Node->getOperand(0))->getZExtValue()) {
+case Intrinsic::wasm_tls_size: {

aheejin wrote:
> Nit: Might be a bit cleaner to extract the expression, which is complicated, 
> like
> ```
> unsigned IntNo = cast(Node->getOperand(0))->getZExtValue());
> switch (IntNo) {
>  ...
> ```
Done.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64537: [WebAssembly] Implement thread-local storage (local-exec model)

2019-07-12 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum updated this revision to Diff 209658.
quantum marked 14 inline comments as done.
quantum added a comment.

Change per review feedback.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537

Files:
  clang/include/clang/Basic/BuiltinsWebAssembly.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/test/CodeGen/builtins-wasm.c
  lld/test/wasm/data-segments.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/BinaryFormat/Wasm.h
  llvm/include/llvm/IR/IntrinsicsWebAssembly.td
  llvm/include/llvm/MC/MCSectionWasm.h
  llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
  llvm/test/CodeGen/WebAssembly/target-features-tls.ll
  llvm/test/CodeGen/WebAssembly/tls.ll

Index: llvm/test/CodeGen/WebAssembly/tls.ll
===
--- llvm/test/CodeGen/WebAssembly/tls.ll
+++ llvm/test/CodeGen/WebAssembly/tls.ll
@@ -1,17 +1,61 @@
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck --check-prefix=SINGLE %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+bulk-memory | FileCheck %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+bulk-memory -fast-isel | FileCheck %s
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
-; SINGLE-LABEL: address_of_tls:
+; CHECK-LABEL: address_of_tls:
 define i32 @address_of_tls() {
-  ; SINGLE: i32.const $push0=, tls
-  ; SINGLE-NEXT: return $pop0
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: return
   ret i32 ptrtoint(i32* @tls to i32)
 }
 
-; SINGLE: .type	tls,@object
-; SINGLE-NEXT: .section	.bss.tls,"",@
-; SINGLE-NEXT: .p2align 2
-; SINGLE-NEXT: tls:
-; SINGLE-NEXT: .int32 0
-@tls = internal thread_local global i32 0
+; CHECK-LABEL: ptr_to_tls
+define i32* @ptr_to_tls() {
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: return
+  ret i32* @tls
+}
+
+; CHECK-LABEL: tls_load
+define i32 @tls_load() {
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: i32.load 0
+  ; CHECK-NEXT: return
+  %tmp = load i32, i32* @tls, align 4
+  ret i32 %tmp
+}
+
+; CHECK-LABEL: tls_store
+define void @tls_store(i32 %x) {
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: i32.store 0
+  ; CHECK-NEXT: return
+  store i32 %x, i32* @tls, align 4
+  ret void
+}
+
+; CHECK-LABEL: tls_size:
+; CHECK-NEXT: .functype tls_size () -> (i32)
+; CHECK-NEXT: global.get __tls_size
+; CHECK-NEXT: return
+declare i32 @llvm.wasm.tls.size.i32()
+define i32 @tls_size() {
+  %1 = call i32 @llvm.wasm.tls.size.i32()
+  ret i32 %1
+}
+
+; CHECK: .type tls,@object
+; CHECK-NEXT: .section .tbss.tls,"",@
+; CHECK-NEXT: .p2align 2
+; CHECK-NEXT: tls:
+; CHECK-NEXT: .int32 0
+@tls = internal thread_local(localexec) global i32 0
Index: llvm/test/CodeGen/WebAssembly/target-features-tls.ll
===
--- llvm/test/CodeGen/WebAssembly/target-features-tls.ll
+++ llvm/test/CodeGen/WebAssembly/target-features-tls.ll
@@ -1,5 +1,5 @@
-; RUN: llc < %s -mattr=-atomics | FileCheck %s --check-prefixes CHECK,NO-ATOMICS
-; RUN: llc < %s -mattr=+atomics | FileCheck %s --check-prefixes CHECK,ATOMICS
+; RUN: llc < %s -mattr=-bulk-memory | FileCheck %s --check-prefixes NO-BULK-MEM
+; RUN: llc < %s -mattr=+bulk-memory | FileCheck %s --check-prefixes BULK-MEM
 
 ; Test that the target features section contains -atomics or +atomics
 ; for modules that have thread local storage in their source.
@@ -9,18 +9,19 @@
 
 @foo = internal thread_local global i32 0
 
-; CHECK-LABEL: .custom_section.target_features,"",@
 
-; -atomics
-; NO-ATOMICS-NEXT: .int8 1
-; NO-ATOMICS-NEXT: .int8 45
-; NO-ATOMICS-NEXT: .int8 7
-; NO-ATOMICS-NEXT: .ascii "atomics"
-; NO-ATOMICS-NEXT: .bss.foo,"",@
+; -bulk-memory
+; NO-BULK-MEM-LABEL: .custom_section.target_features,"",@
+; NO-BULK-MEM-NEXT: .int8 1
+; NO-BULK-MEM-NEXT: .int8 45
+; NO-BULK-MEM-NEXT: .int8 7
+; NO-BULK-MEM-NEXT: .ascii "atomics"
+; NO-BULK-MEM-NEXT: .bss.foo,"",@
 
-; +atomics
-; ATOMICS-NEXT: .int8 1
-; ATOMICS-NEXT: .int8 43
-; ATOMICS-NEXT: .int8 7
-; ATOMICS-NEXT: .ascii "atomics"
-; ATOMICS-NEXT: .tbss.foo,"",@
+; +bulk-memory
+; BULK-MEM-LABEL: .custom_section.target_features,"",@
+; BULK-MEM-NEXT: .int8 1
+; BULK-MEM-NEXT: .int8 43
+; BULK-MEM-NEXT: .int8 11
+; BULK-MEM-NEXT: 

[PATCH] D64537: [WebAssembly] Implement thread-local storage (local-exec model)

2019-07-12 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum updated this revision to Diff 209656.
quantum added a comment.

Use signed LEB128 for `i32.const`. Basically, do what D64612 
 did.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537

Files:
  clang/include/clang/Basic/BuiltinsWebAssembly.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/test/CodeGen/builtins-wasm.c
  lld/test/wasm/data-segments.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/BinaryFormat/Wasm.h
  llvm/include/llvm/IR/IntrinsicsWebAssembly.td
  llvm/include/llvm/MC/MCSectionWasm.h
  llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
  llvm/test/CodeGen/WebAssembly/target-features-tls.ll
  llvm/test/CodeGen/WebAssembly/tls.ll

Index: llvm/test/CodeGen/WebAssembly/tls.ll
===
--- llvm/test/CodeGen/WebAssembly/tls.ll
+++ llvm/test/CodeGen/WebAssembly/tls.ll
@@ -1,17 +1,61 @@
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck --check-prefix=SINGLE %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+bulk-memory | FileCheck %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+bulk-memory -fast-isel | FileCheck %s
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
-; SINGLE-LABEL: address_of_tls:
+; CHECK-LABEL: address_of_tls:
 define i32 @address_of_tls() {
-  ; SINGLE: i32.const $push0=, tls
-  ; SINGLE-NEXT: return $pop0
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: return
   ret i32 ptrtoint(i32* @tls to i32)
 }
 
-; SINGLE: .type	tls,@object
-; SINGLE-NEXT: .section	.bss.tls,"",@
-; SINGLE-NEXT: .p2align 2
-; SINGLE-NEXT: tls:
-; SINGLE-NEXT: .int32 0
-@tls = internal thread_local global i32 0
+; CHECK-LABEL: ptr_to_tls
+define i32* @ptr_to_tls() {
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: return
+  ret i32* @tls
+}
+
+; CHECK-LABEL: tls_load
+define i32 @tls_load() {
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: i32.load 0
+  ; CHECK-NEXT: return
+  %tmp = load i32, i32* @tls, align 4
+  ret i32 %tmp
+}
+
+; CHECK-LABEL: tls_store
+define void @tls_store(i32 %x) {
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: i32.store 0
+  ; CHECK-NEXT: return
+  store i32 %x, i32* @tls, align 4
+  ret void
+}
+
+; CHECK-LABEL: tls_size:
+; CHECK-NEXT: .functype tls_size () -> (i32)
+; CHECK-NEXT: global.get __tls_size
+; CHECK-NEXT: return
+declare i32 @llvm.wasm.tls.size.i32()
+define i32 @tls_size() {
+  %1 = call i32 @llvm.wasm.tls.size.i32()
+  ret i32 %1
+}
+
+; CHECK: .type tls,@object
+; CHECK-NEXT: .section .tbss.tls,"",@
+; CHECK-NEXT: .p2align 2
+; CHECK-NEXT: tls:
+; CHECK-NEXT: .int32 0
+@tls = internal thread_local(localexec) global i32 0
Index: llvm/test/CodeGen/WebAssembly/target-features-tls.ll
===
--- llvm/test/CodeGen/WebAssembly/target-features-tls.ll
+++ llvm/test/CodeGen/WebAssembly/target-features-tls.ll
@@ -1,5 +1,5 @@
-; RUN: llc < %s -mattr=-atomics | FileCheck %s --check-prefixes CHECK,NO-ATOMICS
-; RUN: llc < %s -mattr=+atomics | FileCheck %s --check-prefixes CHECK,ATOMICS
+; RUN: llc < %s -mattr=-bulk-memory | FileCheck %s --check-prefixes NO-BULK-MEM
+; RUN: llc < %s -mattr=+bulk-memory | FileCheck %s --check-prefixes BULK-MEM
 
 ; Test that the target features section contains -atomics or +atomics
 ; for modules that have thread local storage in their source.
@@ -9,18 +9,19 @@
 
 @foo = internal thread_local global i32 0
 
-; CHECK-LABEL: .custom_section.target_features,"",@
 
-; -atomics
-; NO-ATOMICS-NEXT: .int8 1
-; NO-ATOMICS-NEXT: .int8 45
-; NO-ATOMICS-NEXT: .int8 7
-; NO-ATOMICS-NEXT: .ascii "atomics"
-; NO-ATOMICS-NEXT: .bss.foo,"",@
+; -bulk-memory
+; NO-BULK-MEM-LABEL: .custom_section.target_features,"",@
+; NO-BULK-MEM-NEXT: .int8 1
+; NO-BULK-MEM-NEXT: .int8 45
+; NO-BULK-MEM-NEXT: .int8 7
+; NO-BULK-MEM-NEXT: .ascii "atomics"
+; NO-BULK-MEM-NEXT: .bss.foo,"",@
 
-; +atomics
-; ATOMICS-NEXT: .int8 1
-; ATOMICS-NEXT: .int8 43
-; ATOMICS-NEXT: .int8 7
-; ATOMICS-NEXT: .ascii "atomics"
-; ATOMICS-NEXT: .tbss.foo,"",@
+; +bulk-memory
+; BULK-MEM-LABEL: .custom_section.target_features,"",@
+; BULK-MEM-NEXT: .int8 1
+; BULK-MEM-NEXT: .int8 43
+; 

[PATCH] D64537: [WebAssembly] Implement thread-local storage (local-exec model)

2019-07-12 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum added a comment.

In D64537#1584069 , @dschuff wrote:

> Oh, btw, any reason these have to be passive segments? Why can't we just make 
> them active segments and let the VM initialize them for us?


These need to be passive segments so that we can initialize it in different 
locations in linear memory for every thread.

If we had multiple memories, TLS could have been implemented as a separate 
linear memory, but we are stuck with `malloc`ing and initializing for now.

In D64537#1584067 , @dschuff wrote:

> If there's any chance this TLS ABI could be useful for WASI (I don't know if 
> there's been any WASI work on threads yet, but it seems like there's no 
> reason it couldn't be), then we should start a doc in tool-conventions for 
> it. If not then we should get it behind the emscripten OS in LLVM. (and 
> document it anyway; either in tool-conventions or somewhere in the emscripten 
> site).


Documenting this in tool-conventions is planned.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64537: [WebAssembly] Implement thread-local storage (local-exec model)

2019-07-12 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum added a comment.

@sbc100 As for `__tls_base` being immutable, I am not sure how this will 
interact with dynamic linking once we implement it. On native platforms, 
`dlopen`ed libraries have their TLS blocks allocated on first use.

What exactly happens to `dlopen`ed libraries when there are already threads 
around? Would it be feasible to create TLS blocks for when the library is 
loaded on existing thread?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64537: [WebAssembly] Implement thread-local storage (local-exec model)

2019-07-12 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum updated this revision to Diff 209566.
quantum added a comment.

Don't show a crash report for incorrect flags to use TLS


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537

Files:
  clang/include/clang/Basic/BuiltinsWebAssembly.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/test/CodeGen/builtins-wasm.c
  lld/test/wasm/data-segments.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/BinaryFormat/Wasm.h
  llvm/include/llvm/IR/IntrinsicsWebAssembly.td
  llvm/include/llvm/MC/MCSectionWasm.h
  llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
  llvm/test/CodeGen/WebAssembly/target-features-tls.ll
  llvm/test/CodeGen/WebAssembly/tls.ll

Index: llvm/test/CodeGen/WebAssembly/tls.ll
===
--- llvm/test/CodeGen/WebAssembly/tls.ll
+++ llvm/test/CodeGen/WebAssembly/tls.ll
@@ -1,17 +1,61 @@
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck --check-prefix=SINGLE %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+bulk-memory | FileCheck %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+bulk-memory -fast-isel | FileCheck %s
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
-; SINGLE-LABEL: address_of_tls:
+; CHECK-LABEL: address_of_tls:
 define i32 @address_of_tls() {
-  ; SINGLE: i32.const $push0=, tls
-  ; SINGLE-NEXT: return $pop0
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: return
   ret i32 ptrtoint(i32* @tls to i32)
 }
 
-; SINGLE: .type	tls,@object
-; SINGLE-NEXT: .section	.bss.tls,"",@
-; SINGLE-NEXT: .p2align 2
-; SINGLE-NEXT: tls:
-; SINGLE-NEXT: .int32 0
-@tls = internal thread_local global i32 0
+; CHECK-LABEL: ptr_to_tls
+define i32* @ptr_to_tls() {
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: return
+  ret i32* @tls
+}
+
+; CHECK-LABEL: tls_load
+define i32 @tls_load() {
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: i32.load 0
+  ; CHECK-NEXT: return
+  %tmp = load i32, i32* @tls, align 4
+  ret i32 %tmp
+}
+
+; CHECK-LABEL: tls_store
+define void @tls_store(i32 %x) {
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: i32.store 0
+  ; CHECK-NEXT: return
+  store i32 %x, i32* @tls, align 4
+  ret void
+}
+
+; CHECK-LABEL: tls_size:
+; CHECK-NEXT: .functype tls_size () -> (i32)
+; CHECK-NEXT: global.get __tls_size
+; CHECK-NEXT: return
+declare i32 @llvm.wasm.tls.size.i32()
+define i32 @tls_size() {
+  %1 = call i32 @llvm.wasm.tls.size.i32()
+  ret i32 %1
+}
+
+; CHECK: .type tls,@object
+; CHECK-NEXT: .section .tbss.tls,"",@
+; CHECK-NEXT: .p2align 2
+; CHECK-NEXT: tls:
+; CHECK-NEXT: .int32 0
+@tls = internal thread_local(localexec) global i32 0
Index: llvm/test/CodeGen/WebAssembly/target-features-tls.ll
===
--- llvm/test/CodeGen/WebAssembly/target-features-tls.ll
+++ llvm/test/CodeGen/WebAssembly/target-features-tls.ll
@@ -1,5 +1,5 @@
-; RUN: llc < %s -mattr=-atomics | FileCheck %s --check-prefixes CHECK,NO-ATOMICS
-; RUN: llc < %s -mattr=+atomics | FileCheck %s --check-prefixes CHECK,ATOMICS
+; RUN: llc < %s -mattr=-bulk-memory | FileCheck %s --check-prefixes NO-BULK-MEM
+; RUN: llc < %s -mattr=+bulk-memory | FileCheck %s --check-prefixes BULK-MEM
 
 ; Test that the target features section contains -atomics or +atomics
 ; for modules that have thread local storage in their source.
@@ -9,18 +9,19 @@
 
 @foo = internal thread_local global i32 0
 
-; CHECK-LABEL: .custom_section.target_features,"",@
 
-; -atomics
-; NO-ATOMICS-NEXT: .int8 1
-; NO-ATOMICS-NEXT: .int8 45
-; NO-ATOMICS-NEXT: .int8 7
-; NO-ATOMICS-NEXT: .ascii "atomics"
-; NO-ATOMICS-NEXT: .bss.foo,"",@
+; -bulk-memory
+; NO-BULK-MEM-LABEL: .custom_section.target_features,"",@
+; NO-BULK-MEM-NEXT: .int8 1
+; NO-BULK-MEM-NEXT: .int8 45
+; NO-BULK-MEM-NEXT: .int8 7
+; NO-BULK-MEM-NEXT: .ascii "atomics"
+; NO-BULK-MEM-NEXT: .bss.foo,"",@
 
-; +atomics
-; ATOMICS-NEXT: .int8 1
-; ATOMICS-NEXT: .int8 43
-; ATOMICS-NEXT: .int8 7
-; ATOMICS-NEXT: .ascii "atomics"
-; ATOMICS-NEXT: .tbss.foo,"",@
+; +bulk-memory
+; BULK-MEM-LABEL: .custom_section.target_features,"",@
+; BULK-MEM-NEXT: .int8 1
+; BULK-MEM-NEXT: .int8 43
+; BULK-MEM-NEXT: .int8 11
+; BULK-MEM-NEXT: .ascii 

[PATCH] D64537: [WebAssembly] Implement thread-local storage (local-exec model)

2019-07-12 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum updated this revision to Diff 209560.
quantum marked an inline comment as done.
quantum added a comment.

Switch to using ISelDAGToDAG instead of ISelLowering


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537

Files:
  clang/include/clang/Basic/BuiltinsWebAssembly.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/test/CodeGen/builtins-wasm.c
  lld/test/wasm/data-segments.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/BinaryFormat/Wasm.h
  llvm/include/llvm/IR/IntrinsicsWebAssembly.td
  llvm/include/llvm/MC/MCSectionWasm.h
  llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
  llvm/test/CodeGen/WebAssembly/target-features-tls.ll
  llvm/test/CodeGen/WebAssembly/tls.ll

Index: llvm/test/CodeGen/WebAssembly/tls.ll
===
--- llvm/test/CodeGen/WebAssembly/tls.ll
+++ llvm/test/CodeGen/WebAssembly/tls.ll
@@ -1,17 +1,61 @@
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck --check-prefix=SINGLE %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+bulk-memory | FileCheck %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+bulk-memory -fast-isel | FileCheck %s
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
-; SINGLE-LABEL: address_of_tls:
+; CHECK-LABEL: address_of_tls:
 define i32 @address_of_tls() {
-  ; SINGLE: i32.const $push0=, tls
-  ; SINGLE-NEXT: return $pop0
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: return
   ret i32 ptrtoint(i32* @tls to i32)
 }
 
-; SINGLE: .type	tls,@object
-; SINGLE-NEXT: .section	.bss.tls,"",@
-; SINGLE-NEXT: .p2align 2
-; SINGLE-NEXT: tls:
-; SINGLE-NEXT: .int32 0
-@tls = internal thread_local global i32 0
+; CHECK-LABEL: ptr_to_tls
+define i32* @ptr_to_tls() {
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: return
+  ret i32* @tls
+}
+
+; CHECK-LABEL: tls_load
+define i32 @tls_load() {
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: i32.load 0
+  ; CHECK-NEXT: return
+  %tmp = load i32, i32* @tls, align 4
+  ret i32 %tmp
+}
+
+; CHECK-LABEL: tls_store
+define void @tls_store(i32 %x) {
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: i32.store 0
+  ; CHECK-NEXT: return
+  store i32 %x, i32* @tls, align 4
+  ret void
+}
+
+; CHECK-LABEL: tls_size:
+; CHECK-NEXT: .functype tls_size () -> (i32)
+; CHECK-NEXT: global.get __tls_size
+; CHECK-NEXT: return
+declare i32 @llvm.wasm.tls.size.i32()
+define i32 @tls_size() {
+  %1 = call i32 @llvm.wasm.tls.size.i32()
+  ret i32 %1
+}
+
+; CHECK: .type tls,@object
+; CHECK-NEXT: .section .tbss.tls,"",@
+; CHECK-NEXT: .p2align 2
+; CHECK-NEXT: tls:
+; CHECK-NEXT: .int32 0
+@tls = internal thread_local(localexec) global i32 0
Index: llvm/test/CodeGen/WebAssembly/target-features-tls.ll
===
--- llvm/test/CodeGen/WebAssembly/target-features-tls.ll
+++ llvm/test/CodeGen/WebAssembly/target-features-tls.ll
@@ -1,5 +1,5 @@
-; RUN: llc < %s -mattr=-atomics | FileCheck %s --check-prefixes CHECK,NO-ATOMICS
-; RUN: llc < %s -mattr=+atomics | FileCheck %s --check-prefixes CHECK,ATOMICS
+; RUN: llc < %s -mattr=-bulk-memory | FileCheck %s --check-prefixes NO-BULK-MEM
+; RUN: llc < %s -mattr=+bulk-memory | FileCheck %s --check-prefixes BULK-MEM
 
 ; Test that the target features section contains -atomics or +atomics
 ; for modules that have thread local storage in their source.
@@ -9,18 +9,19 @@
 
 @foo = internal thread_local global i32 0
 
-; CHECK-LABEL: .custom_section.target_features,"",@
 
-; -atomics
-; NO-ATOMICS-NEXT: .int8 1
-; NO-ATOMICS-NEXT: .int8 45
-; NO-ATOMICS-NEXT: .int8 7
-; NO-ATOMICS-NEXT: .ascii "atomics"
-; NO-ATOMICS-NEXT: .bss.foo,"",@
+; -bulk-memory
+; NO-BULK-MEM-LABEL: .custom_section.target_features,"",@
+; NO-BULK-MEM-NEXT: .int8 1
+; NO-BULK-MEM-NEXT: .int8 45
+; NO-BULK-MEM-NEXT: .int8 7
+; NO-BULK-MEM-NEXT: .ascii "atomics"
+; NO-BULK-MEM-NEXT: .bss.foo,"",@
 
-; +atomics
-; ATOMICS-NEXT: .int8 1
-; ATOMICS-NEXT: .int8 43
-; ATOMICS-NEXT: .int8 7
-; ATOMICS-NEXT: .ascii "atomics"
-; ATOMICS-NEXT: .tbss.foo,"",@
+; +bulk-memory
+; BULK-MEM-LABEL: .custom_section.target_features,"",@
+; BULK-MEM-NEXT: .int8 1
+; BULK-MEM-NEXT: .int8 43
+; BULK-MEM-NEXT: 

[PATCH] D64537: [WebAssembly] Implement thread-local storage (local-exec model)

2019-07-12 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum marked 4 inline comments as done.
quantum added inline comments.



Comment at: lld/wasm/Writer.cpp:629
+  // Merge .tbss into .tdata so that they share the same offsets.
+  if (name.startswith(".tbss."))
+return ".tdata";

sbc100 wrote:
> Maybe write this as a single conditional so its clear even without this 
> comment?
Changed in latest diff.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64537: [WebAssembly] Implement thread-local storage (local-exec model)

2019-07-12 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum updated this revision to Diff 209535.
quantum added a comment.

Guard `__wasm_init_tls` and TLS globals behind a flag (currently 
`--shared-memory`).

@tlively and I discussed offline and agreed that it's probably best to use the 
existing flag instead of adding another flag that needs to be passed when 
linking multi-threaded executables.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537

Files:
  clang/include/clang/Basic/BuiltinsWebAssembly.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/test/CodeGen/builtins-wasm.c
  lld/test/wasm/data-segments.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/BinaryFormat/Wasm.h
  llvm/include/llvm/IR/IntrinsicsWebAssembly.td
  llvm/include/llvm/MC/MCSectionWasm.h
  llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISD.def
  llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
  llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
  llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
  llvm/test/CodeGen/WebAssembly/target-features-tls.ll
  llvm/test/CodeGen/WebAssembly/tls.ll

Index: llvm/test/CodeGen/WebAssembly/tls.ll
===
--- llvm/test/CodeGen/WebAssembly/tls.ll
+++ llvm/test/CodeGen/WebAssembly/tls.ll
@@ -1,17 +1,61 @@
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck --check-prefix=SINGLE %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+bulk-memory | FileCheck %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+bulk-memory -fast-isel | FileCheck %s
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
-; SINGLE-LABEL: address_of_tls:
+; CHECK-LABEL: address_of_tls:
 define i32 @address_of_tls() {
-  ; SINGLE: i32.const $push0=, tls
-  ; SINGLE-NEXT: return $pop0
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: return
   ret i32 ptrtoint(i32* @tls to i32)
 }
 
-; SINGLE: .type	tls,@object
-; SINGLE-NEXT: .section	.bss.tls,"",@
-; SINGLE-NEXT: .p2align 2
-; SINGLE-NEXT: tls:
-; SINGLE-NEXT: .int32 0
-@tls = internal thread_local global i32 0
+; CHECK-LABEL: ptr_to_tls
+define i32* @ptr_to_tls() {
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: return
+  ret i32* @tls
+}
+
+; CHECK-LABEL: tls_load
+define i32 @tls_load() {
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: i32.load 0
+  ; CHECK-NEXT: return
+  %tmp = load i32, i32* @tls, align 4
+  ret i32 %tmp
+}
+
+; CHECK-LABEL: tls_store
+define void @tls_store(i32 %x) {
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: i32.store 0
+  ; CHECK-NEXT: return
+  store i32 %x, i32* @tls, align 4
+  ret void
+}
+
+; CHECK-LABEL: tls_size:
+; CHECK-NEXT: .functype tls_size () -> (i32)
+; CHECK-NEXT: global.get __tls_size
+; CHECK-NEXT: return
+declare i32 @llvm.wasm.tls.size.i32()
+define i32 @tls_size() {
+  %1 = call i32 @llvm.wasm.tls.size.i32()
+  ret i32 %1
+}
+
+; CHECK: .type tls,@object
+; CHECK-NEXT: .section .tbss.tls,"",@
+; CHECK-NEXT: .p2align 2
+; CHECK-NEXT: tls:
+; CHECK-NEXT: .int32 0
+@tls = internal thread_local(localexec) global i32 0
Index: llvm/test/CodeGen/WebAssembly/target-features-tls.ll
===
--- llvm/test/CodeGen/WebAssembly/target-features-tls.ll
+++ llvm/test/CodeGen/WebAssembly/target-features-tls.ll
@@ -1,5 +1,5 @@
-; RUN: llc < %s -mattr=-atomics | FileCheck %s --check-prefixes CHECK,NO-ATOMICS
-; RUN: llc < %s -mattr=+atomics | FileCheck %s --check-prefixes CHECK,ATOMICS
+; RUN: llc < %s -mattr=-bulk-memory | FileCheck %s --check-prefixes NO-BULK-MEM
+; RUN: llc < %s -mattr=+bulk-memory | FileCheck %s --check-prefixes BULK-MEM
 
 ; Test that the target features section contains -atomics or +atomics
 ; for modules that have thread local storage in their source.
@@ -9,18 +9,19 @@
 
 @foo = internal thread_local global i32 0
 
-; CHECK-LABEL: .custom_section.target_features,"",@
 
-; -atomics
-; NO-ATOMICS-NEXT: .int8 1
-; NO-ATOMICS-NEXT: .int8 45
-; NO-ATOMICS-NEXT: .int8 7
-; NO-ATOMICS-NEXT: .ascii "atomics"
-; NO-ATOMICS-NEXT: .bss.foo,"",@
+; -bulk-memory
+; NO-BULK-MEM-LABEL: .custom_section.target_features,"",@
+; NO-BULK-MEM-NEXT: .int8 1
+; NO-BULK-MEM-NEXT: .int8 45
+; NO-BULK-MEM-NEXT: .int8 7
+; NO-BULK-MEM-NEXT: .ascii 

[PATCH] D64537: [WebAssembly] Implement thread-local storage (local-exec model)

2019-07-11 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum marked 28 inline comments as done.
quantum added inline comments.



Comment at: clang/include/clang/Basic/BuiltinsWebAssembly.def:33
+// Thread-local storage
+TARGET_BUILTIN(__builtin_wasm_tls_size, "z", "nc", "bulk-memory")
+

tlively wrote:
> quantum wrote:
> > quantum wrote:
> > > aheejin wrote:
> > > > Why is it `c`(const)? According to [[ 
> > > > https://github.com/llvm/llvm-project/blob/e6695821e592f95bffe1340b28be7bcfcce04284/clang/include/clang/Basic/Builtins.h#L104-L108
> > > >  | this comment ]], this is true if this function has no side effects 
> > > > and doesn't read memory, i.e., the result should be only dependent on 
> > > > its arguments. Can't wasm globals be memory locations in machines?
> > > I was thinking that since the global is immutable, so the value is always 
> > > a constant.
> > According to @tlively, there is no solid definition on whether a global 
> > (especially a constant one), counts as memory access. For now, I am going 
> > to change this to not constant. We can always change it back later.
> I think this requires more conversation.
We decided that this is really a constant, since this global is immutable.



Comment at: lld/test/wasm/data-layout.ll:43
+; CHECK-NEXT:   - Index:   3
+; CHECK-NEXT: Type:I32
 ; CHECK-NEXT: Mutable: false

tlively wrote:
> These globals don't have enough information to tell the reader what they even 
> are, and they don't have anything to do with the data layout, so how about 
> skipping these in the test with a comment saying what is being skipped?
Going to skip over `__tls_base` and `__tls_size`.



Comment at: lld/test/wasm/tls.ll:57
+;   memory.init 0, 0
+;   end
+

tlively wrote:
> quantum wrote:
> > aheejin wrote:
> > > Hmm, I think there might be a way to actually print disassembly results. 
> > > There are '*.test' files in test directory, in which we have some 
> > > examples. For example, [[ 
> > > https://github.com/llvm/llvm-project/blob/master/lld/test/wasm/export-table.test
> > >  | this test ]] has a sequence of commands you want to run, and you can 
> > > put input files in a separate directory. That test uses `obj2yaml`, but 
> > > can we possibly use `llvm-objdump` or something to disassemble?
> > We already know that we can do something like
> > 
> > Run: obj2yaml %t.wasm | sed -n '/Body:/{s/^\s*Body:\s*//;s/../0x& /gp}' 
> >  | llvm-mc -disassemble -triple=wasm32
> > 
> > to compare the actual assembly. As for `llvm-objdump`, it seems to be 
> > unable to disassemble the WASM properly:
> > 
> > 
> > ```
> > .../tools/lld/test/wasm/Output/tls.ll.tmp.wasm: file format WASM
> > 
> > 
> > Disassembly of section CODE:
> > 
> >  CODE:
> > # 4 functions in section.
> >1: 02 00 block   invalid_type
> >3: 0bend
> >4: 10 00 call0
> >6: 20 00 local.get   0
> >8: 24 01 global.set  1
> >a: 20 00 local.get   0
> >c: 41 00 i32.const   0
> >e: 41 08 i32.const   8
> >   10: fc 08 00 00   memory.init 0, 0
> >   14: 0bend
> >   15: 0freturn
> >   16: 00llvm-objdump: 
> > lib/Target/WebAssembly/WebAssemblyGenAsmWriter.inc:2032: void 
> > llvm::WebAssemblyInstPrinter::printInstruction(const llvm::MCInst *, 
> > llvm::raw_ostream &): Assertion `Bits != 0 && "Cannot print this 
> > instruction."' failed.
> > 
> > ```
> It might be worth filing an LLVM bug for this (or possibly fixing in a 
> separate CL).
Going to fix this at some point in the future.



Comment at: lld/wasm/Symbols.cpp:208
+if (Segment->OutputSeg->Name == ".tdata")
+  return Segment->OutputSegmentOffset + Offset;
 return Segment->OutputSeg->StartVA + Segment->OutputSegmentOffset + Offset;

tlively wrote:
> It would be great to have an explanatory comment here.
Adding a comment.



Comment at: lld/wasm/Writer.cpp:431
+error("'bulk-memory' feature must be used in order to use thread-local "
+  "storage");
+

quantum wrote:
> aheejin wrote:
> > Should we check for "mutable-global" feature too?
> Do we need to? I thought it's always available since we use it for the stack 
> pointer.
On second thought, the `mutable-global` feature is for import/export of mutable 
globals. TLS does not need to do this.



Comment at: lld/wasm/Writer.cpp:777
+  break;
+}
+

tlively wrote:
> quantum wrote:
> > aheejin wrote:
> > > Is it 

[PATCH] D64537: [WebAssembly] Implement thread-local storage (local-exec model)

2019-07-11 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum updated this revision to Diff 209391.
quantum marked 10 inline comments as done.
quantum added a comment.

Apply review feedback


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537

Files:
  clang/include/clang/Basic/BuiltinsWebAssembly.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/test/CodeGen/builtins-wasm.c
  lld/test/wasm/data-layout.ll
  lld/test/wasm/data-segment-merging.ll
  lld/test/wasm/data-segments.ll
  lld/test/wasm/gc-imports.ll
  lld/test/wasm/gc-sections.ll
  lld/test/wasm/load-undefined.test
  lld/test/wasm/tls.ll
  lld/wasm/Driver.cpp
  lld/wasm/Symbols.cpp
  lld/wasm/Symbols.h
  lld/wasm/Writer.cpp
  llvm/include/llvm/BinaryFormat/Wasm.h
  llvm/include/llvm/IR/IntrinsicsWebAssembly.td
  llvm/include/llvm/MC/MCSectionWasm.h
  llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISD.def
  llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
  llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
  llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
  llvm/test/CodeGen/WebAssembly/target-features-tls.ll
  llvm/test/CodeGen/WebAssembly/tls.ll

Index: llvm/test/CodeGen/WebAssembly/tls.ll
===
--- llvm/test/CodeGen/WebAssembly/tls.ll
+++ llvm/test/CodeGen/WebAssembly/tls.ll
@@ -1,17 +1,61 @@
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck --check-prefix=SINGLE %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+bulk-memory | FileCheck %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+bulk-memory -fast-isel | FileCheck %s
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
-; SINGLE-LABEL: address_of_tls:
+; CHECK-LABEL: address_of_tls:
 define i32 @address_of_tls() {
-  ; SINGLE: i32.const $push0=, tls
-  ; SINGLE-NEXT: return $pop0
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: return
   ret i32 ptrtoint(i32* @tls to i32)
 }
 
-; SINGLE: .type	tls,@object
-; SINGLE-NEXT: .section	.bss.tls,"",@
-; SINGLE-NEXT: .p2align 2
-; SINGLE-NEXT: tls:
-; SINGLE-NEXT: .int32 0
-@tls = internal thread_local global i32 0
+; CHECK-LABEL: ptr_to_tls
+define i32* @ptr_to_tls() {
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: return
+  ret i32* @tls
+}
+
+; CHECK-LABEL: tls_load
+define i32 @tls_load() {
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: i32.load 0
+  ; CHECK-NEXT: return
+  %tmp = load i32, i32* @tls, align 4
+  ret i32 %tmp
+}
+
+; CHECK-LABEL: tls_store
+define void @tls_store(i32 %x) {
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: i32.store 0
+  ; CHECK-NEXT: return
+  store i32 %x, i32* @tls, align 4
+  ret void
+}
+
+; CHECK-LABEL: tls_size:
+; CHECK-NEXT: .functype tls_size () -> (i32)
+; CHECK-NEXT: global.get __tls_size
+; CHECK-NEXT: return
+declare i32 @llvm.wasm.tls.size.i32()
+define i32 @tls_size() {
+  %1 = call i32 @llvm.wasm.tls.size.i32()
+  ret i32 %1
+}
+
+; CHECK: .type tls,@object
+; CHECK-NEXT: .section .tbss.tls,"",@
+; CHECK-NEXT: .p2align 2
+; CHECK-NEXT: tls:
+; CHECK-NEXT: .int32 0
+@tls = internal thread_local(localexec) global i32 0
Index: llvm/test/CodeGen/WebAssembly/target-features-tls.ll
===
--- llvm/test/CodeGen/WebAssembly/target-features-tls.ll
+++ llvm/test/CodeGen/WebAssembly/target-features-tls.ll
@@ -1,5 +1,5 @@
-; RUN: llc < %s -mattr=-atomics | FileCheck %s --check-prefixes CHECK,NO-ATOMICS
-; RUN: llc < %s -mattr=+atomics | FileCheck %s --check-prefixes CHECK,ATOMICS
+; RUN: llc < %s -mattr=-bulk-memory | FileCheck %s --check-prefixes NO-BULK-MEM
+; RUN: llc < %s -mattr=+bulk-memory | FileCheck %s --check-prefixes BULK-MEM
 
 ; Test that the target features section contains -atomics or +atomics
 ; for modules that have thread local storage in their source.
@@ -9,18 +9,19 @@
 
 @foo = internal thread_local global i32 0
 
-; CHECK-LABEL: .custom_section.target_features,"",@
 
-; -atomics
-; NO-ATOMICS-NEXT: .int8 1
-; NO-ATOMICS-NEXT: .int8 45
-; NO-ATOMICS-NEXT: .int8 7
-; NO-ATOMICS-NEXT: .ascii "atomics"
-; NO-ATOMICS-NEXT: .bss.foo,"",@
+; -bulk-memory
+; NO-BULK-MEM-LABEL: .custom_section.target_features,"",@
+; NO-BULK-MEM-NEXT: .int8 1
+; NO-BULK-MEM-NEXT: .int8 45
+; NO-BULK-MEM-NEXT: .int8 7
+; NO-BULK-MEM-NEXT: .ascii "atomics"
+; NO-BULK-MEM-NEXT: .bss.foo,"",@
 
-; 

[PATCH] D64537: [WebAssembly] Implement thread-local storage (local-exec model)

2019-07-11 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum updated this revision to Diff 209376.
quantum added a comment.

Rebased


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537

Files:
  clang/include/clang/Basic/BuiltinsWebAssembly.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/test/CodeGen/builtins-wasm.c
  lld/test/wasm/data-layout.ll
  lld/test/wasm/data-segment-merging.ll
  lld/test/wasm/data-segments.ll
  lld/test/wasm/gc-imports.ll
  lld/test/wasm/gc-sections.ll
  lld/test/wasm/load-undefined.test
  lld/test/wasm/tls.ll
  lld/wasm/Driver.cpp
  lld/wasm/Symbols.cpp
  lld/wasm/Symbols.h
  lld/wasm/Writer.cpp
  llvm/include/llvm/BinaryFormat/Wasm.h
  llvm/include/llvm/IR/IntrinsicsWebAssembly.td
  llvm/include/llvm/MC/MCSectionWasm.h
  llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISD.def
  llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
  llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
  llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
  llvm/test/CodeGen/WebAssembly/target-features-tls.ll
  llvm/test/CodeGen/WebAssembly/tls.ll

Index: llvm/test/CodeGen/WebAssembly/tls.ll
===
--- llvm/test/CodeGen/WebAssembly/tls.ll
+++ llvm/test/CodeGen/WebAssembly/tls.ll
@@ -1,17 +1,61 @@
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck --check-prefix=SINGLE %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals | FileCheck %s
+; RUN: llc -O0 < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals | FileCheck %s
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
-; SINGLE-LABEL: address_of_tls:
+; CHECK-LABEL: address_of_tls:
 define i32 @address_of_tls() {
-  ; SINGLE: i32.const $push0=, tls
-  ; SINGLE-NEXT: return $pop0
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: return
   ret i32 ptrtoint(i32* @tls to i32)
 }
 
-; SINGLE: .type	tls,@object
-; SINGLE-NEXT: .section	.bss.tls,"",@
-; SINGLE-NEXT: .p2align 2
-; SINGLE-NEXT: tls:
-; SINGLE-NEXT: .int32 0
-@tls = internal thread_local global i32 0
+; CHECK-LABEL: ptr_to_tls
+define i32* @ptr_to_tls() {
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: return
+  ret i32* @tls
+}
+
+; CHECK-LABEL: tls_load
+define i32 @tls_load() {
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: i32.load 0
+  ; CHECK-NEXT: return
+  %tmp = load i32, i32* @tls, align 4
+  ret i32 %tmp
+}
+
+; CHECK-LABEL: tls_store
+define void @tls_store(i32 %x) {
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: i32.store 0
+  ; CHECK-NEXT: return
+  store i32 %x, i32* @tls, align 4
+  ret void
+}
+
+; CHECK-LABEL: tls_size:
+; CHECK-NEXT: .functype tls_size () -> (i32)
+; CHECK-NEXT: global.get __tls_size
+; CHECK-NEXT: return
+declare i32 @llvm.wasm.tls.size.i32()
+define i32 @tls_size() {
+  %1 = call i32 @llvm.wasm.tls.size.i32()
+  ret i32 %1
+}
+
+; CHECK: .type tls,@object
+; CHECK-NEXT: .section .tbss.tls,"",@
+; CHECK-NEXT: .p2align 2
+; CHECK-NEXT: tls:
+; CHECK-NEXT: .int32 0
+@tls = internal thread_local(localexec) global i32 0
Index: llvm/test/CodeGen/WebAssembly/target-features-tls.ll
===
--- llvm/test/CodeGen/WebAssembly/target-features-tls.ll
+++ llvm/test/CodeGen/WebAssembly/target-features-tls.ll
@@ -1,5 +1,5 @@
-; RUN: llc < %s -mattr=-atomics | FileCheck %s --check-prefixes CHECK,NO-ATOMICS
-; RUN: llc < %s -mattr=+atomics | FileCheck %s --check-prefixes CHECK,ATOMICS
+; RUN: llc < %s -mattr=-atomics | FileCheck %s --check-prefixes NO-ATOMICS
+; RUN: llc < %s -mattr=+atomics | FileCheck %s --check-prefixes ATOMICS
 
 ; Test that the target features section contains -atomics or +atomics
 ; for modules that have thread local storage in their source.
@@ -9,16 +9,13 @@
 
 @foo = internal thread_local global i32 0
 
-; CHECK-LABEL: .custom_section.target_features,"",@
 
 ; -atomics
-; NO-ATOMICS-NEXT: .int8 1
-; NO-ATOMICS-NEXT: .int8 45
-; NO-ATOMICS-NEXT: .int8 7
-; NO-ATOMICS-NEXT: .ascii "atomics"
-; NO-ATOMICS-NEXT: .bss.foo,"",@
+; NO-ATOMICS-NOT: .custom_section.target_features,"",@
+; NO-ATOMICS: .tbss.foo,"",@
 
 ; +atomics
+; ATOMICS-LABEL: .custom_section.target_features,"",@
 ; ATOMICS-NEXT: .int8 1
 ; ATOMICS-NEXT: .int8 43
 ; ATOMICS-NEXT: .int8 7
Index: llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp

[PATCH] D64537: [WebAssembly] Implement thread-local storage for non-PIC cases

2019-07-11 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum updated this revision to Diff 209304.
quantum added a comment.

Treat global.get of an immutable global as a memory access for now.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537

Files:
  clang/include/clang/Basic/BuiltinsWebAssembly.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/test/CodeGen/builtins-wasm.c
  lld/test/wasm/data-layout.ll
  lld/test/wasm/data-segment-merging.ll
  lld/test/wasm/data-segments.ll
  lld/test/wasm/gc-imports.ll
  lld/test/wasm/gc-sections.ll
  lld/test/wasm/load-undefined.test
  lld/test/wasm/tls.ll
  lld/wasm/Driver.cpp
  lld/wasm/Symbols.cpp
  lld/wasm/Symbols.h
  lld/wasm/Writer.cpp
  llvm/include/llvm/BinaryFormat/Wasm.h
  llvm/include/llvm/IR/IntrinsicsWebAssembly.td
  llvm/include/llvm/MC/MCSectionWasm.h
  llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISD.def
  llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
  llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
  llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
  llvm/test/CodeGen/WebAssembly/target-features-tls.ll
  llvm/test/CodeGen/WebAssembly/tls.ll

Index: llvm/test/CodeGen/WebAssembly/tls.ll
===
--- llvm/test/CodeGen/WebAssembly/tls.ll
+++ llvm/test/CodeGen/WebAssembly/tls.ll
@@ -1,17 +1,61 @@
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck --check-prefix=SINGLE %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals | FileCheck %s
+; RUN: llc -O0 < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals | FileCheck %s
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
-; SINGLE-LABEL: address_of_tls:
+; CHECK-LABEL: address_of_tls:
 define i32 @address_of_tls() {
-  ; SINGLE: i32.const $push0=, tls
-  ; SINGLE-NEXT: return $pop0
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: return
   ret i32 ptrtoint(i32* @tls to i32)
 }
 
-; SINGLE: .type	tls,@object
-; SINGLE-NEXT: .section	.bss.tls,"",@
-; SINGLE-NEXT: .p2align 2
-; SINGLE-NEXT: tls:
-; SINGLE-NEXT: .int32 0
-@tls = internal thread_local global i32 0
+; CHECK-LABEL: ptr_to_tls
+define i32* @ptr_to_tls() {
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: return
+  ret i32* @tls
+}
+
+; CHECK-LABEL: tls_load
+define i32 @tls_load() {
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: i32.load 0
+  ; CHECK-NEXT: return
+  %tmp = load i32, i32* @tls, align 4
+  ret i32 %tmp
+}
+
+; CHECK-LABEL: tls_store
+define void @tls_store(i32 %x) {
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: i32.store 0
+  ; CHECK-NEXT: return
+  store i32 %x, i32* @tls, align 4
+  ret void
+}
+
+; CHECK-LABEL: tls_size:
+; CHECK-NEXT: .functype tls_size () -> (i32)
+; CHECK-NEXT: global.get __tls_size
+; CHECK-NEXT: return
+declare i32 @llvm.wasm.tls.size.i32()
+define i32 @tls_size() {
+  %1 = call i32 @llvm.wasm.tls.size.i32()
+  ret i32 %1
+}
+
+; CHECK: .type tls,@object
+; CHECK-NEXT: .section .tbss.tls,"",@
+; CHECK-NEXT: .p2align 2
+; CHECK-NEXT: tls:
+; CHECK-NEXT: .int32 0
+@tls = internal thread_local(localexec) global i32 0
Index: llvm/test/CodeGen/WebAssembly/target-features-tls.ll
===
--- llvm/test/CodeGen/WebAssembly/target-features-tls.ll
+++ llvm/test/CodeGen/WebAssembly/target-features-tls.ll
@@ -1,5 +1,5 @@
-; RUN: llc < %s -mattr=-atomics | FileCheck %s --check-prefixes CHECK,NO-ATOMICS
-; RUN: llc < %s -mattr=+atomics | FileCheck %s --check-prefixes CHECK,ATOMICS
+; RUN: llc < %s -mattr=-atomics | FileCheck %s --check-prefixes NO-ATOMICS
+; RUN: llc < %s -mattr=+atomics | FileCheck %s --check-prefixes ATOMICS
 
 ; Test that the target features section contains -atomics or +atomics
 ; for modules that have thread local storage in their source.
@@ -9,16 +9,13 @@
 
 @foo = internal thread_local global i32 0
 
-; CHECK-LABEL: .custom_section.target_features,"",@
 
 ; -atomics
-; NO-ATOMICS-NEXT: .int8 1
-; NO-ATOMICS-NEXT: .int8 45
-; NO-ATOMICS-NEXT: .int8 7
-; NO-ATOMICS-NEXT: .ascii "atomics"
-; NO-ATOMICS-NEXT: .bss.foo,"",@
+; NO-ATOMICS-NOT: .custom_section.target_features,"",@
+; NO-ATOMICS: .tbss.foo,"",@
 
 ; +atomics
+; ATOMICS-LABEL: .custom_section.target_features,"",@
 ; ATOMICS-NEXT: .int8 1
 ; ATOMICS-NEXT: .int8 43
 ; ATOMICS-NEXT: .int8 7
Index: llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp

[PATCH] D64537: [WebAssembly] Implement thread-local storage for non-PIC cases

2019-07-11 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum marked 5 inline comments as done.
quantum added inline comments.



Comment at: clang/include/clang/Basic/BuiltinsWebAssembly.def:33
+// Thread-local storage
+TARGET_BUILTIN(__builtin_wasm_tls_size, "z", "nc", "bulk-memory")
+

quantum wrote:
> aheejin wrote:
> > Why is it `c`(const)? According to [[ 
> > https://github.com/llvm/llvm-project/blob/e6695821e592f95bffe1340b28be7bcfcce04284/clang/include/clang/Basic/Builtins.h#L104-L108
> >  | this comment ]], this is true if this function has no side effects and 
> > doesn't read memory, i.e., the result should be only dependent on its 
> > arguments. Can't wasm globals be memory locations in machines?
> I was thinking that since the global is immutable, so the value is always a 
> constant.
According to @tlively, there is no solid definition on whether a global 
(especially a constant one), counts as memory access. For now, I am going to 
change this to not constant. We can always change it back later.



Comment at: llvm/include/llvm/IR/IntrinsicsWebAssembly.td:134
+[],
+[IntrNoMem, IntrSpeculatable]>;
+

quantum wrote:
> aheejin wrote:
> > - Why is it speculatable?
> > - I'm not sure if it's `InstNoMem`, because wasm globals can be memory 
> > locations after all. What do other people think?
> @tlively suggested that I do this. It should be speculatable because it has 
> no side effects (since it returns a constant). As for `InstrNoMem`, I am not 
> sure if globals are memory, and whether reading a constant counts as memory 
> access.
I think I am going to remove these attributes for now. We can add them back if 
we end up deciding that immutable globals are not memory accesses.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64537: [WebAssembly] Implement thread-local storage for non-PIC cases

2019-07-11 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum updated this revision to Diff 209274.
quantum added a comment.

Clean up table gen.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537

Files:
  clang/include/clang/Basic/BuiltinsWebAssembly.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/test/CodeGen/builtins-wasm.c
  lld/test/wasm/data-layout.ll
  lld/test/wasm/data-segment-merging.ll
  lld/test/wasm/data-segments.ll
  lld/test/wasm/gc-imports.ll
  lld/test/wasm/gc-sections.ll
  lld/test/wasm/load-undefined.test
  lld/test/wasm/tls.ll
  lld/wasm/Driver.cpp
  lld/wasm/Symbols.cpp
  lld/wasm/Symbols.h
  lld/wasm/Writer.cpp
  llvm/include/llvm/BinaryFormat/Wasm.h
  llvm/include/llvm/IR/IntrinsicsWebAssembly.td
  llvm/include/llvm/MC/MCSectionWasm.h
  llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISD.def
  llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
  llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
  llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
  llvm/test/CodeGen/WebAssembly/target-features-tls.ll
  llvm/test/CodeGen/WebAssembly/tls.ll

Index: llvm/test/CodeGen/WebAssembly/tls.ll
===
--- llvm/test/CodeGen/WebAssembly/tls.ll
+++ llvm/test/CodeGen/WebAssembly/tls.ll
@@ -1,17 +1,61 @@
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck --check-prefix=SINGLE %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals | FileCheck %s
+; RUN: llc -O0 < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals | FileCheck %s
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
-; SINGLE-LABEL: address_of_tls:
+; CHECK-LABEL: address_of_tls:
 define i32 @address_of_tls() {
-  ; SINGLE: i32.const $push0=, tls
-  ; SINGLE-NEXT: return $pop0
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: return
   ret i32 ptrtoint(i32* @tls to i32)
 }
 
-; SINGLE: .type	tls,@object
-; SINGLE-NEXT: .section	.bss.tls,"",@
-; SINGLE-NEXT: .p2align 2
-; SINGLE-NEXT: tls:
-; SINGLE-NEXT: .int32 0
-@tls = internal thread_local global i32 0
+; CHECK-LABEL: ptr_to_tls
+define i32* @ptr_to_tls() {
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: return
+  ret i32* @tls
+}
+
+; CHECK-LABEL: tls_load
+define i32 @tls_load() {
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: i32.load 0
+  ; CHECK-NEXT: return
+  %tmp = load i32, i32* @tls, align 4
+  ret i32 %tmp
+}
+
+; CHECK-LABEL: tls_store
+define void @tls_store(i32 %x) {
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: i32.store 0
+  ; CHECK-NEXT: return
+  store i32 %x, i32* @tls, align 4
+  ret void
+}
+
+; CHECK-LABEL: tls_size:
+; CHECK-NEXT: .functype tls_size () -> (i32)
+; CHECK-NEXT: global.get __tls_size
+; CHECK-NEXT: return
+declare i32 @llvm.wasm.tls.size.i32()
+define i32 @tls_size() {
+  %1 = call i32 @llvm.wasm.tls.size.i32()
+  ret i32 %1
+}
+
+; CHECK: .type tls,@object
+; CHECK-NEXT: .section .tbss.tls,"",@
+; CHECK-NEXT: .p2align 2
+; CHECK-NEXT: tls:
+; CHECK-NEXT: .int32 0
+@tls = internal thread_local(localexec) global i32 0
Index: llvm/test/CodeGen/WebAssembly/target-features-tls.ll
===
--- llvm/test/CodeGen/WebAssembly/target-features-tls.ll
+++ llvm/test/CodeGen/WebAssembly/target-features-tls.ll
@@ -1,5 +1,5 @@
-; RUN: llc < %s -mattr=-atomics | FileCheck %s --check-prefixes CHECK,NO-ATOMICS
-; RUN: llc < %s -mattr=+atomics | FileCheck %s --check-prefixes CHECK,ATOMICS
+; RUN: llc < %s -mattr=-atomics | FileCheck %s --check-prefixes NO-ATOMICS
+; RUN: llc < %s -mattr=+atomics | FileCheck %s --check-prefixes ATOMICS
 
 ; Test that the target features section contains -atomics or +atomics
 ; for modules that have thread local storage in their source.
@@ -9,16 +9,13 @@
 
 @foo = internal thread_local global i32 0
 
-; CHECK-LABEL: .custom_section.target_features,"",@
 
 ; -atomics
-; NO-ATOMICS-NEXT: .int8 1
-; NO-ATOMICS-NEXT: .int8 45
-; NO-ATOMICS-NEXT: .int8 7
-; NO-ATOMICS-NEXT: .ascii "atomics"
-; NO-ATOMICS-NEXT: .bss.foo,"",@
+; NO-ATOMICS-NOT: .custom_section.target_features,"",@
+; NO-ATOMICS: .tbss.foo,"",@
 
 ; +atomics
+; ATOMICS-LABEL: .custom_section.target_features,"",@
 ; ATOMICS-NEXT: .int8 1
 ; ATOMICS-NEXT: .int8 43
 ; ATOMICS-NEXT: .int8 7
Index: llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp

[PATCH] D64537: [WebAssembly] Implement thread-local storage for non-PIC cases

2019-07-11 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum updated this revision to Diff 209271.
quantum marked 6 inline comments as done.
quantum added a comment.

Update comments regarding multable globals. Use `CHECK-DAG`.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537

Files:
  clang/include/clang/Basic/BuiltinsWebAssembly.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/test/CodeGen/builtins-wasm.c
  lld/test/wasm/data-layout.ll
  lld/test/wasm/data-segment-merging.ll
  lld/test/wasm/data-segments.ll
  lld/test/wasm/gc-imports.ll
  lld/test/wasm/gc-sections.ll
  lld/test/wasm/load-undefined.test
  lld/test/wasm/tls.ll
  lld/wasm/Driver.cpp
  lld/wasm/Symbols.cpp
  lld/wasm/Symbols.h
  lld/wasm/Writer.cpp
  llvm/include/llvm/BinaryFormat/Wasm.h
  llvm/include/llvm/IR/IntrinsicsWebAssembly.td
  llvm/include/llvm/MC/MCSectionWasm.h
  llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISD.def
  llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
  llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
  llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
  llvm/test/CodeGen/WebAssembly/target-features-tls.ll
  llvm/test/CodeGen/WebAssembly/tls.ll

Index: llvm/test/CodeGen/WebAssembly/tls.ll
===
--- llvm/test/CodeGen/WebAssembly/tls.ll
+++ llvm/test/CodeGen/WebAssembly/tls.ll
@@ -1,17 +1,61 @@
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck --check-prefix=SINGLE %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals | FileCheck %s
+; RUN: llc -O0 < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals | FileCheck %s
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
-; SINGLE-LABEL: address_of_tls:
+; CHECK-LABEL: address_of_tls:
 define i32 @address_of_tls() {
-  ; SINGLE: i32.const $push0=, tls
-  ; SINGLE-NEXT: return $pop0
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: return
   ret i32 ptrtoint(i32* @tls to i32)
 }
 
-; SINGLE: .type	tls,@object
-; SINGLE-NEXT: .section	.bss.tls,"",@
-; SINGLE-NEXT: .p2align 2
-; SINGLE-NEXT: tls:
-; SINGLE-NEXT: .int32 0
-@tls = internal thread_local global i32 0
+; CHECK-LABEL: ptr_to_tls
+define i32* @ptr_to_tls() {
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: return
+  ret i32* @tls
+}
+
+; CHECK-LABEL: tls_load
+define i32 @tls_load() {
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: i32.load 0
+  ; CHECK-NEXT: return
+  %tmp = load i32, i32* @tls, align 4
+  ret i32 %tmp
+}
+
+; CHECK-LABEL: tls_store
+define void @tls_store(i32 %x) {
+  ; CHECK-DAG: global.get __tls_base
+  ; CHECK-DAG: i32.const tls
+  ; CHECK-NEXT: i32.add
+  ; CHECK-NEXT: i32.store 0
+  ; CHECK-NEXT: return
+  store i32 %x, i32* @tls, align 4
+  ret void
+}
+
+; CHECK-LABEL: tls_size:
+; CHECK-NEXT: .functype tls_size () -> (i32)
+; CHECK-NEXT: global.get __tls_size
+; CHECK-NEXT: return
+declare i32 @llvm.wasm.tls.size.i32()
+define i32 @tls_size() {
+  %1 = call i32 @llvm.wasm.tls.size.i32()
+  ret i32 %1
+}
+
+; CHECK: .type tls,@object
+; CHECK-NEXT: .section .tbss.tls,"",@
+; CHECK-NEXT: .p2align 2
+; CHECK-NEXT: tls:
+; CHECK-NEXT: .int32 0
+@tls = internal thread_local(localexec) global i32 0
Index: llvm/test/CodeGen/WebAssembly/target-features-tls.ll
===
--- llvm/test/CodeGen/WebAssembly/target-features-tls.ll
+++ llvm/test/CodeGen/WebAssembly/target-features-tls.ll
@@ -1,5 +1,5 @@
-; RUN: llc < %s -mattr=-atomics | FileCheck %s --check-prefixes CHECK,NO-ATOMICS
-; RUN: llc < %s -mattr=+atomics | FileCheck %s --check-prefixes CHECK,ATOMICS
+; RUN: llc < %s -mattr=-atomics | FileCheck %s --check-prefixes NO-ATOMICS
+; RUN: llc < %s -mattr=+atomics | FileCheck %s --check-prefixes ATOMICS
 
 ; Test that the target features section contains -atomics or +atomics
 ; for modules that have thread local storage in their source.
@@ -9,16 +9,13 @@
 
 @foo = internal thread_local global i32 0
 
-; CHECK-LABEL: .custom_section.target_features,"",@
 
 ; -atomics
-; NO-ATOMICS-NEXT: .int8 1
-; NO-ATOMICS-NEXT: .int8 45
-; NO-ATOMICS-NEXT: .int8 7
-; NO-ATOMICS-NEXT: .ascii "atomics"
-; NO-ATOMICS-NEXT: .bss.foo,"",@
+; NO-ATOMICS-NOT: .custom_section.target_features,"",@
+; NO-ATOMICS: .tbss.foo,"",@
 
 ; +atomics
+; ATOMICS-LABEL: .custom_section.target_features,"",@
 ; ATOMICS-NEXT: .int8 1
 ; ATOMICS-NEXT: .int8 43
 ; ATOMICS-NEXT: .int8 7
Index: 

[PATCH] D64537: [WebAssembly] Implement thread-local storage for non-PIC cases

2019-07-11 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum marked 20 inline comments as done.
quantum added a comment.

I'll clean up the table gen stuff.




Comment at: clang/include/clang/Basic/BuiltinsWebAssembly.def:33
+// Thread-local storage
+TARGET_BUILTIN(__builtin_wasm_tls_size, "z", "nc", "bulk-memory")
+

aheejin wrote:
> Why is it `c`(const)? According to [[ 
> https://github.com/llvm/llvm-project/blob/e6695821e592f95bffe1340b28be7bcfcce04284/clang/include/clang/Basic/Builtins.h#L104-L108
>  | this comment ]], this is true if this function has no side effects and 
> doesn't read memory, i.e., the result should be only dependent on its 
> arguments. Can't wasm globals be memory locations in machines?
I was thinking that since the global is immutable, so the value is always a 
constant.



Comment at: lld/test/wasm/tls.ll:57
+;   memory.init 0, 0
+;   end
+

aheejin wrote:
> Hmm, I think there might be a way to actually print disassembly results. 
> There are '*.test' files in test directory, in which we have some examples. 
> For example, [[ 
> https://github.com/llvm/llvm-project/blob/master/lld/test/wasm/export-table.test
>  | this test ]] has a sequence of commands you want to run, and you can put 
> input files in a separate directory. That test uses `obj2yaml`, but can we 
> possibly use `llvm-objdump` or something to disassemble?
We already know that we can do something like

Run: obj2yaml %t.wasm | sed -n '/Body:/{s/^\s*Body:\s*//;s/../0x& /gp}'  | 
llvm-mc -disassemble -triple=wasm32

to compare the actual assembly. As for `llvm-objdump`, it seems to be unable to 
disassemble the WASM properly:


```
.../tools/lld/test/wasm/Output/tls.ll.tmp.wasm: file format WASM


Disassembly of section CODE:

 CODE:
# 4 functions in section.
   1: 02 00 block   invalid_type
   3: 0bend
   4: 10 00 call0
   6: 20 00 local.get   0
   8: 24 01 global.set  1
   a: 20 00 local.get   0
   c: 41 00 i32.const   0
   e: 41 08 i32.const   8
  10: fc 08 00 00   memory.init 0, 0
  14: 0bend
  15: 0freturn
  16: 00llvm-objdump: 
lib/Target/WebAssembly/WebAssemblyGenAsmWriter.inc:2032: void 
llvm::WebAssemblyInstPrinter::printInstruction(const llvm::MCInst *, 
llvm::raw_ostream &): Assertion `Bits != 0 && "Cannot print this instruction."' 
failed.

```



Comment at: lld/wasm/Driver.cpp:543
+  "__wasm_init_tls", WASM_SYMBOL_VISIBILITY_HIDDEN,
+  make(I32ArgSignature, "__wasm_init_tls"));
+

aheejin wrote:
> Does this TLS thing work when `Config->Shared == true`, i.e., do we create 
> TLS globals even when this is a library?
Since TLS is module specific (we can't allocate memory for other modules), we 
must in fact generate this symbol for every module. Shared library support will 
not be implemented in this diff, however.



Comment at: lld/wasm/Writer.cpp:431
+error("'bulk-memory' feature must be used in order to use thread-local "
+  "storage");
+

aheejin wrote:
> Should we check for "mutable-global" feature too?
Do we need to? I thought it's always available since we use it for the stack 
pointer.



Comment at: lld/wasm/Writer.cpp:514
   if (G->getGlobalType()->Mutable) {
 // Only the __stack_pointer should ever be create as mutable.
+assert(G == WasmSym::StackPointer || G == WasmSym::TLSBase);

aheejin wrote:
> Now `__tls_base` is also mutable, I think we should fix the comment
Will do.



Comment at: lld/wasm/Writer.cpp:769
+  std::string BodyContent;
+  {
+raw_string_ostream OS(BodyContent);

aheejin wrote:
> Any reason for the new block scope?
Yes, the `raw_string_ostream` must destruct by the end of the scope. This is 
the pattern used in other functions above.



Comment at: lld/wasm/Writer.cpp:777
+  break;
+}
+

aheejin wrote:
> Is it guaranteed that there's only one TLS segment?
Yes, all the TLS input segments will be merged into `.tdata`.



Comment at: llvm/include/llvm/IR/IntrinsicsWebAssembly.td:134
+[],
+[IntrNoMem, IntrSpeculatable]>;
+

aheejin wrote:
> - Why is it speculatable?
> - I'm not sure if it's `InstNoMem`, because wasm globals can be memory 
> locations after all. What do other people think?
@tlively suggested that I do this. It should be speculatable because it has no 
side effects (since it returns a constant). As for `InstrNoMem`, I am not sure 
if globals are memory, and whether reading a constant counts as 

[PATCH] D64537: [WebAssembly] Implement thread-local storage for non-PIC cases

2019-07-11 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum updated this revision to Diff 209258.
quantum added a comment.

Add error for non-local-exec TLS models. Fix unit tests.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537

Files:
  clang/include/clang/Basic/BuiltinsWebAssembly.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/test/CodeGen/builtins-wasm.c
  lld/test/wasm/data-layout.ll
  lld/test/wasm/data-segment-merging.ll
  lld/test/wasm/data-segments.ll
  lld/test/wasm/gc-imports.ll
  lld/test/wasm/gc-sections.ll
  lld/test/wasm/load-undefined.test
  lld/test/wasm/tls.ll
  lld/wasm/Driver.cpp
  lld/wasm/Symbols.cpp
  lld/wasm/Symbols.h
  lld/wasm/Writer.cpp
  llvm/include/llvm/BinaryFormat/Wasm.h
  llvm/include/llvm/IR/IntrinsicsWebAssembly.td
  llvm/include/llvm/MC/MCSectionWasm.h
  llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISD.def
  llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
  llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
  llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
  llvm/test/CodeGen/WebAssembly/target-features-tls.ll
  llvm/test/CodeGen/WebAssembly/tls.ll

Index: llvm/test/CodeGen/WebAssembly/tls.ll
===
--- llvm/test/CodeGen/WebAssembly/tls.ll
+++ llvm/test/CodeGen/WebAssembly/tls.ll
@@ -1,17 +1,87 @@
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck --check-prefix=SINGLE %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals | FileCheck --check-prefixes=CHECK,O2 %s
+; RUN: llc -O0 < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals | FileCheck --check-prefixes=CHECK,O0 %s
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
-; SINGLE-LABEL: address_of_tls:
+; O0-LABEL: address_of_tls:
+; O2-LABEL: address_of_tls:
 define i32 @address_of_tls() {
-  ; SINGLE: i32.const $push0=, tls
-  ; SINGLE-NEXT: return $pop0
+  ; O0: i32.const tls
+  ; O0-NEXT: global.get __tls_base
+  ; O0-NEXT: i32.add
+  ; O0-NEXT: return
+
+  ; O2: global.get __tls_base
+  ; O2-NEXT: i32.const tls
+  ; O2-NEXT: i32.add
+  ; O2-NEXT: return
   ret i32 ptrtoint(i32* @tls to i32)
 }
 
-; SINGLE: .type	tls,@object
-; SINGLE-NEXT: .section	.bss.tls,"",@
-; SINGLE-NEXT: .p2align 2
-; SINGLE-NEXT: tls:
-; SINGLE-NEXT: .int32 0
-@tls = internal thread_local global i32 0
+; O0-LABEL: ptr_to_tls
+; O2-LABEL: ptr_to_tls
+define i32* @ptr_to_tls() {
+  ; O0: i32.const tls
+  ; O0-NEXT: global.get __tls_base
+  ; O0-NEXT: i32.add
+  ; O0-NEXT: return
+
+  ; O2: global.get __tls_base
+  ; O2-NEXT: i32.const tls
+  ; O2-NEXT: i32.add
+  ; O2-NEXT: return
+  ret i32* @tls
+}
+
+; O0-LABEL: tls_load
+; O2-LABEL: tls_load
+define i32 @tls_load() {
+  ; O0: i32.const tls
+  ; O0-NEXT: global.get __tls_base
+  ; O0-NEXT: i32.add
+  ; O0-NEXT: i32.load 0
+  ; O0-NEXT: return
+
+  ; O2: global.get __tls_base
+  ; O2-NEXT: i32.const tls
+  ; O2-NEXT: i32.add
+  ; O2-NEXT: i32.load 0
+  ; O2-NEXT: return
+  %tmp = load i32, i32* @tls, align 4
+  ret i32 %tmp
+}
+
+; O0-LABEL: tls_store
+; O2-LABEL: tls_store
+define void @tls_store(i32 %x) {
+  ; O0: i32.const tls
+  ; O0-NEXT: global.get __tls_base
+  ; O0-NEXT: i32.add
+  ; O0-NEXT: i32.store 0
+  ; O0-NEXT: return
+
+  ; O2: global.get __tls_base
+  ; O2-NEXT: i32.const tls
+  ; O2-NEXT: i32.add
+  ; O2-NEXT: i32.store 0
+  ; O2-NEXT: return
+  store i32 %x, i32* @tls, align 4
+  ret void
+}
+
+; CHECK-LABEL: tls_size:
+; CHECK-NEXT: .functype tls_size () -> (i32)
+; CHECK-NEXT: global.get __tls_size
+; CHECK-NEXT: return
+declare i32 @llvm.wasm.tls.size.i32()
+define i32 @tls_size() {
+  %1 = call i32 @llvm.wasm.tls.size.i32()
+  ret i32 %1
+}
+
+; CHECK: .type tls,@object
+; CHECK-NEXT: .section .tbss.tls,"",@
+; CHECK-NEXT: .p2align 2
+; CHECK-NEXT: tls:
+; CHECK-NEXT: .int32 0
+@tls = internal thread_local(localexec) global i32 0
Index: llvm/test/CodeGen/WebAssembly/target-features-tls.ll
===
--- llvm/test/CodeGen/WebAssembly/target-features-tls.ll
+++ llvm/test/CodeGen/WebAssembly/target-features-tls.ll
@@ -1,5 +1,5 @@
-; RUN: llc < %s -mattr=-atomics | FileCheck %s --check-prefixes CHECK,NO-ATOMICS
-; RUN: llc < %s -mattr=+atomics | FileCheck %s --check-prefixes CHECK,ATOMICS
+; RUN: llc < %s -mattr=-atomics | FileCheck %s --check-prefixes NO-ATOMICS
+; RUN: llc < %s -mattr=+atomics | FileCheck %s --check-prefixes ATOMICS
 
 ; Test that the target features section contains -atomics or +atomics
 ; for modules that have thread local storage in their source.
@@ -9,16 +9,13 @@
 
 @foo = internal thread_local 

[PATCH] D64537: [WebAssembly] Implement thread-local storage for non-PIC cases

2019-07-10 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum marked an inline comment as done.
quantum added a comment.

In D64537#1579626 , @sunfish wrote:

> This looks nice!
>
> > __wasm_init_tls(calloc(__builtin_wasm_tls_size(), 1));
>
> Would it make sense to change the API contract for `__wasm_init_tls` to 
> guarantee that initializes all bytes (with zeros as needed)? 
> `__wasm_init_tls` knows what bytes it's initializing, so we could use plain 
> `malloc` instead of `calloc` and avoid redundant zero initialization of those 
> bytes.


Updated the summary. I just realized that the way the code is written, the 
plain `malloc` would already work.




Comment at: llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp:
+
+  return DAG.getNode(ISD::ADD, DL, VT, TLSBase, TLSOffset);
+}

sunfish wrote:
> It looks like this supports local-exec, but would need to be extended to 
> handle initial-exec or the other TLS models. Assuming this is correct, could 
> you add a check for the TLS model and `report_fatal_error` on unsupported 
> models?
I'll add an error for non-local-exec for now.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64537: [WebAssembly] Implement thread-local storage for non-PIC cases

2019-07-10 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum updated this revision to Diff 209102.
quantum added a comment.

Fix linker warning.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537

Files:
  clang/include/clang/Basic/BuiltinsWebAssembly.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/test/CodeGen/builtins-wasm.c
  lld/test/wasm/data-layout.ll
  lld/test/wasm/gc-sections.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/BinaryFormat/Wasm.h
  llvm/include/llvm/IR/IntrinsicsWebAssembly.td
  llvm/include/llvm/MC/MCSectionWasm.h
  llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISD.def
  llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
  llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
  llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
  llvm/test/CodeGen/WebAssembly/target-features-tls.ll
  llvm/test/CodeGen/WebAssembly/tls.ll

Index: llvm/test/CodeGen/WebAssembly/tls.ll
===
--- llvm/test/CodeGen/WebAssembly/tls.ll
+++ llvm/test/CodeGen/WebAssembly/tls.ll
@@ -1,17 +1,87 @@
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck --check-prefix=SINGLE %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals | FileCheck --check-prefixes=CHECK,O2 %s
+; RUN: llc -O0 < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals | FileCheck --check-prefixes=CHECK,O0 %s
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
-; SINGLE-LABEL: address_of_tls:
+; O0-LABEL: address_of_tls:
+; O2-LABEL: address_of_tls:
 define i32 @address_of_tls() {
-  ; SINGLE: i32.const $push0=, tls
-  ; SINGLE-NEXT: return $pop0
+  ; O0: i32.const tls
+  ; O0-NEXT: global.get __tls_base
+  ; O0-NEXT: i32.add
+  ; O0-NEXT: return
+
+  ; O2: global.get __tls_base
+  ; O2-NEXT: i32.const tls
+  ; O2-NEXT: i32.add
+  ; O2-NEXT: return
   ret i32 ptrtoint(i32* @tls to i32)
 }
 
-; SINGLE: .type	tls,@object
-; SINGLE-NEXT: .section	.bss.tls,"",@
-; SINGLE-NEXT: .p2align 2
-; SINGLE-NEXT: tls:
-; SINGLE-NEXT: .int32 0
+; O0-LABEL: ptr_to_tls
+; O2-LABEL: ptr_to_tls
+define i32* @ptr_to_tls() {
+  ; O0: i32.const tls
+  ; O0-NEXT: global.get __tls_base
+  ; O0-NEXT: i32.add
+  ; O0-NEXT: return
+
+  ; O2: global.get __tls_base
+  ; O2-NEXT: i32.const tls
+  ; O2-NEXT: i32.add
+  ; O2-NEXT: return
+  ret i32* @tls
+}
+
+; O0-LABEL: tls_load
+; O2-LABEL: tls_load
+define i32 @tls_load() {
+  ; O0: i32.const tls
+  ; O0-NEXT: global.get __tls_base
+  ; O0-NEXT: i32.add
+  ; O0-NEXT: i32.load 0
+  ; O0-NEXT: return
+
+  ; O2: global.get __tls_base
+  ; O2-NEXT: i32.const tls
+  ; O2-NEXT: i32.add
+  ; O2-NEXT: i32.load 0
+  ; O2-NEXT: return
+  %tmp = load i32, i32* @tls, align 4
+  ret i32 %tmp
+}
+
+; O0-LABEL: tls_store
+; O2-LABEL: tls_store
+define void @tls_store(i32 %x) {
+  ; O0: i32.const tls
+  ; O0-NEXT: global.get __tls_base
+  ; O0-NEXT: i32.add
+  ; O0-NEXT: i32.store 0
+  ; O0-NEXT: return
+
+  ; O2: global.get __tls_base
+  ; O2-NEXT: i32.const tls
+  ; O2-NEXT: i32.add
+  ; O2-NEXT: i32.store 0
+  ; O2-NEXT: return
+  store i32 %x, i32* @tls, align 4
+  ret void
+}
+
+; CHECK-LABEL: tls_size:
+; CHECK-NEXT: .functype tls_size () -> (i32)
+; CHECK-NEXT: global.get __tls_size
+; CHECK-NEXT: return
+declare i32 @llvm.wasm.tls.size.i32()
+define i32 @tls_size() {
+  %1 = call i32 @llvm.wasm.tls.size.i32()
+  ret i32 %1
+}
+
+; CHECK: .type tls,@object
+; CHECK-NEXT: .section .tbss.tls,"",@
+; CHECK-NEXT: .p2align 2
+; CHECK-NEXT: tls:
+; CHECK-NEXT: .int32 0
 @tls = internal thread_local global i32 0
Index: llvm/test/CodeGen/WebAssembly/target-features-tls.ll
===
--- llvm/test/CodeGen/WebAssembly/target-features-tls.ll
+++ llvm/test/CodeGen/WebAssembly/target-features-tls.ll
@@ -1,5 +1,5 @@
-; RUN: llc < %s -mattr=-atomics | FileCheck %s --check-prefixes CHECK,NO-ATOMICS
-; RUN: llc < %s -mattr=+atomics | FileCheck %s --check-prefixes CHECK,ATOMICS
+; RUN: llc < %s -mattr=-atomics | FileCheck %s --check-prefixes NO-ATOMICS
+; RUN: llc < %s -mattr=+atomics | FileCheck %s --check-prefixes ATOMICS
 
 ; Test that the target features section contains -atomics or +atomics
 ; for modules that have thread local storage in their source.
@@ -9,16 +9,13 @@
 
 @foo = internal thread_local global i32 0
 
-; CHECK-LABEL: .custom_section.target_features,"",@
 
 ; -atomics
-; NO-ATOMICS-NEXT: .int8 1
-; NO-ATOMICS-NEXT: .int8 45
-; NO-ATOMICS-NEXT: .int8 7
-; NO-ATOMICS-NEXT: .ascii "atomics"
-; NO-ATOMICS-NEXT: 

[PATCH] D64537: [WebAssembly] Implement thread-local storage for non-PIC cases

2019-07-10 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum updated this revision to Diff 209090.
quantum added a comment.

Fix `fail` call.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537

Files:
  clang/include/clang/Basic/BuiltinsWebAssembly.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/test/CodeGen/builtins-wasm.c
  lld/test/wasm/data-layout.ll
  lld/test/wasm/gc-sections.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/BinaryFormat/Wasm.h
  llvm/include/llvm/IR/IntrinsicsWebAssembly.td
  llvm/include/llvm/MC/MCSectionWasm.h
  llvm/lib/MC/WasmObjectWriter.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISD.def
  llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
  llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
  llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
  llvm/test/CodeGen/WebAssembly/target-features-tls.ll
  llvm/test/CodeGen/WebAssembly/tls.ll

Index: llvm/test/CodeGen/WebAssembly/tls.ll
===
--- llvm/test/CodeGen/WebAssembly/tls.ll
+++ llvm/test/CodeGen/WebAssembly/tls.ll
@@ -1,17 +1,87 @@
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck --check-prefix=SINGLE %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals | FileCheck --check-prefixes=CHECK,O2 %s
+; RUN: llc -O0 < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals | FileCheck --check-prefixes=CHECK,O0 %s
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
-; SINGLE-LABEL: address_of_tls:
+; O0-LABEL: address_of_tls:
+; O2-LABEL: address_of_tls:
 define i32 @address_of_tls() {
-  ; SINGLE: i32.const $push0=, tls
-  ; SINGLE-NEXT: return $pop0
+  ; O0: i32.const tls
+  ; O0-NEXT: global.get __tls_base
+  ; O0-NEXT: i32.add
+  ; O0-NEXT: return
+
+  ; O2: global.get __tls_base
+  ; O2-NEXT: i32.const tls
+  ; O2-NEXT: i32.add
+  ; O2-NEXT: return
   ret i32 ptrtoint(i32* @tls to i32)
 }
 
-; SINGLE: .type	tls,@object
-; SINGLE-NEXT: .section	.bss.tls,"",@
-; SINGLE-NEXT: .p2align 2
-; SINGLE-NEXT: tls:
-; SINGLE-NEXT: .int32 0
+; O0-LABEL: ptr_to_tls
+; O2-LABEL: ptr_to_tls
+define i32* @ptr_to_tls() {
+  ; O0: i32.const tls
+  ; O0-NEXT: global.get __tls_base
+  ; O0-NEXT: i32.add
+  ; O0-NEXT: return
+
+  ; O2: global.get __tls_base
+  ; O2-NEXT: i32.const tls
+  ; O2-NEXT: i32.add
+  ; O2-NEXT: return
+  ret i32* @tls
+}
+
+; O0-LABEL: tls_load
+; O2-LABEL: tls_load
+define i32 @tls_load() {
+  ; O0: i32.const tls
+  ; O0-NEXT: global.get __tls_base
+  ; O0-NEXT: i32.add
+  ; O0-NEXT: i32.load 0
+  ; O0-NEXT: return
+
+  ; O2: global.get __tls_base
+  ; O2-NEXT: i32.const tls
+  ; O2-NEXT: i32.add
+  ; O2-NEXT: i32.load 0
+  ; O2-NEXT: return
+  %tmp = load i32, i32* @tls, align 4
+  ret i32 %tmp
+}
+
+; O0-LABEL: tls_store
+; O2-LABEL: tls_store
+define void @tls_store(i32 %x) {
+  ; O0: i32.const tls
+  ; O0-NEXT: global.get __tls_base
+  ; O0-NEXT: i32.add
+  ; O0-NEXT: i32.store 0
+  ; O0-NEXT: return
+
+  ; O2: global.get __tls_base
+  ; O2-NEXT: i32.const tls
+  ; O2-NEXT: i32.add
+  ; O2-NEXT: i32.store 0
+  ; O2-NEXT: return
+  store i32 %x, i32* @tls, align 4
+  ret void
+}
+
+; CHECK-LABEL: tls_size:
+; CHECK-NEXT: .functype tls_size () -> (i32)
+; CHECK-NEXT: global.get __tls_size
+; CHECK-NEXT: return
+declare i32 @llvm.wasm.tls.size.i32()
+define i32 @tls_size() {
+  %1 = call i32 @llvm.wasm.tls.size.i32()
+  ret i32 %1
+}
+
+; CHECK: .type tls,@object
+; CHECK-NEXT: .section .tbss.tls,"",@
+; CHECK-NEXT: .p2align 2
+; CHECK-NEXT: tls:
+; CHECK-NEXT: .int32 0
 @tls = internal thread_local global i32 0
Index: llvm/test/CodeGen/WebAssembly/target-features-tls.ll
===
--- llvm/test/CodeGen/WebAssembly/target-features-tls.ll
+++ llvm/test/CodeGen/WebAssembly/target-features-tls.ll
@@ -1,5 +1,5 @@
-; RUN: llc < %s -mattr=-atomics | FileCheck %s --check-prefixes CHECK,NO-ATOMICS
-; RUN: llc < %s -mattr=+atomics | FileCheck %s --check-prefixes CHECK,ATOMICS
+; RUN: llc < %s -mattr=-atomics | FileCheck %s --check-prefixes NO-ATOMICS
+; RUN: llc < %s -mattr=+atomics | FileCheck %s --check-prefixes ATOMICS
 
 ; Test that the target features section contains -atomics or +atomics
 ; for modules that have thread local storage in their source.
@@ -9,16 +9,13 @@
 
 @foo = internal thread_local global i32 0
 
-; CHECK-LABEL: .custom_section.target_features,"",@
 
 ; -atomics
-; NO-ATOMICS-NEXT: .int8 1
-; NO-ATOMICS-NEXT: .int8 45
-; NO-ATOMICS-NEXT: .int8 7
-; NO-ATOMICS-NEXT: .ascii "atomics"

[PATCH] D64537: [WebAssembly] Implement thread-local storage for non-PIC cases

2019-07-10 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum updated this revision to Diff 209084.
quantum added a comment.

Add tests for `__builtin_wasm_tls_size`.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537

Files:
  clang/include/clang/Basic/BuiltinsWebAssembly.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/test/CodeGen/builtins-wasm.c
  lld/test/wasm/data-layout.ll
  lld/test/wasm/gc-sections.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/BinaryFormat/Wasm.h
  llvm/include/llvm/IR/IntrinsicsWebAssembly.td
  llvm/include/llvm/MC/MCSectionWasm.h
  llvm/lib/MC/WasmObjectWriter.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISD.def
  llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
  llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
  llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
  llvm/test/CodeGen/WebAssembly/target-features-tls.ll
  llvm/test/CodeGen/WebAssembly/tls.ll

Index: llvm/test/CodeGen/WebAssembly/tls.ll
===
--- llvm/test/CodeGen/WebAssembly/tls.ll
+++ llvm/test/CodeGen/WebAssembly/tls.ll
@@ -1,17 +1,87 @@
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck --check-prefix=SINGLE %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals | FileCheck --check-prefixes=CHECK,O2 %s
+; RUN: llc -O0 < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals | FileCheck --check-prefixes=CHECK,O0 %s
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
-; SINGLE-LABEL: address_of_tls:
+; O0-LABEL: address_of_tls:
+; O2-LABEL: address_of_tls:
 define i32 @address_of_tls() {
-  ; SINGLE: i32.const $push0=, tls
-  ; SINGLE-NEXT: return $pop0
+  ; O0: i32.const tls
+  ; O0-NEXT: global.get __tls_base
+  ; O0-NEXT: i32.add
+  ; O0-NEXT: return
+
+  ; O2: global.get __tls_base
+  ; O2-NEXT: i32.const tls
+  ; O2-NEXT: i32.add
+  ; O2-NEXT: return
   ret i32 ptrtoint(i32* @tls to i32)
 }
 
-; SINGLE: .type	tls,@object
-; SINGLE-NEXT: .section	.bss.tls,"",@
-; SINGLE-NEXT: .p2align 2
-; SINGLE-NEXT: tls:
-; SINGLE-NEXT: .int32 0
+; O0-LABEL: ptr_to_tls
+; O2-LABEL: ptr_to_tls
+define i32* @ptr_to_tls() {
+  ; O0: i32.const tls
+  ; O0-NEXT: global.get __tls_base
+  ; O0-NEXT: i32.add
+  ; O0-NEXT: return
+
+  ; O2: global.get __tls_base
+  ; O2-NEXT: i32.const tls
+  ; O2-NEXT: i32.add
+  ; O2-NEXT: return
+  ret i32* @tls
+}
+
+; O0-LABEL: tls_load
+; O2-LABEL: tls_load
+define i32 @tls_load() {
+  ; O0: i32.const tls
+  ; O0-NEXT: global.get __tls_base
+  ; O0-NEXT: i32.add
+  ; O0-NEXT: i32.load 0
+  ; O0-NEXT: return
+
+  ; O2: global.get __tls_base
+  ; O2-NEXT: i32.const tls
+  ; O2-NEXT: i32.add
+  ; O2-NEXT: i32.load 0
+  ; O2-NEXT: return
+  %tmp = load i32, i32* @tls, align 4
+  ret i32 %tmp
+}
+
+; O0-LABEL: tls_store
+; O2-LABEL: tls_store
+define void @tls_store(i32 %x) {
+  ; O0: i32.const tls
+  ; O0-NEXT: global.get __tls_base
+  ; O0-NEXT: i32.add
+  ; O0-NEXT: i32.store 0
+  ; O0-NEXT: return
+
+  ; O2: global.get __tls_base
+  ; O2-NEXT: i32.const tls
+  ; O2-NEXT: i32.add
+  ; O2-NEXT: i32.store 0
+  ; O2-NEXT: return
+  store i32 %x, i32* @tls, align 4
+  ret void
+}
+
+; CHECK-LABEL: tls_size:
+; CHECK-NEXT: .functype tls_size () -> (i32)
+; CHECK-NEXT: global.get __tls_size
+; CHECK-NEXT: return
+declare i32 @llvm.wasm.tls.size.i32()
+define i32 @tls_size() {
+  %1 = call i32 @llvm.wasm.tls.size.i32()
+  ret i32 %1
+}
+
+; CHECK: .type tls,@object
+; CHECK-NEXT: .section .tbss.tls,"",@
+; CHECK-NEXT: .p2align 2
+; CHECK-NEXT: tls:
+; CHECK-NEXT: .int32 0
 @tls = internal thread_local global i32 0
Index: llvm/test/CodeGen/WebAssembly/target-features-tls.ll
===
--- llvm/test/CodeGen/WebAssembly/target-features-tls.ll
+++ llvm/test/CodeGen/WebAssembly/target-features-tls.ll
@@ -1,5 +1,5 @@
-; RUN: llc < %s -mattr=-atomics | FileCheck %s --check-prefixes CHECK,NO-ATOMICS
-; RUN: llc < %s -mattr=+atomics | FileCheck %s --check-prefixes CHECK,ATOMICS
+; RUN: llc < %s -mattr=-atomics | FileCheck %s --check-prefixes NO-ATOMICS
+; RUN: llc < %s -mattr=+atomics | FileCheck %s --check-prefixes ATOMICS
 
 ; Test that the target features section contains -atomics or +atomics
 ; for modules that have thread local storage in their source.
@@ -9,16 +9,13 @@
 
 @foo = internal thread_local global i32 0
 
-; CHECK-LABEL: .custom_section.target_features,"",@
 
 ; -atomics
-; NO-ATOMICS-NEXT: .int8 1
-; NO-ATOMICS-NEXT: .int8 45
-; NO-ATOMICS-NEXT: .int8 7
-; 

[PATCH] D64537: [WebAssembly] Implement thread-local storage for non-PIC cases

2019-07-10 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum planned changes to this revision.
quantum added a comment.

Need to add tests for the compiler intrinsic `__builtin_wasm_tls_size`.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64537/new/

https://reviews.llvm.org/D64537



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64537: [WebAssembly] Implement thread-local storage for non-PIC cases

2019-07-10 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum created this revision.
quantum added reviewers: tlively, aheejin, kripken, sbc100.
Herald added subscribers: llvm-commits, cfe-commits, jfb, sunfish, hiraditya, 
jgravelle-google, dschuff.
Herald added projects: clang, LLVM.
quantum planned changes to this revision.
quantum added a comment.

Need to add tests for the compiler intrinsic `__builtin_wasm_tls_size`.


Thread local variables are placed inside a `.tdata` segment. Their symbols are
offsets from the start of the segment. The address of a thread local variable
is computed as `__tls_base` + the offset from the start of the segment.

`.tdata` segment is a passive segment and `memory.init` is used once per thread
to initialize the thread local storage.

`__tls_base` is a wasm global. Since each thread has its own wasm instance,
it is effectively thread local. Currently, `__tls_base` must be initialized
at thread startup, and so cannot be used with dynamic libraries.

`__tls_base` is to be initialized with a new linker-synthesized function,
`__wasm_init_tls`, which takes as an argument a block of memory to use as the
storage for thread locals. It then initializes the block of memory and sets
`__tls_base`.

To help allocating memory for thread-local storage, a new compiler intrinsic
is introduced: `__builtin_wasm_tls_size()`. This instrinsic function returns
the size of the thread-local storage for the current function.

The expected usage is to run something like the following upon thread startup:

  __wasm_init_tls(calloc(__builtin_wasm_tls_size(), 1));


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D64537

Files:
  clang/include/clang/Basic/BuiltinsWebAssembly.def
  clang/lib/CodeGen/CGBuiltin.cpp
  lld/test/wasm/data-layout.ll
  lld/test/wasm/gc-sections.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/BinaryFormat/Wasm.h
  llvm/include/llvm/IR/IntrinsicsWebAssembly.td
  llvm/include/llvm/MC/MCSectionWasm.h
  llvm/lib/MC/WasmObjectWriter.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISD.def
  llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
  llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
  llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
  llvm/test/CodeGen/WebAssembly/target-features-tls.ll
  llvm/test/CodeGen/WebAssembly/tls.ll

Index: llvm/test/CodeGen/WebAssembly/tls.ll
===
--- llvm/test/CodeGen/WebAssembly/tls.ll
+++ llvm/test/CodeGen/WebAssembly/tls.ll
@@ -1,17 +1,77 @@
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck --check-prefix=SINGLE %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals | FileCheck --check-prefixes=CHECK,O2 %s
+; RUN: llc -O0 < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals | FileCheck --check-prefixes=CHECK,O0 %s
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
-; SINGLE-LABEL: address_of_tls:
+; O0-LABEL: address_of_tls:
+; O2-LABEL: address_of_tls:
 define i32 @address_of_tls() {
-  ; SINGLE: i32.const $push0=, tls
-  ; SINGLE-NEXT: return $pop0
+  ; O0: i32.const tls
+  ; O0-NEXT: global.get __tls_base
+  ; O0-NEXT: i32.add
+  ; O0-NEXT: return
+
+  ; O2: global.get __tls_base
+  ; O2-NEXT: i32.const tls
+  ; O2-NEXT: i32.add
+  ; O2-NEXT: return
   ret i32 ptrtoint(i32* @tls to i32)
 }
 
-; SINGLE: .type	tls,@object
-; SINGLE-NEXT: .section	.bss.tls,"",@
-; SINGLE-NEXT: .p2align 2
-; SINGLE-NEXT: tls:
-; SINGLE-NEXT: .int32 0
+; O0-LABEL: ptr_to_tls
+; O2-LABEL: ptr_to_tls
+define i32* @ptr_to_tls() {
+  ; O0: i32.const tls
+  ; O0-NEXT: global.get __tls_base
+  ; O0-NEXT: i32.add
+  ; O0-NEXT: return
+
+  ; O2: global.get __tls_base
+  ; O2-NEXT: i32.const tls
+  ; O2-NEXT: i32.add
+  ; O2-NEXT: return
+  ret i32* @tls
+}
+
+; O0-LABEL: tls_load
+; O2-LABEL: tls_load
+define i32 @tls_load() {
+  ; O0: i32.const tls
+  ; O0-NEXT: global.get __tls_base
+  ; O0-NEXT: i32.add
+  ; O0-NEXT: i32.load 0
+  ; O0-NEXT: return
+
+  ; O2: global.get __tls_base
+  ; O2-NEXT: i32.const tls
+  ; O2-NEXT: i32.add
+  ; O2-NEXT: i32.load 0
+  ; O2-NEXT: return
+  %tmp = load i32, i32* @tls, align 4
+  ret i32 %tmp
+}
+
+; O0-LABEL: tls_store
+; O2-LABEL: tls_store
+define void @tls_store(i32 %x) {
+  ; O0: i32.const tls
+  ; O0-NEXT: global.get __tls_base
+  ; O0-NEXT: i32.add
+  ; O0-NEXT: i32.store 0
+  ; O0-NEXT: return
+
+  ; O2: global.get __tls_base
+  ; O2-NEXT: i32.const tls
+  ; O2-NEXT: i32.add
+  ; O2-NEXT: i32.store 0
+  ; O2-NEXT: return
+  store i32 %x, i32* @tls, align 4
+  ret void
+}
+
+; CHECK: .type tls,@object
+; CHECK-NEXT: 

[PATCH] D63742: [WebAssembly] Implement Address Sanitizer for Emscripten

2019-06-26 Thread Guanzhong Chen via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL364468: [WebAssembly] Implement Address Sanitizer for 
Emscripten (authored by quantum, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D63742?vs=206719=206732#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D63742/new/

https://reviews.llvm.org/D63742

Files:
  cfe/trunk/lib/Driver/ToolChains/WebAssembly.cpp
  cfe/trunk/test/Driver/wasm-toolchain.c
  llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp


Index: llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp
===
--- llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -109,6 +109,7 @@
 static const uint64_t kNetBSDKasan_ShadowOffset64 = 0xdfff9000;
 static const uint64_t kPS4CPU_ShadowOffset64 = 1ULL << 40;
 static const uint64_t kWindowsShadowOffset32 = 3ULL << 28;
+static const uint64_t kEmscriptenShadowOffset = 0;
 
 static const uint64_t kMyriadShadowScale = 5;
 static const uint64_t kMyriadMemoryOffset32 = 0x8000ULL;
@@ -433,6 +434,7 @@
   bool IsWindows = TargetTriple.isOSWindows();
   bool IsFuchsia = TargetTriple.isOSFuchsia();
   bool IsMyriad = TargetTriple.getVendor() == llvm::Triple::Myriad;
+  bool IsEmscripten = TargetTriple.isOSEmscripten();
 
   ShadowMapping Mapping;
 
@@ -454,6 +456,8 @@
   Mapping.Offset = kDynamicShadowSentinel;
 else if (IsWindows)
   Mapping.Offset = kWindowsShadowOffset32;
+else if (IsEmscripten)
+  Mapping.Offset = kEmscriptenShadowOffset;
 else if (IsMyriad) {
   uint64_t ShadowOffset = (kMyriadMemoryOffset32 + kMyriadMemorySize32 -
(kMyriadMemorySize32 >> Mapping.Scale));
Index: cfe/trunk/test/Driver/wasm-toolchain.c
===
--- cfe/trunk/test/Driver/wasm-toolchain.c
+++ cfe/trunk/test/Driver/wasm-toolchain.c
@@ -60,3 +60,7 @@
 // RUN: --sysroot=/foo %s -pthread -mno-atomics 2>&1 \
 // RUN:   | FileCheck -check-prefix=PTHREAD_NO_ATOMICS %s
 // PTHREAD_NO_ATOMICS: invalid argument '-pthread' not allowed with 
'-mno-atomics'
+
+// RUN: %clang %s -### -fsanitize=address -target wasm32-unknown-emscripten 
2>&1 | FileCheck -check-prefix=CHECK-ASAN-EMSCRIPTEN %s
+// CHECK-ASAN-EMSCRIPTEN: "-fsanitize=address"
+// CHECK-ASAN-EMSCRIPTEN: "-fsanitize-address-globals-dead-stripping"
Index: cfe/trunk/lib/Driver/ToolChains/WebAssembly.cpp
===
--- cfe/trunk/lib/Driver/ToolChains/WebAssembly.cpp
+++ cfe/trunk/lib/Driver/ToolChains/WebAssembly.cpp
@@ -238,7 +238,7 @@
 SanitizerMask WebAssembly::getSupportedSanitizers() const {
   SanitizerMask Res = ToolChain::getSupportedSanitizers();
   if (getTriple().isOSEmscripten()) {
-Res |= SanitizerKind::Vptr | SanitizerKind::Leak;
+Res |= SanitizerKind::Vptr | SanitizerKind::Leak | SanitizerKind::Address;
   }
   return Res;
 }


Index: llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp
===
--- llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -109,6 +109,7 @@
 static const uint64_t kNetBSDKasan_ShadowOffset64 = 0xdfff9000;
 static const uint64_t kPS4CPU_ShadowOffset64 = 1ULL << 40;
 static const uint64_t kWindowsShadowOffset32 = 3ULL << 28;
+static const uint64_t kEmscriptenShadowOffset = 0;
 
 static const uint64_t kMyriadShadowScale = 5;
 static const uint64_t kMyriadMemoryOffset32 = 0x8000ULL;
@@ -433,6 +434,7 @@
   bool IsWindows = TargetTriple.isOSWindows();
   bool IsFuchsia = TargetTriple.isOSFuchsia();
   bool IsMyriad = TargetTriple.getVendor() == llvm::Triple::Myriad;
+  bool IsEmscripten = TargetTriple.isOSEmscripten();
 
   ShadowMapping Mapping;
 
@@ -454,6 +456,8 @@
   Mapping.Offset = kDynamicShadowSentinel;
 else if (IsWindows)
   Mapping.Offset = kWindowsShadowOffset32;
+else if (IsEmscripten)
+  Mapping.Offset = kEmscriptenShadowOffset;
 else if (IsMyriad) {
   uint64_t ShadowOffset = (kMyriadMemoryOffset32 + kMyriadMemorySize32 -
(kMyriadMemorySize32 >> Mapping.Scale));
Index: cfe/trunk/test/Driver/wasm-toolchain.c
===
--- cfe/trunk/test/Driver/wasm-toolchain.c
+++ cfe/trunk/test/Driver/wasm-toolchain.c
@@ -60,3 +60,7 @@
 // RUN: --sysroot=/foo %s -pthread -mno-atomics 2>&1 \
 // RUN:   | FileCheck -check-prefix=PTHREAD_NO_ATOMICS %s
 // PTHREAD_NO_ATOMICS: invalid argument '-pthread' not allowed with '-mno-atomics'
+
+// RUN: %clang %s -### -fsanitize=address -target wasm32-unknown-emscripten 2>&1 | FileCheck -check-prefix=CHECK-ASAN-EMSCRIPTEN %s
+// 

[PATCH] D63742: [WebAssembly] Implement Address Sanitizer for Emscripten

2019-06-26 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum updated this revision to Diff 206719.
quantum added a comment.

Split wasm-ld change into D63833 .


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D63742/new/

https://reviews.llvm.org/D63742

Files:
  clang/lib/Driver/ToolChains/WebAssembly.cpp
  clang/test/Driver/wasm-toolchain.c
  llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp


Index: llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
===
--- llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -112,6 +112,7 @@
 static const uint64_t kNetBSDKasan_ShadowOffset64 = 0xdfff9000;
 static const uint64_t kPS4CPU_ShadowOffset64 = 1ULL << 40;
 static const uint64_t kWindowsShadowOffset32 = 3ULL << 28;
+static const uint64_t kEmscriptenShadowOffset = 0;
 
 static const uint64_t kMyriadShadowScale = 5;
 static const uint64_t kMyriadMemoryOffset32 = 0x8000ULL;
@@ -437,6 +438,7 @@
   bool IsWindows = TargetTriple.isOSWindows();
   bool IsFuchsia = TargetTriple.isOSFuchsia();
   bool IsMyriad = TargetTriple.getVendor() == llvm::Triple::Myriad;
+  bool IsEmscripten = TargetTriple.isOSEmscripten();
 
   ShadowMapping Mapping;
 
@@ -459,6 +461,8 @@
   Mapping.Offset = IsX86 ? kIOSSimShadowOffset32 : kIOSShadowOffset32;
 else if (IsWindows)
   Mapping.Offset = kWindowsShadowOffset32;
+else if (IsEmscripten)
+  Mapping.Offset = kEmscriptenShadowOffset;
 else if (IsMyriad) {
   uint64_t ShadowOffset = (kMyriadMemoryOffset32 + kMyriadMemorySize32 -
(kMyriadMemorySize32 >> Mapping.Scale));
Index: clang/test/Driver/wasm-toolchain.c
===
--- clang/test/Driver/wasm-toolchain.c
+++ clang/test/Driver/wasm-toolchain.c
@@ -49,3 +49,7 @@
 // '-pthread' not allowed with '-mno-atomics'
 // RUN: %clang -### -no-canonical-prefixes -target wasm32-unknown-unknown 
--sysroot=/foo %s -pthread -mno-atomics 2>&1 | FileCheck 
-check-prefix=PTHREAD_NO_ATOMICS %s
 // PTHREAD_NO_ATOMICS: invalid argument '-pthread' not allowed with 
'-mno-atomics'
+
+// RUN: %clang %s -### -fsanitize=address -target wasm32-unknown-emscripten 
2>&1 | FileCheck -check-prefix=CHECK-ASAN-EMSCRIPTEN %s
+// CHECK-ASAN-EMSCRIPTEN: "-fsanitize=address"
+// CHECK-ASAN-EMSCRIPTEN: "-fsanitize-address-globals-dead-stripping"
Index: clang/lib/Driver/ToolChains/WebAssembly.cpp
===
--- clang/lib/Driver/ToolChains/WebAssembly.cpp
+++ clang/lib/Driver/ToolChains/WebAssembly.cpp
@@ -211,7 +211,7 @@
 SanitizerMask WebAssembly::getSupportedSanitizers() const {
   SanitizerMask Res = ToolChain::getSupportedSanitizers();
   if (getTriple().isOSEmscripten()) {
-Res |= SanitizerKind::Vptr | SanitizerKind::Leak;
+Res |= SanitizerKind::Vptr | SanitizerKind::Leak | SanitizerKind::Address;
   }
   return Res;
 }


Index: llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
===
--- llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -112,6 +112,7 @@
 static const uint64_t kNetBSDKasan_ShadowOffset64 = 0xdfff9000;
 static const uint64_t kPS4CPU_ShadowOffset64 = 1ULL << 40;
 static const uint64_t kWindowsShadowOffset32 = 3ULL << 28;
+static const uint64_t kEmscriptenShadowOffset = 0;
 
 static const uint64_t kMyriadShadowScale = 5;
 static const uint64_t kMyriadMemoryOffset32 = 0x8000ULL;
@@ -437,6 +438,7 @@
   bool IsWindows = TargetTriple.isOSWindows();
   bool IsFuchsia = TargetTriple.isOSFuchsia();
   bool IsMyriad = TargetTriple.getVendor() == llvm::Triple::Myriad;
+  bool IsEmscripten = TargetTriple.isOSEmscripten();
 
   ShadowMapping Mapping;
 
@@ -459,6 +461,8 @@
   Mapping.Offset = IsX86 ? kIOSSimShadowOffset32 : kIOSShadowOffset32;
 else if (IsWindows)
   Mapping.Offset = kWindowsShadowOffset32;
+else if (IsEmscripten)
+  Mapping.Offset = kEmscriptenShadowOffset;
 else if (IsMyriad) {
   uint64_t ShadowOffset = (kMyriadMemoryOffset32 + kMyriadMemorySize32 -
(kMyriadMemorySize32 >> Mapping.Scale));
Index: clang/test/Driver/wasm-toolchain.c
===
--- clang/test/Driver/wasm-toolchain.c
+++ clang/test/Driver/wasm-toolchain.c
@@ -49,3 +49,7 @@
 // '-pthread' not allowed with '-mno-atomics'
 // RUN: %clang -### -no-canonical-prefixes -target wasm32-unknown-unknown --sysroot=/foo %s -pthread -mno-atomics 2>&1 | FileCheck -check-prefix=PTHREAD_NO_ATOMICS %s
 // PTHREAD_NO_ATOMICS: invalid argument '-pthread' not allowed with '-mno-atomics'
+
+// RUN: %clang %s -### -fsanitize=address -target wasm32-unknown-emscripten 2>&1 | FileCheck 

[PATCH] D63742: [WebAssembly] Implement Address Sanitizer for Emscripten

2019-06-25 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum marked an inline comment as done.
quantum added a comment.

As for the name, I think `__global_base` matches the command line flag and 
makes it more clear what controls it, so I lean towards that.




Comment at: lld/wasm/Writer.cpp:228
+  if (WasmSym::GlobalBase)
+WasmSym::GlobalBase->setVirtualAddress(Config->GlobalBase);
+

sbc100 wrote:
> Surly if emscripten is passing in --global-base it already knows this value?  
> 
> Otherwise lgtm.   Perhaps split of the lld part into a separate change?
In theory, emscripten knows this value. But as some library code needs this 
information, the alternative would be to have build an object file with this 
information and link it in. Since we already have `__data_end` and 
`__heap_base`, I think it makes sense for this information to be available too.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D63742/new/

https://reviews.llvm.org/D63742



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D63742: [WebAssembly] Implement Address Sanitizer for Emscripten

2019-06-24 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum created this revision.
quantum added reviewers: tlively, aheejin.
Herald added subscribers: llvm-commits, cfe-commits, sunfish, hiraditya, 
jgravelle-google, sbc100, dschuff.
Herald added projects: clang, LLVM.

This diff enables address sanitizer on Emscripten.

On Emscripten, real memory starts at the value passed to --global-base.

All memory before this is used as shadow memory, and thus the shadow mapping
function is simply dividing by 8.

A symbol __global_base is added so that code may know where the shadow
memory ends and real memory begins.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D63742

Files:
  clang/lib/Driver/ToolChains/WebAssembly.cpp
  clang/test/Driver/wasm-toolchain.c
  lld/test/wasm/global-base.ll
  lld/wasm/Driver.cpp
  lld/wasm/Symbols.cpp
  lld/wasm/Symbols.h
  lld/wasm/Writer.cpp
  llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp

Index: llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
===
--- llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -112,6 +112,7 @@
 static const uint64_t kNetBSDKasan_ShadowOffset64 = 0xdfff9000;
 static const uint64_t kPS4CPU_ShadowOffset64 = 1ULL << 40;
 static const uint64_t kWindowsShadowOffset32 = 3ULL << 28;
+static const uint64_t kEmscriptenShadowOffset = 0;
 
 static const uint64_t kMyriadShadowScale = 5;
 static const uint64_t kMyriadMemoryOffset32 = 0x8000ULL;
@@ -437,6 +438,7 @@
   bool IsWindows = TargetTriple.isOSWindows();
   bool IsFuchsia = TargetTriple.isOSFuchsia();
   bool IsMyriad = TargetTriple.getVendor() == llvm::Triple::Myriad;
+  bool IsEmscripten = TargetTriple.isOSEmscripten();
 
   ShadowMapping Mapping;
 
@@ -459,6 +461,8 @@
   Mapping.Offset = IsX86 ? kIOSSimShadowOffset32 : kIOSShadowOffset32;
 else if (IsWindows)
   Mapping.Offset = kWindowsShadowOffset32;
+else if (IsEmscripten)
+  Mapping.Offset = kEmscriptenShadowOffset;
 else if (IsMyriad) {
   uint64_t ShadowOffset = (kMyriadMemoryOffset32 + kMyriadMemorySize32 -
(kMyriadMemorySize32 >> Mapping.Scale));
Index: lld/wasm/Writer.cpp
===
--- lld/wasm/Writer.cpp
+++ lld/wasm/Writer.cpp
@@ -224,6 +224,9 @@
 log("mem: global base = " + Twine(Config->GlobalBase));
   }
 
+  if (WasmSym::GlobalBase)
+WasmSym::GlobalBase->setVirtualAddress(Config->GlobalBase);
+
   uint32_t DataStart = MemoryPtr;
 
   // Arbitrarily set __dso_handle handle to point to the start of the data
Index: lld/wasm/Symbols.h
===
--- lld/wasm/Symbols.h
+++ lld/wasm/Symbols.h
@@ -415,6 +415,10 @@
 
 // linker-generated symbols
 struct WasmSym {
+  // __global_base
+  // Symbol marking the start of the global section.
+  static DefinedData *GlobalBase;
+
   // __stack_pointer
   // Global that holds the address of the top of the explicit value stack in
   // linear memory.
Index: lld/wasm/Symbols.cpp
===
--- lld/wasm/Symbols.cpp
+++ lld/wasm/Symbols.cpp
@@ -28,6 +28,7 @@
 DefinedFunction *WasmSym::ApplyRelocs;
 DefinedData *WasmSym::DsoHandle;
 DefinedData *WasmSym::DataEnd;
+DefinedData *WasmSym::GlobalBase;
 DefinedData *WasmSym::HeapBase;
 GlobalSymbol *WasmSym::StackPointer;
 UndefinedGlobal *WasmSym::TableBase;
Index: lld/wasm/Driver.cpp
===
--- lld/wasm/Driver.cpp
+++ lld/wasm/Driver.cpp
@@ -482,6 +482,7 @@
 WasmSym::StackPointer = Symtab->addSyntheticGlobal(
 "__stack_pointer", WASM_SYMBOL_VISIBILITY_HIDDEN, StackPointer);
 WasmSym::DataEnd = Symtab->addOptionalDataSymbol("__data_end");
+WasmSym::GlobalBase = Symtab->addOptionalDataSymbol("__global_base");
 WasmSym::HeapBase = Symtab->addOptionalDataSymbol("__heap_base");
   }
 
Index: lld/test/wasm/global-base.ll
===
--- /dev/null
+++ lld/test/wasm/global-base.ll
@@ -0,0 +1,73 @@
+; RUN: llc -filetype=obj %s -o %t.o
+
+target triple = "wasm32-unknown-unknown"
+
+; RUN: wasm-ld -no-gc-sections --export=__global_base --export=__data_end --allow-undefined --no-entry -o %t.wasm %t.o
+; RUN: obj2yaml %t.wasm | FileCheck %s  -check-prefix=CHECK-1024
+; CHECK-1024:   - Type:GLOBAL
+; CHECK-1024-NEXT:Globals: 
+; CHECK-1024-NEXT:  - Index:   0
+; CHECK-1024-NEXT:Type:I32
+; CHECK-1024-NEXT:Mutable: true
+; CHECK-1024-NEXT:InitExpr:
+; CHECK-1024-NEXT:  Opcode:  I32_CONST
+; CHECK-1024-NEXT:  Value:   66560
+; CHECK-1024-NEXT:  - Index:   1
+; CHECK-1024-NEXT:Type:I32
+; CHECK-1024-NEXT:Mutable: 

[PATCH] D62830: [WebAssembly] Support Leak Sanitizer on Emscripten

2019-06-04 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum added a comment.

It's not urgent, so I am willing to wait a day or two for commit access. If I 
still can't get access by then, I'll ask someone else to commit this.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D62830/new/

https://reviews.llvm.org/D62830



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D62830: [WebAssembly] Support Leak Sanitizer on Emscripten

2019-06-04 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum added a comment.

LSan is supposed to be linked in to replace some C library functions, and does 
not change the generated LLVM IR code, so there is nothing to actually test in 
LLVM.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D62830/new/

https://reviews.llvm.org/D62830



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D62830: [WebAssembly] Support Leak Sanitizer on Emscripten

2019-06-03 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum created this revision.
quantum added reviewers: tlively, aheejin.
Herald added subscribers: cfe-commits, sunfish, jgravelle-google, sbc100, 
dschuff.
Herald added a project: clang.

LSan is currently being ported to Emscripten and mostly works.

Enabling the support in upstream would simplify testing.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D62830

Files:
  clang/lib/Driver/ToolChains/WebAssembly.cpp


Index: clang/lib/Driver/ToolChains/WebAssembly.cpp
===
--- clang/lib/Driver/ToolChains/WebAssembly.cpp
+++ clang/lib/Driver/ToolChains/WebAssembly.cpp
@@ -211,7 +211,7 @@
 SanitizerMask WebAssembly::getSupportedSanitizers() const {
   SanitizerMask Res = ToolChain::getSupportedSanitizers();
   if (getTriple().isOSEmscripten()) {
-Res |= SanitizerKind::Vptr;
+Res |= SanitizerKind::Vptr | SanitizerKind::Leak;
   }
   return Res;
 }


Index: clang/lib/Driver/ToolChains/WebAssembly.cpp
===
--- clang/lib/Driver/ToolChains/WebAssembly.cpp
+++ clang/lib/Driver/ToolChains/WebAssembly.cpp
@@ -211,7 +211,7 @@
 SanitizerMask WebAssembly::getSupportedSanitizers() const {
   SanitizerMask Res = ToolChain::getSupportedSanitizers();
   if (getTriple().isOSEmscripten()) {
-Res |= SanitizerKind::Vptr;
+Res |= SanitizerKind::Vptr | SanitizerKind::Leak;
   }
   return Res;
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D62559: [WebAssembly] Support VPtr sanitizer for Emscripten

2019-05-28 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum marked 2 inline comments as done.
quantum added inline comments.



Comment at: clang/lib/Driver/ToolChains/WebAssembly.cpp:214
+  if (getTriple().isOSEmscripten()) {
+Res |= SanitizerKind::Vptr;
+  }

aheejin wrote:
> quantum wrote:
> > aheejin wrote:
> > > Does this mean we only support `Vptr` among sanitizers [[ 
> > > https://github.com/llvm/llvm-project/blob/92d706eaca6cc79501066eae4392b68e52c1/clang/include/clang/Basic/Sanitizers.def#L76-L103
> > >  | here ]]?
> > No, by default all of UBSan except `Vptr` and `Function` are declared as 
> > supported. This adds Vptr to the list as it's supported on Emscripten.
> I see. By the way where do we say we support the undefined sanitizer group?
The base `ToolChain` class says it's supported on all platforms.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D62559/new/

https://reviews.llvm.org/D62559



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D62559: [WebAssembly] Support VPtr sanitizer for Emscripten

2019-05-28 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum updated this revision to Diff 201803.
quantum marked an inline comment as done.
quantum added a comment.

Add a test


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D62559/new/

https://reviews.llvm.org/D62559

Files:
  clang/lib/Driver/ToolChains/WebAssembly.cpp
  clang/lib/Driver/ToolChains/WebAssembly.h
  clang/test/CodeGenCXX/wasm-sanitize-vptr.cpp


Index: clang/test/CodeGenCXX/wasm-sanitize-vptr.cpp
===
--- /dev/null
+++ clang/test/CodeGenCXX/wasm-sanitize-vptr.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -std=c++11 -fsanitize=vptr -emit-llvm %s -o - -triple 
wasm32-unknown-emscripten | FileCheck %s
+
+struct S {
+  virtual ~S() {}
+  int a;
+};
+
+struct T : S {
+  int b;
+};
+
+// CHECK-LABEL: @_Z15bad_static_castv
+void bad_static_cast() {
+  S s;
+  // CHECK: br i1 %[[NONNULL:.*]], label %[[CONT:.*]], label %[[MISS:.*]], 
!prof
+  // CHECK: [[MISS]]:
+  // CHECK: call void @__ubsan_handle_dynamic_type_cache_miss_abort
+  // CHECK: [[CONT]]:
+  T  = static_cast(s);
+}
Index: clang/lib/Driver/ToolChains/WebAssembly.h
===
--- clang/lib/Driver/ToolChains/WebAssembly.h
+++ clang/lib/Driver/ToolChains/WebAssembly.h
@@ -66,6 +66,7 @@
   llvm::opt::ArgStringList ) const override;
   void AddCXXStdlibLibArgs(const llvm::opt::ArgList ,
llvm::opt::ArgStringList ) const override;
+  SanitizerMask getSupportedSanitizers() const override;
 
   const char *getDefaultLinker() const override { return "wasm-ld"; }
 
Index: clang/lib/Driver/ToolChains/WebAssembly.cpp
===
--- clang/lib/Driver/ToolChains/WebAssembly.cpp
+++ clang/lib/Driver/ToolChains/WebAssembly.cpp
@@ -208,6 +208,14 @@
   }
 }
 
+SanitizerMask WebAssembly::getSupportedSanitizers() const {
+  SanitizerMask Res = ToolChain::getSupportedSanitizers();
+  if (getTriple().isOSEmscripten()) {
+Res |= SanitizerKind::Vptr;
+  }
+  return Res;
+}
+
 Tool *WebAssembly::buildLinker() const {
   return new tools::wasm::Linker(*this);
 }


Index: clang/test/CodeGenCXX/wasm-sanitize-vptr.cpp
===
--- /dev/null
+++ clang/test/CodeGenCXX/wasm-sanitize-vptr.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -std=c++11 -fsanitize=vptr -emit-llvm %s -o - -triple wasm32-unknown-emscripten | FileCheck %s
+
+struct S {
+  virtual ~S() {}
+  int a;
+};
+
+struct T : S {
+  int b;
+};
+
+// CHECK-LABEL: @_Z15bad_static_castv
+void bad_static_cast() {
+  S s;
+  // CHECK: br i1 %[[NONNULL:.*]], label %[[CONT:.*]], label %[[MISS:.*]], !prof
+  // CHECK: [[MISS]]:
+  // CHECK: call void @__ubsan_handle_dynamic_type_cache_miss_abort
+  // CHECK: [[CONT]]:
+  T  = static_cast(s);
+}
Index: clang/lib/Driver/ToolChains/WebAssembly.h
===
--- clang/lib/Driver/ToolChains/WebAssembly.h
+++ clang/lib/Driver/ToolChains/WebAssembly.h
@@ -66,6 +66,7 @@
   llvm::opt::ArgStringList ) const override;
   void AddCXXStdlibLibArgs(const llvm::opt::ArgList ,
llvm::opt::ArgStringList ) const override;
+  SanitizerMask getSupportedSanitizers() const override;
 
   const char *getDefaultLinker() const override { return "wasm-ld"; }
 
Index: clang/lib/Driver/ToolChains/WebAssembly.cpp
===
--- clang/lib/Driver/ToolChains/WebAssembly.cpp
+++ clang/lib/Driver/ToolChains/WebAssembly.cpp
@@ -208,6 +208,14 @@
   }
 }
 
+SanitizerMask WebAssembly::getSupportedSanitizers() const {
+  SanitizerMask Res = ToolChain::getSupportedSanitizers();
+  if (getTriple().isOSEmscripten()) {
+Res |= SanitizerKind::Vptr;
+  }
+  return Res;
+}
+
 Tool *WebAssembly::buildLinker() const {
   return new tools::wasm::Linker(*this);
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D62559: [WebAssembly] Support VPtr sanitizer for Emscripten

2019-05-28 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum marked 2 inline comments as done.
quantum added inline comments.



Comment at: clang/lib/Driver/ToolChains/WebAssembly.cpp:214
+  if (getTriple().isOSEmscripten()) {
+Res |= SanitizerKind::Vptr;
+  }

aheejin wrote:
> Does this mean we only support `Vptr` among sanitizers [[ 
> https://github.com/llvm/llvm-project/blob/92d706eaca6cc79501066eae4392b68e52c1/clang/include/clang/Basic/Sanitizers.def#L76-L103
>  | here ]]?
No, by default all of UBSan except `Vptr` and `Function` are declared as 
supported. This adds Vptr to the list as it's supported on Emscripten.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D62559/new/

https://reviews.llvm.org/D62559



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D62559: [WebAssembly] Support VPtr sanitizer for Emscripten

2019-05-28 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum created this revision.
quantum added reviewers: tlively, aheejin.
Herald added subscribers: cfe-commits, sunfish, jgravelle-google, sbc100, 
dschuff.
Herald added a project: clang.

After https://github.com/emscripten-core/emscripten/pull/8651, Emscripten
supports the full UBSan runtime. This includes the VPtr sanitizer.

This diff allows clang to generate code that uses the VPtr sanitizer for
Emscripten.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D62559

Files:
  clang/lib/Driver/ToolChains/WebAssembly.cpp
  clang/lib/Driver/ToolChains/WebAssembly.h


Index: clang/lib/Driver/ToolChains/WebAssembly.h
===
--- clang/lib/Driver/ToolChains/WebAssembly.h
+++ clang/lib/Driver/ToolChains/WebAssembly.h
@@ -66,6 +66,7 @@
   llvm::opt::ArgStringList ) const override;
   void AddCXXStdlibLibArgs(const llvm::opt::ArgList ,
llvm::opt::ArgStringList ) const override;
+  SanitizerMask getSupportedSanitizers() const override;
 
   const char *getDefaultLinker() const override { return "wasm-ld"; }
 
Index: clang/lib/Driver/ToolChains/WebAssembly.cpp
===
--- clang/lib/Driver/ToolChains/WebAssembly.cpp
+++ clang/lib/Driver/ToolChains/WebAssembly.cpp
@@ -208,6 +208,14 @@
   }
 }
 
+SanitizerMask WebAssembly::getSupportedSanitizers() const {
+  SanitizerMask Res = ToolChain::getSupportedSanitizers();
+  if (getTriple().isOSEmscripten()) {
+Res |= SanitizerKind::Vptr;
+  }
+  return Res;
+}
+
 Tool *WebAssembly::buildLinker() const {
   return new tools::wasm::Linker(*this);
 }


Index: clang/lib/Driver/ToolChains/WebAssembly.h
===
--- clang/lib/Driver/ToolChains/WebAssembly.h
+++ clang/lib/Driver/ToolChains/WebAssembly.h
@@ -66,6 +66,7 @@
   llvm::opt::ArgStringList ) const override;
   void AddCXXStdlibLibArgs(const llvm::opt::ArgList ,
llvm::opt::ArgStringList ) const override;
+  SanitizerMask getSupportedSanitizers() const override;
 
   const char *getDefaultLinker() const override { return "wasm-ld"; }
 
Index: clang/lib/Driver/ToolChains/WebAssembly.cpp
===
--- clang/lib/Driver/ToolChains/WebAssembly.cpp
+++ clang/lib/Driver/ToolChains/WebAssembly.cpp
@@ -208,6 +208,14 @@
   }
 }
 
+SanitizerMask WebAssembly::getSupportedSanitizers() const {
+  SanitizerMask Res = ToolChain::getSupportedSanitizers();
+  if (getTriple().isOSEmscripten()) {
+Res |= SanitizerKind::Vptr;
+  }
+  return Res;
+}
+
 Tool *WebAssembly::buildLinker() const {
   return new tools::wasm::Linker(*this);
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D62333: Fix unresolved symbols when linking tools/clang/unittests/Tooling/ToolingTests

2019-05-28 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum marked 2 inline comments as done.
quantum added inline comments.



Comment at: cfe/trunk/unittests/Tooling/CMakeLists.txt:4
   Support
   TestingSupport
   )

thakis wrote:
> The library is already up here. Why do we need it twice?
We don't. It's removed in the code that's merged.


Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D62333/new/

https://reviews.llvm.org/D62333



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D62333: Fix unresolved symbols when linking tools/clang/unittests/Tooling/ToolingTests

2019-05-23 Thread Guanzhong Chen via Phabricator via cfe-commits
quantum created this revision.
quantum added reviewers: tlively, aheejin.
Herald added subscribers: cfe-commits, mgorny.
Herald added a project: clang.

Add correct cmake dependencies so that `ToolingTests` link successfully.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D62333

Files:
  clang/unittests/Tooling/CMakeLists.txt


Index: clang/unittests/Tooling/CMakeLists.txt
===
--- clang/unittests/Tooling/CMakeLists.txt
+++ clang/unittests/Tooling/CMakeLists.txt
@@ -2,6 +2,7 @@
   ${LLVM_TARGETS_TO_BUILD}
   Support
   TestingSupport
+  LLVMTestingSupport
   )
 
 # By default MSVC has a 2^16 limit on the number of sections in an object file,
@@ -71,6 +72,7 @@
   clangToolingCore
   clangToolingInclusions
   clangToolingRefactor
+  LLVMTestingSupport
   )
 
 


Index: clang/unittests/Tooling/CMakeLists.txt
===
--- clang/unittests/Tooling/CMakeLists.txt
+++ clang/unittests/Tooling/CMakeLists.txt
@@ -2,6 +2,7 @@
   ${LLVM_TARGETS_TO_BUILD}
   Support
   TestingSupport
+  LLVMTestingSupport
   )
 
 # By default MSVC has a 2^16 limit on the number of sections in an object file,
@@ -71,6 +72,7 @@
   clangToolingCore
   clangToolingInclusions
   clangToolingRefactor
+  LLVMTestingSupport
   )
 
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits