# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-emscripten -o %t.o %s # RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-emscripten %S/Inputs/internal_func.s -o %t.internal_func.o # RUN: wasm-ld --no-gc-sections --experimental-pic -pie -o %t.wasm %t.o %t.internal_func.o # RUN: obj2yaml %t.wasm | FileCheck %s # RUN: llvm-objdump --disassemble-symbols=__wasm_call_ctors,__wasm_apply_data_relocs --no-show-raw-insn --no-leading-addr %t.wasm | FileCheck %s --check-prefixes DISASSEM .functype external_func () -> () .functype internal_func1 () -> (i32) .functype internal_func2 () -> (i32) .globaltype __stack_pointer, i32 .section .data,"",@ .p2align 2 data: .int32 2 .size data, 4 indirect_func: .int32 foo .size indirect_func, 4 data_addr: .int32 data .size data_addr, 4 data_addr_external: .int32 data_external .size data_addr_external, 4 .section .text,"",@ foo: .functype foo () -> (i32) global.get data@GOT i32.load 0 drop global.get indirect_func@GOT i32.load 0 call_indirect () -> (i32) drop global.get __stack_pointer end_function get_data_address: .functype get_data_address () -> (i32) global.get data_addr_external@GOT end_function get_internal_func1_address: .functype get_internal_func1_address () -> (i32) global.get internal_func1@GOT end_function get_internal_func2_address: .functype get_internal_func2_address () -> (i32) global.get internal_func2@GOT end_function .globl _start _start: .functype _start () -> () call external_func end_function .section .custom_section.target_features,"",@ .int8 2 .int8 43 .int8 7 .ascii "atomics" .int8 43 .int8 11 .ascii "bulk-memory" # CHECK: Sections: # CHECK-NEXT: - Type: CUSTOM # CHECK-NEXT: Name: dylink.0 # CHECK-NEXT: MemorySize: 16 # CHECK-NEXT: MemoryAlignment: 2 # CHECK-NEXT: TableSize: 3 # CHECK-NEXT: TableAlignment: 0 # CHECK-NEXT: Needed: [] # CHECK: - Type: IMPORT # CHECK-NEXT: Imports: # CHECK-NEXT: - Module: env # CHECK-NEXT: Field: __indirect_function_table # CHECK-NEXT: Kind: TABLE # CHECK-NEXT: Table: # CHECK-NEXT: Index: 0 # CHECK-NEXT: ElemType: FUNCREF # CHECK-NEXT: Limits: # CHECK-NEXT: Minimum: 0x3 # CHECK-NEXT: - Module: env # CHECK-NEXT: Field: __stack_pointer # CHECK-NEXT: Kind: GLOBAL # CHECK-NEXT: GlobalType: I32 # CHECK-NEXT: GlobalMutable: true # CHECK-NEXT: - Module: env # CHECK-NEXT: Field: __memory_base # CHECK-NEXT: Kind: GLOBAL # CHECK-NEXT: GlobalType: I32 # CHECK-NEXT: GlobalMutable: false # CHECK-NEXT: - Module: env # CHECK-NEXT: Field: __table_base # CHECK-NEXT: Kind: GLOBAL # CHECK-NEXT: GlobalType: I32 # CHECK-NEXT: GlobalMutable: false # CHECK: - Type: START # CHECK-NEXT: StartFunction: 3 # CHECK: - Type: CUSTOM # CHECK-NEXT: Name: name # CHECK-NEXT: FunctionNames: # CHECK-NEXT: - Index: 0 # CHECK-NEXT: Name: external_func # CHECK-NEXT: - Index: 1 # CHECK-NEXT: Name: __wasm_call_ctors # CHECK-NEXT: - Index: 2 # CHECK-NEXT: Name: __wasm_apply_data_relocs # CHECK-NEXT: - Index: 3 # CHECK-NEXT: Name: __wasm_apply_global_relocs # CHECK-NEXT: - Index: 4 # CHECK-NEXT: Name: foo # CHECK-NEXT: - Index: 5 # CHECK-NEXT: Name: get_data_address # CHECK-NEXT: - Index: 6 # CHECK-NEXT: Name: get_internal_func1_address # CHECK-NEXT: - Index: 7 # CHECK-NEXT: Name: get_internal_func2_address # CHECK-NEXT: - Index: 8 # CHECK-NEXT: Name: _start # CHECK-NEXT: - Index: 9 # CHECK-NEXT: Name: internal_func1 # CHECK-NEXT: - Index: 10 # CHECK-NEXT: Name: internal_func2 # CHECK-NEXT: GlobalNames: # DISASSEM-LABEL: <__wasm_call_ctors>: # DISASSEM-EMPTY: # DISASSEM-NEXT: end # DISASSEM-LABEL: <__wasm_apply_data_relocs>: # DISASSEM: end # Run the same test with extended-const support. When this is available # we don't need __wasm_apply_global_relocs and instead rely on the add # instruction in the InitExpr. We also, therefore, do not need these globals # to be mutable. # RUN: wasm-ld --no-gc-sections --experimental-pic -pie --extra-features=extended-const -o %t.extended.wasm %t.o %t.internal_func.o # RUN: obj2yaml %t.extended.wasm | FileCheck %s --check-prefix=EXTENDED-CONST # EXTENDED-CONST-NOT: __wasm_apply_global_relocs # EXTENDED-CONST: - Type: GLOBAL # EXTENDED-CONST-NEXT: Globals: # EXTENDED-CONST-NEXT: - Index: 4 # EXTENDED-CONST-NEXT: Type: I32 # EXTENDED-CONST-NEXT: Mutable: false # EXTENDED-CONST-NEXT: InitExpr: # EXTENDED-CONST-NEXT: Opcode: GLOBAL_GET # EXTENDED-CONST-NEXT: Index: 1 # EXTENDED-CONST-NEXT: - Index: 5 # EXTENDED-CONST-NEXT: Type: I32 # EXTENDED-CONST-NEXT: Mutable: false # EXTENDED-CONST-NEXT: InitExpr: # EXTENDED-CONST-NEXT: Extended: true # EXTENDED-CONST-NEXT: Body: 230141046A0B # EXTENDED-CONST-NEXT: - Index: 6 # EXTENDED-CONST-NEXT: Type: I32 # EXTENDED-CONST-NEXT: Mutable: false # EXTENDED-CONST-NEXT: InitExpr: # EXTENDED-CONST-NEXT: Extended: true # This instruction sequence decodes to: # (global.get[0x23] 0x1 i32.const[0x41] 0x0C i32.add[0x6A] end[0x0b]) # EXTENDED-CONST-NEXT: Body: 2301410C6A0B # EXTENDED-CONST-NEXT: - Index: 7 # EXTENDED-CONST-NEXT: Type: I32 # EXTENDED-CONST-NEXT: Mutable: false # EXTENDED-CONST-NEXT: InitExpr: # EXTENDED-CONST-NEXT: Opcode: GLOBAL_GET # EXTENDED-CONST-NEXT: Index: 2 # EXTENDED-CONST-NEXT: - Index: 8 # EXTENDED-CONST-NEXT: Type: I32 # EXTENDED-CONST-NEXT: Mutable: false # EXTENDED-CONST-NEXT: InitExpr: # EXTENDED-CONST-NEXT: Extended: true # This instruction sequence decodes to: # (global.get[0x23] 0x2 i32.const[0x41] 0x1 i32.add[0x6A] end[0x0b]) # EXTENDED-CONST-NEXT: Body: 230241016A0B # EXTENDED-CONST-NOT: - Type: START # EXTENDED-CONST: FunctionNames: # EXTENDED-CONST-NEXT: - Index: 0 # EXTENDED-CONST-NEXT: Name: external_func # EXTENDED-CONST-NEXT: - Index: 1 # EXTENDED-CONST-NEXT: Name: __wasm_call_ctors # EXTENDED-CONST-NEXT: - Index: 2 # EXTENDED-CONST-NEXT: Name: __wasm_apply_data_relocs # Run the same test with threading support. In this mode # we expect __wasm_init_memory and __wasm_apply_data_relocs # to be generated along with __wasm_start as the start # function. # RUN: wasm-ld --no-gc-sections --shared-memory --experimental-pic -pie -o %t.shmem.wasm %t.o %t.internal_func.o # RUN: obj2yaml %t.shmem.wasm | FileCheck %s --check-prefix=SHMEM # RUN: llvm-objdump --disassemble-symbols=__wasm_start --no-show-raw-insn --no-leading-addr %t.shmem.wasm | FileCheck %s --check-prefix DISASSEM-SHMEM # SHMEM: - Type: START # SHMEM-NEXT: StartFunction: 6 # DISASSEM-SHMEM-LABEL: <__wasm_start>: # DISASSEM-SHMEM-EMPTY: # DISASSEM-SHMEM-NEXT: call 5 # DISASSEM-SHMEM-NEXT: call 4 # DISASSEM-SHMEM-NEXT: end # SHMEM: FunctionNames: # SHMEM-NEXT: - Index: 0 # SHMEM-NEXT: Name: external_func # SHMEM-NEXT: - Index: 1 # SHMEM-NEXT: Name: __wasm_call_ctors # SHMEM-NEXT: - Index: 2 # SHMEM-NEXT: Name: __wasm_init_tls # SHMEM-NEXT: - Index: 3 # SHMEM-NEXT: Name: __wasm_apply_data_relocs # SHMEM-NEXT: - Index: 4 # SHMEM-NEXT: Name: __wasm_init_memory # SHMEM-NEXT: - Index: 5 # SHMEM-NEXT: Name: __wasm_apply_global_relocs # SHMEM-NEXT: - Index: 6 # SHMEM-NEXT: Name: __wasm_start # SHMEM-NEXT: - Index: 7 # SHMEM-NEXT: Name: foo # SHMEM-NEXT: - Index: 8 # SHMEM-NEXT: Name: get_data_address # SHMEM-NEXT: - Index: 9 # SHMEM-NEXT: Name: get_internal_func1_address # SHMEM-NEXT: - Index: 10 # SHMEM-NEXT: Name: get_internal_func2_address # SHMEM-NEXT: - Index: 11 # SHMEM-NEXT: Name: _start