diff options
Diffstat (limited to 'lib/CodeGen/MIRParser/MIParser.cpp')
| -rw-r--r-- | lib/CodeGen/MIRParser/MIParser.cpp | 150 | 
1 files changed, 122 insertions, 28 deletions
diff --git a/lib/CodeGen/MIRParser/MIParser.cpp b/lib/CodeGen/MIRParser/MIParser.cpp index 1a78ae3aad07f..a61e7872f1ae1 100644 --- a/lib/CodeGen/MIRParser/MIParser.cpp +++ b/lib/CodeGen/MIRParser/MIParser.cpp @@ -98,6 +98,18 @@ VRegInfo &PerFunctionMIParsingState::getVRegInfo(unsigned Num) {    return *I.first->second;  } +VRegInfo &PerFunctionMIParsingState::getVRegInfoNamed(StringRef RegName) { +  assert(RegName != "" && "Expected named reg."); + +  auto I = VRegInfosNamed.insert(std::make_pair(RegName.str(), nullptr)); +  if (I.second) { +    VRegInfo *Info = new (Allocator) VRegInfo; +    Info->VReg = MF.getRegInfo().createIncompleteVirtualRegister(RegName); +    I.first->second = Info; +  } +  return *I.first->second; +} +  namespace {  /// A wrapper struct around the 'MachineOperand' struct that includes a source @@ -182,6 +194,7 @@ public:    bool parseNamedRegister(unsigned &Reg);    bool parseVirtualRegister(VRegInfo *&Info); +  bool parseNamedVirtualRegister(VRegInfo *&Info);    bool parseRegister(unsigned &Reg, VRegInfo *&VRegInfo);    bool parseRegisterFlag(unsigned &Flags);    bool parseRegisterClassOrBank(VRegInfo &RegInfo); @@ -190,7 +203,7 @@ public:    bool parseRegisterOperand(MachineOperand &Dest,                              Optional<unsigned> &TiedDefIdx, bool IsDef = false);    bool parseImmediateOperand(MachineOperand &Dest); -  bool parseIRConstant(StringRef::iterator Loc, StringRef Source, +  bool parseIRConstant(StringRef::iterator Loc, StringRef StringValue,                         const Constant *&C);    bool parseIRConstant(StringRef::iterator Loc, const Constant *&C);    bool parseLowLevelType(StringRef::iterator Loc, LLT &Ty); @@ -209,7 +222,7 @@ public:    bool parseJumpTableIndexOperand(MachineOperand &Dest);    bool parseExternalSymbolOperand(MachineOperand &Dest);    bool parseMDNode(MDNode *&Node); -  bool parseDIExpression(MDNode *&Node); +  bool parseDIExpression(MDNode *&Expr);    bool parseMetadataOperand(MachineOperand &Dest);    bool parseCFIOffset(int &Offset);    bool parseCFIRegister(unsigned &Reg); @@ -228,6 +241,7 @@ public:                                           Optional<unsigned> &TiedDefIdx);    bool parseOffset(int64_t &Offset);    bool parseAlignment(unsigned &Alignment); +  bool parseAddrspace(unsigned &Addrspace);    bool parseOperandsOffset(MachineOperand &Op);    bool parseIRValue(const Value *&V);    bool parseMemoryOperandFlag(MachineMemOperand::Flags &Flags); @@ -915,15 +929,43 @@ bool MIParser::verifyImplicitOperands(ArrayRef<ParsedMachineOperand> Operands,        continue;      return error(Operands.empty() ? Token.location() : Operands.back().End,                   Twine("missing implicit register operand '") + -                     printImplicitRegisterFlag(I) + " %" + +                     printImplicitRegisterFlag(I) + " $" +                       getRegisterName(TRI, I.getReg()) + "'");    }    return false;  }  bool MIParser::parseInstruction(unsigned &OpCode, unsigned &Flags) { -  if (Token.is(MIToken::kw_frame_setup)) { -    Flags |= MachineInstr::FrameSetup; +  // Allow frame and fast math flags for OPCODE +  while (Token.is(MIToken::kw_frame_setup) || +         Token.is(MIToken::kw_frame_destroy) || +         Token.is(MIToken::kw_nnan) || +         Token.is(MIToken::kw_ninf) || +         Token.is(MIToken::kw_nsz) || +         Token.is(MIToken::kw_arcp) || +         Token.is(MIToken::kw_contract) || +         Token.is(MIToken::kw_afn) || +         Token.is(MIToken::kw_reassoc)) { +    // Mine frame and fast math flags +    if (Token.is(MIToken::kw_frame_setup)) +      Flags |= MachineInstr::FrameSetup; +    if (Token.is(MIToken::kw_frame_destroy)) +      Flags |= MachineInstr::FrameDestroy; +    if (Token.is(MIToken::kw_nnan)) +      Flags |= MachineInstr::FmNoNans; +    if (Token.is(MIToken::kw_ninf)) +      Flags |= MachineInstr::FmNoInfs; +    if (Token.is(MIToken::kw_nsz)) +      Flags |= MachineInstr::FmNsz; +    if (Token.is(MIToken::kw_arcp)) +      Flags |= MachineInstr::FmArcp; +    if (Token.is(MIToken::kw_contract)) +      Flags |= MachineInstr::FmContract; +    if (Token.is(MIToken::kw_afn)) +      Flags |= MachineInstr::FmAfn; +    if (Token.is(MIToken::kw_reassoc)) +      Flags |= MachineInstr::FmReassoc; +      lex();    }    if (Token.isNot(MIToken::Identifier)) @@ -943,7 +985,18 @@ bool MIParser::parseNamedRegister(unsigned &Reg) {    return false;  } +bool MIParser::parseNamedVirtualRegister(VRegInfo *&Info) { +  assert(Token.is(MIToken::NamedVirtualRegister) && "Expected NamedVReg token"); +  StringRef Name = Token.stringValue(); +  // TODO: Check that the VReg name is not the same as a physical register name. +  //       If it is, then print a warning (when warnings are implemented). +  Info = &PFS.getVRegInfoNamed(Name); +  return false; +} +  bool MIParser::parseVirtualRegister(VRegInfo *&Info) { +  if (Token.is(MIToken::NamedVirtualRegister)) +    return parseNamedVirtualRegister(Info);    assert(Token.is(MIToken::VirtualRegister) && "Needs VirtualRegister token");    unsigned ID;    if (getUnsigned(ID)) @@ -959,6 +1012,7 @@ bool MIParser::parseRegister(unsigned &Reg, VRegInfo *&Info) {      return false;    case MIToken::NamedRegister:      return parseNamedRegister(Reg); +  case MIToken::NamedVirtualRegister:    case MIToken::VirtualRegister:      if (parseVirtualRegister(Info))        return true; @@ -1249,11 +1303,17 @@ bool MIParser::parseIRConstant(StringRef::iterator Loc, const Constant *&C) {  }  bool MIParser::parseLowLevelType(StringRef::iterator Loc, LLT &Ty) { -  if (Token.is(MIToken::ScalarType)) { +  if (Token.range().front() == 's' || Token.range().front() == 'p') { +    StringRef SizeStr = Token.range().drop_front(); +    if (SizeStr.size() == 0 || !llvm::all_of(SizeStr, isdigit)) +      return error("expected integers after 's'/'p' type character"); +  } + +  if (Token.range().front() == 's') {      Ty = LLT::scalar(APSInt(Token.range().drop_front()).getZExtValue());      lex();      return false; -  } else if (Token.is(MIToken::PointerType)) { +  } else if (Token.range().front() == 'p') {      const DataLayout &DL = MF.getDataLayout();      unsigned AS = APSInt(Token.range().drop_front()).getZExtValue();      Ty = LLT::pointer(AS, DL.getPointerSizeInBits(AS)); @@ -1264,38 +1324,60 @@ bool MIParser::parseLowLevelType(StringRef::iterator Loc, LLT &Ty) {    // Now we're looking for a vector.    if (Token.isNot(MIToken::less))      return error(Loc, -                 "expected unsized, pN, sN or <N x sM> for GlobalISel type"); - +                 "expected sN, pA, <M x sN>, or <M x pA> for GlobalISel type");    lex();    if (Token.isNot(MIToken::IntegerLiteral)) -    return error(Loc, "expected <N x sM> for vctor type"); +    return error(Loc, "expected <M x sN> or <M x pA> for vector type");    uint64_t NumElements = Token.integerValue().getZExtValue();    lex();    if (Token.isNot(MIToken::Identifier) || Token.stringValue() != "x") -    return error(Loc, "expected '<N x sM>' for vector type"); +    return error(Loc, "expected <M x sN> or <M x pA> for vector type");    lex(); -  if (Token.isNot(MIToken::ScalarType)) -    return error(Loc, "expected '<N x sM>' for vector type"); -  uint64_t ScalarSize = APSInt(Token.range().drop_front()).getZExtValue(); +  if (Token.range().front() != 's' && Token.range().front() != 'p') +    return error(Loc, "expected <M x sN> or <M x pA> for vector type"); +  StringRef SizeStr = Token.range().drop_front(); +  if (SizeStr.size() == 0 || !llvm::all_of(SizeStr, isdigit)) +    return error("expected integers after 's'/'p' type character"); + +  if (Token.range().front() == 's') +    Ty = LLT::scalar(APSInt(Token.range().drop_front()).getZExtValue()); +  else if (Token.range().front() == 'p') { +    const DataLayout &DL = MF.getDataLayout(); +    unsigned AS = APSInt(Token.range().drop_front()).getZExtValue(); +    Ty = LLT::pointer(AS, DL.getPointerSizeInBits(AS)); +  } else +    return error(Loc, "expected <M x sN> or <M x pA> for vector type");    lex();    if (Token.isNot(MIToken::greater)) -    return error(Loc, "expected '<N x sM>' for vector type"); +    return error(Loc, "expected <M x sN> or <M x pA> for vector type");    lex(); -  Ty = LLT::vector(NumElements, ScalarSize); +  Ty = LLT::vector(NumElements, Ty);    return false;  }  bool MIParser::parseTypedImmediateOperand(MachineOperand &Dest) { -  assert(Token.is(MIToken::IntegerType)); +  assert(Token.is(MIToken::Identifier)); +  StringRef TypeStr = Token.range(); +  if (TypeStr.front() != 'i' && TypeStr.front() != 's' && +      TypeStr.front() != 'p') +    return error( +        "a typed immediate operand should start with one of 'i', 's', or 'p'"); +  StringRef SizeStr = Token.range().drop_front(); +  if (SizeStr.size() == 0 || !llvm::all_of(SizeStr, isdigit)) +    return error("expected integers after 'i'/'s'/'p' type character"); +    auto Loc = Token.location();    lex(); -  if (Token.isNot(MIToken::IntegerLiteral)) -    return error("expected an integer literal"); +  if (Token.isNot(MIToken::IntegerLiteral)) { +    if (Token.isNot(MIToken::Identifier) || +        !(Token.range() == "true" || Token.range() == "false")) +      return error("expected an integer literal"); +  }    const Constant *C = nullptr;    if (parseIRConstant(Loc, C))      return true; @@ -1876,13 +1958,11 @@ bool MIParser::parseTargetIndexOperand(MachineOperand &Dest) {  bool MIParser::parseCustomRegisterMaskOperand(MachineOperand &Dest) {    assert(Token.stringValue() == "CustomRegMask" && "Expected a custom RegMask"); -  const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); -  assert(TRI && "Expected target register info");    lex();    if (expectAndConsume(MIToken::lparen))      return true; -  uint32_t *Mask = MF.allocateRegisterMask(TRI->getNumRegs()); +  uint32_t *Mask = MF.allocateRegMask();    while (true) {      if (Token.isNot(MIToken::NamedRegister))        return error("expected a named register"); @@ -1905,9 +1985,7 @@ bool MIParser::parseCustomRegisterMaskOperand(MachineOperand &Dest) {  bool MIParser::parseLiveoutRegisterMaskOperand(MachineOperand &Dest) {    assert(Token.is(MIToken::kw_liveout)); -  const auto *TRI = MF.getSubtarget().getRegisterInfo(); -  assert(TRI && "Expected target register info"); -  uint32_t *Mask = MF.allocateRegisterMask(TRI->getNumRegs()); +  uint32_t *Mask = MF.allocateRegMask();    lex();    if (expectAndConsume(MIToken::lparen))      return true; @@ -1946,11 +2024,10 @@ bool MIParser::parseMachineOperand(MachineOperand &Dest,    case MIToken::underscore:    case MIToken::NamedRegister:    case MIToken::VirtualRegister: +  case MIToken::NamedVirtualRegister:      return parseRegisterOperand(Dest, TiedDefIdx);    case MIToken::IntegerLiteral:      return parseImmediateOperand(Dest); -  case MIToken::IntegerType: -    return parseTypedImmediateOperand(Dest);    case MIToken::kw_half:    case MIToken::kw_float:    case MIToken::kw_double: @@ -2011,8 +2088,10 @@ bool MIParser::parseMachineOperand(MachineOperand &Dest,        Dest = MachineOperand::CreateRegMask(RegMask);        lex();        break; -    } else +    } else if (Token.stringValue() == "CustomRegMask") {        return parseCustomRegisterMaskOperand(Dest); +    } else +      return parseTypedImmediateOperand(Dest);    default:      // FIXME: Parse the MCSymbol machine operand.      return error("expected a machine operand"); @@ -2091,6 +2170,17 @@ bool MIParser::parseAlignment(unsigned &Alignment) {    return false;  } +bool MIParser::parseAddrspace(unsigned &Addrspace) { +  assert(Token.is(MIToken::kw_addrspace)); +  lex(); +  if (Token.isNot(MIToken::IntegerLiteral) || Token.integerValue().isSigned()) +    return error("expected an integer literal after 'addrspace'"); +  if (getUnsigned(Addrspace)) +    return true; +  lex(); +  return false; +} +  bool MIParser::parseOperandsOffset(MachineOperand &Op) {    int64_t Offset = 0;    if (parseOffset(Offset)) @@ -2402,6 +2492,10 @@ bool MIParser::parseMachineMemoryOperand(MachineMemOperand *&Dest) {        if (parseAlignment(BaseAlignment))          return true;        break; +    case MIToken::kw_addrspace: +      if (parseAddrspace(Ptr.AddrSpace)) +        return true; +      break;      case MIToken::md_tbaa:        lex();        if (parseMDNode(AAInfo.TBAA))  | 
