diff --git a/lld/test/wasm/compress-relocs.ll b/lld/test/wasm/compress-relocs.ll deleted file mode 100644 index cea9f3476e996..0000000000000 --- a/lld/test/wasm/compress-relocs.ll +++ /dev/null @@ -1,26 +0,0 @@ -; RUN: llc -filetype=obj %s -o %t.o -; RUN: llvm-mc -mattr=+call-indirect-overlong -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/call-indirect.s -o %t2.o -; RUN: wasm-ld --export-dynamic -o %t.wasm %t2.o %t.o -; RUN: obj2yaml %t.wasm | FileCheck %s -; RUN: wasm-ld --export-dynamic -O2 -o %t-opt.wasm %t2.o %t.o -; RUN: obj2yaml %t-opt.wasm | FileCheck %s -; RUN: not wasm-ld --compress-relocations -o %t-compressed.wasm %t2.o %t.o 2>&1 | FileCheck %s -check-prefix=ERROR -; RUN: wasm-ld --export-dynamic --strip-debug --compress-relocations -o %t-compressed.wasm %t2.o %t.o -; RUN: obj2yaml %t-compressed.wasm | FileCheck %s -check-prefix=COMPRESS - -target triple = "wasm32-unknown-unknown-wasm" - -define i32 @foo() { -entry: - ret i32 2 -} - -define void @_start() local_unnamed_addr { -entry: - ret void -} - -; ERROR: wasm-ld: error: --compress-relocations is incompatible with output debug information. Please pass --strip-debug or --strip-all - -; CHECK: Body: 41002802808880800011808080800080808080001A41002802848880800011818080800080808080001A0B -; COMPRESS: Body: 4100280280081100001A4100280284081101001A0B diff --git a/lld/test/wasm/compress-relocs.s b/lld/test/wasm/compress-relocs.s new file mode 100644 index 0000000000000..41d4ff567d501 --- /dev/null +++ b/lld/test/wasm/compress-relocs.s @@ -0,0 +1,129 @@ +# RUN: llvm-mc -mattr=+reference-types,+exception-handling -filetype=obj -triple=wasm32-unknown-unknown %s -o %t.o +# RUN: wasm-ld --export-dynamic -o %t.wasm %t.o +# RUN: llvm-objdump -d %t.wasm | FileCheck %s +# RUN: wasm-ld --export-dynamic -O2 -o %t-opt.wasm %t.o +# RUN: llvm-objdump -d %t-opt.wasm | FileCheck %s +# RUN: not wasm-ld --compress-relocations -o %t-compressed.wasm %t.o 2>&1 | FileCheck %s -check-prefix=ERROR +# RUN: wasm-ld --export-dynamic --strip-debug --compress-relocations -o %t-compressed.wasm %t.o +# RUN: llvm-objdump -d %t-compressed.wasm | FileCheck %s -check-prefix=COMPRESS + + .globl _start +_start: + .functype _start () -> () + end_function + + .globl func_ret_i64 +func_ret_i64: + .functype func_ret_i64 () -> (i64) + i64.const 1 + end_function + + .globl func_ret_i32 +func_ret_i32: + .functype func_ret_i32 () -> (i32) + i32.const 2 + end_function + +i32_global: + .globaltype i32_global, i32 + +i32_tag: + .tagtype i32_tag i32 + + .globl test_memory_and_indirect_call_relocs +test_memory_and_indirect_call_relocs: + .functype test_memory_and_indirect_call_relocs () -> () + i32.const indirect_func_ret_i64 # R_WASM_MEMORY_ADDR_SLEB + i32.load 0 + call_indirect () -> (i64) # R_WASM_TYPE_INDEX_LEB, R_WASM_TABLE_NUMBER_LEB + drop + i32.const 0 + i32.load indirect_func_ret_i32 # R_WASM_MEMORY_ADDR_LEB + call_indirect () -> (i32) + drop + i32.const func_ret_i64 # R_WASM_TABLE_INDEX_SLEB + call_indirect () -> (i64) + drop + end_function + +# CHECK: test_memory_and_indirect_call_relocs +# CHECK: 41 90 88 80 80 00 i32.const 1040 +# CHECK: 11 80 80 80 80 00 80 80 80 80 00 call_indirect 0 +# CHECK: 28 02 94 88 80 80 00 i32.load 1044 +# CHECK: 11 81 80 80 80 00 80 80 80 80 00 call_indirect 1 +# CHECK: 41 81 80 80 80 00 i32.const 1 +# CHECK: 11 80 80 80 80 00 80 80 80 80 00 call_indirect 0 +# COMPRESS: test_memory_and_indirect_call_relocs +# COMPRESS: 41 90 08 i32.const 1040 +# COMPRESS: 11 00 00 call_indirect 0 +# COMPRESS: 28 02 94 08 i32.load 1044 +# COMPRESS: 11 01 00 call_indirect 1 +# COMPRESS: 41 01 i32.const 1 +# COMPRESS: 11 00 00 call_indirect 0 + + .globl test_simple_index_relocs +test_simple_index_relocs: + .functype test_simple_index_relocs () -> () + call func_ret_i32 # R_WASM_FUNCTION_INDEX_LEB + global.set i32_global # R_WASM_GLOBAL_INDEX_LEB + i32.const 0 + throw i32_tag # R_WASM_TAG_INDEX_LEB + end_function + +# CHECK: test_simple_index_relocs +# CHECK: 10 82 80 80 80 00 call 2 +# CHECK: 24 81 80 80 80 00 global.set 1 +# CHECK: 08 80 80 80 80 00 throw 0 +# COMPRESS: test_simple_index_relocs +# COMPRESS: 10 02 call 2 +# COMPRESS: 24 01 global.set 1 +# COMPRESS: 08 00 throw 0 + + .globl test_relative_relocs +test_relative_relocs: + .functype test_relative_relocs () -> () + i32.const indirect_func_ret_i64@MBREL # R_WASM_MEMORY_ADDR_REL_SLEB + drop + i32.const func_ret_i32@TBREL # R_WASM_TABLE_INDEX_REL_SLEB + drop + i32.const i32_tls_data@TLSREL # R_WASM_MEMORY_ADDR_TLS_SLEB + drop + end_function + +# CHECK: test_relative_relocs +# CHECK: 41 90 88 80 80 00 i32.const 1040 +# CHECK: 41 81 80 80 80 00 i32.const 1 +# CHECK: 41 83 80 80 80 00 i32.const 3 +# COMPRESS: test_relative_relocs +# COMPRESS: 41 90 08 i32.const 1040 +# COMPRESS: 41 01 i32.const 1 +# COMPRESS: 41 03 i32.const 3 + +# ERROR: wasm-ld: error: --compress-relocations is incompatible with output debug information. Please pass --strip-debug or --strip-all + + .section .tdata,"T",@ + .int8 0 + .int8 0 + .int8 0 +i32_tls_data: + .int32 65 + .size i32_tls_data, 4 + + .section .data,"",@ + .p2align 4 +indirect_func_ret_i64: + .int32 func_ret_i64 + .size indirect_func_ret_i64, 4 + +indirect_func_ret_i32: + .int32 func_ret_i32 + .size indirect_func_ret_i32, 4 + +.section .custom_section.target_features,"",@ + .int8 2 + .int8 43 + .int8 7 + .ascii "atomics" + .int8 43 + .int8 11 + .ascii "bulk-memory" diff --git a/lld/test/wasm/compress-relocs64.s b/lld/test/wasm/compress-relocs64.s new file mode 100644 index 0000000000000..44e7a089275bb --- /dev/null +++ b/lld/test/wasm/compress-relocs64.s @@ -0,0 +1,92 @@ +# RUN: llvm-mc -filetype=obj -triple=wasm64-unknown-unknown %s -o %t.o +# RUN: wasm-ld -mwasm64 --export-dynamic -o %t.wasm %t.o +# RUN: llvm-objdump -d %t.wasm | FileCheck %s +# RUN: wasm-ld -mwasm64 --export-dynamic -O2 -o %t-opt.wasm %t.o +# RUN: llvm-objdump -d %t-opt.wasm | FileCheck %s +# RUN: wasm-ld -mwasm64 --export-dynamic --strip-debug --compress-relocations -o %t-compressed.wasm %t.o +# RUN: llvm-objdump -d %t-compressed.wasm | FileCheck %s -check-prefix=COMPRESS + + .globl _start +_start: + .functype _start () -> () + end_function + + .globl func_ret_i64 +func_ret_i64: + .functype func_ret_i64 () -> (i64) + i64.const 1 + end_function + + .globl func_ret_i32 +func_ret_i32: + .functype func_ret_i32 () -> (i32) + i32.const 2 + end_function + + .globl test_memory_and_indirect_call_relocs +test_memory_and_indirect_call_relocs: + .functype test_memory_and_indirect_call_relocs () -> () + i64.const indirect_func_ret_i64 # R_WASM_MEMORY_ADDR_SLEB64 + drop + i64.const 0 + i64.load indirect_func_ret_i32 # R_WASM_MEMORY_ADDR_LEB64 + drop + i64.const func_ret_i64 # R_WASM_TABLE_INDEX_SLEB64 + drop + end_function + +# CHECK: test_memory_and_indirect_call_relocs +# CHECK: 42 90 88 80 80 80 80 80 80 80 00 i64.const 1040 +# CHECK: 29 03 98 88 80 80 80 80 80 80 80 00 i64.load 1048 +# CHECK: 42 81 80 80 80 80 80 80 80 80 00 i64.const 1 +# COMPRESS: test_memory_and_indirect_call_relocs +# COMPRESS: 42 90 08 i64.const 1040 +# COMPRESS: 29 03 98 08 i64.load 1048 +# COMPRESS: 42 01 i64.const 1 + + .globl test_relative_relocs +test_relative_relocs: + .functype test_relative_relocs () -> () + i64.const indirect_func_ret_i64@MBREL # R_WASM_MEMORY_ADDR_REL_SLEB64 + drop + i64.const func_ret_i32@TBREL # R_WASM_TABLE_INDEX_REL_SLEB64 + drop + i64.const i32_tls_data@TLSREL # R_WASM_MEMORY_ADDR_TLS_SLEB64 + drop + end_function + +# CHECK: test_relative_relocs +# CHECK: 42 90 88 80 80 80 80 80 80 80 00 i64.const 1040 +# CHECK: 42 81 80 80 80 80 80 80 80 80 00 i64.const 1 +# CHECK: 42 83 80 80 80 80 80 80 80 80 00 i64.const 3 +# COMPRESS: test_relative_relocs +# COMPRESS: 42 90 08 i64.const 1040 +# COMPRESS: 42 01 i64.const 1 +# COMPRESS: 42 03 i64.const 3 + + .section .tdata,"T",@ + .int8 0 + .int8 0 + .int8 0 +i32_tls_data: + .int32 65 + .size i32_tls_data, 4 + + .section .data,"",@ + .p2align 4 +indirect_func_ret_i64: + .int64 func_ret_i64 + .size indirect_func_ret_i64, 8 + +indirect_func_ret_i32: + .int64 func_ret_i32 + .size indirect_func_ret_i32, 8 + +.section .custom_section.target_features,"",@ + .int8 2 + .int8 43 + .int8 7 + .ascii "atomics" + .int8 43 + .int8 11 + .ascii "bulk-memory" diff --git a/lld/wasm/InputChunks.cpp b/lld/wasm/InputChunks.cpp index 855589353e4f6..181221a77b106 100644 --- a/lld/wasm/InputChunks.cpp +++ b/lld/wasm/InputChunks.cpp @@ -228,7 +228,7 @@ void InputFunction::setTableIndex(uint32_t index) { // witten. static unsigned writeCompressedReloc(uint8_t *buf, const WasmRelocation &rel, uint64_t value) { - switch (rel.Type) { + switch (rel.getType()) { case R_WASM_TYPE_INDEX_LEB: case R_WASM_FUNCTION_INDEX_LEB: case R_WASM_GLOBAL_INDEX_LEB: @@ -239,16 +239,33 @@ static unsigned writeCompressedReloc(uint8_t *buf, const WasmRelocation &rel, return encodeULEB128(value, buf); case R_WASM_TABLE_INDEX_SLEB: case R_WASM_TABLE_INDEX_SLEB64: + case R_WASM_TABLE_INDEX_REL_SLEB64: case R_WASM_MEMORY_ADDR_SLEB: case R_WASM_MEMORY_ADDR_SLEB64: + case R_WASM_MEMORY_ADDR_REL_SLEB: + case R_WASM_MEMORY_ADDR_REL_SLEB64: + case R_WASM_MEMORY_ADDR_TLS_SLEB: + case R_WASM_MEMORY_ADDR_TLS_SLEB64: + case R_WASM_TABLE_INDEX_REL_SLEB: return encodeSLEB128(static_cast(value), buf); - default: - llvm_unreachable("unexpected relocation type"); + case R_WASM_TABLE_INDEX_I32: + case R_WASM_MEMORY_ADDR_I32: + case R_WASM_FUNCTION_OFFSET_I32: + case R_WASM_SECTION_OFFSET_I32: + case R_WASM_GLOBAL_INDEX_I32: + case R_WASM_MEMORY_ADDR_I64: + case R_WASM_TABLE_INDEX_I64: + case R_WASM_FUNCTION_OFFSET_I64: + case R_WASM_MEMORY_ADDR_LOCREL_I32: + case R_WASM_FUNCTION_INDEX_I32: + fatal("relocation compression not supported for " + + relocTypeToString(rel.Type)); } + llvm_unreachable("unhandled relocation type"); } static unsigned getRelocWidthPadded(const WasmRelocation &rel) { - switch (rel.Type) { + switch (rel.getType()) { case R_WASM_TYPE_INDEX_LEB: case R_WASM_FUNCTION_INDEX_LEB: case R_WASM_GLOBAL_INDEX_LEB: @@ -256,15 +273,32 @@ static unsigned getRelocWidthPadded(const WasmRelocation &rel) { case R_WASM_MEMORY_ADDR_LEB: case R_WASM_TABLE_NUMBER_LEB: case R_WASM_TABLE_INDEX_SLEB: + case R_WASM_TABLE_INDEX_REL_SLEB: case R_WASM_MEMORY_ADDR_SLEB: + case R_WASM_MEMORY_ADDR_REL_SLEB: + case R_WASM_MEMORY_ADDR_TLS_SLEB: return 5; case R_WASM_TABLE_INDEX_SLEB64: + case R_WASM_TABLE_INDEX_REL_SLEB64: case R_WASM_MEMORY_ADDR_LEB64: case R_WASM_MEMORY_ADDR_SLEB64: + case R_WASM_MEMORY_ADDR_REL_SLEB64: + case R_WASM_MEMORY_ADDR_TLS_SLEB64: return 10; - default: - llvm_unreachable("unexpected relocation type"); + case R_WASM_TABLE_INDEX_I32: + case R_WASM_MEMORY_ADDR_I32: + case R_WASM_FUNCTION_OFFSET_I32: + case R_WASM_SECTION_OFFSET_I32: + case R_WASM_GLOBAL_INDEX_I32: + case R_WASM_MEMORY_ADDR_I64: + case R_WASM_TABLE_INDEX_I64: + case R_WASM_FUNCTION_OFFSET_I64: + case R_WASM_MEMORY_ADDR_LOCREL_I32: + case R_WASM_FUNCTION_INDEX_I32: + fatal("relocation compression not supported for " + + relocTypeToString(rel.Type)); } + llvm_unreachable("unhandled relocation type"); } static unsigned getRelocWidth(const WasmRelocation &rel, uint64_t value) { diff --git a/llvm/include/llvm/BinaryFormat/Wasm.h b/llvm/include/llvm/BinaryFormat/Wasm.h index 604104ff3cca3..cf90a43d0d7e8 100644 --- a/llvm/include/llvm/BinaryFormat/Wasm.h +++ b/llvm/include/llvm/BinaryFormat/Wasm.h @@ -253,7 +253,7 @@ const unsigned WASM_SYMBOL_ABSOLUTE = 0x200; #define WASM_RELOC(name, value) name = value, -enum : unsigned { +enum WasmRelocType : unsigned { #include "WasmRelocs.def" }; @@ -452,6 +452,8 @@ struct WasmRelocation { uint32_t Index; // Index into either symbol or type index space. uint64_t Offset; // Offset from the start of the section. int64_t Addend; // A value to add to the symbol. + + WasmRelocType getType() const { return static_cast(Type); } }; struct WasmInitFunc {