1; RUN: llc -relocation-model=pic -mattr=+mutable-globals -filetype=obj %s -o %t.o 2; RUN: wasm-ld --experimental-pic -shared -o %t.wasm %t.o 3; RUN: obj2yaml %t.wasm | FileCheck %s 4 5target triple = "wasm32-unknown-emscripten" 6 7@data = hidden global i32 2, align 4 8@data_external = external global i32 9@indirect_func = local_unnamed_addr global i32 ()* @foo, align 4 10@indirect_func_external = local_unnamed_addr global void ()* @func_external, align 4 11 12; Test data relocations 13@data_addr = local_unnamed_addr global i32* @data, align 4 14; .. against external symbols 15@data_addr_external = local_unnamed_addr global i32* @data_external, align 4 16; .. including addends 17%struct.s = type { i32, i32 } 18@extern_struct = external global %struct.s 19@extern_struct_internal_ptr = local_unnamed_addr global i32* getelementptr inbounds (%struct.s, %struct.s* @extern_struct, i32 0, i32 1), align 4 20 21define hidden i32 @foo() { 22entry: 23 ; To ensure we use __stack_pointer 24 %ptr = alloca i32 25 %0 = load i32, i32* @data, align 4 26 %1 = load i32 ()*, i32 ()** @indirect_func, align 4 27 call i32 %1() 28 ret i32 %0 29} 30 31define hidden i32* @get_data_address() { 32entry: 33 ret i32* @data_external 34} 35 36define hidden i8* @get_func_address() { 37entry: 38 ret i8* bitcast (void ()* @func_external to i8*) 39} 40 41define default i8* @get_local_func_address() { 42entry: 43 ; Verify that a function which is otherwise not address taken *is* added to 44 ; the wasm table with referenced via R_WASM_TABLE_INDEX_REL_SLEB 45 ret i8* bitcast (i8* ()* @get_func_address to i8*) 46} 47 48declare void @func_external() 49 50; check for dylink section at start 51 52; CHECK: Sections: 53; CHECK-NEXT: - Type: CUSTOM 54; CHECK-NEXT: Name: dylink 55; CHECK-NEXT: MemorySize: 24 56; CHECK-NEXT: MemoryAlignment: 2 57; CHECK-NEXT: TableSize: 2 58; CHECK-NEXT: TableAlignment: 0 59; CHECK-NEXT: Needed: [] 60; CHECK-NEXT: - Type: TYPE 61 62; check for import of __table_base and __memory_base globals 63 64; CHECK: - Type: IMPORT 65; CHECK-NEXT: Imports: 66; CHECK-NEXT: - Module: env 67; CHECK-NEXT: Field: memory 68; CHECK-NEXT: Kind: MEMORY 69; CHECK-NEXT: Memory: 70; CHECK-NEXT: Initial: 0x1 71; CHECK-NEXT: - Module: env 72; CHECK-NEXT: Field: __indirect_function_table 73; CHECK-NEXT: Kind: TABLE 74; CHECK-NEXT: Table: 75; CHECK-NEXT: Index: 0 76; CHECK-NEXT: ElemType: FUNCREF 77; CHECK-NEXT: Limits: 78; CHECK-NEXT: Initial: 0x2 79; CHECK-NEXT: - Module: env 80; CHECK-NEXT: Field: __stack_pointer 81; CHECK-NEXT: Kind: GLOBAL 82; CHECK-NEXT: GlobalType: I32 83; CHECK-NEXT: GlobalMutable: true 84; CHECK-NEXT: - Module: env 85; CHECK-NEXT: Field: __memory_base 86; CHECK-NEXT: Kind: GLOBAL 87; CHECK-NEXT: GlobalType: I32 88; CHECK-NEXT: GlobalMutable: false 89; CHECK-NEXT: - Module: env 90; CHECK-NEXT: Field: __table_base 91; CHECK-NEXT: Kind: GLOBAL 92; CHECK-NEXT: GlobalType: I32 93; CHECK-NEXT: GlobalMutable: false 94; CHECK-NEXT: - Module: env 95; CHECK-NEXT: Field: func_external 96; CHECK-NEXT: Kind: FUNCTION 97; CHECK-NEXT: SigIndex: 1 98; CHECK-NEXT: - Module: GOT.mem 99; CHECK-NEXT: Field: indirect_func 100; CHECK-NEXT: Kind: GLOBAL 101; CHECK-NEXT: GlobalType: I32 102; CHECK-NEXT: GlobalMutable: true 103; CHECK-NEXT: - Module: GOT.func 104; CHECK-NEXT: Field: func_external 105; CHECK-NEXT: Kind: GLOBAL 106; CHECK-NEXT: GlobalType: I32 107; CHECK-NEXT: GlobalMutable: true 108; CHECK-NEXT: - Module: GOT.mem 109; CHECK-NEXT: Field: data_external 110; CHECK-NEXT: Kind: GLOBAL 111; CHECK-NEXT: GlobalType: I32 112; CHECK-NEXT: GlobalMutable: true 113; CHECK-NEXT: - Module: GOT.mem 114; CHECK-NEXT: Field: extern_struct 115; CHECK-NEXT: Kind: GLOBAL 116; CHECK-NEXT: GlobalType: I32 117; CHECK-NEXT: GlobalMutable: true 118; CHECK-NEXT: - Type: FUNCTION 119 120; CHECK: - Type: EXPORT 121; CHECK-NEXT: Exports: 122; CHECK-NEXT: - Name: __wasm_call_ctors 123; CHECK-NEXT: Kind: FUNCTION 124; CHECK-NEXT: Index: 1 125 126; check for elem segment initialized with __table_base global as offset 127 128; CHECK: - Type: ELEM 129; CHECK-NEXT: Segments: 130; CHECK-NEXT: - Offset: 131; CHECK-NEXT: Opcode: GLOBAL_GET 132; CHECK-NEXT: Index: 2 133; CHECK-NEXT: Functions: [ 4, 3 ] 134 135; check the generated code in __wasm_call_ctors and __wasm_apply_relocs functions 136; TODO(sbc): Disassemble and verify instructions. 137 138; CHECK: - Type: CODE 139; CHECK-NEXT: Functions: 140; CHECK-NEXT: - Index: 1 141; CHECK-NEXT: Locals: [] 142; CHECK-NEXT: Body: 10020B 143; CHECK-NEXT: - Index: 2 144; CHECK-NEXT: Locals: [] 145; CHECK-NEXT: Body: 230141046A230241016A360200230141086A23043602002301410C6A230141006A360200230141106A2305360200230141146A230641046A3602000B 146 147; check the data segment initialized with __memory_base global as offset 148 149; CHECK: - Type: DATA 150; CHECK-NEXT: Segments: 151; CHECK-NEXT: - SectionOffset: 6 152; CHECK-NEXT: InitFlags: 0 153; CHECK-NEXT: Offset: 154; CHECK-NEXT: Opcode: GLOBAL_GET 155; CHECK-NEXT: Index: 1 156; CHECK-NEXT: Content: '020000000100000000000000000000000000000000000000' 157