CXCursor cxcursor::MakeCursorTypeRef(const TypeDecl *Type, SourceLocation Loc, CXTranslationUnit TU) { assert(Type && TU && "Invalid arguments!"); void *RawLoc = Loc.getPtrEncoding(); CXCursor C = { CXCursor_TypeRef, 0, { Type, RawLoc, TU } }; return C; }
CXCursor cxcursor::MakeMacroExpansionCursor(MacroDefinition *MI, SourceLocation Loc, CXTranslationUnit TU) { assert(Loc.isValid()); CXCursor C = { CXCursor_MacroExpansion, 0, { MI, Loc.getPtrEncoding(), TU } }; return C; }
CXCursor cxcursor::MakeCursorLabelRef(LabelStmt *Label, SourceLocation Loc, CXTranslationUnit TU) { assert(Label && TU && "Invalid arguments!"); void *RawLoc = Loc.getPtrEncoding(); CXCursor C = { CXCursor_LabelRef, 0, { Label, RawLoc, TU } }; return C; }
CXCursor cxcursor::MakeCursorMemberRef(const FieldDecl *Field, SourceLocation Loc, CXTranslationUnit TU) { assert(Field && TU && "Invalid arguments!"); void *RawLoc = Loc.getPtrEncoding(); CXCursor C = { CXCursor_MemberRef, 0, { Field, RawLoc, TU } }; return C; }
CXCursor cxcursor::MakeCursorVariableRef(const VarDecl *Var, SourceLocation Loc, CXTranslationUnit TU) { assert(Var && TU && "Invalid arguments!"); void *RawLoc = Loc.getPtrEncoding(); CXCursor C = { CXCursor_VariableRef, 0, { Var, RawLoc, TU } }; return C; }
CXCursor cxcursor::MakeCursorObjCProtocolRef(const ObjCProtocolDecl *Proto, SourceLocation Loc, CXTranslationUnit TU) { assert(Proto && TU && "Invalid arguments!"); void *RawLoc = Loc.getPtrEncoding(); CXCursor C = { CXCursor_ObjCProtocolRef, 0, { Proto, RawLoc, TU } }; return C; }
CXCursor cxcursor::MakeCursorObjCSuperClassRef(ObjCInterfaceDecl *Super, SourceLocation Loc, CXTranslationUnit TU) { assert(Super && TU && "Invalid arguments!"); void *RawLoc = Loc.getPtrEncoding(); CXCursor C = { CXCursor_ObjCSuperClassRef, 0, { Super, RawLoc, TU } }; return C; }
CXCursor cxcursor::MakeCursorNamespaceRef(const NamedDecl *NS, SourceLocation Loc, CXTranslationUnit TU) { assert(NS && (isa<NamespaceDecl>(NS) || isa<NamespaceAliasDecl>(NS)) && TU && "Invalid arguments!"); void *RawLoc = Loc.getPtrEncoding(); CXCursor C = { CXCursor_NamespaceRef, 0, { NS, RawLoc, TU } }; return C; }
CXCursor cxcursor::MakeCursorObjCClassRef(const ObjCInterfaceDecl *Class, SourceLocation Loc, CXTranslationUnit TU) { // 'Class' can be null for invalid code. if (!Class) return MakeCXCursorInvalid(CXCursor_InvalidCode); assert(TU && "Invalid arguments!"); void *RawLoc = Loc.getPtrEncoding(); CXCursor C = { CXCursor_ObjCClassRef, 0, { Class, RawLoc, TU } }; return C; }
CXCursor cxcursor::MakeCursorOverloadedDeclRef(TemplateName Name, SourceLocation Loc, CXTranslationUnit TU) { assert(Name.getAsOverloadedTemplate() && TU && "Invalid arguments!"); void *RawLoc = Loc.getPtrEncoding(); OverloadedDeclRefStorage Storage(Name.getAsOverloadedTemplate()); CXCursor C = { CXCursor_OverloadedDeclRef, 0, { Storage.getOpaqueValue(), RawLoc, TU } }; return C; }
bool EmptyStructToIntRewriteVisitor::VisitRecordTypeLoc(RecordTypeLoc RTLoc) { const RecordDecl *RD = RTLoc.getDecl(); if (RD->getCanonicalDecl() == ConsumerInstance->TheRecordDecl) { SourceLocation LocStart = RTLoc.getLocStart(); void *LocPtr = LocStart.getPtrEncoding(); if (ConsumerInstance->VisitedLocs.count(LocPtr)) return true; ConsumerInstance->VisitedLocs.insert(LocPtr); // handle a special case - // struct S1 { // struct { } S; // }; const IdentifierInfo *TypeId = RTLoc.getType().getBaseTypeIdentifier(); if (!TypeId) return true; ConsumerInstance->RewriteHelper->replaceRecordType(RTLoc, "int"); ConsumerInstance->Rewritten = true; } return true; }
StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, ArrayRef<Token> AsmToks,SourceLocation EndLoc) { SmallVector<IdentifierInfo*, 4> Names; SmallVector<StringRef, 4> ConstraintRefs; SmallVector<Expr*, 4> Exprs; SmallVector<StringRef, 4> ClobberRefs; llvm::Triple TheTriple = Context.getTargetInfo().getTriple(); llvm::Triple::ArchType ArchTy = TheTriple.getArch(); bool UnsupportedArch = ArchTy != llvm::Triple::x86 && ArchTy != llvm::Triple::x86_64; if (UnsupportedArch) Diag(AsmLoc, diag::err_msasm_unsupported_arch) << TheTriple.getArchName(); // Empty asm statements don't need to instantiate the AsmParser, etc. if (UnsupportedArch || AsmToks.empty()) { StringRef EmptyAsmStr; MSAsmStmt *NS = new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true, /*IsVolatile*/ true, AsmToks, /*NumOutputs*/ 0, /*NumInputs*/ 0, Names, ConstraintRefs, Exprs, EmptyAsmStr, ClobberRefs, EndLoc); return Owned(NS); } std::string AsmString; SmallVector<unsigned, 8> TokOffsets; if (buildMSAsmString(*this, AsmLoc, AsmToks, TokOffsets, AsmString)) return StmtError(); // Get the target specific parser. std::string Error; const std::string &TT = TheTriple.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, "", "")); llvm::SourceMgr SrcMgr; llvm::MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr); llvm::MemoryBuffer *Buffer = llvm::MemoryBuffer::getMemBuffer(AsmString, "<MS 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)); // Get the instruction descriptor. const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo(); llvm::MCInstPrinter *IP = TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI); // Change to the Intel dialect. Parser->setAssemblerDialect(1); Parser->setTargetParser(*TargetParser.get()); Parser->setParsingInlineAsm(true); TargetParser->setParsingInlineAsm(true); MCAsmParserSemaCallbackImpl MCAPSI(*this, AsmLoc, AsmToks, TokOffsets); TargetParser->setSemaCallback(&MCAPSI); SrcMgr.setDiagHandler(MCAsmParserSemaCallbackImpl::MSAsmDiagHandlerCallback, &MCAPSI); unsigned NumOutputs; unsigned NumInputs; std::string AsmStringIR; SmallVector<std::pair<void *, bool>, 4> OpDecls; SmallVector<std::string, 4> Constraints; SmallVector<std::string, 4> Clobbers; if (Parser->parseMSInlineAsm(AsmLoc.getPtrEncoding(), AsmStringIR, NumOutputs, NumInputs, OpDecls, Constraints, Clobbers, MII, IP, MCAPSI)) return StmtError(); // Build the vector of clobber StringRefs. unsigned NumClobbers = Clobbers.size(); ClobberRefs.resize(NumClobbers); for (unsigned i = 0; i != NumClobbers; ++i) ClobberRefs[i] = StringRef(Clobbers[i]); // Recast the void pointers and build the vector of constraint StringRefs. unsigned NumExprs = NumOutputs + NumInputs; Names.resize(NumExprs); ConstraintRefs.resize(NumExprs); Exprs.resize(NumExprs); for (unsigned i = 0, e = NumExprs; i != e; ++i) { NamedDecl *OpDecl = static_cast<NamedDecl *>(OpDecls[i].first); if (!OpDecl) return StmtError(); DeclarationNameInfo NameInfo(OpDecl->getDeclName(), AsmLoc); ExprResult OpExpr = BuildDeclarationNameExpr(CXXScopeSpec(), NameInfo, OpDecl); if (OpExpr.isInvalid()) return StmtError(); // Need address of variable. if (OpDecls[i].second) OpExpr = BuildUnaryOp(getCurScope(), AsmLoc, clang::UO_AddrOf, OpExpr.take()); Names[i] = OpDecl->getIdentifier(); ConstraintRefs[i] = StringRef(Constraints[i]); Exprs[i] = OpExpr.take(); } bool IsSimple = NumExprs > 0; MSAsmStmt *NS = new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple, /*IsVolatile*/ true, AsmToks, NumOutputs, NumInputs, Names, ConstraintRefs, Exprs, AsmStringIR, ClobberRefs, EndLoc); return Owned(NS); }
/// ParseMicrosoftAsmStatement. When -fms-extensions/-fasm-blocks is enabled, /// this routine is called to collect the tokens for an MS asm statement. /// /// [MS] ms-asm-statement: /// ms-asm-block /// ms-asm-block ms-asm-statement /// /// [MS] ms-asm-block: /// '__asm' ms-asm-line '\n' /// '__asm' '{' ms-asm-instruction-block[opt] '}' ';'[opt] /// /// [MS] ms-asm-instruction-block /// ms-asm-line /// ms-asm-line '\n' ms-asm-instruction-block /// StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { SourceManager &SrcMgr = PP.getSourceManager(); SourceLocation EndLoc = AsmLoc; SmallVector<Token, 4> AsmToks; bool SingleLineMode = true; unsigned BraceNesting = 0; unsigned short savedBraceCount = BraceCount; bool InAsmComment = false; FileID FID; unsigned LineNo = 0; unsigned NumTokensRead = 0; SmallVector<SourceLocation, 4> LBraceLocs; bool SkippedStartOfLine = false; if (Tok.is(tok::l_brace)) { // Braced inline asm: consume the opening brace. SingleLineMode = false; BraceNesting = 1; EndLoc = ConsumeBrace(); LBraceLocs.push_back(EndLoc); ++NumTokensRead; } else { // Single-line inline asm; compute which line it is on. std::pair<FileID, unsigned> ExpAsmLoc = SrcMgr.getDecomposedExpansionLoc(EndLoc); FID = ExpAsmLoc.first; LineNo = SrcMgr.getLineNumber(FID, ExpAsmLoc.second); LBraceLocs.push_back(SourceLocation()); } SourceLocation TokLoc = Tok.getLocation(); do { // If we hit EOF, we're done, period. if (isEofOrEom()) break; if (!InAsmComment && Tok.is(tok::l_brace)) { // Consume the opening brace. SkippedStartOfLine = Tok.isAtStartOfLine(); EndLoc = ConsumeBrace(); BraceNesting++; LBraceLocs.push_back(EndLoc); TokLoc = Tok.getLocation(); ++NumTokensRead; continue; } else if (!InAsmComment && Tok.is(tok::semi)) { // A semicolon in an asm is the start of a comment. InAsmComment = true; if (!SingleLineMode) { // Compute which line the comment is on. std::pair<FileID, unsigned> ExpSemiLoc = SrcMgr.getDecomposedExpansionLoc(TokLoc); FID = ExpSemiLoc.first; LineNo = SrcMgr.getLineNumber(FID, ExpSemiLoc.second); } } else if (SingleLineMode || InAsmComment) { // If end-of-line is significant, check whether this token is on a // new line. std::pair<FileID, unsigned> ExpLoc = SrcMgr.getDecomposedExpansionLoc(TokLoc); if (ExpLoc.first != FID || SrcMgr.getLineNumber(ExpLoc.first, ExpLoc.second) != LineNo) { // If this is a single-line __asm, we're done, except if the next // line begins with an __asm too, in which case we finish a comment // if needed and then keep processing the next line as a single // line __asm. bool isAsm = Tok.is(tok::kw_asm); if (SingleLineMode && !isAsm) break; // We're no longer in a comment. InAsmComment = false; if (isAsm) { LineNo = SrcMgr.getLineNumber(ExpLoc.first, ExpLoc.second); SkippedStartOfLine = Tok.isAtStartOfLine(); } } else if (!InAsmComment && Tok.is(tok::r_brace)) { // In MSVC mode, braces only participate in brace matching and // separating the asm statements. This is an intentional // departure from the Apple gcc behavior. if (!BraceNesting) break; } } if (!InAsmComment && BraceNesting && Tok.is(tok::r_brace) && BraceCount == (savedBraceCount + BraceNesting)) { // Consume the closing brace. SkippedStartOfLine = Tok.isAtStartOfLine(); EndLoc = ConsumeBrace(); BraceNesting--; // Finish if all of the opened braces in the inline asm section were // consumed. if (BraceNesting == 0 && !SingleLineMode) break; else { LBraceLocs.pop_back(); TokLoc = Tok.getLocation(); ++NumTokensRead; continue; } } // Consume the next token; make sure we don't modify the brace count etc. // if we are in a comment. EndLoc = TokLoc; if (InAsmComment) PP.Lex(Tok); else { // Set the token as the start of line if we skipped the original start // of line token in case it was a nested brace. if (SkippedStartOfLine) Tok.setFlag(Token::StartOfLine); AsmToks.push_back(Tok); ConsumeAnyToken(); } TokLoc = Tok.getLocation(); ++NumTokensRead; SkippedStartOfLine = false; } while (1); if (BraceNesting && BraceCount != savedBraceCount) { // __asm without closing brace (this can happen at EOF). for (unsigned i = 0; i < BraceNesting; ++i) { Diag(Tok, diag::err_expected) << tok::r_brace; Diag(LBraceLocs.back(), diag::note_matching) << tok::l_brace; LBraceLocs.pop_back(); } return StmtError(); } else if (NumTokensRead == 0) { // Empty __asm. Diag(Tok, diag::err_expected) << tok::l_brace; return StmtError(); } // Okay, prepare to use MC to parse the assembly. SmallVector<StringRef, 4> ConstraintRefs; SmallVector<Expr *, 4> Exprs; SmallVector<StringRef, 4> ClobberRefs; // We need an actual supported target. const llvm::Triple &TheTriple = Actions.Context.getTargetInfo().getTriple(); llvm::Triple::ArchType ArchTy = TheTriple.getArch(); const std::string &TT = TheTriple.getTriple(); const llvm::Target *TheTarget = nullptr; bool UnsupportedArch = (ArchTy != llvm::Triple::x86 && ArchTy != llvm::Triple::x86_64); if (UnsupportedArch) { Diag(AsmLoc, diag::err_msasm_unsupported_arch) << TheTriple.getArchName(); } else { std::string Error; TheTarget = llvm::TargetRegistry::lookupTarget(TT, Error); if (!TheTarget) Diag(AsmLoc, diag::err_msasm_unable_to_create_target) << Error; } assert(!LBraceLocs.empty() && "Should have at least one location here"); // If we don't support assembly, or the assembly is empty, we don't // need to instantiate the AsmParser, etc. if (!TheTarget || AsmToks.empty()) { return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLocs[0], AsmToks, StringRef(), /*NumOutputs*/ 0, /*NumInputs*/ 0, ConstraintRefs, ClobberRefs, Exprs, EndLoc); } // Expand the tokens into a string buffer. SmallString<512> AsmString; SmallVector<unsigned, 8> TokOffsets; if (buildMSAsmString(PP, AsmLoc, AsmToks, TokOffsets, AsmString)) return StmtError(); std::unique_ptr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT)); std::unique_ptr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TT)); // Get the instruction descriptor. std::unique_ptr<llvm::MCInstrInfo> MII(TheTarget->createMCInstrInfo()); std::unique_ptr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo()); std::unique_ptr<llvm::MCSubtargetInfo> STI( TheTarget->createMCSubtargetInfo(TT, "", "")); llvm::SourceMgr TempSrcMgr; llvm::MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &TempSrcMgr); MOFI->InitMCObjectFileInfo(TheTriple, llvm::Reloc::Default, llvm::CodeModel::Default, Ctx); std::unique_ptr<llvm::MemoryBuffer> Buffer = llvm::MemoryBuffer::getMemBuffer(AsmString, "<MS inline asm>"); // Tell SrcMgr about this buffer, which is what the parser will pick up. TempSrcMgr.AddNewSourceBuffer(std::move(Buffer), llvm::SMLoc()); std::unique_ptr<llvm::MCStreamer> Str(createNullStreamer(Ctx)); std::unique_ptr<llvm::MCAsmParser> Parser( createMCAsmParser(TempSrcMgr, Ctx, *Str.get(), *MAI)); // FIXME: init MCOptions from sanitizer flags here. llvm::MCTargetOptions MCOptions; std::unique_ptr<llvm::MCTargetAsmParser> TargetParser( TheTarget->createMCAsmParser(*STI, *Parser, *MII, MCOptions)); std::unique_ptr<llvm::MCInstPrinter> IP( TheTarget->createMCInstPrinter(llvm::Triple(TT), 1, *MAI, *MII, *MRI)); // Change to the Intel dialect. Parser->setAssemblerDialect(1); Parser->setTargetParser(*TargetParser.get()); Parser->setParsingInlineAsm(true); TargetParser->setParsingInlineAsm(true); ClangAsmParserCallback Callback(*this, AsmLoc, AsmString, AsmToks, TokOffsets); TargetParser->setSemaCallback(&Callback); TempSrcMgr.setDiagHandler(ClangAsmParserCallback::DiagHandlerCallback, &Callback); unsigned NumOutputs; unsigned NumInputs; std::string AsmStringIR; SmallVector<std::pair<void *, bool>, 4> OpExprs; SmallVector<std::string, 4> Constraints; SmallVector<std::string, 4> Clobbers; if (Parser->parseMSInlineAsm(AsmLoc.getPtrEncoding(), AsmStringIR, NumOutputs, NumInputs, OpExprs, Constraints, Clobbers, MII.get(), IP.get(), Callback)) return StmtError(); // Filter out "fpsw". Clang doesn't accept it, and it always lists flags and // fpsr as clobbers. auto End = std::remove(Clobbers.begin(), Clobbers.end(), "fpsw"); Clobbers.erase(End, Clobbers.end()); // Build the vector of clobber StringRefs. ClobberRefs.insert(ClobberRefs.end(), Clobbers.begin(), Clobbers.end()); // Recast the void pointers and build the vector of constraint StringRefs. unsigned NumExprs = NumOutputs + NumInputs; ConstraintRefs.resize(NumExprs); Exprs.resize(NumExprs); for (unsigned i = 0, e = NumExprs; i != e; ++i) { Expr *OpExpr = static_cast<Expr *>(OpExprs[i].first); if (!OpExpr) return StmtError(); // Need address of variable. if (OpExprs[i].second) OpExpr = Actions.BuildUnaryOp(getCurScope(), AsmLoc, UO_AddrOf, OpExpr).get(); ConstraintRefs[i] = StringRef(Constraints[i]); Exprs[i] = OpExpr; } // FIXME: We should be passing source locations for better diagnostics. return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLocs[0], AsmToks, AsmStringIR, NumOutputs, NumInputs, ConstraintRefs, ClobberRefs, Exprs, EndLoc); }