1; Test that PIC code can be linked into static binaries.
2; In this case the GOT entries will end up as internalized wasm globals with
3; fixed values.
4; RUN: llc -relocation-model=pic -filetype=obj %p/Inputs/ret32.ll -o %t.ret32.o
5; RUN: llc -relocation-model=pic -filetype=obj %s -o %t.o
6; RUN: wasm-ld --allow-undefined --export-all -o %t.wasm %t.o %t.ret32.o
7; RUN: obj2yaml %t.wasm | FileCheck %s
8
9target triple = "wasm32-unknown-emscripten"
10
11declare i32 @ret32(float)
12declare i32 @missing_function(float)
13@global_float = global float 1.0
14@hidden_float = hidden global float 2.0
15@missing_float = extern_weak global float
16
17@ret32_ptr = global i32 (float)* @ret32, align 4
18
19define i32 (float)* @getaddr_external() {
20  ret i32 (float)* @ret32;
21}
22
23define i32 (float)* @getaddr_missing_function() {
24  ret i32 (float)* @missing_function;
25}
26
27define i32 ()* @getaddr_hidden() {
28  ret i32 ()* @hidden_func;
29}
30
31define float* @getaddr_missing_float() {
32  ret float* @missing_float
33}
34
35define hidden i32 @hidden_func() {
36  ret i32 1
37}
38
39define void @_start() {
40entry:
41  %f = load float, float* @hidden_float, align 4
42  %addr = load i32 (float)*, i32 (float)** @ret32_ptr, align 4
43  %arg = load float, float* @global_float, align 4
44  call i32 %addr(float %arg)
45
46  %addr2 = call i32 (float)* @getaddr_external()
47  %arg2 = load float, float* @hidden_float, align 4
48  call i32 %addr2(float %arg2)
49
50  %addr3 = call i32 ()* @getaddr_hidden()
51  call i32 %addr3()
52
53  ret void
54}
55
56; CHECK:        - Type:            GLOBAL
57; CHECK-NEXT:     Globals:
58
59; __stack_pointer
60; CHECK-NEXT:       - Index:           0
61; CHECK-NEXT:         Type:            I32
62; CHECK-NEXT:         Mutable:         true
63; CHECK-NEXT:         InitExpr:
64; CHECK-NEXT:           Opcode:          I32_CONST
65; CHECK-NEXT:           Value:           66576
66
67; GOT.func.ret32
68; CHECK-NEXT:       - Index:           1
69; CHECK-NEXT:         Type:            I32
70; CHECK-NEXT:         Mutable:         false
71; CHECK-NEXT:         InitExpr:
72; CHECK-NEXT:           Opcode:          I32_CONST
73; CHECK-NEXT:           Value:           1
74
75; GOT.func.missing_function
76; CHECK-NEXT:       - Index:           2
77; CHECK-NEXT:         Type:            I32
78; CHECK-NEXT:         Mutable:         false
79; CHECK-NEXT:         InitExpr:
80; CHECK-NEXT:           Opcode:          I32_CONST
81; CHECK-NEXT:           Value:           2
82
83; __table_base
84; CHECK-NEXT:       - Index:           3
85; CHECK-NEXT:         Type:            I32
86; CHECK-NEXT:         Mutable:         false
87; CHECK-NEXT:         InitExpr:
88; CHECK-NEXT:           Opcode:          I32_CONST
89; CHECK-NEXT:           Value:           1
90
91; GOT.mem.missing_float
92; CHECK-NEXT:       - Index:           4
93; CHECK-NEXT:         Type:            I32
94; CHECK-NEXT:         Mutable:         false
95; CHECK-NEXT:         InitExpr:
96; CHECK-NEXT:           Opcode:          I32_CONST
97; CHECK-NEXT:           Value:           0
98
99; GOT.mem.global_float
100; CHECK-NEXT:       - Index:           5
101; CHECK-NEXT:         Type:            I32
102; CHECK-NEXT:         Mutable:         false
103; CHECK-NEXT:         InitExpr:
104; CHECK-NEXT:           Opcode:          I32_CONST
105; CHECK-NEXT:           Value:           1024
106
107; GOT.mem.ret32_ptr
108; CHECK-NEXT:       - Index:           6
109; CHECK-NEXT:         Type:            I32
110; CHECK-NEXT:         Mutable:         false
111; CHECK-NEXT:         InitExpr:
112; CHECK-NEXT:           Opcode:          I32_CONST
113; CHECK-NEXT:           Value:           1032
114
115; __memory_base
116; CHECK-NEXT:       - Index:           7
117; CHECK-NEXT:         Type:            I32
118; CHECK-NEXT:         Mutable:         false
119; CHECK-NEXT:         InitExpr:
120; CHECK-NEXT:           Opcode:          I32_CONST
121; CHECK-NEXT:           Value:           0
122