bool CheckString::CheckSame(const SourceMgr &SM, StringRef Buffer) const { if (CheckTy != Check::CheckSame) return false; // Count the number of newlines between the previous match and this one. assert(Buffer.data() != SM.getMemoryBuffer(SM.FindBufferContainingLoc( SMLoc::getFromPointer(Buffer.data()))) ->getBufferStart() && "CHECK-SAME can't be the first check in a file"); const char *FirstNewLine = nullptr; unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine); if (NumNewLines != 0) { SM.PrintMessage(Loc, SourceMgr::DK_Error, Prefix + "-SAME: is not on the same line as the previous match"); SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note, "'next' match was here"); SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note, "previous match ended here"); return true; } return false; }
static int AsLexInput(SourceMgr &SrcMgr, MCAsmInfo &MAI, raw_ostream &OS) { AsmLexer Lexer(MAI); Lexer.setBuffer(SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())->getBuffer()); bool Error = false; while (Lexer.Lex().isNot(AsmToken::Eof)) { const AsmToken &Tok = Lexer.getTok(); switch (Tok.getKind()) { default: SrcMgr.PrintMessage(Lexer.getLoc(), SourceMgr::DK_Warning, "unknown token"); Error = true; break; case AsmToken::Error: Error = true; // error already printed. break; case AsmToken::Identifier: OS << "identifier: " << Lexer.getTok().getString(); break; case AsmToken::Integer: OS << "int: " << Lexer.getTok().getString(); break; case AsmToken::Real: OS << "real: " << Lexer.getTok().getString(); break; case AsmToken::String: OS << "string: " << Lexer.getTok().getString(); break; case AsmToken::Amp: OS << "Amp"; break; case AsmToken::AmpAmp: OS << "AmpAmp"; break; case AsmToken::At: OS << "At"; break; case AsmToken::Caret: OS << "Caret"; break; case AsmToken::Colon: OS << "Colon"; break; case AsmToken::Comma: OS << "Comma"; break; case AsmToken::Dollar: OS << "Dollar"; break; case AsmToken::Dot: OS << "Dot"; break; case AsmToken::EndOfStatement: OS << "EndOfStatement"; break; case AsmToken::Eof: OS << "Eof"; break; case AsmToken::Equal: OS << "Equal"; break; case AsmToken::EqualEqual: OS << "EqualEqual"; break; case AsmToken::Exclaim: OS << "Exclaim"; break; case AsmToken::ExclaimEqual: OS << "ExclaimEqual"; break; case AsmToken::Greater: OS << "Greater"; break; case AsmToken::GreaterEqual: OS << "GreaterEqual"; break; case AsmToken::GreaterGreater: OS << "GreaterGreater"; break; case AsmToken::Hash: OS << "Hash"; break; case AsmToken::LBrac: OS << "LBrac"; break; case AsmToken::LCurly: OS << "LCurly"; break; case AsmToken::LParen: OS << "LParen"; break; case AsmToken::Less: OS << "Less"; break; case AsmToken::LessEqual: OS << "LessEqual"; break; case AsmToken::LessGreater: OS << "LessGreater"; break; case AsmToken::LessLess: OS << "LessLess"; break; case AsmToken::Minus: OS << "Minus"; break; case AsmToken::Percent: OS << "Percent"; break; case AsmToken::Pipe: OS << "Pipe"; break; case AsmToken::PipePipe: OS << "PipePipe"; break; case AsmToken::Plus: OS << "Plus"; break; case AsmToken::RBrac: OS << "RBrac"; break; case AsmToken::RCurly: OS << "RCurly"; break; case AsmToken::RParen: OS << "RParen"; break; case AsmToken::Slash: OS << "Slash"; break; case AsmToken::Star: OS << "Star"; break; case AsmToken::Tilde: OS << "Tilde"; break; } // Print the token string. OS << " (\""; OS.write_escaped(Tok.getString()); OS << "\")\n"; } return Error; }
static int AsLexInput(const char *ProgName) { std::string ErrorMessage; MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFilename, &ErrorMessage); if (Buffer == 0) { errs() << ProgName << ": "; if (ErrorMessage.size()) errs() << ErrorMessage << "\n"; else errs() << "input file didn't read correctly.\n"; return 1; } SourceMgr SrcMgr; // Tell SrcMgr about this buffer, which is what TGParser will pick up. SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); // Record the location of the include directories so that the lexer can find // it later. SrcMgr.setIncludeDirs(IncludeDirs); const Target *TheTarget = GetTarget(ProgName); if (!TheTarget) return 1; llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createAsmInfo(TripleName)); assert(MAI && "Unable to create target asm info!"); AsmLexer Lexer(*MAI); Lexer.setBuffer(SrcMgr.getMemoryBuffer(0)); bool Error = false; while (Lexer.Lex().isNot(AsmToken::Eof)) { switch (Lexer.getKind()) { default: SrcMgr.PrintMessage(Lexer.getLoc(), "unknown token", "warning"); Error = true; break; case AsmToken::Error: Error = true; // error already printed. break; case AsmToken::Identifier: outs() << "identifier: " << Lexer.getTok().getString() << '\n'; break; case AsmToken::String: outs() << "string: " << Lexer.getTok().getString() << '\n'; break; case AsmToken::Integer: outs() << "int: " << Lexer.getTok().getString() << '\n'; break; case AsmToken::Amp: outs() << "Amp\n"; break; case AsmToken::AmpAmp: outs() << "AmpAmp\n"; break; case AsmToken::Caret: outs() << "Caret\n"; break; case AsmToken::Colon: outs() << "Colon\n"; break; case AsmToken::Comma: outs() << "Comma\n"; break; case AsmToken::Dollar: outs() << "Dollar\n"; break; case AsmToken::EndOfStatement: outs() << "EndOfStatement\n"; break; case AsmToken::Eof: outs() << "Eof\n"; break; case AsmToken::Equal: outs() << "Equal\n"; break; case AsmToken::EqualEqual: outs() << "EqualEqual\n"; break; case AsmToken::Exclaim: outs() << "Exclaim\n"; break; case AsmToken::ExclaimEqual: outs() << "ExclaimEqual\n"; break; case AsmToken::Greater: outs() << "Greater\n"; break; case AsmToken::GreaterEqual: outs() << "GreaterEqual\n"; break; case AsmToken::GreaterGreater: outs() << "GreaterGreater\n"; break; case AsmToken::LParen: outs() << "LParen\n"; break; case AsmToken::Less: outs() << "Less\n"; break; case AsmToken::LessEqual: outs() << "LessEqual\n"; break; case AsmToken::LessGreater: outs() << "LessGreater\n"; break; case AsmToken::LessLess: outs() << "LessLess\n"; break; case AsmToken::Minus: outs() << "Minus\n"; break; case AsmToken::Percent: outs() << "Percent\n"; break; case AsmToken::Pipe: outs() << "Pipe\n"; break; case AsmToken::PipePipe: outs() << "PipePipe\n"; break; case AsmToken::Plus: outs() << "Plus\n"; break; case AsmToken::RParen: outs() << "RParen\n"; break; case AsmToken::Slash: outs() << "Slash\n"; break; case AsmToken::Star: outs() << "Star\n"; break; case AsmToken::Tilde: outs() << "Tilde\n"; break; } } return Error; }
static bool ExecuteAssembler(AssemblerInvocation &Opts, DiagnosticsEngine &Diags) { // Get the target specific parser. std::string Error; const Target *TheTarget = TargetRegistry::lookupTarget(Opts.Triple, Error); if (!TheTarget) return Diags.Report(diag::err_target_unknown_triple) << Opts.Triple; ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer = MemoryBuffer::getFileOrSTDIN(Opts.InputFile); if (std::error_code EC = Buffer.getError()) { Error = EC.message(); return Diags.Report(diag::err_fe_error_reading) << Opts.InputFile; } SourceMgr SrcMgr; // Tell SrcMgr about this buffer, which is what the parser will pick up. unsigned BufferIndex = SrcMgr.AddNewSourceBuffer(std::move(*Buffer), SMLoc()); // Record the location of the include directories so that the lexer can find // it later. SrcMgr.setIncludeDirs(Opts.IncludePaths); std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(Opts.Triple)); assert(MRI && "Unable to create target register info!"); std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, Opts.Triple)); assert(MAI && "Unable to create target asm info!"); // Ensure MCAsmInfo initialization occurs before any use, otherwise sections // may be created with a combination of default and explicit settings. MAI->setCompressDebugSections(Opts.CompressDebugSections); MAI->setRelaxELFRelocations(Opts.RelaxELFRelocations); bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj; if (Opts.OutputPath.empty()) Opts.OutputPath = "-"; std::unique_ptr<raw_fd_ostream> FDOS = getOutputStream(Opts.OutputPath, Diags, IsBinary); if (!FDOS) return true; std::unique_ptr<raw_fd_ostream> DwoOS; if (!Opts.SplitDwarfFile.empty()) DwoOS = getOutputStream(Opts.SplitDwarfFile, Diags, IsBinary); // FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and // MCObjectFileInfo needs a MCContext reference in order to initialize itself. std::unique_ptr<MCObjectFileInfo> MOFI(new MCObjectFileInfo()); MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &SrcMgr); bool PIC = false; if (Opts.RelocationModel == "static") { PIC = false; } else if (Opts.RelocationModel == "pic") { PIC = true; } else { assert(Opts.RelocationModel == "dynamic-no-pic" && "Invalid PIC model!"); PIC = false; } MOFI->InitMCObjectFileInfo(Triple(Opts.Triple), PIC, Ctx); if (Opts.SaveTemporaryLabels) Ctx.setAllowTemporaryLabels(false); if (Opts.GenDwarfForAssembly) Ctx.setGenDwarfForAssembly(true); if (!Opts.DwarfDebugFlags.empty()) Ctx.setDwarfDebugFlags(StringRef(Opts.DwarfDebugFlags)); if (!Opts.DwarfDebugProducer.empty()) Ctx.setDwarfDebugProducer(StringRef(Opts.DwarfDebugProducer)); if (!Opts.DebugCompilationDir.empty()) Ctx.setCompilationDir(Opts.DebugCompilationDir); else { // If no compilation dir is set, try to use the current directory. SmallString<128> CWD; if (!sys::fs::current_path(CWD)) Ctx.setCompilationDir(CWD); } if (!Opts.DebugPrefixMap.empty()) for (const auto &KV : Opts.DebugPrefixMap) Ctx.addDebugPrefixMapEntry(KV.first, KV.second); if (!Opts.MainFileName.empty()) Ctx.setMainFileName(StringRef(Opts.MainFileName)); Ctx.setDwarfVersion(Opts.DwarfVersion); if (Opts.GenDwarfForAssembly) Ctx.setGenDwarfRootFile(Opts.InputFile, SrcMgr.getMemoryBuffer(BufferIndex)->getBuffer()); // Build up the feature string from the target feature list. std::string FS; if (!Opts.Features.empty()) { FS = Opts.Features[0]; for (unsigned i = 1, e = Opts.Features.size(); i != e; ++i) FS += "," + Opts.Features[i]; } std::unique_ptr<MCStreamer> Str; std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); std::unique_ptr<MCSubtargetInfo> STI( TheTarget->createMCSubtargetInfo(Opts.Triple, Opts.CPU, FS)); raw_pwrite_stream *Out = FDOS.get(); std::unique_ptr<buffer_ostream> BOS; // FIXME: There is a bit of code duplication with addPassesToEmitFile. if (Opts.OutputType == AssemblerInvocation::FT_Asm) { MCInstPrinter *IP = TheTarget->createMCInstPrinter( llvm::Triple(Opts.Triple), Opts.OutputAsmVariant, *MAI, *MCII, *MRI); std::unique_ptr<MCCodeEmitter> CE; if (Opts.ShowEncoding) CE.reset(TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx)); MCTargetOptions MCOptions; std::unique_ptr<MCAsmBackend> MAB( TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions)); auto FOut = llvm::make_unique<formatted_raw_ostream>(*Out); Str.reset(TheTarget->createAsmStreamer( Ctx, std::move(FOut), /*asmverbose*/ true, /*useDwarfDirectory*/ true, IP, std::move(CE), std::move(MAB), Opts.ShowInst)); } else if (Opts.OutputType == AssemblerInvocation::FT_Null) { Str.reset(createNullStreamer(Ctx)); } else { assert(Opts.OutputType == AssemblerInvocation::FT_Obj && "Invalid file type!"); if (!FDOS->supportsSeeking()) { BOS = make_unique<buffer_ostream>(*FDOS); Out = BOS.get(); } std::unique_ptr<MCCodeEmitter> CE( TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx)); MCTargetOptions MCOptions; std::unique_ptr<MCAsmBackend> MAB( TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions)); std::unique_ptr<MCObjectWriter> OW = DwoOS ? MAB->createDwoObjectWriter(*Out, *DwoOS) : MAB->createObjectWriter(*Out); Triple T(Opts.Triple); Str.reset(TheTarget->createMCObjectStreamer( T, Ctx, std::move(MAB), std::move(OW), std::move(CE), *STI, Opts.RelaxAll, Opts.IncrementalLinkerCompatible, /*DWARFMustBeAtTheEnd*/ true)); Str.get()->InitSections(Opts.NoExecStack); } // When -fembed-bitcode is passed to clang_as, a 1-byte marker // is emitted in __LLVM,__asm section if the object file is MachO format. if (Opts.EmbedBitcode && Ctx.getObjectFileInfo()->getObjectFileType() == MCObjectFileInfo::IsMachO) { MCSection *AsmLabel = Ctx.getMachOSection( "__LLVM", "__asm", MachO::S_REGULAR, 4, SectionKind::getReadOnly()); Str.get()->SwitchSection(AsmLabel); Str.get()->EmitZeros(1); } // Assembly to object compilation should leverage assembly info. Str->setUseAssemblerInfoForParsing(true); bool Failed = false; std::unique_ptr<MCAsmParser> Parser( createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI)); // FIXME: init MCTargetOptions from sanitizer flags here. MCTargetOptions Options; std::unique_ptr<MCTargetAsmParser> TAP( TheTarget->createMCAsmParser(*STI, *Parser, *MCII, Options)); if (!TAP) Failed = Diags.Report(diag::err_target_unknown_triple) << Opts.Triple; // Set values for symbols, if any. for (auto &S : Opts.SymbolDefs) { auto Pair = StringRef(S).split('='); auto Sym = Pair.first; auto Val = Pair.second; int64_t Value; // We have already error checked this in the driver. Val.getAsInteger(0, Value); Ctx.setSymbolValue(Parser->getStreamer(), Sym, Value); } if (!Failed) { Parser->setTargetParser(*TAP.get()); Failed = Parser->Run(Opts.NoInitialTextSection); } // Close Streamer first. // It might have a reference to the output stream. Str.reset(); // Close the output stream early. BOS.reset(); FDOS.reset(); // Delete output file if there were errors. if (Failed) { if (Opts.OutputPath != "-") sys::fs::remove(Opts.OutputPath); if (!Opts.SplitDwarfFile.empty() && Opts.SplitDwarfFile != "-") sys::fs::remove(Opts.SplitDwarfFile); } return Failed; }