Home | History | Annotate | Download | only in CodeGen
      1 //===- MIRYAMLMapping.h - Describes the mapping between MIR and YAML ------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // The MIR serialization library is currently a work in progress. It can't
     11 // serialize machine functions at this time.
     12 //
     13 // This file implements the mapping between various MIR data structures and
     14 // their corresponding YAML representation.
     15 //
     16 //===----------------------------------------------------------------------===//
     17 
     18 #ifndef LLVM_LIB_CODEGEN_MIRYAMLMAPPING_H
     19 #define LLVM_LIB_CODEGEN_MIRYAMLMAPPING_H
     20 
     21 #include "llvm/ADT/StringRef.h"
     22 #include "llvm/CodeGen/MachineJumpTableInfo.h"
     23 #include "llvm/Support/YAMLTraits.h"
     24 #include <vector>
     25 
     26 namespace llvm {
     27 namespace yaml {
     28 
     29 /// A wrapper around std::string which contains a source range that's being
     30 /// set during parsing.
     31 struct StringValue {
     32   std::string Value;
     33   SMRange SourceRange;
     34 
     35   StringValue() {}
     36   StringValue(std::string Value) : Value(std::move(Value)) {}
     37 
     38   bool operator==(const StringValue &Other) const {
     39     return Value == Other.Value;
     40   }
     41 };
     42 
     43 template <> struct ScalarTraits<StringValue> {
     44   static void output(const StringValue &S, void *, llvm::raw_ostream &OS) {
     45     OS << S.Value;
     46   }
     47 
     48   static StringRef input(StringRef Scalar, void *Ctx, StringValue &S) {
     49     S.Value = Scalar.str();
     50     if (const auto *Node =
     51             reinterpret_cast<yaml::Input *>(Ctx)->getCurrentNode())
     52       S.SourceRange = Node->getSourceRange();
     53     return "";
     54   }
     55 
     56   static bool mustQuote(StringRef Scalar) { return needsQuotes(Scalar); }
     57 };
     58 
     59 struct FlowStringValue : StringValue {
     60   FlowStringValue() {}
     61   FlowStringValue(std::string Value) : StringValue(Value) {}
     62 };
     63 
     64 template <> struct ScalarTraits<FlowStringValue> {
     65   static void output(const FlowStringValue &S, void *, llvm::raw_ostream &OS) {
     66     return ScalarTraits<StringValue>::output(S, nullptr, OS);
     67   }
     68 
     69   static StringRef input(StringRef Scalar, void *Ctx, FlowStringValue &S) {
     70     return ScalarTraits<StringValue>::input(Scalar, Ctx, S);
     71   }
     72 
     73   static bool mustQuote(StringRef Scalar) { return needsQuotes(Scalar); }
     74 };
     75 
     76 struct BlockStringValue {
     77   StringValue Value;
     78 };
     79 
     80 template <> struct BlockScalarTraits<BlockStringValue> {
     81   static void output(const BlockStringValue &S, void *Ctx, raw_ostream &OS) {
     82     return ScalarTraits<StringValue>::output(S.Value, Ctx, OS);
     83   }
     84 
     85   static StringRef input(StringRef Scalar, void *Ctx, BlockStringValue &S) {
     86     return ScalarTraits<StringValue>::input(Scalar, Ctx, S.Value);
     87   }
     88 };
     89 
     90 /// A wrapper around unsigned which contains a source range that's being set
     91 /// during parsing.
     92 struct UnsignedValue {
     93   unsigned Value;
     94   SMRange SourceRange;
     95 
     96   UnsignedValue() : Value(0) {}
     97   UnsignedValue(unsigned Value) : Value(Value) {}
     98 
     99   bool operator==(const UnsignedValue &Other) const {
    100     return Value == Other.Value;
    101   }
    102 };
    103 
    104 template <> struct ScalarTraits<UnsignedValue> {
    105   static void output(const UnsignedValue &Value, void *Ctx, raw_ostream &OS) {
    106     return ScalarTraits<unsigned>::output(Value.Value, Ctx, OS);
    107   }
    108 
    109   static StringRef input(StringRef Scalar, void *Ctx, UnsignedValue &Value) {
    110     if (const auto *Node =
    111             reinterpret_cast<yaml::Input *>(Ctx)->getCurrentNode())
    112       Value.SourceRange = Node->getSourceRange();
    113     return ScalarTraits<unsigned>::input(Scalar, Ctx, Value.Value);
    114   }
    115 
    116   static bool mustQuote(StringRef Scalar) {
    117     return ScalarTraits<unsigned>::mustQuote(Scalar);
    118   }
    119 };
    120 
    121 template <> struct ScalarEnumerationTraits<MachineJumpTableInfo::JTEntryKind> {
    122   static void enumeration(yaml::IO &IO,
    123                           MachineJumpTableInfo::JTEntryKind &EntryKind) {
    124     IO.enumCase(EntryKind, "block-address",
    125                 MachineJumpTableInfo::EK_BlockAddress);
    126     IO.enumCase(EntryKind, "gp-rel64-block-address",
    127                 MachineJumpTableInfo::EK_GPRel64BlockAddress);
    128     IO.enumCase(EntryKind, "gp-rel32-block-address",
    129                 MachineJumpTableInfo::EK_GPRel32BlockAddress);
    130     IO.enumCase(EntryKind, "label-difference32",
    131                 MachineJumpTableInfo::EK_LabelDifference32);
    132     IO.enumCase(EntryKind, "inline", MachineJumpTableInfo::EK_Inline);
    133     IO.enumCase(EntryKind, "custom32", MachineJumpTableInfo::EK_Custom32);
    134   }
    135 };
    136 
    137 } // end namespace yaml
    138 } // end namespace llvm
    139 
    140 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::StringValue)
    141 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::FlowStringValue)
    142 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::UnsignedValue)
    143 
    144 namespace llvm {
    145 namespace yaml {
    146 
    147 struct VirtualRegisterDefinition {
    148   UnsignedValue ID;
    149   StringValue Class;
    150   StringValue PreferredRegister;
    151   // TODO: Serialize the target specific register hints.
    152 };
    153 
    154 template <> struct MappingTraits<VirtualRegisterDefinition> {
    155   static void mapping(IO &YamlIO, VirtualRegisterDefinition &Reg) {
    156     YamlIO.mapRequired("id", Reg.ID);
    157     YamlIO.mapRequired("class", Reg.Class);
    158     YamlIO.mapOptional("preferred-register", Reg.PreferredRegister,
    159                        StringValue()); // Don't print out when it's empty.
    160   }
    161 
    162   static const bool flow = true;
    163 };
    164 
    165 struct MachineFunctionLiveIn {
    166   StringValue Register;
    167   StringValue VirtualRegister;
    168 };
    169 
    170 template <> struct MappingTraits<MachineFunctionLiveIn> {
    171   static void mapping(IO &YamlIO, MachineFunctionLiveIn &LiveIn) {
    172     YamlIO.mapRequired("reg", LiveIn.Register);
    173     YamlIO.mapOptional(
    174         "virtual-reg", LiveIn.VirtualRegister,
    175         StringValue()); // Don't print the virtual register when it's empty.
    176   }
    177 
    178   static const bool flow = true;
    179 };
    180 
    181 /// Serializable representation of stack object from the MachineFrameInfo class.
    182 ///
    183 /// The flags 'isImmutable' and 'isAliased' aren't serialized, as they are
    184 /// determined by the object's type and frame information flags.
    185 /// Dead stack objects aren't serialized.
    186 ///
    187 /// The 'isPreallocated' flag is determined by the local offset.
    188 struct MachineStackObject {
    189   enum ObjectType { DefaultType, SpillSlot, VariableSized };
    190   UnsignedValue ID;
    191   StringValue Name;
    192   // TODO: Serialize unnamed LLVM alloca reference.
    193   ObjectType Type = DefaultType;
    194   int64_t Offset = 0;
    195   uint64_t Size = 0;
    196   unsigned Alignment = 0;
    197   StringValue CalleeSavedRegister;
    198   Optional<int64_t> LocalOffset;
    199   StringValue DebugVar;
    200   StringValue DebugExpr;
    201   StringValue DebugLoc;
    202 };
    203 
    204 template <> struct ScalarEnumerationTraits<MachineStackObject::ObjectType> {
    205   static void enumeration(yaml::IO &IO, MachineStackObject::ObjectType &Type) {
    206     IO.enumCase(Type, "default", MachineStackObject::DefaultType);
    207     IO.enumCase(Type, "spill-slot", MachineStackObject::SpillSlot);
    208     IO.enumCase(Type, "variable-sized", MachineStackObject::VariableSized);
    209   }
    210 };
    211 
    212 template <> struct MappingTraits<MachineStackObject> {
    213   static void mapping(yaml::IO &YamlIO, MachineStackObject &Object) {
    214     YamlIO.mapRequired("id", Object.ID);
    215     YamlIO.mapOptional("name", Object.Name,
    216                        StringValue()); // Don't print out an empty name.
    217     YamlIO.mapOptional(
    218         "type", Object.Type,
    219         MachineStackObject::DefaultType); // Don't print the default type.
    220     YamlIO.mapOptional("offset", Object.Offset);
    221     if (Object.Type != MachineStackObject::VariableSized)
    222       YamlIO.mapRequired("size", Object.Size);
    223     YamlIO.mapOptional("alignment", Object.Alignment);
    224     YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister,
    225                        StringValue()); // Don't print it out when it's empty.
    226     YamlIO.mapOptional("local-offset", Object.LocalOffset);
    227     YamlIO.mapOptional("di-variable", Object.DebugVar,
    228                        StringValue()); // Don't print it out when it's empty.
    229     YamlIO.mapOptional("di-expression", Object.DebugExpr,
    230                        StringValue()); // Don't print it out when it's empty.
    231     YamlIO.mapOptional("di-location", Object.DebugLoc,
    232                        StringValue()); // Don't print it out when it's empty.
    233   }
    234 
    235   static const bool flow = true;
    236 };
    237 
    238 /// Serializable representation of the fixed stack object from the
    239 /// MachineFrameInfo class.
    240 struct FixedMachineStackObject {
    241   enum ObjectType { DefaultType, SpillSlot };
    242   UnsignedValue ID;
    243   ObjectType Type = DefaultType;
    244   int64_t Offset = 0;
    245   uint64_t Size = 0;
    246   unsigned Alignment = 0;
    247   bool IsImmutable = false;
    248   bool IsAliased = false;
    249   StringValue CalleeSavedRegister;
    250 };
    251 
    252 template <>
    253 struct ScalarEnumerationTraits<FixedMachineStackObject::ObjectType> {
    254   static void enumeration(yaml::IO &IO,
    255                           FixedMachineStackObject::ObjectType &Type) {
    256     IO.enumCase(Type, "default", FixedMachineStackObject::DefaultType);
    257     IO.enumCase(Type, "spill-slot", FixedMachineStackObject::SpillSlot);
    258   }
    259 };
    260 
    261 template <> struct MappingTraits<FixedMachineStackObject> {
    262   static void mapping(yaml::IO &YamlIO, FixedMachineStackObject &Object) {
    263     YamlIO.mapRequired("id", Object.ID);
    264     YamlIO.mapOptional(
    265         "type", Object.Type,
    266         FixedMachineStackObject::DefaultType); // Don't print the default type.
    267     YamlIO.mapOptional("offset", Object.Offset);
    268     YamlIO.mapOptional("size", Object.Size);
    269     YamlIO.mapOptional("alignment", Object.Alignment);
    270     if (Object.Type != FixedMachineStackObject::SpillSlot) {
    271       YamlIO.mapOptional("isImmutable", Object.IsImmutable);
    272       YamlIO.mapOptional("isAliased", Object.IsAliased);
    273     }
    274     YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister,
    275                        StringValue()); // Don't print it out when it's empty.
    276   }
    277 
    278   static const bool flow = true;
    279 };
    280 
    281 struct MachineConstantPoolValue {
    282   UnsignedValue ID;
    283   StringValue Value;
    284   unsigned Alignment = 0;
    285 };
    286 
    287 template <> struct MappingTraits<MachineConstantPoolValue> {
    288   static void mapping(IO &YamlIO, MachineConstantPoolValue &Constant) {
    289     YamlIO.mapRequired("id", Constant.ID);
    290     YamlIO.mapOptional("value", Constant.Value);
    291     YamlIO.mapOptional("alignment", Constant.Alignment);
    292   }
    293 };
    294 
    295 struct MachineJumpTable {
    296   struct Entry {
    297     UnsignedValue ID;
    298     std::vector<FlowStringValue> Blocks;
    299   };
    300 
    301   MachineJumpTableInfo::JTEntryKind Kind = MachineJumpTableInfo::EK_Custom32;
    302   std::vector<Entry> Entries;
    303 };
    304 
    305 template <> struct MappingTraits<MachineJumpTable::Entry> {
    306   static void mapping(IO &YamlIO, MachineJumpTable::Entry &Entry) {
    307     YamlIO.mapRequired("id", Entry.ID);
    308     YamlIO.mapOptional("blocks", Entry.Blocks);
    309   }
    310 };
    311 
    312 } // end namespace yaml
    313 } // end namespace llvm
    314 
    315 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineFunctionLiveIn)
    316 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::VirtualRegisterDefinition)
    317 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineStackObject)
    318 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::FixedMachineStackObject)
    319 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineConstantPoolValue)
    320 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineJumpTable::Entry)
    321 
    322 namespace llvm {
    323 namespace yaml {
    324 
    325 template <> struct MappingTraits<MachineJumpTable> {
    326   static void mapping(IO &YamlIO, MachineJumpTable &JT) {
    327     YamlIO.mapRequired("kind", JT.Kind);
    328     YamlIO.mapOptional("entries", JT.Entries);
    329   }
    330 };
    331 
    332 /// Serializable representation of MachineFrameInfo.
    333 ///
    334 /// Doesn't serialize attributes like 'StackAlignment', 'IsStackRealignable' and
    335 /// 'RealignOption' as they are determined by the target and LLVM function
    336 /// attributes.
    337 /// It also doesn't serialize attributes like 'NumFixedObject' and
    338 /// 'HasVarSizedObjects' as they are determined by the frame objects themselves.
    339 struct MachineFrameInfo {
    340   bool IsFrameAddressTaken = false;
    341   bool IsReturnAddressTaken = false;
    342   bool HasStackMap = false;
    343   bool HasPatchPoint = false;
    344   uint64_t StackSize = 0;
    345   int OffsetAdjustment = 0;
    346   unsigned MaxAlignment = 0;
    347   bool AdjustsStack = false;
    348   bool HasCalls = false;
    349   StringValue StackProtector;
    350   // TODO: Serialize FunctionContextIdx
    351   unsigned MaxCallFrameSize = 0;
    352   bool HasOpaqueSPAdjustment = false;
    353   bool HasVAStart = false;
    354   bool HasMustTailInVarArgFunc = false;
    355   StringValue SavePoint;
    356   StringValue RestorePoint;
    357 };
    358 
    359 template <> struct MappingTraits<MachineFrameInfo> {
    360   static void mapping(IO &YamlIO, MachineFrameInfo &MFI) {
    361     YamlIO.mapOptional("isFrameAddressTaken", MFI.IsFrameAddressTaken);
    362     YamlIO.mapOptional("isReturnAddressTaken", MFI.IsReturnAddressTaken);
    363     YamlIO.mapOptional("hasStackMap", MFI.HasStackMap);
    364     YamlIO.mapOptional("hasPatchPoint", MFI.HasPatchPoint);
    365     YamlIO.mapOptional("stackSize", MFI.StackSize);
    366     YamlIO.mapOptional("offsetAdjustment", MFI.OffsetAdjustment);
    367     YamlIO.mapOptional("maxAlignment", MFI.MaxAlignment);
    368     YamlIO.mapOptional("adjustsStack", MFI.AdjustsStack);
    369     YamlIO.mapOptional("hasCalls", MFI.HasCalls);
    370     YamlIO.mapOptional("stackProtector", MFI.StackProtector,
    371                        StringValue()); // Don't print it out when it's empty.
    372     YamlIO.mapOptional("maxCallFrameSize", MFI.MaxCallFrameSize);
    373     YamlIO.mapOptional("hasOpaqueSPAdjustment", MFI.HasOpaqueSPAdjustment);
    374     YamlIO.mapOptional("hasVAStart", MFI.HasVAStart);
    375     YamlIO.mapOptional("hasMustTailInVarArgFunc", MFI.HasMustTailInVarArgFunc);
    376     YamlIO.mapOptional("savePoint", MFI.SavePoint,
    377                        StringValue()); // Don't print it out when it's empty.
    378     YamlIO.mapOptional("restorePoint", MFI.RestorePoint,
    379                        StringValue()); // Don't print it out when it's empty.
    380   }
    381 };
    382 
    383 struct MachineFunction {
    384   StringRef Name;
    385   unsigned Alignment = 0;
    386   bool ExposesReturnsTwice = false;
    387   bool HasInlineAsm = false;
    388   // Register information
    389   bool IsSSA = false;
    390   bool TracksRegLiveness = false;
    391   bool TracksSubRegLiveness = false;
    392   std::vector<VirtualRegisterDefinition> VirtualRegisters;
    393   std::vector<MachineFunctionLiveIn> LiveIns;
    394   Optional<std::vector<FlowStringValue>> CalleeSavedRegisters;
    395   // TODO: Serialize the various register masks.
    396   // Frame information
    397   MachineFrameInfo FrameInfo;
    398   std::vector<FixedMachineStackObject> FixedStackObjects;
    399   std::vector<MachineStackObject> StackObjects;
    400   std::vector<MachineConstantPoolValue> Constants; /// Constant pool.
    401   MachineJumpTable JumpTableInfo;
    402   BlockStringValue Body;
    403 };
    404 
    405 template <> struct MappingTraits<MachineFunction> {
    406   static void mapping(IO &YamlIO, MachineFunction &MF) {
    407     YamlIO.mapRequired("name", MF.Name);
    408     YamlIO.mapOptional("alignment", MF.Alignment);
    409     YamlIO.mapOptional("exposesReturnsTwice", MF.ExposesReturnsTwice);
    410     YamlIO.mapOptional("hasInlineAsm", MF.HasInlineAsm);
    411     YamlIO.mapOptional("isSSA", MF.IsSSA);
    412     YamlIO.mapOptional("tracksRegLiveness", MF.TracksRegLiveness);
    413     YamlIO.mapOptional("tracksSubRegLiveness", MF.TracksSubRegLiveness);
    414     YamlIO.mapOptional("registers", MF.VirtualRegisters);
    415     YamlIO.mapOptional("liveins", MF.LiveIns);
    416     YamlIO.mapOptional("calleeSavedRegisters", MF.CalleeSavedRegisters);
    417     YamlIO.mapOptional("frameInfo", MF.FrameInfo);
    418     YamlIO.mapOptional("fixedStack", MF.FixedStackObjects);
    419     YamlIO.mapOptional("stack", MF.StackObjects);
    420     YamlIO.mapOptional("constants", MF.Constants);
    421     if (!YamlIO.outputting() || !MF.JumpTableInfo.Entries.empty())
    422       YamlIO.mapOptional("jumpTable", MF.JumpTableInfo);
    423     YamlIO.mapOptional("body", MF.Body);
    424   }
    425 };
    426 
    427 } // end namespace yaml
    428 } // end namespace llvm
    429 
    430 #endif
    431