xref: /freebsd/contrib/llvm-project/llvm/lib/MC/MCLinkerOptimizationHint.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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