10b57cec5SDimitry Andric //===- llvm/MC/MCLinkerOptimizationHint.cpp ----- LOH handling ------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "llvm/MC/MCLinkerOptimizationHint.h"
100b57cec5SDimitry Andric #include "llvm/MC/MCMachObjectWriter.h"
110b57cec5SDimitry Andric #include "llvm/Support/LEB128.h"
120b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
130b57cec5SDimitry Andric #include <cstddef>
140b57cec5SDimitry Andric #include <cstdint>
150b57cec5SDimitry Andric
160b57cec5SDimitry Andric using namespace llvm;
170b57cec5SDimitry Andric
180b57cec5SDimitry Andric // Each LOH is composed by, in this order (each field is encoded using ULEB128):
190b57cec5SDimitry Andric // - Its kind.
200b57cec5SDimitry Andric // - Its number of arguments (let say N).
210b57cec5SDimitry Andric // - Its arg1.
220b57cec5SDimitry Andric // - ...
230b57cec5SDimitry Andric // - Its argN.
240b57cec5SDimitry Andric // <arg1> to <argN> are absolute addresses in the object file, i.e.,
250b57cec5SDimitry Andric // relative addresses from the beginning of the object file.
emit_impl(const MCAssembler & Asm,raw_ostream & OutStream,const MachObjectWriter & ObjWriter) const26*0fca6ea1SDimitry Andric void MCLOHDirective::emit_impl(const MCAssembler &Asm, raw_ostream &OutStream,
27*0fca6ea1SDimitry Andric const MachObjectWriter &ObjWriter
28*0fca6ea1SDimitry Andric
29*0fca6ea1SDimitry Andric ) const {
300b57cec5SDimitry Andric encodeULEB128(Kind, OutStream);
310b57cec5SDimitry Andric encodeULEB128(Args.size(), OutStream);
320b57cec5SDimitry Andric for (const MCSymbol *Arg : Args)
33*0fca6ea1SDimitry Andric encodeULEB128(ObjWriter.getSymbolAddress(*Arg, Asm), OutStream);
340b57cec5SDimitry Andric }
350b57cec5SDimitry Andric
emit(const MCAssembler & Asm,MachObjectWriter & ObjWriter) const36*0fca6ea1SDimitry Andric void MCLOHDirective::emit(const MCAssembler &Asm,
37*0fca6ea1SDimitry Andric MachObjectWriter &ObjWriter) const {
380b57cec5SDimitry Andric raw_ostream &OutStream = ObjWriter.W.OS;
39*0fca6ea1SDimitry Andric emit_impl(Asm, OutStream, ObjWriter);
400b57cec5SDimitry Andric }
410b57cec5SDimitry Andric
getEmitSize(const MCAssembler & Asm,const MachObjectWriter & ObjWriter) const42*0fca6ea1SDimitry Andric uint64_t MCLOHDirective::getEmitSize(const MCAssembler &Asm,
43*0fca6ea1SDimitry Andric const MachObjectWriter &ObjWriter) const {
440b57cec5SDimitry Andric class raw_counting_ostream : public raw_ostream {
450b57cec5SDimitry Andric uint64_t Count = 0;
460b57cec5SDimitry Andric
470b57cec5SDimitry Andric void write_impl(const char *, size_t size) override { Count += size; }
480b57cec5SDimitry Andric
490b57cec5SDimitry Andric uint64_t current_pos() const override { return Count; }
500b57cec5SDimitry Andric
510b57cec5SDimitry Andric public:
520b57cec5SDimitry Andric raw_counting_ostream() = default;
530b57cec5SDimitry Andric ~raw_counting_ostream() override { flush(); }
540b57cec5SDimitry Andric };
550b57cec5SDimitry Andric
560b57cec5SDimitry Andric raw_counting_ostream OutStream;
57*0fca6ea1SDimitry Andric emit_impl(Asm, OutStream, ObjWriter);
580b57cec5SDimitry Andric return OutStream.tell();
590b57cec5SDimitry Andric }
60