llvm/lld/test/wasm/pie.s

# 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 --unresolved-symbols=import-dynamic -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 --unresolved-symbols=import-dynamic --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 --unresolved-symbols=import-dynamic -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