/// \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); }