ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS, SourceLocation TemplateKWLoc, UnqualifiedId &Id, llvm::InlineAsmIdentifierInfo &Info, bool IsUnevaluatedContext) { Info.clear(); if (IsUnevaluatedContext) PushExpressionEvaluationContext(UnevaluatedAbstract, ReuseLambdaContextDecl); ExprResult Result = ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Id, /*trailing lparen*/ false, /*is & operand*/ false, /*CorrectionCandidateCallback=*/nullptr, /*IsInlineAsmIdentifier=*/ true); if (IsUnevaluatedContext) PopExpressionEvaluationContext(); if (!Result.isUsable()) return Result; Result = CheckPlaceholderExpr(Result.get()); if (!Result.isUsable()) return Result; QualType T = Result.get()->getType(); // For now, reject dependent types. if (T->isDependentType()) { Diag(Id.getLocStart(), diag::err_asm_incomplete_type) << T; return ExprError(); } // Any sort of function type is fine. if (T->isFunctionType()) { return Result; } // Otherwise, it needs to be a complete type. if (RequireCompleteExprType(Result.get(), diag::err_asm_incomplete_type)) { return ExprError(); } // Compute the type size (and array length if applicable?). Info.Type = Info.Size = Context.getTypeSizeInChars(T).getQuantity(); if (T->isArrayType()) { const ArrayType *ATy = Context.getAsArrayType(T); Info.Type = Context.getTypeSizeInChars(ATy->getElementType()).getQuantity(); Info.Length = Info.Size / Info.Type; } // We can work with the expression as long as it's not an r-value. if (!Result.get()->isRValue()) Info.IsVarDecl = true; return Result; }
ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS, SourceLocation TemplateKWLoc, UnqualifiedId &Id, llvm::InlineAsmIdentifierInfo &Info, bool IsUnevaluatedContext) { Info.clear(); if (IsUnevaluatedContext) PushExpressionEvaluationContext(UnevaluatedAbstract, ReuseLambdaContextDecl); ExprResult Result = ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Id, /*trailing lparen*/ false, /*is & operand*/ false, /*CorrectionCandidateCallback=*/nullptr, /*IsInlineAsmIdentifier=*/ true); if (IsUnevaluatedContext) PopExpressionEvaluationContext(); if (!Result.isUsable()) return Result; Result = CheckPlaceholderExpr(Result.get()); if (!Result.isUsable()) return Result; // Referring to parameters is not allowed in naked functions. if (CheckNakedParmReference(Result.get(), *this)) return ExprError(); QualType T = Result.get()->getType(); // For now, reject dependent types. if (T->isDependentType()) { Diag(Id.getLocStart(), diag::err_asm_incomplete_type) << T; return ExprError(); } // Any sort of function type is fine. if (T->isFunctionType()) { return Result; } // Otherwise, it needs to be a complete type. if (RequireCompleteExprType(Result.get(), diag::err_asm_incomplete_type)) { return ExprError(); } fillInlineAsmTypeInfo(Context, T, Info); // We can work with the expression as long as it's not an r-value. if (!Result.get()->isRValue()) Info.IsVarDecl = true; return Result; }
Type * TypeCheck::visit(PrimaryExpression *ast) { FUNCLOG; //Type * t; switch (ast->op) { case PRIMARY_ID: { ScopedId *scopedId = ast->v.id; if (scopedId->scope) { //TODO: } UnqualifiedId *unqualifiedId = scopedId->id; String s = unqualifiedId->toSource(); Type *t = SymbolTable.findVar(Symbol::symbol(s)); if (!t) { SEMANTIC_ERROR(SE_UNDEFINED_SYMBOL); } return t; } case PRIMARY_INT: { IntType *itype = new IntType(32, true); if (ast->v.i == 0) { itype->setNullable(true); } return itype; } case PRIMARY_BOOL: return new IntType(8, false); case PRIMARY_STR: { PointerType *ptrType = new PointerType(); ptrType->reference = new IntType(8, true); DBG("$$ %s", ptrType->toString().c_str()); return ptrType; } case PRIMARY_EXP: return ast->v.exp->accept(this); default: assert(0); break; } return NULL; }
static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, UnqualifiedId &ReductionId) { SourceLocation TemplateKWLoc; if (ReductionIdScopeSpec.isEmpty()) { auto OOK = OO_None; switch (P.getCurToken().getKind()) { case tok::plus: OOK = OO_Plus; break; case tok::minus: OOK = OO_Minus; break; case tok::star: OOK = OO_Star; break; case tok::amp: OOK = OO_Amp; break; case tok::pipe: OOK = OO_Pipe; break; case tok::caret: OOK = OO_Caret; break; case tok::ampamp: OOK = OO_AmpAmp; break; case tok::pipepipe: OOK = OO_PipePipe; break; default: break; } if (OOK != OO_None) { SourceLocation OpLoc = P.ConsumeToken(); SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()}; ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations); return false; } } return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false, /*AllowDestructorName*/ false, /*AllowConstructorName*/ false, ParsedType(), TemplateKWLoc, ReductionId); }
/// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate', /// 'shared', 'copyin', 'copyprivate', 'flush' or 'reduction'. /// /// private-clause: /// 'private' '(' list ')' /// firstprivate-clause: /// 'firstprivate' '(' list ')' /// lastprivate-clause: /// 'lastprivate' '(' list ')' /// shared-clause: /// 'shared' '(' list ')' /// linear-clause: /// 'linear' '(' list [ ':' linear-step ] ')' /// aligned-clause: /// 'aligned' '(' list [ ':' alignment ] ')' /// reduction-clause: /// 'reduction' '(' reduction-identifier ':' list ')' /// copyprivate-clause: /// 'copyprivate' '(' list ')' /// flush-clause: /// 'flush' '(' list ')' /// OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { SourceLocation Loc = Tok.getLocation(); SourceLocation LOpen = ConsumeToken(); SourceLocation ColonLoc = SourceLocation(); // Optional scope specifier and unqualified id for reduction identifier. CXXScopeSpec ReductionIdScopeSpec; UnqualifiedId ReductionId; bool InvalidReductionId = false; // Parse '('. BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); if (T.expectAndConsume(diag::err_expected_lparen_after, getOpenMPClauseName(Kind))) return nullptr; // Handle reduction-identifier for reduction clause. if (Kind == OMPC_reduction) { ColonProtectionRAIIObject ColonRAII(*this); if (getLangOpts().CPlusPlus) { ParseOptionalCXXScopeSpecifier(ReductionIdScopeSpec, ParsedType(), false); } InvalidReductionId = ParseReductionId(*this, ReductionIdScopeSpec, ReductionId); if (InvalidReductionId) { SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); } if (Tok.is(tok::colon)) { ColonLoc = ConsumeToken(); } else { Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier"; } } SmallVector<Expr *, 5> Vars; bool IsComma = !InvalidReductionId; const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned); while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) && Tok.isNot(tok::annot_pragma_openmp_end))) { ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail); // Parse variable ExprResult VarExpr = ParseAssignmentExpression(); if (VarExpr.isUsable()) { Vars.push_back(VarExpr.get()); } else { SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); } // Skip ',' if any IsComma = Tok.is(tok::comma); if (IsComma) ConsumeToken(); else if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end) && (!MayHaveTail || Tok.isNot(tok::colon))) Diag(Tok, diag::err_omp_expected_punc) << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush) : getOpenMPClauseName(Kind)) << (Kind == OMPC_flush); } // Parse ':' linear-step (or ':' alignment). Expr *TailExpr = nullptr; const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon); if (MustHaveTail) { ColonLoc = Tok.getLocation(); ConsumeToken(); ExprResult Tail = ParseAssignmentExpression(); if (Tail.isUsable()) TailExpr = Tail.get(); else SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); } // Parse ')'. T.consumeClose(); if (Vars.empty() || (MustHaveTail && !TailExpr) || InvalidReductionId) return nullptr; return Actions.ActOnOpenMPVarListClause( Kind, Vars, TailExpr, Loc, LOpen, ColonLoc, Tok.getLocation(), ReductionIdScopeSpec, ReductionId.isValid() ? Actions.GetNameFromUnqualifiedId(ReductionId) : DeclarationNameInfo()); }
/// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate', /// 'shared', 'copyin', 'copyprivate', 'flush' or 'reduction'. /// /// private-clause: /// 'private' '(' list ')' /// firstprivate-clause: /// 'firstprivate' '(' list ')' /// lastprivate-clause: /// 'lastprivate' '(' list ')' /// shared-clause: /// 'shared' '(' list ')' /// linear-clause: /// 'linear' '(' linear-list [ ':' linear-step ] ')' /// aligned-clause: /// 'aligned' '(' list [ ':' alignment ] ')' /// reduction-clause: /// 'reduction' '(' reduction-identifier ':' list ')' /// copyprivate-clause: /// 'copyprivate' '(' list ')' /// flush-clause: /// 'flush' '(' list ')' /// depend-clause: /// 'depend' '(' in | out | inout : list ')' /// /// For 'linear' clause linear-list may have the following forms: /// list /// modifier(list) /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++). OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { SourceLocation Loc = Tok.getLocation(); SourceLocation LOpen = ConsumeToken(); SourceLocation ColonLoc = SourceLocation(); // Optional scope specifier and unqualified id for reduction identifier. CXXScopeSpec ReductionIdScopeSpec; UnqualifiedId ReductionId; bool InvalidReductionId = false; OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown; // OpenMP 4.1 [2.15.3.7, linear Clause] // If no modifier is specified it is assumed to be val. OpenMPLinearClauseKind LinearModifier = OMPC_LINEAR_val; SourceLocation DepLinLoc; // Parse '('. BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); if (T.expectAndConsume(diag::err_expected_lparen_after, getOpenMPClauseName(Kind))) return nullptr; bool NeedRParenForLinear = false; BalancedDelimiterTracker LinearT(*this, tok::l_paren, tok::annot_pragma_openmp_end); // Handle reduction-identifier for reduction clause. if (Kind == OMPC_reduction) { ColonProtectionRAIIObject ColonRAII(*this); if (getLangOpts().CPlusPlus) { ParseOptionalCXXScopeSpecifier(ReductionIdScopeSpec, ParsedType(), false); } InvalidReductionId = ParseReductionId(*this, ReductionIdScopeSpec, ReductionId); if (InvalidReductionId) { SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); } if (Tok.is(tok::colon)) { ColonLoc = ConsumeToken(); } else { Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier"; } } else if (Kind == OMPC_depend) { // Handle dependency type for depend clause. ColonProtectionRAIIObject ColonRAII(*this); DepKind = static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType( Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "")); DepLinLoc = Tok.getLocation(); if (DepKind == OMPC_DEPEND_unknown) { SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); } else { ConsumeToken(); } if (Tok.is(tok::colon)) { ColonLoc = ConsumeToken(); } else { Diag(Tok, diag::warn_pragma_expected_colon) << "dependency type"; } } else if (Kind == OMPC_linear) { // Try to parse modifier if any. if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) { LinearModifier = static_cast<OpenMPLinearClauseKind>( getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))); DepLinLoc = ConsumeToken(); LinearT.consumeOpen(); NeedRParenForLinear = true; } } SmallVector<Expr *, 5> Vars; bool IsComma = ((Kind != OMPC_reduction) && (Kind != OMPC_depend)) || ((Kind == OMPC_reduction) && !InvalidReductionId) || ((Kind == OMPC_depend) && DepKind != OMPC_DEPEND_unknown); const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned); while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) && Tok.isNot(tok::annot_pragma_openmp_end))) { ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail); // Parse variable ExprResult VarExpr = Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); if (VarExpr.isUsable()) { Vars.push_back(VarExpr.get()); } else { SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); } // Skip ',' if any IsComma = Tok.is(tok::comma); if (IsComma) ConsumeToken(); else if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end) && (!MayHaveTail || Tok.isNot(tok::colon))) Diag(Tok, diag::err_omp_expected_punc) << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush) : getOpenMPClauseName(Kind)) << (Kind == OMPC_flush); } // Parse ')' for linear clause with modifier. if (NeedRParenForLinear) LinearT.consumeClose(); // Parse ':' linear-step (or ':' alignment). Expr *TailExpr = nullptr; const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon); if (MustHaveTail) { ColonLoc = Tok.getLocation(); ConsumeToken(); ExprResult Tail = Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); if (Tail.isUsable()) TailExpr = Tail.get(); else SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); } // Parse ')'. T.consumeClose(); if ((Kind == OMPC_depend && DepKind != OMPC_DEPEND_unknown && Vars.empty()) || (Kind != OMPC_depend && Vars.empty()) || (MustHaveTail && !TailExpr) || InvalidReductionId) return nullptr; return Actions.ActOnOpenMPVarListClause( Kind, Vars, TailExpr, Loc, LOpen, ColonLoc, Tok.getLocation(), ReductionIdScopeSpec, ReductionId.isValid() ? Actions.GetNameFromUnqualifiedId(ReductionId) : DeclarationNameInfo(), DepKind, LinearModifier, DepLinLoc); }
/// \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; }
/// \brief Replace the tokens that form a simple-template-id with an /// annotation token containing the complete template-id. /// /// The first token in the stream must be the name of a template that /// is followed by a '<'. This routine will parse the complete /// simple-template-id and replace the tokens with a single annotation /// token with one of two different kinds: if the template-id names a /// type (and \p AllowTypeAnnotation is true), the annotation token is /// a type annotation that includes the optional nested-name-specifier /// (\p SS). Otherwise, the annotation token is a template-id /// annotation that does not include the optional /// nested-name-specifier. /// /// \param Template the declaration of the template named by the first /// token (an identifier), as returned from \c Action::isTemplateName(). /// /// \param TemplateNameKind the kind of template that \p Template /// refers to, as returned from \c Action::isTemplateName(). /// /// \param SS if non-NULL, the nested-name-specifier that precedes /// this template name. /// /// \param TemplateKWLoc if valid, specifies that this template-id /// annotation was preceded by the 'template' keyword and gives the /// location of that keyword. If invalid (the default), then this /// template-id was not preceded by a 'template' keyword. /// /// \param AllowTypeAnnotation if true (the default), then a /// simple-template-id that refers to a class template, template /// template parameter, or other template that produces a type will be /// replaced with a type annotation token. Otherwise, the /// simple-template-id is always replaced with a template-id /// annotation token. /// /// If an unrecoverable parse error occurs and no annotation token can be /// formed, this function returns true. /// bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, CXXScopeSpec &SS, UnqualifiedId &TemplateName, SourceLocation TemplateKWLoc, bool AllowTypeAnnotation) { assert(getLang().CPlusPlus && "Can only annotate template-ids in C++"); assert(Template && Tok.is(tok::less) && "Parser isn't at the beginning of a template-id"); // Consume the template-name. SourceLocation TemplateNameLoc = TemplateName.getSourceRange().getBegin(); // Parse the enclosed template argument list. SourceLocation LAngleLoc, RAngleLoc; TemplateArgList TemplateArgs; bool Invalid = ParseTemplateIdAfterTemplateName(Template, TemplateNameLoc, SS, false, LAngleLoc, TemplateArgs, RAngleLoc); if (Invalid) { // If we failed to parse the template ID but skipped ahead to a >, we're not // going to be able to form a token annotation. Eat the '>' if present. if (Tok.is(tok::greater)) ConsumeToken(); return true; } ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateArgs.data(), TemplateArgs.size()); // Build the annotation token. if (TNK == TNK_Type_template && AllowTypeAnnotation) { TypeResult Type = Actions.ActOnTemplateIdType(SS, Template, TemplateNameLoc, LAngleLoc, TemplateArgsPtr, RAngleLoc); if (Type.isInvalid()) { // If we failed to parse the template ID but skipped ahead to a >, we're not // going to be able to form a token annotation. Eat the '>' if present. if (Tok.is(tok::greater)) ConsumeToken(); return true; } Tok.setKind(tok::annot_typename); setTypeAnnotation(Tok, Type.get()); if (SS.isNotEmpty()) Tok.setLocation(SS.getBeginLoc()); else if (TemplateKWLoc.isValid()) Tok.setLocation(TemplateKWLoc); else Tok.setLocation(TemplateNameLoc); } else { // Build a template-id annotation token that can be processed // later. Tok.setKind(tok::annot_template_id); TemplateIdAnnotation *TemplateId = TemplateIdAnnotation::Allocate(TemplateArgs.size()); TemplateId->TemplateNameLoc = TemplateNameLoc; if (TemplateName.getKind() == UnqualifiedId::IK_Identifier) { TemplateId->Name = TemplateName.Identifier; TemplateId->Operator = OO_None; } else { TemplateId->Name = 0; TemplateId->Operator = TemplateName.OperatorFunctionId.Operator; } TemplateId->SS = SS; TemplateId->Template = Template; TemplateId->Kind = TNK; TemplateId->LAngleLoc = LAngleLoc; TemplateId->RAngleLoc = RAngleLoc; ParsedTemplateArgument *Args = TemplateId->getTemplateArgs(); for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg) Args[Arg] = ParsedTemplateArgument(TemplateArgs[Arg]); Tok.setAnnotationValue(TemplateId); if (TemplateKWLoc.isValid()) Tok.setLocation(TemplateKWLoc); else Tok.setLocation(TemplateNameLoc); TemplateArgsPtr.release(); } // Common fields for the annotation token Tok.setAnnotationEndLoc(RAngleLoc); // In case the tokens were cached, have Preprocessor replace them with the // annotation token. PP.AnnotateCachedTokens(Tok); return false; }
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); }