summaryrefslogtreecommitdiffstats
path: root/lld/test
diff options
context:
space:
mode:
authorSam Clegg <sbc@chromium.org>2017-11-17 18:14:09 +0000
committerSam Clegg <sbc@chromium.org>2017-11-17 18:14:09 +0000
commitc94d393ad52b6698b15400ee7a33a68b4bda274b (patch)
tree2609add8ef4574c40a55c0604abd6a98d6e4857a /lld/test
parentae304b07176190a69853d3430c7206146ac8d0e6 (diff)
downloadbcm5719-llvm-c94d393ad52b6698b15400ee7a33a68b4bda274b.tar.gz
bcm5719-llvm-c94d393ad52b6698b15400ee7a33a68b4bda274b.zip
[WebAssembly] Initial wasm linker implementation
This linker backend is still a work in progress but is enough to link simple programs including linking against library archives. Differential Revision: https://reviews.llvm.org/D34851 llvm-svn: 318539
Diffstat (limited to 'lld/test')
-rw-r--r--lld/test/lit.cfg.py3
-rw-r--r--lld/test/wasm/Inputs/archive1.ll7
-rw-r--r--lld/test/wasm/Inputs/archive2.ll7
-rw-r--r--lld/test/wasm/Inputs/call-indirect.ll18
-rw-r--r--lld/test/wasm/Inputs/hello.ll18
-rw-r--r--lld/test/wasm/Inputs/many-funcs.ll779
-rw-r--r--lld/test/wasm/Inputs/ret32.ll9
-rw-r--r--lld/test/wasm/Inputs/ret64.ll7
-rw-r--r--lld/test/wasm/Inputs/weak-alias.ll12
-rw-r--r--lld/test/wasm/archive.ll24
-rw-r--r--lld/test/wasm/call-indirect.ll110
-rw-r--r--lld/test/wasm/conflict.test6
-rw-r--r--lld/test/wasm/data-layout.ll64
-rw-r--r--lld/test/wasm/entry.ll22
-rw-r--r--lld/test/wasm/function-imports-first.ll45
-rw-r--r--lld/test/wasm/function-imports.ll40
-rw-r--r--lld/test/wasm/function-index.test18
-rw-r--r--lld/test/wasm/import-memory.test13
-rw-r--r--lld/test/wasm/invalid-stack-size.test9
-rw-r--r--lld/test/wasm/lit.local.cfg4
-rw-r--r--lld/test/wasm/local-symbols.ll81
-rw-r--r--lld/test/wasm/many-functions.ll699
-rw-r--r--lld/test/wasm/relocatable.ll185
-rw-r--r--lld/test/wasm/strip-debug.test6
-rw-r--r--lld/test/wasm/symtol-type-mismatch.ll12
-rw-r--r--lld/test/wasm/undefined-entry.test4
-rw-r--r--lld/test/wasm/undefined.ll23
-rw-r--r--lld/test/wasm/version.ll16
-rw-r--r--lld/test/wasm/weak-alias-overide.ll92
-rw-r--r--lld/test/wasm/weak-alias.ll82
-rw-r--r--lld/test/wasm/weak-external.ll86
31 files changed, 2500 insertions, 1 deletions
diff --git a/lld/test/lit.cfg.py b/lld/test/lit.cfg.py
index 05efee9e2f3..ae0dd187c60 100644
--- a/lld/test/lit.cfg.py
+++ b/lld/test/lit.cfg.py
@@ -39,7 +39,7 @@ llvm_config.use_default_substitutions()
llvm_config.use_lld()
tool_patterns = [
- 'llvm-as', 'llvm-mc', 'llvm-nm',
+ 'llc', 'llvm-as', 'llvm-mc', 'llvm-nm',
'llvm-objdump', 'llvm-pdbutil', 'llvm-readobj', 'obj2yaml', 'yaml2obj']
llvm_config.add_tool_substitutions(tool_patterns)
@@ -67,6 +67,7 @@ llvm_config.feature_config(
'Mips': 'mips',
'PowerPC': 'ppc',
'Sparc': 'sparc',
+ 'WebAssembly': 'wasm',
'X86': 'x86'})
])
diff --git a/lld/test/wasm/Inputs/archive1.ll b/lld/test/wasm/Inputs/archive1.ll
new file mode 100644
index 00000000000..c942fa2c1b5
--- /dev/null
+++ b/lld/test/wasm/Inputs/archive1.ll
@@ -0,0 +1,7 @@
+declare i32 @bar() local_unnamed_addr #1
+
+define i32 @foo() local_unnamed_addr #0 {
+entry:
+ %call = tail call i32 @bar() #2
+ ret i32 %call
+}
diff --git a/lld/test/wasm/Inputs/archive2.ll b/lld/test/wasm/Inputs/archive2.ll
new file mode 100644
index 00000000000..35534dc9e07
--- /dev/null
+++ b/lld/test/wasm/Inputs/archive2.ll
@@ -0,0 +1,7 @@
+declare i32 @foo() local_unnamed_addr #1
+
+define i32 @bar() local_unnamed_addr #0 {
+entry:
+ %call = tail call i32 @foo() #2
+ ret i32 %call
+}
diff --git a/lld/test/wasm/Inputs/call-indirect.ll b/lld/test/wasm/Inputs/call-indirect.ll
new file mode 100644
index 00000000000..1ffd2427ce6
--- /dev/null
+++ b/lld/test/wasm/Inputs/call-indirect.ll
@@ -0,0 +1,18 @@
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32-unknown-unknown-wasm"
+
+@indirect_bar = hidden local_unnamed_addr global i32 ()* @bar, align 4
+
+; Function Attrs: norecurse nounwind readnone
+define hidden i32 @bar() #0 {
+entry:
+ ret i32 1
+}
+
+; Function Attrs: nounwind
+define hidden void @call_bar_indirect() local_unnamed_addr #1 {
+entry:
+ %0 = load i32 ()*, i32 ()** @indirect_bar, align 4
+ %call = tail call i32 %0() #2
+ ret void
+}
diff --git a/lld/test/wasm/Inputs/hello.ll b/lld/test/wasm/Inputs/hello.ll
new file mode 100644
index 00000000000..73334add99d
--- /dev/null
+++ b/lld/test/wasm/Inputs/hello.ll
@@ -0,0 +1,18 @@
+; Wasm module generated from the following C code:
+; void puts(const char*);
+; void hello() { puts("hello\n"); }
+
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32-unknown-unknown-wasm"
+
+@hello_str = unnamed_addr constant [7 x i8] c"hello\0A\00", align 1
+
+; Function Attrs: nounwind
+define hidden void @hello() local_unnamed_addr #0 {
+entry:
+ tail call void @puts(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @hello_str, i32 0, i32 0))
+ ret void
+}
+
+; Function Attrs: nounwind
+declare void @puts(i8* nocapture readonly) local_unnamed_addr #1
diff --git a/lld/test/wasm/Inputs/many-funcs.ll b/lld/test/wasm/Inputs/many-funcs.ll
new file mode 100644
index 00000000000..d468563e734
--- /dev/null
+++ b/lld/test/wasm/Inputs/many-funcs.ll
@@ -0,0 +1,779 @@
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32-unknown-unknown-wasm"
+
+@g0 = global i32 1, align 4
+@foo = global i32 1, align 4
+
+define i32 @f1() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f2() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f3() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f4() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f5() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f6() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f7() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f8() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f9() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f10() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f11() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f12() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f13() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f14() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f15() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f16() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f17() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f18() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f19() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f20() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f21() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f22() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f23() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f24() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f25() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f26() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f27() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f28() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f29() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f30() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f31() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f32() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f33() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f34() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f35() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f36() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f37() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f38() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f39() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f40() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f41() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f42() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f43() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f44() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f45() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f46() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f47() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f48() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f49() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f50() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f51() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f52() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f53() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f54() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f55() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f56() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f57() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f58() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f59() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f60() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f61() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f62() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f63() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f64() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f65() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f66() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f67() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f68() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f69() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f70() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f71() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f72() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f73() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f74() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f75() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f76() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f77() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f78() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f79() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f80() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f81() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f82() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f83() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f84() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f85() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f86() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f87() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f88() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f89() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f90() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f91() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f92() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f93() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f94() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f95() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f96() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f97() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f98() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f99() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f100() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f101() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f102() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f103() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f104() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f105() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f106() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f107() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f108() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f109() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f110() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f111() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f112() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f113() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f114() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f115() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f116() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f117() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f118() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f119() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f120() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f121() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f122() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f123() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f124() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f125() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f126() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f127() {
+entry:
+ %0 = load i32, i32* @foo, align 4
+ ret i32 %0
+}
+
+define i32 @f128() {
+entry:
+ %0 = load i32, i32* @g0, align 4
+ ret i32 %0
+}
+
+define i32 @f129() {
+entry:
+ %0 = load i32, i32* @g0, align 4
+ ret i32 %0
+}
diff --git a/lld/test/wasm/Inputs/ret32.ll b/lld/test/wasm/Inputs/ret32.ll
new file mode 100644
index 00000000000..fd840de97c0
--- /dev/null
+++ b/lld/test/wasm/Inputs/ret32.ll
@@ -0,0 +1,9 @@
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32-unknown-unknown-wasm"
+
+; Function Attrs: norecurse nounwind readnone
+define hidden i32 @ret32(float %arg) #0 {
+entry:
+ ret i32 0
+ ; ptrtoint (i32 (float)* @ret32 to i32)
+}
diff --git a/lld/test/wasm/Inputs/ret64.ll b/lld/test/wasm/Inputs/ret64.ll
new file mode 100644
index 00000000000..8ece8d7cf9c
--- /dev/null
+++ b/lld/test/wasm/Inputs/ret64.ll
@@ -0,0 +1,7 @@
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32-unknown-unknown-wasm"
+
+define hidden i64 @ret64(double %arg) local_unnamed_addr #0 {
+entry:
+ ret i64 1
+}
diff --git a/lld/test/wasm/Inputs/weak-alias.ll b/lld/test/wasm/Inputs/weak-alias.ll
new file mode 100644
index 00000000000..86664b489d0
--- /dev/null
+++ b/lld/test/wasm/Inputs/weak-alias.ll
@@ -0,0 +1,12 @@
+define i32 @foo() #0 {
+entry:
+ ret i32 0
+}
+
+@bar = weak alias i32 (), i32 ()* @foo
+
+define hidden i32 @call_bar() #0 {
+entry:
+ %call = call i32 @bar()
+ ret i32 %call
+}
diff --git a/lld/test/wasm/archive.ll b/lld/test/wasm/archive.ll
new file mode 100644
index 00000000000..2bc79467f02
--- /dev/null
+++ b/lld/test/wasm/archive.ll
@@ -0,0 +1,24 @@
+; Verify that multually dependant object files in an archive is handled
+; correctly.
+;
+; RUN: llc -filetype=obj -mtriple=wasm32-unknown-uknown-wasm %s -o %t.o
+; RUN: llc -filetype=obj -mtriple=wasm32-unknown-uknown-wasm %S/Inputs/archive1.ll -o %t2.o
+; RUN: llc -filetype=obj -mtriple=wasm32-unknown-uknown-wasm %S/Inputs/archive2.ll -o %t3.o
+; RUN: llvm-ar rcs %t.a %t2.o %t3.o
+; RUN: lld -flavor wasm %t.a %t.o -o %t.wasm
+; RUN: llvm-nm -a %t.wasm | FileCheck %s
+
+; Specifying the same archive twice is allowed.
+; RUN: lld -flavor wasm %t.a %t.a %t.o -o %t.wasm
+
+declare i32 @foo() local_unnamed_addr #1
+
+define i32 @_start() local_unnamed_addr #0 {
+entry:
+ %call = tail call i32 @foo() #2
+ ret i32 %call
+}
+
+; CHECK: T _start
+; CHECK: T bar
+; CHECK: T foo
diff --git a/lld/test/wasm/call-indirect.ll b/lld/test/wasm/call-indirect.ll
new file mode 100644
index 00000000000..ecc91dc6933
--- /dev/null
+++ b/lld/test/wasm/call-indirect.ll
@@ -0,0 +1,110 @@
+; RUN: llc -filetype=obj %p/Inputs/call-indirect.ll -o %t2.o
+; RUN: llc -filetype=obj %s -o %t.o
+; RUN: lld -flavor wasm -o %t.wasm %t2.o %t.o
+; RUN: obj2yaml %t.wasm | FileCheck %s
+
+; bitcode generated from the following C code:
+; int foo(void) { return 1; }
+; int (*indirect_func)(void) = &foo;
+; void _start(void) { indirect_func(); }
+
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32-unknown-unknown-wasm"
+
+@indirect_func = hidden local_unnamed_addr global i32 ()* @foo, align 4
+
+; Function Attrs: norecurse nounwind readnone
+define hidden i32 @foo() #0 {
+entry:
+ ret i32 1
+}
+
+; Function Attrs: nounwind
+define hidden void @_start() local_unnamed_addr #1 {
+entry:
+ %0 = load i32 ()*, i32 ()** @indirect_func, align 4
+ %call = tail call i32 %0() #2
+ ret void
+}
+
+; CHECK: !WASM
+; CHECK-NEXT: FileHeader:
+; CHECK-NEXT: Version: 0x00000001
+; CHECK-NEXT: Sections:
+; CHECK-NEXT: - Type: TYPE
+; CHECK-NEXT: Signatures:
+; CHECK-NEXT: - Index: 0
+; CHECK-NEXT: ReturnType: I32
+; CHECK-NEXT: ParamTypes:
+; CHECK-NEXT: - Index: 1
+; CHECK-NEXT: ReturnType: NORESULT
+; CHECK-NEXT: ParamTypes:
+; CHECK-NEXT: - Type: FUNCTION
+; CHECK-NEXT: FunctionTypes: [ 0, 1, 0, 1 ]
+; CHECK-NEXT: - Type: TABLE
+; CHECK-NEXT: Tables:
+; CHECK-NEXT: - ElemType: ANYFUNC
+; CHECK-NEXT: Limits:
+; CHECK-NEXT: Flags: 0x00000001
+; CHECK-NEXT: Initial: 0x00000003
+; CHECK-NEXT: Maximum: 0x00000003
+; CHECK-NEXT: - Type: MEMORY
+; CHECK-NEXT: Memories:
+; CHECK-NEXT: - Initial: 0x00000002
+; CHECK-NEXT: - Type: GLOBAL
+; CHECK-NEXT: Globals:
+; CHECK-NEXT: - Type: I32
+; CHECK-NEXT: Mutable: true
+; CHECK-NEXT: InitExpr:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 66576
+; CHECK-NEXT: - Type: EXPORT
+; CHECK-NEXT: Exports:
+; CHECK-NEXT: - Name: memory
+; CHECK-NEXT: Kind: MEMORY
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: - Name: bar
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: - Name: call_bar_indirect
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: Index: 1
+; CHECK-NEXT: - Name: foo
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: Index: 2
+; CHECK-NEXT: - Name: _start
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: Index: 3
+; CHECK: - Type: ELEM
+; CHECK-NEXT: Segments:
+; CHECK-NEXT: - Offset:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 1
+; CHECK-NEXT: Functions: [ 0, 2 ]
+; CHECK-NEXT: - Type: CODE
+; CHECK-NEXT: Functions:
+; CHECK: - Locals:
+; CHECK: - Locals:
+; CHECK: - Locals:
+; CHECK: - Type: DATA
+; CHECK-NEXT: Segments:
+; CHECK-NEXT: - SectionOffset: 7
+; CHECK-NEXT: MemoryIndex: 0
+; CHECK-NEXT: Offset:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 1024
+; CHECK-NEXT: Content: '0100000002000000'
+; CHECK-NEXT: - Type: CUSTOM
+; CHECK-NEXT: Name: linking
+; CHECK-NEXT: DataSize: 8
+; CHECK-NEXT: - Type: CUSTOM
+; CHECK-NEXT: Name: name
+; CHECK-NEXT: FunctionNames:
+; CHECK-NEXT: - Index: 0
+; CHECK-NEXT: Name: bar
+; CHECK-NEXT: - Index: 1
+; CHECK-NEXT: Name: call_bar_indirect
+; CHECK-NEXT: - Index: 2
+; CHECK-NEXT: Name: foo
+; CHECK-NEXT: - Index: 3
+; CHECK-NEXT: Name: _start
diff --git a/lld/test/wasm/conflict.test b/lld/test/wasm/conflict.test
new file mode 100644
index 00000000000..64ed3844a82
--- /dev/null
+++ b/lld/test/wasm/conflict.test
@@ -0,0 +1,6 @@
+# RUN: llc -filetype=obj %p/Inputs/ret32.ll -o %t.ret32.o
+# RUN: not lld -flavor wasm -o %t.wasm %t.ret32.o %t.ret32.o 2>&1 | FileCheck %s
+
+# CHECK: duplicate symbol: ret32
+# CHECK-NEXT: >>> defined in {{.*}}conflict.test.tmp.ret32.o
+# CHECK-NEXT: >>> defined in {{.*}}conflict.test.tmp.ret32.o
diff --git a/lld/test/wasm/data-layout.ll b/lld/test/wasm/data-layout.ll
new file mode 100644
index 00000000000..350b76a5837
--- /dev/null
+++ b/lld/test/wasm/data-layout.ll
@@ -0,0 +1,64 @@
+; RUN: llc -filetype=obj %p/Inputs/hello.ll -o %t.hello.o
+; RUN: llc -filetype=obj %s -o %t.o
+; RUN: lld -flavor wasm --emit-relocs --allow-undefined -o %t.wasm %t.o %t.hello.o
+; RUN: obj2yaml %t.wasm | FileCheck %s
+
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32-unknown-unknown-wasm"
+
+@foo = hidden global i32 1, align 4
+@aligned_bar = hidden global i32 3, align 16
+
+@hello_str = external global i8*
+@external_ref = global i8** @hello_str, align 8
+
+; CHECK: - Type: GLOBAL
+; CHECK-NEXT: Globals:
+; CHECK-NEXT: - Type: I32
+; CHECK-NEXT: Mutable: true
+; CHECK-NEXT: InitExpr:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 66608
+; CHECK-NEXT: - Type: I32
+; CHECK-NEXT: Mutable: false
+; CHECK-NEXT: InitExpr:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 1024
+; CHECK-NEXT: - Type: I32
+; CHECK-NEXT: Mutable: false
+; CHECK-NEXT: InitExpr:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 1040
+; CHECK-NEXT: - Type: I32
+; CHECK-NEXT: Mutable: false
+; CHECK-NEXT: InitExpr:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 1048
+; CHECK-NEXT: - Type: I32
+; CHECK-NEXT: Mutable: false
+; CHECK-NEXT: InitExpr:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 1052
+
+; CHECK: - Type: DATA
+; CHECK-NEXT: Relocations:
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_I32
+; CHECK-NEXT: Index: 4
+; CHECK-NEXT: Offset: 0x0000001F
+; CHECK-NEXT: Segments:
+; CHECK-NEXT: - SectionOffset: 7
+; CHECK-NEXT: MemoryIndex: 0
+; CHECK-NEXT: Offset:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 1024
+; CHECK-NEXT: Content: 0100000000000000000000000000000003000000000000001C040000
+; CHECK-NEXT: - SectionOffset: 41
+; CHECK-NEXT: MemoryIndex: 0
+; CHECK-NEXT: Offset:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 1052
+; CHECK-NEXT: Content: 68656C6C6F0A00
+
+; CHECK: - Type: CUSTOM
+; CHECK-NEXT: Name: linking
+; CHECK-NEXT: DataSize: 35
diff --git a/lld/test/wasm/entry.ll b/lld/test/wasm/entry.ll
new file mode 100644
index 00000000000..65a1e39f533
--- /dev/null
+++ b/lld/test/wasm/entry.ll
@@ -0,0 +1,22 @@
+; RUN: llc -filetype=obj %s -o %t.o
+; RUN: lld -flavor wasm -e entry -o %t.wasm %t.o
+; RUN: obj2yaml %t.wasm | FileCheck %s
+; RUN: lld -flavor wasm --entry=entry -o %t.wasm %t.o
+; RUN: obj2yaml %t.wasm | FileCheck %s
+
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32-unknown-unknown-wasm"
+
+define hidden void @entry() local_unnamed_addr #0 {
+entry:
+ ret void
+}
+
+; CHECK: - Type: EXPORT
+; CHECK: Exports:
+; CHECK: - Name: memory
+; CHECK: Kind: MEMORY
+; CHECK: Index: 0
+; CHECK: - Name: entry
+; CHECK: Kind: FUNCTION
+; CHECK: Index: 0
diff --git a/lld/test/wasm/function-imports-first.ll b/lld/test/wasm/function-imports-first.ll
new file mode 100644
index 00000000000..ba0bde23ddc
--- /dev/null
+++ b/lld/test/wasm/function-imports-first.ll
@@ -0,0 +1,45 @@
+; RUN: llc -filetype=obj %p/Inputs/ret32.ll -o %t.ret32.o
+; RUN: llc -filetype=obj %s -o %t.o
+; RUN: lld -flavor wasm -o %t.wasm %t.o %t.ret32.o
+; RUN: obj2yaml %t.wasm | FileCheck %s
+
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32-unknown-unknown-wasm"
+
+; Function Attrs: nounwind
+define hidden void @_start() local_unnamed_addr #0 {
+entry:
+ %call = tail call i32 @ret32(float 0.000000e+00) #2
+ ret void
+}
+
+declare i32 @ret32(float) local_unnamed_addr #1
+
+; CHECK: - Type: TYPE
+; CHECK: Signatures:
+; CHECK-NEXT: - Index: 0
+; CHECK-NEXT: ReturnType: NORESULT
+; CHECK-NEXT: ParamTypes:
+; CHECK-NEXT: - Index: 1
+; CHECK-NEXT: ReturnType: I32
+; CHECK-NEXT: ParamTypes:
+; CHECK-NEXT: - F32
+; CHECK: - Type: FUNCTION
+; CHECK-NEXT: FunctionTypes: [ 0, 1 ]
+; CHECK: - Type: CODE
+; CHECK-NEXT: Functions:
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 43000000001081808080001A0B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 41000B
+; CHECK-NEXT: - Type: CUSTOM
+; CHECK-NEXT: Name: linking
+; CHECK-NEXT: DataSize: 0
+; CHECK-NEXT: - Type: CUSTOM
+; CHECK-NEXT: Name: name
+; CHECK-NEXT: FunctionNames:
+; CHECK-NEXT: - Index: 0
+; CHECK-NEXT: Name: _start
+; CHECK-NEXT: - Index: 1
+; CHECK-NEXT: Name: ret32
+; CHECK-NEXT: ...
diff --git a/lld/test/wasm/function-imports.ll b/lld/test/wasm/function-imports.ll
new file mode 100644
index 00000000000..2e97a07650a
--- /dev/null
+++ b/lld/test/wasm/function-imports.ll
@@ -0,0 +1,40 @@
+; RUN: llc -filetype=obj %p/Inputs/ret32.ll -o %t.ret32.o
+; RUN: llc -filetype=obj %s -o %t.o
+; RUN: lld -flavor wasm -o %t.wasm %t.ret32.o %t.o
+; RUN: obj2yaml %t.wasm | FileCheck %s
+
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32-unknown-unknown-wasm"
+
+; Function Attrs: nounwind
+define hidden void @_start() local_unnamed_addr #0 {
+entry:
+ %call = tail call i32 @ret32(float 0.000000e+00) #2
+ ret void
+}
+
+declare i32 @ret32(float) local_unnamed_addr #1
+
+; CHECK: Sections:
+; CHECK: - Type: TYPE
+; CHECK-NEXT: Signatures:
+; CHECK-NEXT: - Index: 0
+; CHECK-NEXT: ReturnType: I32
+; CHECK-NEXT: ParamTypes:
+; CHECK-NEXT: - F32
+; CHECK-NEXT: - Index: 1
+; CHECK-NEXT: ReturnType: NORESULT
+; CHECK-NEXT: ParamTypes:
+; CHECK-NEXT: - Type: FUNCTION
+; CHECK-NEXT: FunctionTypes: [ 0, 1 ]
+; CHECK: - Type: CODE
+; CHECK-NEXT: Functions:
+; CHECK: - Locals:
+; CHECK: - Locals:
+; CHECK: Name: name
+; CHECK-NEXT: FunctionNames:
+; CHECK-NEXT: - Index: 0
+; CHECK-NEXT: Name: ret32
+; CHECK-NEXT: - Index: 1
+; CHECK-NEXT: Name: _start
+; CHECK-NEXT: ...
diff --git a/lld/test/wasm/function-index.test b/lld/test/wasm/function-index.test
new file mode 100644
index 00000000000..546da30ede0
--- /dev/null
+++ b/lld/test/wasm/function-index.test
@@ -0,0 +1,18 @@
+# RUN: llc -filetype=obj %p/Inputs/ret32.ll -o %t.ret32.o
+# RUN: llc -filetype=obj %p/Inputs/ret64.ll -o %t.ret64.o
+# RUN: lld -flavor wasm -r -o %t.wasm %t.ret32.o %t.ret64.o
+# RUN: obj2yaml %t.wasm | FileCheck %s
+
+CHECK: Sections:
+CHECK: - Type: TYPE
+CHECK: Signatures:
+CHECK: - Index: 0
+CHECK: ReturnType: I32
+CHECK: ParamTypes:
+CHECK: - F32
+CHECK: - Index: 1
+CHECK: ReturnType: I64
+CHECK: ParamTypes:
+CHECK: - F64
+CHECK: - Type: FUNCTION
+CHECK: FunctionTypes: [ 0, 1 ]
diff --git a/lld/test/wasm/import-memory.test b/lld/test/wasm/import-memory.test
new file mode 100644
index 00000000000..d076b1b69df
--- /dev/null
+++ b/lld/test/wasm/import-memory.test
@@ -0,0 +1,13 @@
+# RUN: llc -filetype=obj %p/Inputs/ret32.ll -o %t.ret32.o
+# RUN: lld -flavor wasm -entry ret32 --import-memory -o %t.wasm %t.ret32.o
+# RUN: obj2yaml %t.wasm | FileCheck %s
+
+# Verify the --import-memory flag creates a memory import
+
+# CHECK: - Type: IMPORT
+# CHECK-NEXT: Imports:
+# CHECK-NEXT: - Module: env
+# CHECK-NEXT: Field: memory
+# CHECK-NEXT: Kind: MEMORY
+# CHECK-NEXT: Memory:
+# CHECK-NEXT: Initial: 0x00000002
diff --git a/lld/test/wasm/invalid-stack-size.test b/lld/test/wasm/invalid-stack-size.test
new file mode 100644
index 00000000000..6597c548499
--- /dev/null
+++ b/lld/test/wasm/invalid-stack-size.test
@@ -0,0 +1,9 @@
+; RUN: llc -mtriple wasm32-unknown-unknown-wasm -filetype=obj %s -o %t.o
+; RUN: not lld -flavor wasm -o %t.wasm -z stack-size=1 %t.o 2>&1 | FileCheck %s
+
+define i32 @_start() local_unnamed_addr #1 {
+entry:
+ ret i32 0
+}
+
+; CHECK: error: stack size must be 16-byte aligned
diff --git a/lld/test/wasm/lit.local.cfg b/lld/test/wasm/lit.local.cfg
new file mode 100644
index 00000000000..bc76e57c8e8
--- /dev/null
+++ b/lld/test/wasm/lit.local.cfg
@@ -0,0 +1,4 @@
+if 'wasm' not in config.available_features:
+ config.unsupported = True
+
+config.suffixes = ['.test', '.yaml', '.ll']
diff --git a/lld/test/wasm/local-symbols.ll b/lld/test/wasm/local-symbols.ll
new file mode 100644
index 00000000000..4bb7cf9b0cc
--- /dev/null
+++ b/lld/test/wasm/local-symbols.ll
@@ -0,0 +1,81 @@
+; RUN: llc -filetype=obj %s -o %t.o
+; RUN: lld -flavor wasm -o %t.wasm %t.o
+; RUN: obj2yaml %t.wasm | FileCheck %s
+
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32-unknown-unknown-wasm"
+
+@foo = default global i32 1, align 4
+@bar = internal default global i32 3, align 4
+
+define internal i32 @baz() local_unnamed_addr {
+entry:
+ ret i32 2
+}
+
+define i32 @_start() local_unnamed_addr {
+entry:
+ ret i32 1
+}
+
+; CHECK: --- !WASM
+; CHECK-NEXT: FileHeader:
+; CHECK-NEXT: Version: 0x00000001
+; CHECK-NEXT: Sections:
+; CHECK-NEXT: - Type: TYPE
+; CHECK-NEXT: Signatures:
+; CHECK-NEXT: - Index: 0
+; CHECK-NEXT: ReturnType: I32
+; CHECK-NEXT: ParamTypes:
+; CHECK-NEXT: - Type: FUNCTION
+; CHECK-NEXT: FunctionTypes: [ 0, 0 ]
+; CHECK-NEXT: - Type: TABLE
+; CHECK-NEXT: Tables:
+; CHECK-NEXT: - ElemType: ANYFUNC
+; CHECK-NEXT: Limits:
+; CHECK-NEXT: Flags: 0x00000001
+; CHECK-NEXT: Initial: 0x00000001
+; CHECK-NEXT: Maximum: 0x00000001
+; CHECK-NEXT: - Type: MEMORY
+; CHECK-NEXT: Memories:
+; CHECK-NEXT: - Initial: 0x00000002
+; CHECK-NEXT: - Type: GLOBAL
+; CHECK-NEXT: Globals:
+; CHECK-NEXT: - Type: I32
+; CHECK-NEXT: Mutable: true
+; CHECK-NEXT: InitExpr:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 66576
+; CHECK-NEXT: - Type: EXPORT
+; CHECK-NEXT: Exports:
+; CHECK-NEXT: - Name: memory
+; CHECK-NEXT: Kind: MEMORY
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: - Name: _start
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: Index: 1
+; CHECK-NEXT: - Type: CODE
+; CHECK-NEXT: Functions:
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 41020B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 41010B
+; CHECK-NEXT: - Type: DATA
+; CHECK-NEXT: Segments:
+; CHECK-NEXT: - SectionOffset: 7
+; CHECK-NEXT: MemoryIndex: 0
+; CHECK-NEXT: Offset:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 1024
+; CHECK-NEXT: Content: '0100000003000000'
+; CHECK-NEXT: - Type: CUSTOM
+; CHECK-NEXT: Name: linking
+; CHECK-NEXT: DataSize: 8
+; CHECK-NEXT: - Type: CUSTOM
+; CHECK-NEXT: Name: name
+; CHECK-NEXT: FunctionNames:
+; CHECK-NEXT: - Index: 0
+; CHECK-NEXT: Name: baz
+; CHECK-NEXT: - Index: 1
+; CHECK-NEXT: Name: _start
+; CHECK-NEXT: ...
diff --git a/lld/test/wasm/many-functions.ll b/lld/test/wasm/many-functions.ll
new file mode 100644
index 00000000000..ba4a90fe2d8
--- /dev/null
+++ b/lld/test/wasm/many-functions.ll
@@ -0,0 +1,699 @@
+; RUN: llc -filetype=obj %p/Inputs/many-funcs.ll -o %t.many.o
+; RUN: llc -filetype=obj %s -o %t.o
+; RUN: lld -flavor wasm -r -o %t.wasm %t.many.o %t.o
+; RUN: obj2yaml %t.wasm | FileCheck %s
+
+; Test that relocations within the CODE section correctly handle
+; linking object with different header sizes. many-funcs.ll has
+; 128 function and so the final output requires a 2-byte LEB in
+; the CODE section header to store the function count.
+
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32-unknown-unknown-wasm"
+
+define i32 @func() {
+entry:
+ %call = tail call i32 @func()
+ ret i32 %call
+}
+
+; CHECK: - Type: CODE
+; CHECK-NEXT: Relocations:
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000008
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000014
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000020
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x0000002C
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000038
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000044
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000050
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x0000005C
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000068
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000074
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000080
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x0000008C
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000098
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000000A4
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000000B0
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000000BC
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000000C8
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000000D4
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000000E0
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000000EC
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000000F8
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000104
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000110
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x0000011C
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000128
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000134
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000140
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x0000014C
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000158
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000164
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000170
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x0000017C
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000188
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000194
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000001A0
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000001AC
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000001B8
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000001C4
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000001D0
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000001DC
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000001E8
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000001F4
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000200
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x0000020C
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000218
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000224
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000230
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x0000023C
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000248
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000254
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000260
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x0000026C
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000278
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000284
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000290
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x0000029C
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000002A8
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000002B4
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000002C0
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000002CC
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000002D8
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000002E4
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000002F0
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000002FC
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000308
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000314
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000320
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x0000032C
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000338
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000344
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000350
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x0000035C
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000368
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000374
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000380
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x0000038C
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000398
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000003A4
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000003B0
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000003BC
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000003C8
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000003D4
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000003E0
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000003EC
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000003F8
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000404
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000410
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x0000041C
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000428
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000434
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000440
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x0000044C
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000458
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000464
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000470
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x0000047C
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000488
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000494
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000004A0
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000004AC
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000004B8
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000004C4
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000004D0
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000004DC
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000004E8
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000004F4
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000500
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x0000050C
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000518
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000524
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000530
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x0000053C
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000548
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000554
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000560
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x0000056C
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000578
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000584
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000590
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x0000059C
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000005A8
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000005B4
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000005C0
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000005CC
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000005D8
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000005E4
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x000005F0
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 1
+; CHECK-NEXT: Offset: 0x000005FC
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB
+; CHECK-NEXT: Index: 1
+; CHECK-NEXT: Offset: 0x00000608
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB
+; CHECK-NEXT: Index: 129
+; CHECK-NEXT: Offset: 0x00000611
+; CHECK-NEXT: Functions:
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280284808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280280808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4100280280808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 1081818080000B
+; CHECK-NEXT: - Type: DATA
+; CHECK-NEXT: Segments:
+; CHECK-NEXT: - SectionOffset: 6
+; CHECK-NEXT: MemoryIndex: 0
+; CHECK-NEXT: Offset:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 0
+; CHECK-NEXT: Content: '01000000'
+; CHECK-NEXT: - SectionOffset: 15
+; CHECK-NEXT: MemoryIndex: 0
+; CHECK-NEXT: Offset:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 4
+; CHECK-NEXT: Content: '01000000'
+; CHECK-NEXT: - Type: CUSTOM
+; CHECK-NEXT: Name: linking
+; CHECK-NEXT: DataSize: 8
+; CHECK-NEXT: SegmentInfo:
+; CHECK-NEXT: - Index: 0
+; CHECK-NEXT: Name: .data.g0
+; CHECK-NEXT: Alignment: 4
+; CHECK-NEXT: Flags: 0
+; CHECK-NEXT: - Index: 1
+; CHECK-NEXT: Name: .data.foo
+; CHECK-NEXT: Alignment: 4
+; CHECK-NEXT: Flags: 0
+
diff --git a/lld/test/wasm/relocatable.ll b/lld/test/wasm/relocatable.ll
new file mode 100644
index 00000000000..b8491e06b15
--- /dev/null
+++ b/lld/test/wasm/relocatable.ll
@@ -0,0 +1,185 @@
+; RUN: llc -filetype=obj %p/Inputs/hello.ll -o %t.hello.o
+; RUN: llc -filetype=obj %s -o %t.o
+; RUN: lld -flavor wasm -r -o %t.wasm %t.hello.o %t.o
+; RUN: obj2yaml %t.wasm | FileCheck %s
+
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32-unknown-unknown-wasm"
+
+; Function Attrs: nounwind
+define hidden i32 @my_func() local_unnamed_addr {
+entry:
+ %call = tail call i32 @foo_import()
+ ret i32 1
+}
+
+declare i32 @foo_import() local_unnamed_addr
+@data_import = external global i64
+
+@func_addr1 = hidden global i32()* @my_func, align 4
+@func_addr2 = hidden global i32()* @foo_import, align 4
+@data_addr1 = hidden global i64* @data_import, align 8
+
+; CHECK: --- !WASM
+; CHECK-NEXT: FileHeader:
+; CHECK-NEXT: Version: 0x00000001
+; CHECK-NEXT: Sections:
+; CHECK-NEXT: - Type: TYPE
+; CHECK-NEXT: Signatures:
+; CHECK-NEXT: - Index: 0
+; CHECK-NEXT: ReturnType: NORESULT
+; CHECK-NEXT: ParamTypes:
+; CHECK-NEXT: - Index: 1
+; CHECK-NEXT: ReturnType: NORESULT
+; CHECK-NEXT: ParamTypes:
+; CHECK-NEXT: - I32
+; CHECK-NEXT: - Index: 2
+; CHECK-NEXT: ReturnType: I32
+; CHECK-NEXT: ParamTypes:
+; CHECK-NEXT: - Type: IMPORT
+; CHECK-NEXT: Imports:
+; CHECK-NEXT: - Module: env
+; CHECK-NEXT: Field: puts
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: SigIndex: 1
+; CHECK-NEXT: - Module: env
+; CHECK-NEXT: Field: foo_import
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: SigIndex: 2
+; CHECK-NEXT: - Module: env
+; CHECK-NEXT: Field: data_import
+; CHECK-NEXT: Kind: GLOBAL
+; CHECK-NEXT: GlobalType: I32
+; CHECK-NEXT: GlobalMutable: false
+; CHECK-NEXT: - Type: FUNCTION
+; CHECK-NEXT: FunctionTypes: [ 0, 2 ]
+; CHECK-NEXT: - Type: TABLE
+; CHECK-NEXT: Tables:
+; CHECK-NEXT: - ElemType: ANYFUNC
+; CHECK-NEXT: Limits:
+; CHECK-NEXT: Flags: 0x00000001
+; CHECK-NEXT: Initial: 0x00000002
+; CHECK-NEXT: Maximum: 0x00000002
+; CHECK-NEXT: - Type: MEMORY
+; CHECK-NEXT: Memories:
+; CHECK-NEXT: - Initial: 0x00000001
+; CHECK-NEXT: - Type: GLOBAL
+; CHECK-NEXT: Globals:
+; CHECK-NEXT: - Type: I32
+; CHECK-NEXT: Mutable: false
+; CHECK-NEXT: InitExpr:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 0
+; CHECK-NEXT: - Type: I32
+; CHECK-NEXT: Mutable: false
+; CHECK-NEXT: InitExpr:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 8
+; CHECK-NEXT: - Type: I32
+; CHECK-NEXT: Mutable: false
+; CHECK-NEXT: InitExpr:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 12
+; CHECK-NEXT: - Type: I32
+; CHECK-NEXT: Mutable: false
+; CHECK-NEXT: InitExpr:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 16
+; CHECK-NEXT: - Type: EXPORT
+; CHECK-NEXT: Exports:
+; CHECK-NEXT: - Name: hello
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: Index: 2
+; CHECK-NEXT: - Name: my_func
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: Index: 3
+; CHECK-NEXT: - Type: ELEM
+; CHECK-NEXT: Segments:
+; CHECK-NEXT: - Offset:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 0
+; CHECK-NEXT: Functions: [ 3, 1 ]
+; CHECK-NEXT: - Type: CODE
+; CHECK-NEXT: Relocations:
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB
+; CHECK-NEXT: Index: 1
+; CHECK-NEXT: Offset: 0x00000004
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x0000000A
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB
+; CHECK-NEXT: Index: 1
+; CHECK-NEXT: Offset: 0x00000013
+; CHECK-NEXT: Functions:
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4180808080001080808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 1081808080001A41010B
+; CHECK-NEXT: - Type: DATA
+; CHECK-NEXT: Relocations:
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000012
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32
+; CHECK-NEXT: Index: 1
+; CHECK-NEXT: Offset: 0x0000001B
+; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_I32
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: Offset: 0x00000024
+; CHECK-NEXT: Segments:
+; CHECK-NEXT: - SectionOffset: 6
+; CHECK-NEXT: MemoryIndex: 0
+; CHECK-NEXT: Offset:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 0
+; CHECK-NEXT: Content: 68656C6C6F0A00
+; CHECK-NEXT: - SectionOffset: 18
+; CHECK-NEXT: MemoryIndex: 0
+; CHECK-NEXT: Offset:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 8
+; CHECK-NEXT: Content: '00000000'
+; CHECK-NEXT: - SectionOffset: 27
+; CHECK-NEXT: MemoryIndex: 0
+; CHECK-NEXT: Offset:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 12
+; CHECK-NEXT: Content: '01000000'
+; CHECK-NEXT: - SectionOffset: 36
+; CHECK-NEXT: MemoryIndex: 0
+; CHECK-NEXT: Offset:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 16
+; CHECK-NEXT: Content: FFFFFFFF
+; CHECK-NEXT: - Type: CUSTOM
+; CHECK-NEXT: Name: linking
+; CHECK-NEXT: DataSize: 20
+; CHECK-NEXT: SegmentInfo:
+; CHECK-NEXT: - Index: 0
+; CHECK-NEXT: Name: .rodata.hello_str
+; CHECK-NEXT: Alignment: 1
+; CHECK-NEXT: Flags: 0
+; CHECK-NEXT: - Index: 1
+; CHECK-NEXT: Name: .data.func_addr1
+; CHECK-NEXT: Alignment: 4
+; CHECK-NEXT: Flags: 0
+; CHECK-NEXT: - Index: 2
+; CHECK-NEXT: Name: .data.func_addr2
+; CHECK-NEXT: Alignment: 4
+; CHECK-NEXT: Flags: 0
+; CHECK-NEXT: - Index: 3
+; CHECK-NEXT: Name: .data.data_addr1
+; CHECK-NEXT: Alignment: 8
+; CHECK-NEXT: Flags: 0
+; CHECK-NEXT: - Type: CUSTOM
+; CHECK-NEXT: Name: name
+; CHECK-NEXT: FunctionNames:
+; CHECK-NEXT: - Index: 0
+; CHECK-NEXT: Name: puts
+; CHECK-NEXT: - Index: 1
+; CHECK-NEXT: Name: foo_import
+; CHECK-NEXT: - Index: 2
+; CHECK-NEXT: Name: hello
+; CHECK-NEXT: - Index: 3
+; CHECK-NEXT: Name: my_func
+; CHECK-NEXT: ...
diff --git a/lld/test/wasm/strip-debug.test b/lld/test/wasm/strip-debug.test
new file mode 100644
index 00000000000..5efeb5cb564
--- /dev/null
+++ b/lld/test/wasm/strip-debug.test
@@ -0,0 +1,6 @@
+RUN: llc -filetype=obj %p/Inputs/ret32.ll -o %t.ret32.o
+RUN: lld -flavor wasm --strip-debug --entry=ret32 -o %t.wasm %t.ret32.o
+RUN: obj2yaml %t.wasm | FileCheck %s
+
+# Check that there is no name section
+CHECK-NOT: Name: name
diff --git a/lld/test/wasm/symtol-type-mismatch.ll b/lld/test/wasm/symtol-type-mismatch.ll
new file mode 100644
index 00000000000..af8ea408894
--- /dev/null
+++ b/lld/test/wasm/symtol-type-mismatch.ll
@@ -0,0 +1,12 @@
+; RUN: llc -filetype=obj %s -o %t.o
+; RUN: llc -filetype=obj %p/Inputs/ret32.ll -o %t.ret32.o
+; RUN: not lld -flavor wasm -o %t.wasm %t.o %t.ret32.o 2>&1 | FileCheck %s
+
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32-unknown-unknown-wasm"
+
+@ret32 = extern_weak global i32, align 4
+
+; CHECK: error: symbol type mismatch: ret32
+; CHECK: >>> defined as Global in {{.*}}symtol-type-mismatch.ll.tmp.o
+; CHECK: >>> defined as Function in {{.*}}.ret32.o
diff --git a/lld/test/wasm/undefined-entry.test b/lld/test/wasm/undefined-entry.test
new file mode 100644
index 00000000000..72986e7d6db
--- /dev/null
+++ b/lld/test/wasm/undefined-entry.test
@@ -0,0 +1,4 @@
+RUN: llc -filetype=obj %p/Inputs/ret32.ll -o %t.ret32.o
+RUN: not lld -flavor wasm -o %t.wasm %t.ret32.o 2>&1 | FileCheck %s
+
+CHECK: error: undefined symbol: _start
diff --git a/lld/test/wasm/undefined.ll b/lld/test/wasm/undefined.ll
new file mode 100644
index 00000000000..a2ac3e2ced1
--- /dev/null
+++ b/lld/test/wasm/undefined.ll
@@ -0,0 +1,23 @@
+; RUN: llc -filetype=obj %s -o %t.o
+; RUN: lld -flavor wasm --allow-undefined -o %t.wasm %t.o
+
+; Fails due to undefined 'foo'
+; RUN: not lld -flavor wasm -o %t.wasm %t.o 2>&1 | FileCheck %s
+; CHECK: error: {{.*}}.o: undefined symbol: foo
+
+; But succeeds if we pass a file containing 'foo' as --allow-undefined-file.
+; RUN: echo 'foo' > %t.txt
+; RUN: lld -flavor wasm --allow-undefined-file=%t.txt -o %t.wasm %t.o
+
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32-unknown-unknown-wasm"
+
+; Takes the address of the external foo() resulting in undefined external
+@bar = hidden local_unnamed_addr global i8* bitcast (i32 ()* @foo to i8*), align 4
+
+declare i32 @foo() #0
+
+define hidden void @_start() local_unnamed_addr #0 {
+entry:
+ ret void
+}
diff --git a/lld/test/wasm/version.ll b/lld/test/wasm/version.ll
new file mode 100644
index 00000000000..813f8265347
--- /dev/null
+++ b/lld/test/wasm/version.ll
@@ -0,0 +1,16 @@
+; RUN: llc -filetype=obj %s -o %t.o
+; RUN: lld -flavor wasm -o %t.wasm %t.o
+; RUN: llvm-readobj -file-headers %t.wasm | FileCheck %s
+
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32-unknown-unknown-wasm"
+
+define hidden void @_start() local_unnamed_addr #0 {
+entry:
+ ret void
+}
+
+; CHECK: Format: WASM
+; CHECK: Arch: wasm32
+; CHECK: AddressSize: 32bit
+; CHECK: Version: 0x1
diff --git a/lld/test/wasm/weak-alias-overide.ll b/lld/test/wasm/weak-alias-overide.ll
new file mode 100644
index 00000000000..d929d918181
--- /dev/null
+++ b/lld/test/wasm/weak-alias-overide.ll
@@ -0,0 +1,92 @@
+; RUN: llc -mtriple wasm32-unknown-unknown-wasm -filetype=obj -o %t.o %s
+; RUN: llc -mtriple=wasm32-unknown-unknown-wasm -filetype=obj %S/Inputs/weak-alias.ll -o %t2.o
+; RUN: lld -flavor wasm %t.o %t2.o -o %t.wasm
+; RUN: obj2yaml %t.wasm | FileCheck %s
+
+; Test that the strongly defined bar is used correctly despite the existence
+; of the weak alias
+
+define i32 @bar() local_unnamed_addr #1 {
+ ret i32 1
+}
+
+; Function Attrs: nounwind uwtable
+define void @_start() local_unnamed_addr #1 {
+entry:
+ %call = tail call i32 @bar() #2
+ ret void
+}
+
+; CHECK: --- !WASM
+; CHECK-NEXT: FileHeader:
+; CHECK-NEXT: Version: 0x00000001
+; CHECK-NEXT: Sections:
+; CHECK-NEXT: - Type: TYPE
+; CHECK-NEXT: Signatures:
+; CHECK-NEXT: - Index: 0
+; CHECK-NEXT: ReturnType: I32
+; CHECK-NEXT: ParamTypes:
+; CHECK-NEXT: - Index: 1
+; CHECK-NEXT: ReturnType: NORESULT
+; CHECK-NEXT: ParamTypes:
+; CHECK-NEXT: - Type: FUNCTION
+; CHECK-NEXT: FunctionTypes: [ 0, 1, 0, 0 ]
+; CHECK-NEXT: - Type: TABLE
+; CHECK-NEXT: Tables:
+; CHECK-NEXT: - ElemType: ANYFUNC
+; CHECK-NEXT: Limits:
+; CHECK-NEXT: Flags: 0x00000001
+; CHECK-NEXT: Initial: 0x00000001
+; CHECK-NEXT: Maximum: 0x00000001
+; CHECK-NEXT: - Type: MEMORY
+; CHECK-NEXT: Memories:
+; CHECK-NEXT: - Initial: 0x00000002
+; CHECK-NEXT: - Type: GLOBAL
+; CHECK-NEXT: Globals:
+; CHECK-NEXT: - Type: I32
+; CHECK-NEXT: Mutable: true
+; CHECK-NEXT: InitExpr:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 66560
+; CHECK-NEXT: - Type: EXPORT
+; CHECK-NEXT: Exports:
+; CHECK-NEXT: - Name: memory
+; CHECK-NEXT: Kind: MEMORY
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: - Name: bar
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: - Name: _start
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: Index: 1
+; CHECK-NEXT: - Name: foo
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: Index: 2
+; CHECK-NEXT: - Name: call_bar
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: Index: 3
+; CHECK-NEXT: - Type: CODE
+; CHECK-NEXT: Functions:
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 41010B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 1080808080001A0B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 41000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 1080808080000B
+; CHECK-NEXT: - Type: CUSTOM
+; CHECK-NEXT: Name: linking
+; CHECK-NEXT: DataSize: 0
+; CHECK-NEXT: - Type: CUSTOM
+; CHECK-NEXT: Name: name
+; CHECK-NEXT: FunctionNames:
+; CHECK-NEXT: - Index: 0
+; CHECK-NEXT: Name: bar
+; CHECK-NEXT: - Index: 1
+; CHECK-NEXT: Name: _start
+; CHECK-NEXT: - Index: 2
+; CHECK-NEXT: Name: foo
+; CHECK-NEXT: - Index: 3
+; CHECK-NEXT: Name: call_bar
+; CHECK-NEXT: ...
diff --git a/lld/test/wasm/weak-alias.ll b/lld/test/wasm/weak-alias.ll
new file mode 100644
index 00000000000..94907b5ac42
--- /dev/null
+++ b/lld/test/wasm/weak-alias.ll
@@ -0,0 +1,82 @@
+; RUN: llc -mtriple wasm32-unknown-unknown-wasm -filetype=obj -o %t.o %s
+; RUN: llc -mtriple=wasm32-unknown-unknown-wasm -filetype=obj %S/Inputs/weak-alias.ll -o %t2.o
+; RUN: lld -flavor wasm %t.o %t2.o -o %t.wasm
+; RUN: obj2yaml %t.wasm | FileCheck %s
+
+; Test that weak aliases (bar is a weak alias of foo) are linked correctly
+
+declare i32 @bar() local_unnamed_addr #1
+
+; Function Attrs: nounwind uwtable
+define i32 @_start() local_unnamed_addr #1 {
+entry:
+ %call = tail call i32 @bar() #2
+ ret i32 %call
+}
+
+; CHECK: --- !WASM
+; CHECK-NEXT: FileHeader:
+; CHECK-NEXT: Version: 0x00000001
+; CHECK-NEXT: Sections:
+; CHECK-NEXT: - Type: TYPE
+; CHECK-NEXT: Signatures:
+; CHECK-NEXT: - Index: 0
+; CHECK-NEXT: ReturnType: I32
+; CHECK-NEXT: ParamTypes:
+; CHECK-NEXT: - Type: FUNCTION
+; CHECK-NEXT: FunctionTypes: [ 0, 0, 0 ]
+; CHECK-NEXT: - Type: TABLE
+; CHECK-NEXT: Tables:
+; CHECK-NEXT: - ElemType: ANYFUNC
+; CHECK-NEXT: Limits:
+; CHECK-NEXT: Flags: 0x00000001
+; CHECK-NEXT: Initial: 0x00000001
+; CHECK-NEXT: Maximum: 0x00000001
+; CHECK-NEXT: - Type: MEMORY
+; CHECK-NEXT: Memories:
+; CHECK-NEXT: - Initial: 0x00000002
+; CHECK-NEXT: - Type: GLOBAL
+; CHECK-NEXT: Globals:
+; CHECK-NEXT: - Type: I32
+; CHECK-NEXT: Mutable: true
+; CHECK-NEXT: InitExpr:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 66560
+; CHECK-NEXT: - Type: EXPORT
+; CHECK-NEXT: Exports:
+; CHECK-NEXT: - Name: memory
+; CHECK-NEXT: Kind: MEMORY
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: - Name: bar
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: Index: 1
+; CHECK-NEXT: - Name: _start
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: - Name: foo
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: Index: 1
+; CHECK-NEXT: - Name: call_bar
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: Index: 2
+; CHECK-NEXT: - Type: CODE
+; CHECK-NEXT: Functions:
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 1081808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 41000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 1081808080000B
+; CHECK-NEXT: - Type: CUSTOM
+; CHECK-NEXT: Name: linking
+; CHECK-NEXT: DataSize: 0
+; CHECK-NEXT: - Type: CUSTOM
+; CHECK-NEXT: Name: name
+; CHECK-NEXT: FunctionNames:
+; CHECK-NEXT: - Index: 0
+; CHECK-NEXT: Name: _start
+; CHECK-NEXT: - Index: 1
+; CHECK-NEXT: Name: foo
+; CHECK-NEXT: - Index: 2
+; CHECK-NEXT: Name: call_bar
+; CHECK-NEXT: ...
diff --git a/lld/test/wasm/weak-external.ll b/lld/test/wasm/weak-external.ll
new file mode 100644
index 00000000000..a600eaee1a8
--- /dev/null
+++ b/lld/test/wasm/weak-external.ll
@@ -0,0 +1,86 @@
+; RUN: llc -mtriple wasm32-unknown-unknown-wasm -filetype=obj -o %t.o %s
+; RUN: lld -flavor wasm -strip-debug %t.o -o %t.wasm
+; RUN: obj2yaml %t.wasm | FileCheck %s
+
+; Test that undefined weak externals (global_var) and (foo) don't cause
+; link failures and resolve to zero.
+
+@global_var = extern_weak global i32, align 4
+
+declare extern_weak i32 @foo()
+
+define hidden i8* @get_address_of_foo() #0 {
+entry:
+ ret i8* bitcast (i32 ()* @foo to i8*)
+}
+
+define hidden i32* @get_address_of_global_var() #0 {
+ ret i32* @global_var
+}
+
+define hidden i32 @_start() #0 {
+entry:
+ %0 = load i32, i32* @global_var, align 4
+ ret i32 %0
+}
+
+; CHECK: --- !WASM
+; CHECK-NEXT: FileHeader:
+; CHECK-NEXT: Version: 0x00000001
+; CHECK-NEXT: Sections:
+; CHECK-NEXT: - Type: TYPE
+; CHECK-NEXT: Signatures:
+; CHECK-NEXT: - Index: 0
+; CHECK-NEXT: ReturnType: I32
+; CHECK-NEXT: ParamTypes:
+; CHECK-NEXT: - Type: FUNCTION
+; CHECK-NEXT: FunctionTypes: [ 0, 0, 0 ]
+; CHECK-NEXT: - Type: TABLE
+; CHECK-NEXT: Tables:
+; CHECK-NEXT: - ElemType: ANYFUNC
+; CHECK-NEXT: Limits:
+; CHECK-NEXT: Flags: 0x00000001
+; CHECK-NEXT: Initial: 0x00000002
+; CHECK-NEXT: Maximum: 0x00000002
+; CHECK-NEXT: - Type: MEMORY
+; CHECK-NEXT: Memories:
+; CHECK-NEXT: - Initial: 0x00000002
+; CHECK-NEXT: - Type: GLOBAL
+; CHECK-NEXT: Globals:
+; CHECK-NEXT: - Type: I32
+; CHECK-NEXT: Mutable: true
+; CHECK-NEXT: InitExpr:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 66560
+; CHECK-NEXT: - Type: EXPORT
+; CHECK-NEXT: Exports:
+; CHECK-NEXT: - Name: memory
+; CHECK-NEXT: Kind: MEMORY
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: - Name: get_address_of_foo
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: Index: 0
+; CHECK-NEXT: - Name: get_address_of_global_var
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: Index: 1
+; CHECK-NEXT: - Name: _start
+; CHECK-NEXT: Kind: FUNCTION
+; CHECK-NEXT: Index: 2
+; CHECK-NEXT: - Type: ELEM
+; CHECK-NEXT: Segments:
+; CHECK-NEXT: - Offset:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 1
+; CHECK-NEXT: Functions: [ 0 ]
+; CHECK-NEXT: - Type: CODE
+; CHECK-NEXT: Functions:
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 4181808080000B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 41FFFFFFFF7F0B
+; CHECK-NEXT: - Locals:
+; CHECK-NEXT: Body: 41002802FFFFFFFF0F0B
+; CHECK-NEXT: - Type: CUSTOM
+; CHECK-NEXT: Name: linking
+; CHECK-NEXT: DataSize: 0
+; CHECK-NEXT: ...
OpenPOWER on IntegriCloud