Esempio n. 1
0
/// \brief Parse a C++ template template argument.
ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
  if (!Tok.is(tok::identifier) && !Tok.is(tok::coloncolon) &&
      !Tok.is(tok::annot_cxxscope))
    return ParsedTemplateArgument();

  // C++0x [temp.arg.template]p1:
  //   A template-argument for a template template-parameter shall be the name
  //   of a class template or a template alias, expressed as id-expression.
  //   
  // We parse an id-expression that refers to a class template or template
  // alias. The grammar we parse is:
  //
  //   nested-name-specifier[opt] template[opt] identifier ...[opt]
  //
  // followed by a token that terminates a template argument, such as ',', 
  // '>', or (in some cases) '>>'.
  CXXScopeSpec SS; // nested-name-specifier, if present
  ParseOptionalCXXScopeSpecifier(SS, ParsedType(),
                                 /*EnteringContext=*/false);
  
  ParsedTemplateArgument Result;
  SourceLocation EllipsisLoc;
  if (SS.isSet() && Tok.is(tok::kw_template)) {
    // Parse the optional 'template' keyword following the 
    // nested-name-specifier.
    SourceLocation TemplateLoc = ConsumeToken();
    
    if (Tok.is(tok::identifier)) {
      // We appear to have a dependent template name.
      UnqualifiedId Name;
      Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
      ConsumeToken(); // the identifier
      
      // Parse the ellipsis.
      if (Tok.is(tok::ellipsis))
        EllipsisLoc = ConsumeToken();
      
      // If the next token signals the end of a template argument,
      // then we have a dependent template name that could be a template
      // template argument.
      TemplateTy Template;
      if (isEndOfTemplateArgument(Tok) &&
          Actions.ActOnDependentTemplateName(getCurScope(), TemplateLoc,
                                             SS, Name, 
                                             /*ObjectType=*/ ParsedType(),
                                             /*EnteringContext=*/false,
                                             Template))
        Result = ParsedTemplateArgument(SS, Template, Name.StartLocation);
    }
  } else if (Tok.is(tok::identifier)) {
    // We may have a (non-dependent) template name.
    TemplateTy Template;
    UnqualifiedId Name;
    Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
    ConsumeToken(); // the identifier
    
    // Parse the ellipsis.
    if (Tok.is(tok::ellipsis))
      EllipsisLoc = ConsumeToken();

    if (isEndOfTemplateArgument(Tok)) {
      bool MemberOfUnknownSpecialization;
      TemplateNameKind TNK = Actions.isTemplateName(getCurScope(), SS,
                                               /*hasTemplateKeyword=*/false,
                                                    Name,
                                               /*ObjectType=*/ ParsedType(), 
                                                    /*EnteringContext=*/false, 
                                                    Template,
                                                MemberOfUnknownSpecialization);
      if (TNK == TNK_Dependent_template_name || TNK == TNK_Type_template) {
        // We have an id-expression that refers to a class template or
        // (C++0x) template alias. 
        Result = ParsedTemplateArgument(SS, Template, Name.StartLocation);
      }
    }
  }
  
  // If this is a pack expansion, build it as such.
  if (EllipsisLoc.isValid() && !Result.isInvalid())
    Result = Actions.ActOnPackExpansion(Result, EllipsisLoc);
  
  return Result;
}
StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc,
                                SourceLocation LBraceLoc,
                                ArrayRef<Token> AsmToks,
                                SourceLocation EndLoc) {
  SmallVector<StringRef,4> Clobbers;
  std::set<std::string> ClobberRegs;
  SmallVector<IdentifierInfo*, 4> Inputs;
  SmallVector<IdentifierInfo*, 4> Outputs;
  SmallVector<Expr*, 4> InputExprs;
  SmallVector<Expr*, 4> OutputExprs;

  // Empty asm statements don't need to instantiate the AsmParser, etc.
  if (AsmToks.empty()) {
    StringRef AsmString;
    DEF_SIMPLE_MSASM;
    return Owned(NS);
  }

  std::vector<std::string> AsmStrings;
  std::vector<std::pair<unsigned,unsigned> > AsmTokRanges;
  std::string AsmString = buildMSAsmString(*this, AsmToks, AsmStrings,
                                           AsmTokRanges);

  std::vector<std::vector<StringRef> > Pieces(AsmStrings.size());
  buildMSAsmPieces(AsmStrings, Pieces);

  bool IsSimple = isSimpleMSAsm(Pieces, Context.getTargetInfo());

  // AsmParser doesn't fully support these asm statements.
  if (bailOnMSAsm(Pieces)) { DEF_SIMPLE_MSASM; return Owned(NS); }

  // Initialize targets and assembly printers/parsers.
  llvm::InitializeAllTargetInfos();
  llvm::InitializeAllTargetMCs();
  llvm::InitializeAllAsmParsers();

  // Get the target specific parser.
  std::string Error;
  const std::string &TT = Context.getTargetInfo().getTriple().getTriple();
  const llvm::Target *TheTarget(llvm::TargetRegistry::lookupTarget(TT, Error));

  OwningPtr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TT));
  OwningPtr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT));
  OwningPtr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo());
  OwningPtr<llvm::MCSubtargetInfo>
    STI(TheTarget->createMCSubtargetInfo(TT, "", ""));

  for (unsigned StrIdx = 0, e = AsmStrings.size(); StrIdx != e; ++StrIdx) {
    llvm::SourceMgr SrcMgr;
    llvm::MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr);
    llvm::MemoryBuffer *Buffer =
      llvm::MemoryBuffer::getMemBuffer(AsmStrings[StrIdx], "<inline asm>");

    // Tell SrcMgr about this buffer, which is what the parser will pick up.
    SrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc());

    OwningPtr<llvm::MCStreamer> Str(createNullStreamer(Ctx));
    OwningPtr<llvm::MCAsmParser>
      Parser(createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI));
    OwningPtr<llvm::MCTargetAsmParser>
      TargetParser(TheTarget->createMCAsmParser(*STI, *Parser));
    // Change to the Intel dialect.
    Parser->setAssemblerDialect(1);
    Parser->setTargetParser(*TargetParser.get());

    // Prime the lexer.
    Parser->Lex();

    // Parse the opcode.
    StringRef IDVal;
    Parser->ParseIdentifier(IDVal);

    // Canonicalize the opcode to lower case.
    SmallString<128> Opcode;
    for (unsigned j = 0, e = IDVal.size(); j != e; ++j)
      Opcode.push_back(tolower(IDVal[j]));

    // Parse the operands.
    llvm::SMLoc IDLoc;
    SmallVector<llvm::MCParsedAsmOperand*, 8> Operands;
    bool HadError = TargetParser->ParseInstruction(Opcode.str(), IDLoc,
                                                   Operands);
    // If we had an error parsing the operands, fail gracefully.
    if (HadError) { DEF_SIMPLE_MSASM; return Owned(NS); }

    // Match the MCInstr.
    unsigned ErrorInfo;
    SmallVector<llvm::MCInst, 2> Instrs;
    HadError = TargetParser->MatchInstruction(IDLoc, Operands, Instrs,
                                              ErrorInfo,
                                              /*matchingInlineAsm*/ true);
    // If we had an error parsing the operands, fail gracefully.
    if (HadError) { DEF_SIMPLE_MSASM; return Owned(NS); }

    // Get the instruction descriptor.
    llvm::MCInst Inst = Instrs[0];
    const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo();
    const llvm::MCInstrDesc &Desc = MII->get(Inst.getOpcode());
    llvm::MCInstPrinter *IP =
      TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI);

    // Build the list of clobbers, outputs and inputs.
    unsigned NumDefs = Desc.getNumDefs();
    for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i) {
      const llvm::MCOperand &Op = Inst.getOperand(i);

      // Immediate.
      if (Op.isImm() || Op.isFPImm())
        continue;

      bool isDef = NumDefs && (i < NumDefs);

      // Register/Clobber.
      if (Op.isReg() && isDef) {
        std::string Reg;
        llvm::raw_string_ostream OS(Reg);
        IP->printRegName(OS, Op.getReg());

        StringRef Clobber(OS.str());
        if (!Context.getTargetInfo().isValidClobber(Clobber))
          return StmtError(Diag(AsmLoc, diag::err_asm_unknown_register_name) <<
                           Clobber);
        ClobberRegs.insert(Reg);
        continue;
      }
      // Expr/Input or Output.
      if (Op.isExpr()) {
        const llvm::MCExpr *Expr = Op.getExpr();
        const llvm::MCSymbolRefExpr *SymRef;
        if ((SymRef = dyn_cast<llvm::MCSymbolRefExpr>(Expr))) {
          StringRef Name = SymRef->getSymbol().getName();
          IdentifierInfo *II = getIdentifierInfo(Name, AsmToks,
                                                 AsmTokRanges[StrIdx].first,
                                                 AsmTokRanges[StrIdx].second);
          if (II) {
            CXXScopeSpec SS;
            UnqualifiedId Id;
            SourceLocation Loc;
            Id.setIdentifier(II, AsmLoc);
            ExprResult Result = ActOnIdExpression(getCurScope(), SS, Loc, Id,
                                                  false, false);
            if (!Result.isInvalid()) {
              if (isDef) {
                Outputs.push_back(II);
                OutputExprs.push_back(Result.take());
              } else {
                Inputs.push_back(II);
                InputExprs.push_back(Result.take());
              }
            }
          }
        }
      }
    }
  }
  for (std::set<std::string>::iterator I = ClobberRegs.begin(),
         E = ClobberRegs.end(); I != E; ++I)
    Clobbers.push_back(*I);

  MSAsmStmt *NS =
    new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple,
                            /*IsVolatile*/ true, AsmToks, Inputs, Outputs,
                            InputExprs, OutputExprs, AsmString, Clobbers,
                            EndLoc);
  return Owned(NS);
}