diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp --- a/lld/MachO/SyntheticSections.cpp +++ b/lld/MachO/SyntheticSections.cpp @@ -361,6 +361,16 @@ if (i == opcodes.size()) opcodes[pWrite] = opcodes[i - 1]; opcodes.resize(pWrite + 1); + + // Pass 3: Use immediate encodings + for (BindIR* p = &opcodes[0]; p->opcode != BIND_OPCODE_DONE; ++p) { + if ((p->opcode == BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB) + && (p->data < (15*sizeof(uint64_t))) + && ((p->data % sizeof(uint64_t)) == 0)) { + p->opcode = BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED; + p->data = p->data/sizeof(uint64_t); + } + } } static void flushOpcodes(const BindIR &op, raw_svector_ostream &os) { @@ -384,6 +394,9 @@ encodeULEB128(op.consecutiveCount, os); encodeULEB128(op.data, os); break; + case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: + os << static_cast(op.opcode | op.data); + break; default: llvm_unreachable("cannot bind to an unrecognized symbol"); } diff --git a/lld/test/MachO/bind-opcodes.s b/lld/test/MachO/bind-opcodes.s --- a/lld/test/MachO/bind-opcodes.s +++ b/lld/test/MachO/bind-opcodes.s @@ -9,6 +9,7 @@ ## 1/ We emit exactly one BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM per symbol. ## 2/ Combine BIND_OPCODE_DO_BIND and BIND_OPCODE_ADD_ADDR_ULEB pairs. ## 3/ Compact BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB +## 4/ Use BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED if possible. # RUN: obj2yaml %t/test | FileCheck %s # CHECK: BindOpcodes: @@ -54,9 +55,8 @@ # CHECK-NEXT: Imm: 0 # CHECK-NEXT: ULEBExtraData: [ 0xFFFFFFFFFFFFEFD0 ] # CHECK-NEXT: Symbol: '' -# CHECK-NEXT: Opcode: BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB -# CHECK-NEXT: Imm: 0 -# CHECK-NEXT: ULEBExtraData: [ 0x8 ] +# CHECK-NEXT: Opcode: BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED +# CHECK-NEXT: Imm: 1 # CHECK-NEXT: Symbol: '' # CHECK-NEXT: Opcode: BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB # CHECK-NEXT: Imm: 0