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