Generate slightly more compressed binding opcodes when entries are the same as last time.

We already had logic for binding opcodes had the same addend as last time.  This adds
the cases where the ordinal, symbol name, type, and segment offsets are the same as
the last emitted ordinal.

This gets us one step closer to emitting rebase opcodes as compressed as ld64 can manage.

llvm-svn: 278405
This commit is contained in:
Pete Cooper 2016-08-11 20:37:02 +00:00
parent 2698cbb4f1
commit 21f475e1c4
2 changed files with 46 additions and 27 deletions

View File

@ -1192,19 +1192,44 @@ void MachOFileLayout::buildRebaseInfo() {
void MachOFileLayout::buildBindInfo() {
// TODO: compress bind info.
uint64_t lastAddend = 0;
int lastOrdinal = 0x80000000;
StringRef lastSymbolName;
BindType lastType = (BindType)0;
Hex32 lastSegOffset = ~0U;
uint8_t lastSegIndex = (uint8_t)~0U;
for (const BindLocation& entry : _file.bindingInfo) {
if (entry.ordinal != lastOrdinal) {
if (entry.ordinal <= 0)
_bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
(entry.ordinal & BIND_IMMEDIATE_MASK));
else if (entry.ordinal <= BIND_IMMEDIATE_MASK)
_bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
entry.ordinal);
else {
_bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
_bindingInfo.append_uleb128(entry.ordinal);
}
lastOrdinal = entry.ordinal;
}
if (lastSymbolName != entry.symbolName) {
_bindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
_bindingInfo.append_string(entry.symbolName);
lastSymbolName = entry.symbolName;
}
if (lastType != entry.kind) {
_bindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
lastType = entry.kind;
}
if (lastSegIndex != entry.segIndex || lastSegOffset != entry.segOffset) {
_bindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
| entry.segIndex);
_bindingInfo.append_uleb128(entry.segOffset);
if (entry.ordinal > 0)
_bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
(entry.ordinal & 0xF));
else
_bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
(entry.ordinal & 0xF));
_bindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
_bindingInfo.append_string(entry.symbolName);
lastSegIndex = entry.segIndex;
lastSegOffset = entry.segOffset;
}
if (entry.addend != lastAddend) {
_bindingInfo.append_byte(BIND_OPCODE_SET_ADDEND_SLEB);
_bindingInfo.append_sleb128(entry.addend);

View File

@ -88,6 +88,12 @@ undefined-symbols:
# CHECK: BindOpcodes:
# CHECK: - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
# CHECK: Imm: 1
# CHECK: Symbol: ''
# CHECK: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
# CHECK: Imm: 0
# CHECK: Symbol: dyld_stub_binder
# CHECK: - Opcode: BIND_OPCODE_SET_TYPE_IMM
# CHECK: Imm: 1
# CHECK: Symbol: ''
@ -96,29 +102,17 @@ undefined-symbols:
# CHECK: ULEBExtraData:
# CHECK: - 0x0000000000000000
# CHECK: Symbol: ''
# CHECK: - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
# CHECK: Imm: 1
# CHECK: Symbol: ''
# CHECK: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
# CHECK: Imm: 0
# CHECK: Symbol: dyld_stub_binder
# CHECK: - Opcode: BIND_OPCODE_DO_BIND
# CHECK: Imm: 0
# CHECK: Symbol: ''
# CHECK: - Opcode: BIND_OPCODE_SET_TYPE_IMM
# CHECK: Imm: 1
# CHECK: Symbol: ''
# CHECK: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
# CHECK: Imm: 0
# CHECK: Symbol: ___stdoutp
# CHECK: - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
# CHECK: Imm: 2
# CHECK: ULEBExtraData:
# CHECK: - 0x0000000000000010
# CHECK: Symbol: ''
# CHECK: - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
# CHECK: Imm: 1
# CHECK: Symbol: ''
# CHECK: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
# CHECK: Imm: 0
# CHECK: Symbol: ___stdoutp
# CHECK: - Opcode: BIND_OPCODE_DO_BIND
# CHECK: Imm: 0
# CHECK: Symbol: ''