LLVM API Documentation

MCLinkerOptimizationHint.h
Go to the documentation of this file.
00001 //===- MCLinkerOptimizationHint.h - LOH interface ---------------*- C++ -*-===//
00002 //
00003 //
00004 //                     The LLVM Compiler Infrastructure
00005 //
00006 // This file is distributed under the University of Illinois Open Source
00007 // License. See LICENSE.TXT for details.
00008 //
00009 //===----------------------------------------------------------------------===//
00010 //
00011 // This file declares some helpers classes to handle Linker Optimization Hint
00012 // (LOH).
00013 //
00014 // FIXME: LOH interface supports only MachO format at the moment.
00015 //===----------------------------------------------------------------------===//
00016 
00017 #ifndef LLVM_MC_MCLINKEROPTIMIZATIONHINT_H
00018 #define LLVM_MC_MCLINKEROPTIMIZATIONHINT_H
00019 
00020 #include "llvm/ADT/SmallVector.h"
00021 #include "llvm/ADT/StringSwitch.h"
00022 #include "llvm/ADT/StringRef.h"
00023 #include "llvm/MC/MCMachObjectWriter.h"
00024 #include "llvm/Support/raw_ostream.h"
00025 
00026 namespace llvm {
00027 
00028 // Forward declarations.
00029 class MCAsmLayout;
00030 class MCSymbol;
00031 
00032 /// Linker Optimization Hint Type.
00033 enum MCLOHType {
00034   MCLOH_AdrpAdrp = 0x1u,      ///< Adrp xY, _v1@PAGE -> Adrp xY, _v2@PAGE.
00035   MCLOH_AdrpLdr = 0x2u,       ///< Adrp _v@PAGE -> Ldr _v@PAGEOFF.
00036   MCLOH_AdrpAddLdr = 0x3u,    ///< Adrp _v@PAGE -> Add _v@PAGEOFF -> Ldr.
00037   MCLOH_AdrpLdrGotLdr = 0x4u, ///< Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF -> Ldr.
00038   MCLOH_AdrpAddStr = 0x5u,    ///< Adrp _v@PAGE -> Add _v@PAGEOFF -> Str.
00039   MCLOH_AdrpLdrGotStr = 0x6u, ///< Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF -> Str.
00040   MCLOH_AdrpAdd = 0x7u,       ///< Adrp _v@PAGE -> Add _v@PAGEOFF.
00041   MCLOH_AdrpLdrGot = 0x8u     ///< Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF.
00042 };
00043 
00044 static inline StringRef MCLOHDirectiveName() {
00045   return StringRef(".loh");
00046 }
00047 
00048 static inline bool isValidMCLOHType(unsigned Kind) {
00049   return Kind >= MCLOH_AdrpAdrp && Kind <= MCLOH_AdrpLdrGot;
00050 }
00051 
00052 static inline int MCLOHNameToId(StringRef Name) {
00053 #define MCLOHCaseNameToId(Name)     .Case(#Name, MCLOH_ ## Name)
00054   return StringSwitch<int>(Name)
00055     MCLOHCaseNameToId(AdrpAdrp)
00056     MCLOHCaseNameToId(AdrpLdr)
00057     MCLOHCaseNameToId(AdrpAddLdr)
00058     MCLOHCaseNameToId(AdrpLdrGotLdr)
00059     MCLOHCaseNameToId(AdrpAddStr)
00060     MCLOHCaseNameToId(AdrpLdrGotStr)
00061     MCLOHCaseNameToId(AdrpAdd)
00062     MCLOHCaseNameToId(AdrpLdrGot)
00063     .Default(-1);
00064 }
00065 
00066 static inline StringRef MCLOHIdToName(MCLOHType Kind) {
00067 #define MCLOHCaseIdToName(Name)      case MCLOH_ ## Name: return StringRef(#Name);
00068   switch (Kind) {
00069     MCLOHCaseIdToName(AdrpAdrp);
00070     MCLOHCaseIdToName(AdrpLdr);
00071     MCLOHCaseIdToName(AdrpAddLdr);
00072     MCLOHCaseIdToName(AdrpLdrGotLdr);
00073     MCLOHCaseIdToName(AdrpAddStr);
00074     MCLOHCaseIdToName(AdrpLdrGotStr);
00075     MCLOHCaseIdToName(AdrpAdd);
00076     MCLOHCaseIdToName(AdrpLdrGot);
00077   }
00078   return StringRef();
00079 }
00080 
00081 static inline int MCLOHIdToNbArgs(MCLOHType Kind) {
00082   switch (Kind) {
00083     // LOH with two arguments
00084   case MCLOH_AdrpAdrp:
00085   case MCLOH_AdrpLdr:
00086   case MCLOH_AdrpAdd:
00087   case MCLOH_AdrpLdrGot:
00088     return 2;
00089     // LOH with three arguments
00090   case MCLOH_AdrpAddLdr:
00091   case MCLOH_AdrpLdrGotLdr:
00092   case MCLOH_AdrpAddStr:
00093   case MCLOH_AdrpLdrGotStr:
00094     return 3;
00095   }
00096   return -1;
00097 }
00098 
00099 /// Store Linker Optimization Hint information (LOH).
00100 class MCLOHDirective {
00101   MCLOHType Kind;
00102 
00103   /// Arguments of this directive. Order matters.
00104   SmallVector<MCSymbol *, 3> Args;
00105 
00106   /// Emit this directive in @p OutStream using the information available
00107   /// in the given @p ObjWriter and @p Layout to get the address of the
00108   /// arguments within the object file.
00109   void Emit_impl(raw_ostream &OutStream, const MachObjectWriter &ObjWriter,
00110                  const MCAsmLayout &Layout) const;
00111 
00112 public:
00113   typedef SmallVectorImpl<MCSymbol *> LOHArgs;
00114 
00115   MCLOHDirective(MCLOHType Kind, const LOHArgs &Args)
00116       : Kind(Kind), Args(Args.begin(), Args.end()) {
00117     assert(isValidMCLOHType(Kind) && "Invalid LOH directive type!");
00118   }
00119 
00120   MCLOHType getKind() const { return Kind; }
00121 
00122   const LOHArgs &getArgs() const { return Args; }
00123 
00124   /// Emit this directive as:
00125   /// <kind, numArgs, addr1, ..., addrN>
00126   void Emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const {
00127     raw_ostream &OutStream = ObjWriter.getStream();
00128     Emit_impl(OutStream, ObjWriter, Layout);
00129   }
00130 
00131   /// Get the size in bytes of this directive if emitted in @p ObjWriter with
00132   /// the given @p Layout.
00133   uint64_t getEmitSize(const MachObjectWriter &ObjWriter,
00134                        const MCAsmLayout &Layout) const {
00135     class raw_counting_ostream : public raw_ostream {
00136       uint64_t Count;
00137 
00138       void write_impl(const char *, size_t size) override { Count += size; }
00139 
00140       uint64_t current_pos() const override { return Count; }
00141 
00142     public:
00143       raw_counting_ostream() : Count(0) {}
00144       ~raw_counting_ostream() { flush(); }
00145     };
00146 
00147     raw_counting_ostream OutStream;
00148     Emit_impl(OutStream, ObjWriter, Layout);
00149     return OutStream.tell();
00150   }
00151 };
00152 
00153 class MCLOHContainer {
00154   /// Keep track of the emit size of all the LOHs.
00155   mutable uint64_t EmitSize;
00156 
00157   /// Keep track of all LOH directives.
00158   SmallVector<MCLOHDirective, 32> Directives;
00159 
00160 public:
00161   typedef SmallVectorImpl<MCLOHDirective> LOHDirectives;
00162 
00163   MCLOHContainer() : EmitSize(0) {};
00164 
00165   /// Const accessor to the directives.
00166   const LOHDirectives &getDirectives() const {
00167     return Directives;
00168   }
00169 
00170   /// Add the directive of the given kind @p Kind with the given arguments
00171   /// @p Args to the container.
00172   void addDirective(MCLOHType Kind, const MCLOHDirective::LOHArgs &Args) {
00173     Directives.push_back(MCLOHDirective(Kind, Args));
00174   }
00175 
00176   /// Get the size of the directives if emitted.
00177   uint64_t getEmitSize(const MachObjectWriter &ObjWriter,
00178                        const MCAsmLayout &Layout) const {
00179     if (!EmitSize) {
00180       for (const MCLOHDirective &D : Directives)
00181         EmitSize += D.getEmitSize(ObjWriter, Layout);
00182     }
00183     return EmitSize;
00184   }
00185 
00186   /// Emit all Linker Optimization Hint in one big table.
00187   /// Each line of the table is emitted by LOHDirective::Emit.
00188   void Emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const {
00189     for (const MCLOHDirective &D : Directives)
00190       D.Emit(ObjWriter, Layout);
00191   }
00192 
00193   void reset() {
00194     Directives.clear();
00195     EmitSize = 0;
00196   }
00197 };
00198 
00199 // Add types for specialized template using MCSymbol.
00200 typedef MCLOHDirective::LOHArgs MCLOHArgs;
00201 typedef MCLOHContainer::LOHDirectives MCLOHDirectives;
00202 
00203 } // end namespace llvm
00204 
00205 #endif