ptrdiff_t Assembler::LinkAndGetOffsetTo(BufferOffset branch, Label* label) { if (armbuffer_.oom()) return js::jit::LabelBase::INVALID_OFFSET; if (label->bound()) { // The label is bound: all uses are already linked. ptrdiff_t branch_offset = ptrdiff_t(branch.getOffset() / element_size); ptrdiff_t label_offset = ptrdiff_t(label->offset() / element_size); return label_offset - branch_offset; } if (!label->used()) { // The label is unbound and unused: store the offset in the label itself // for patching by bind(). label->use(branch.getOffset()); return js::jit::LabelBase::INVALID_OFFSET; } // The label is unbound but used. Create an implicit linked list between // the branches, and update the linked list head in the label struct. ptrdiff_t prevHeadOffset = static_cast<ptrdiff_t>(label->offset()); label->use(branch.getOffset()); VIXL_ASSERT(prevHeadOffset - branch.getOffset() != js::jit::LabelBase::INVALID_OFFSET); return prevHeadOffset - branch.getOffset(); }
void MozBaseAssembler::WritePoolGuard(BufferOffset branch, Instruction* inst, BufferOffset dest) { int byteOffset = dest.getOffset() - branch.getOffset(); VIXL_ASSERT(byteOffset % kInstructionSize == 0); int instOffset = byteOffset >> kInstructionSizeLog2; Assembler::b(inst, instOffset); }
static ptrdiff_t EncodeOffset(BufferOffset cur, BufferOffset next) { MOZ_ASSERT(next.assigned() && cur.assigned()); ptrdiff_t offset = next.getOffset() - cur.getOffset(); MOZ_ASSERT(offset % kInstructionSize == 0); return offset / kInstructionSize; }
// A common implementation for the LinkAndGet<Type>OffsetTo helpers. // // If the label is bound, returns the offset as a multiple of 1 << elementShift. // Otherwise, links the instruction to the label and returns the raw offset to // encode. (This will be an instruction count.) // // The offset is calculated by aligning the PC and label addresses down to a // multiple of 1 << elementShift, then calculating the (scaled) offset between // them. This matches the semantics of adrp, for example. (Assuming that the // assembler buffer is page-aligned, which it probably isn't.) // // For an unbound label, the returned offset will be encodable in the provided // branch range. If the label is already bound, the caller is expected to make // sure that it is in range, and emit the necessary branch instrutions if it // isn't. // ptrdiff_t MozBaseAssembler::LinkAndGetOffsetTo(BufferOffset branch, ImmBranchRangeType branchRange, unsigned elementShift, Label* label) { if (armbuffer_.oom()) return kEndOfLabelUseList; if (label->bound()) { // The label is bound: all uses are already linked. ptrdiff_t branch_offset = ptrdiff_t(branch.getOffset() >> elementShift); ptrdiff_t label_offset = ptrdiff_t(label->offset() >> elementShift); return label_offset - branch_offset; }