static bool ParseFile(const std::string &Filename, const std::vector<std::string> &IncludeDirs) { llvm::OwningPtr<llvm::MemoryBuffer> MB; if (llvm::error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(Filename.c_str(), MB)) { llvm::errs() << "Could not open input file '" << Filename << "': " << ec.message() <<"\n"; return true; } // Record the location of the include directory so that the lexer can find it // later. SourceMgr SrcMgr; SrcMgr.setIncludeDirs(IncludeDirs); // Tell SrcMgr about this buffer, which is what Parser will pick up. SrcMgr.AddNewSourceBuffer(MB.take(), SMLoc()); LangOptions Opts; Opts.ReturnComments = ReturnComments; TextDiagnosticPrinter TDP(SrcMgr); Diagnostic Diag(&SrcMgr, &TDP, false); #if 0 PrintAction PA(Diag); #endif ASTContext Context(SrcMgr); Sema SA(Context, Diag); Parser P(SrcMgr, Opts, Diag, SA); return P.ParseProgramUnits(); }
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) { Diags.Report(diag::err_target_unknown_triple) << Opts.Triple; return false; } std::unique_ptr<MemoryBuffer> BufferPtr; if (error_code ec = MemoryBuffer::getFileOrSTDIN(Opts.InputFile, BufferPtr)) { Error = ec.message(); Diags.Report(diag::err_fe_error_reading) << Opts.InputFile; return false; } MemoryBuffer *Buffer = BufferPtr.release(); SourceMgr SrcMgr; // Tell SrcMgr about this buffer, which is what the parser will pick up. SrcMgr.AddNewSourceBuffer(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. if (Opts.CompressDebugSections) MAI->setCompressDebugSections(true); bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj; formatted_raw_ostream *Out = GetOutputStream(Opts, Diags, IsBinary); if (!Out) return false; // 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); // FIXME: Assembler behavior can change with -static. MOFI->InitMCObjectFileInfo(Opts.Triple, Reloc::Default, CodeModel::Default, 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); if (!Opts.MainFileName.empty()) Ctx.setMainFileName(StringRef(Opts.MainFileName)); Ctx.setDwarfVersion(Opts.DwarfVersion); // 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)); // FIXME: There is a bit of code duplication with addPassesToEmitFile. if (Opts.OutputType == AssemblerInvocation::FT_Asm) { MCInstPrinter *IP = TheTarget->createMCInstPrinter(Opts.OutputAsmVariant, *MAI, *MCII, *MRI, *STI); MCCodeEmitter *CE = 0; MCAsmBackend *MAB = 0; if (Opts.ShowEncoding) { CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx); MAB = TheTarget->createMCAsmBackend(*MRI, Opts.Triple, Opts.CPU); } Str.reset(TheTarget->createAsmStreamer(Ctx, *Out, /*asmverbose*/true, /*useDwarfDirectory*/ true, IP, CE, MAB, Opts.ShowInst)); } else if (Opts.OutputType == AssemblerInvocation::FT_Null) { Str.reset(createNullStreamer(Ctx)); } else { assert(Opts.OutputType == AssemblerInvocation::FT_Obj && "Invalid file type!"); MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx); MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, Opts.Triple, Opts.CPU); Str.reset(TheTarget->createMCObjectStreamer(Opts.Triple, Ctx, *MAB, *Out, CE, *STI, Opts.RelaxAll, Opts.NoExecStack)); Str.get()->InitSections(); } 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) { Diags.Report(diag::err_target_unknown_triple) << Opts.Triple; return false; } Parser->setTargetParser(*TAP.get()); bool Success = !Parser->Run(Opts.NoInitialTextSection); // Close the output. delete Out; // Delete output on errors. if (!Success && Opts.OutputPath != "-") sys::fs::remove(Opts.OutputPath); return Success; }
int main(int argc, char **argv) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(argv[0]); PrettyStackTraceProgram X(argc, argv); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. // Initialize targets and assembly printers/parsers. llvm::InitializeAllTargetInfos(); llvm::InitializeAllTargetMCs(); llvm::InitializeAllAsmParsers(); llvm::InitializeAllDisassemblers(); // Register the target printer for --version. cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion); cl::ParseCommandLineOptions(argc, argv, "llvm machine code playground\n"); MCTargetOptions MCOptions = InitMCTargetOptionsFromFlags(); TripleName = Triple::normalize(TripleName); setDwarfDebugFlags(argc, argv); setDwarfDebugProducer(); const char *ProgName = argv[0]; const Target *TheTarget = GetTarget(ProgName); if (!TheTarget) return 1; // Now that GetTarget() has (potentially) replaced TripleName, it's safe to // construct the Triple object. Triple TheTriple(TripleName); ErrorOr<std::unique_ptr<MemoryBuffer>> BufferPtr = MemoryBuffer::getFileOrSTDIN(InputFilename); if (std::error_code EC = BufferPtr.getError()) { errs() << InputFilename << ": " << EC.message() << '\n'; return 1; } MemoryBuffer *Buffer = BufferPtr->get(); SourceMgr SrcMgr; // Tell SrcMgr about this buffer, which is what the parser will pick up. SrcMgr.AddNewSourceBuffer(std::move(*BufferPtr), SMLoc()); // Record the location of the include directories so that the lexer can find // it later. SrcMgr.setIncludeDirs(IncludeDirs); std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); assert(MRI && "Unable to create target register info!"); std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TripleName)); assert(MAI && "Unable to create target asm info!"); MAI->setRelaxELFRelocations(RelaxELFRel); if (CompressDebugSections != DebugCompressionType::DCT_None) { if (!zlib::isAvailable()) { errs() << ProgName << ": build tools with zlib to enable -compress-debug-sections"; return 1; } MAI->setCompressDebugSections(CompressDebugSections); } // FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and // MCObjectFileInfo needs a MCContext reference in order to initialize itself. MCObjectFileInfo MOFI; MCContext Ctx(MAI.get(), MRI.get(), &MOFI, &SrcMgr); MOFI.InitMCObjectFileInfo(TheTriple, PIC, CMModel, Ctx); if (SaveTempLabels) Ctx.setAllowTemporaryLabels(false); Ctx.setGenDwarfForAssembly(GenDwarfForAssembly); // Default to 4 for dwarf version. unsigned DwarfVersion = MCOptions.DwarfVersion ? MCOptions.DwarfVersion : 4; if (DwarfVersion < 2 || DwarfVersion > 4) { errs() << ProgName << ": Dwarf version " << DwarfVersion << " is not supported." << '\n'; return 1; } Ctx.setDwarfVersion(DwarfVersion); if (!DwarfDebugFlags.empty()) Ctx.setDwarfDebugFlags(StringRef(DwarfDebugFlags)); if (!DwarfDebugProducer.empty()) Ctx.setDwarfDebugProducer(StringRef(DwarfDebugProducer)); if (!DebugCompilationDir.empty()) Ctx.setCompilationDir(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 (!MainFileName.empty()) Ctx.setMainFileName(MainFileName); // Package up features to be passed to target/subtarget std::string FeaturesStr; if (MAttrs.size()) { SubtargetFeatures Features; for (unsigned i = 0; i != MAttrs.size(); ++i) Features.AddFeature(MAttrs[i]); FeaturesStr = Features.getString(); } std::unique_ptr<tool_output_file> Out = GetOutputStream(); if (!Out) return 1; std::unique_ptr<buffer_ostream> BOS; raw_pwrite_stream *OS = &Out->os(); std::unique_ptr<MCStreamer> Str; std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); std::unique_ptr<MCSubtargetInfo> STI( TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr)); MCInstPrinter *IP = nullptr; if (FileType == OFT_AssemblyFile) { IP = TheTarget->createMCInstPrinter(Triple(TripleName), OutputAsmVariant, *MAI, *MCII, *MRI); // Set the display preference for hex vs. decimal immediates. IP->setPrintImmHex(PrintImmHex); // Set up the AsmStreamer. MCCodeEmitter *CE = nullptr; MCAsmBackend *MAB = nullptr; if (ShowEncoding) { CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx); MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU); } auto FOut = llvm::make_unique<formatted_raw_ostream>(*OS); Str.reset(TheTarget->createAsmStreamer( Ctx, std::move(FOut), /*asmverbose*/ true, /*useDwarfDirectory*/ true, IP, CE, MAB, ShowInst)); } else if (FileType == OFT_Null) { Str.reset(TheTarget->createNullStreamer(Ctx)); } else { assert(FileType == OFT_ObjectFile && "Invalid file type!"); // Don't waste memory on names of temp labels. Ctx.setUseNamesOnTempLabels(false); if (!Out->os().supportsSeeking()) { BOS = make_unique<buffer_ostream>(Out->os()); OS = BOS.get(); } MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx); MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU); Str.reset(TheTarget->createMCObjectStreamer( TheTriple, Ctx, *MAB, *OS, CE, *STI, MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible, /*DWARFMustBeAtTheEnd*/ false)); if (NoExecStack) Str->InitSections(true); } int Res = 1; bool disassemble = false; switch (Action) { case AC_AsLex: Res = AsLexInput(SrcMgr, *MAI, Out->os()); break; case AC_Assemble: Res = AssembleInput(ProgName, TheTarget, SrcMgr, Ctx, *Str, *MAI, *STI, *MCII, MCOptions); break; case AC_MDisassemble: assert(IP && "Expected assembly output"); IP->setUseMarkup(1); disassemble = true; break; case AC_Disassemble: disassemble = true; break; } if (disassemble) Res = Disassembler::disassemble(*TheTarget, TripleName, *STI, *Str, *Buffer, SrcMgr, Out->os()); // Keep output if no errors. if (Res == 0) Out->keep(); return Res; }
static int AssembleInput(const char *ProgName) { const Target *TheTarget = GetTarget(ProgName); if (!TheTarget) return 1; std::string Error; MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFilename, &Error); if (Buffer == 0) { errs() << ProgName << ": "; if (Error.size()) errs() << Error << "\n"; else errs() << "input file didn't read correctly.\n"; return 1; } SourceMgr SrcMgr; // Tell SrcMgr about this buffer, which is what the parser 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); MCContext Ctx; formatted_raw_ostream *Out = GetOutputStream(); if (!Out) return 1; // FIXME: We shouldn't need to do this (and link in codegen). OwningPtr<TargetMachine> TM(TheTarget->createTargetMachine(TripleName, "")); if (!TM) { errs() << ProgName << ": error: could not create target for triple '" << TripleName << "'.\n"; return 1; } OwningPtr<AsmPrinter> AP; OwningPtr<MCStreamer> Str; if (FileType == OFT_AssemblyFile) { const TargetAsmInfo *TAI = TheTarget->createAsmInfo(TripleName); assert(TAI && "Unable to create target asm info!"); AP.reset(TheTarget->createAsmPrinter(*Out, *TM, TAI, true)); Str.reset(createAsmStreamer(Ctx, *Out, *TAI, AP.get())); } else { assert(FileType == OFT_ObjectFile && "Invalid file type!"); Str.reset(createMachOStreamer(Ctx, *Out)); } // FIXME: Target hook & command line option for initial section. Str.get()->SwitchSection(MCSectionMachO::Create("__TEXT","__text", MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 0, SectionKind::getText(), Ctx)); AsmParser Parser(SrcMgr, Ctx, *Str.get()); OwningPtr<TargetAsmParser> TAP(TheTarget->createAsmParser(Parser)); if (!TAP) { errs() << ProgName << ": error: this target does not support assembly parsing.\n"; return 1; } Parser.setTargetParser(*TAP.get()); int Res = Parser.Run(); if (Out != &fouts()) delete Out; return Res; }
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); AsmLexer Lexer(SrcMgr); bool Error = false; while (Lexer.Lex().isNot(AsmToken::Eof)) { switch (Lexer.getKind()) { default: Lexer.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::Register: outs() << "register: " << 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) { Diags.Report(diag::err_target_unknown_triple) << Opts.Triple; return false; } OwningPtr<MemoryBuffer> BufferPtr; if (error_code ec = MemoryBuffer::getFileOrSTDIN(Opts.InputFile, BufferPtr)) { Error = ec.message(); Diags.Report(diag::err_fe_error_reading) << Opts.InputFile; return false; } MemoryBuffer *Buffer = BufferPtr.take(); SourceMgr SrcMgr; // Tell SrcMgr about this buffer, which is what the parser will pick up. SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); // Record the location of the include directories so that the lexer can find // it later. SrcMgr.setIncludeDirs(Opts.IncludePaths); OwningPtr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(Opts.Triple)); assert(MAI && "Unable to create target asm info!"); OwningPtr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(Opts.Triple)); assert(MRI && "Unable to create target register info!"); bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj; formatted_raw_ostream *Out = GetOutputStream(Opts, Diags, IsBinary); if (!Out) return false; // FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and // MCObjectFileInfo needs a MCContext reference in order to initialize itself. OwningPtr<MCObjectFileInfo> MOFI(new MCObjectFileInfo()); MCContext Ctx(*MAI, *MRI, MOFI.get()); // FIXME: Assembler behavior can change with -static. MOFI->InitMCObjectFileInfo(Opts.Triple, Reloc::Default, CodeModel::Default, Ctx); if (Opts.SaveTemporaryLabels) Ctx.setAllowTemporaryLabels(false); OwningPtr<MCStreamer> Str; OwningPtr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); OwningPtr<MCSubtargetInfo> STI(TheTarget->createMCSubtargetInfo(Opts.Triple, "", "")); // FIXME: There is a bit of code duplication with addPassesToEmitFile. if (Opts.OutputType == AssemblerInvocation::FT_Asm) { MCInstPrinter *IP = TheTarget->createMCInstPrinter(Opts.OutputAsmVariant, *MAI, *MCII, *MRI, *STI); MCCodeEmitter *CE = 0; MCAsmBackend *MAB = 0; if (Opts.ShowEncoding) { CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx); MAB = TheTarget->createMCAsmBackend(Opts.Triple); } Str.reset(TheTarget->createAsmStreamer(Ctx, *Out, /*asmverbose*/true, /*useLoc*/ true, /*useCFI*/ true, /*useDwarfDirectory*/ true, IP, CE, MAB, Opts.ShowInst)); } else if (Opts.OutputType == AssemblerInvocation::FT_Null) { Str.reset(createNullStreamer(Ctx)); } else { assert(Opts.OutputType == AssemblerInvocation::FT_Obj && "Invalid file type!"); MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx); MCAsmBackend *MAB = TheTarget->createMCAsmBackend(Opts.Triple); Str.reset(TheTarget->createMCObjectStreamer(Opts.Triple, Ctx, *MAB, *Out, CE, Opts.RelaxAll, Opts.NoExecStack)); Str.get()->InitSections(); } OwningPtr<MCAsmParser> Parser(createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI)); OwningPtr<MCTargetAsmParser> TAP(TheTarget->createMCAsmParser(*STI, *Parser)); if (!TAP) { Diags.Report(diag::err_target_unknown_triple) << Opts.Triple; return false; } Parser->setTargetParser(*TAP.get()); bool Success = !Parser->Run(Opts.NoInitialTextSection); // Close the output. delete Out; // Delete output on errors. if (!Success && Opts.OutputPath != "-") sys::Path(Opts.OutputPath).eraseFromDisk(); return Success; }
int AssembleOneInput(const uint8_t *Data, size_t Size) { const bool ShowInst = false; const bool AsmVerbose = false; const bool UseDwarfDirectory = true; Triple TheTriple(Triple::normalize(TripleName)); SourceMgr SrcMgr; std::unique_ptr<MemoryBuffer> BufferPtr(new LLVMFuzzerInputBuffer(Data, Size)); // Tell SrcMgr about this buffer, which is what the parser will pick up. SrcMgr.AddNewSourceBuffer(std::move(BufferPtr), SMLoc()); static const std::vector<std::string> NoIncludeDirs; SrcMgr.setIncludeDirs(NoIncludeDirs); static std::string ArchName; std::string Error; const Target *TheTarget = TargetRegistry::lookupTarget(ArchName, TheTriple, Error); if (!TheTarget) { errs() << "error: this target '" << TheTriple.normalize() << "/" << ArchName << "', was not found: '" << Error << "'\n"; abort(); } std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); if (!MRI) { errs() << "Unable to create target register info!"; abort(); } std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TripleName)); if (!MAI) { errs() << "Unable to create target asm info!"; abort(); } MCObjectFileInfo MOFI; MCContext Ctx(MAI.get(), MRI.get(), &MOFI, &SrcMgr); static const bool UsePIC = false; MOFI.InitMCObjectFileInfo(TheTriple, UsePIC, Ctx); const unsigned OutputAsmVariant = 0; std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); MCInstPrinter *IP = TheTarget->createMCInstPrinter(Triple(TripleName), OutputAsmVariant, *MAI, *MCII, *MRI); if (!IP) { errs() << "error: unable to create instruction printer for target triple '" << TheTriple.normalize() << "' with assembly variant " << OutputAsmVariant << ".\n"; abort(); } const char *ProgName = "llvm-mc-fuzzer"; std::unique_ptr<MCSubtargetInfo> STI( TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr)); MCCodeEmitter *CE = nullptr; MCAsmBackend *MAB = nullptr; MCTargetOptions MCOptions = InitMCTargetOptionsFromFlags(); std::string OutputString; raw_string_ostream Out(OutputString); auto FOut = llvm::make_unique<formatted_raw_ostream>(Out); std::unique_ptr<MCStreamer> Str; if (FileType == OFT_AssemblyFile) { Str.reset(TheTarget->createAsmStreamer( Ctx, std::move(FOut), AsmVerbose, UseDwarfDirectory, IP, CE, MAB, ShowInst)); } else { assert(FileType == OFT_ObjectFile && "Invalid file type!"); std::error_code EC; const std::string OutputFilename = "-"; auto Out = llvm::make_unique<ToolOutputFile>(OutputFilename, EC, sys::fs::F_None); if (EC) { errs() << EC.message() << '\n'; abort(); } // Don't waste memory on names of temp labels. Ctx.setUseNamesOnTempLabels(false); std::unique_ptr<buffer_ostream> BOS; raw_pwrite_stream *OS = &Out->os(); if (!Out->os().supportsSeeking()) { BOS = make_unique<buffer_ostream>(Out->os()); OS = BOS.get(); } MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx); MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU, MCOptions); Str.reset(TheTarget->createMCObjectStreamer( TheTriple, Ctx, *MAB, *OS, CE, *STI, MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible, /*DWARFMustBeAtTheEnd*/ false)); } const int Res = AssembleInput(ProgName, TheTarget, SrcMgr, Ctx, *Str, *MAI, *STI, *MCII, MCOptions); (void) Res; return 0; }
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. 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); 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); // 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; }
int main(int argc, char **argv) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. // Initialize targets and assembly printers/parsers. llvm::InitializeAllTargetInfos(); llvm::InitializeAllTargetMCs(); llvm::InitializeAllAsmParsers(); llvm::InitializeAllDisassemblers(); // Register the target printer for --version. cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion); cl::ParseCommandLineOptions(argc, argv, "llvm machine code playground\n"); TripleName = Triple::normalize(TripleName); setDwarfDebugFlags(argc, argv); setDwarfDebugProducer(); const char *ProgName = argv[0]; const Target *TheTarget = GetTarget(ProgName); if (!TheTarget) return 1; std::unique_ptr<MemoryBuffer> BufferPtr; if (std::error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, BufferPtr)) { errs() << ProgName << ": " << ec.message() << '\n'; return 1; } MemoryBuffer *Buffer = BufferPtr.release(); SourceMgr SrcMgr; // Tell SrcMgr about this buffer, which is what the parser 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); std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); assert(MRI && "Unable to create target register info!"); std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TripleName)); assert(MAI && "Unable to create target asm info!"); if (CompressDebugSections) { if (!zlib::isAvailable()) { errs() << ProgName << ": build tools with zlib to enable -compress-debug-sections"; return 1; } MAI->setCompressDebugSections(true); } // 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); MOFI->InitMCObjectFileInfo(TripleName, RelocModel, CMModel, Ctx); if (SaveTempLabels) Ctx.setAllowTemporaryLabels(false); Ctx.setGenDwarfForAssembly(GenDwarfForAssembly); if (DwarfVersion < 2 || DwarfVersion > 4) { errs() << ProgName << ": Dwarf version " << DwarfVersion << " is not supported." << '\n'; return 1; } Ctx.setDwarfVersion(DwarfVersion); if (!DwarfDebugFlags.empty()) Ctx.setDwarfDebugFlags(StringRef(DwarfDebugFlags)); if (!DwarfDebugProducer.empty()) Ctx.setDwarfDebugProducer(StringRef(DwarfDebugProducer)); if (!DebugCompilationDir.empty()) Ctx.setCompilationDir(DebugCompilationDir); if (!MainFileName.empty()) Ctx.setMainFileName(MainFileName); // Package up features to be passed to target/subtarget std::string FeaturesStr; if (MAttrs.size()) { SubtargetFeatures Features; for (unsigned i = 0; i != MAttrs.size(); ++i) Features.AddFeature(MAttrs[i]); FeaturesStr = Features.getString(); } std::unique_ptr<tool_output_file> Out(GetOutputStream()); if (!Out) return 1; formatted_raw_ostream FOS(Out->os()); std::unique_ptr<MCStreamer> Str; std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); std::unique_ptr<MCSubtargetInfo> STI( TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr)); MCInstPrinter *IP = nullptr; if (FileType == OFT_AssemblyFile) { IP = TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI, *MCII, *MRI, *STI); // Set the display preference for hex vs. decimal immediates. IP->setPrintImmHex(PrintImmHex); // Set up the AsmStreamer. MCCodeEmitter *CE = nullptr; MCAsmBackend *MAB = nullptr; if (ShowEncoding) { CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx); MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU); } Str.reset(TheTarget->createAsmStreamer(Ctx, FOS, /*asmverbose*/ true, /*useDwarfDirectory*/ true, IP, CE, MAB, ShowInst)); } else if (FileType == OFT_Null) { Str.reset(createNullStreamer(Ctx)); } else { assert(FileType == OFT_ObjectFile && "Invalid file type!"); MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx); MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU); Str.reset(TheTarget->createMCObjectStreamer(TripleName, Ctx, *MAB, FOS, CE, *STI, RelaxAll, NoExecStack)); } int Res = 1; bool disassemble = false; switch (Action) { case AC_AsLex: Res = AsLexInput(SrcMgr, *MAI, Out.get()); break; case AC_Assemble: Res = AssembleInput(ProgName, TheTarget, SrcMgr, Ctx, *Str, *MAI, *STI, *MCII); break; case AC_MDisassemble: assert(IP && "Expected assembly output"); IP->setUseMarkup(1); disassemble = true; break; case AC_Disassemble: disassemble = true; break; } if (disassemble) Res = Disassembler::disassemble(*TheTarget, TripleName, *STI, *Str, *Buffer, SrcMgr, Out->os()); // Keep output if no errors. if (Res == 0) Out->keep(); return Res; }
int main(int argc, char **argv) { RecordKeeper Records; sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); cl::ParseCommandLineOptions(argc, argv); try { // Parse the input file. OwningPtr<MemoryBuffer> File; if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), File)) { errs() << "Could not open input file '" << InputFilename << "': " << ec.message() <<"\n"; return 1; } MemoryBuffer *F = File.take(); // Tell SrcMgr about this buffer, which is what TGParser will pick up. SrcMgr.AddNewSourceBuffer(F, SMLoc()); // Record the location of the include directory so that the lexer can find // it later. SrcMgr.setIncludeDirs(IncludeDirs); TGParser Parser(SrcMgr, Records); if (Parser.ParseFile()) return 1; std::string Error; tool_output_file Out(OutputFilename.c_str(), Error); if (!Error.empty()) { errs() << argv[0] << ": error opening " << OutputFilename << ":" << Error << "\n"; return 1; } if (!DependFilename.empty()) { if (OutputFilename == "-") { errs() << argv[0] << ": the option -d must be used together with -o\n"; return 1; } tool_output_file DepOut(DependFilename.c_str(), Error); if (!Error.empty()) { errs() << argv[0] << ": error opening " << DependFilename << ":" << Error << "\n"; return 1; } DepOut.os() << DependFilename << ":"; const std::vector<std::string> &Dependencies = Parser.getDependencies(); for (std::vector<std::string>::const_iterator I = Dependencies.begin(), E = Dependencies.end(); I != E; ++I) { DepOut.os() << " " << (*I); } DepOut.os() << "\n"; DepOut.keep(); } switch (Action) { case PrintRecords: Out.os() << Records; // No argument, dump all contents break; case GenEmitter: CodeEmitterGen(Records).run(Out.os()); break; case GenRegisterEnums: RegisterInfoEmitter(Records).runEnums(Out.os()); break; case GenRegister: RegisterInfoEmitter(Records).run(Out.os()); break; case GenRegisterHeader: RegisterInfoEmitter(Records).runHeader(Out.os()); break; case GenInstrEnums: InstrEnumEmitter(Records).run(Out.os()); break; case GenInstrs: InstrInfoEmitter(Records).run(Out.os()); break; case GenCallingConv: CallingConvEmitter(Records).run(Out.os()); break; case GenAsmWriter: AsmWriterEmitter(Records).run(Out.os()); break; case GenARMDecoder: ARMDecoderEmitter(Records).run(Out.os()); break; case GenAsmMatcher: AsmMatcherEmitter(Records).run(Out.os()); break; case GenClangAttrClasses: ClangAttrClassEmitter(Records).run(Out.os()); break; case GenClangAttrImpl: ClangAttrImplEmitter(Records).run(Out.os()); break; case GenClangAttrList: ClangAttrListEmitter(Records).run(Out.os()); break; case GenClangAttrPCHRead: ClangAttrPCHReadEmitter(Records).run(Out.os()); break; case GenClangAttrPCHWrite: ClangAttrPCHWriteEmitter(Records).run(Out.os()); break; case GenClangAttrSpellingList: ClangAttrSpellingListEmitter(Records).run(Out.os()); break; case GenClangDiagsDefs: ClangDiagsDefsEmitter(Records, ClangComponent).run(Out.os()); break; case GenClangDiagGroups: ClangDiagGroupsEmitter(Records).run(Out.os()); break; case GenClangDiagsIndexName: ClangDiagsIndexNameEmitter(Records).run(Out.os()); break; case GenClangDeclNodes: ClangASTNodesEmitter(Records, "Decl", "Decl").run(Out.os()); ClangDeclContextEmitter(Records).run(Out.os()); break; case GenClangStmtNodes: ClangASTNodesEmitter(Records, "Stmt", "").run(Out.os()); break; case GenClangSACheckers: ClangSACheckersEmitter(Records).run(Out.os()); break; case GenDisassembler: DisassemblerEmitter(Records).run(Out.os()); break; case GenOptParserDefs: OptParserEmitter(Records, true).run(Out.os()); break; case GenOptParserImpl: OptParserEmitter(Records, false).run(Out.os()); break; case GenDAGISel: DAGISelEmitter(Records).run(Out.os()); break; case GenFastISel: FastISelEmitter(Records).run(Out.os()); break; case GenSubtarget: SubtargetEmitter(Records).run(Out.os()); break; case GenIntrinsic: IntrinsicEmitter(Records).run(Out.os()); break; case GenTgtIntrinsic: IntrinsicEmitter(Records, true).run(Out.os()); break; case GenLLVMCConf: LLVMCConfigurationEmitter(Records).run(Out.os()); break; case GenEDInfo: EDEmitter(Records).run(Out.os()); break; case GenArmNeon: NeonEmitter(Records).run(Out.os()); break; case GenArmNeonSema: NeonEmitter(Records).runHeader(Out.os()); break; case GenArmNeonTest: NeonEmitter(Records).runTests(Out.os()); break; case PrintEnums: { std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class); for (unsigned i = 0, e = Recs.size(); i != e; ++i) Out.os() << Recs[i]->getName() << ", "; Out.os() << "\n"; break; } case PrintSets: { SetTheory Sets; Sets.addFieldExpander("Set", "Elements"); std::vector<Record*> Recs = Records.getAllDerivedDefinitions("Set"); for (unsigned i = 0, e = Recs.size(); i != e; ++i) { Out.os() << Recs[i]->getName() << " = ["; const std::vector<Record*> *Elts = Sets.expand(Recs[i]); assert(Elts && "Couldn't expand Set instance"); for (unsigned ei = 0, ee = Elts->size(); ei != ee; ++ei) Out.os() << ' ' << (*Elts)[ei]->getName(); Out.os() << " ]\n"; } break; } default: assert(1 && "Invalid Action"); return 1; } // Declare success. Out.keep(); return 0; } catch (const TGError &Error) { errs() << argv[0] << ": error:\n"; PrintError(Error.getLoc(), Error.getMessage()); } catch (const std::string &Error) { errs() << argv[0] << ": " << Error << "\n"; } catch (const char *Error) { errs() << argv[0] << ": " << Error << "\n"; } catch (...) { errs() << argv[0] << ": Unknown unexpected exception occurred.\n"; } return 1; }
static bool ParseFile(const std::string &Filename, const std::vector<std::string> &IncludeDirs, SmallVectorImpl<std::string> &OutputFiles) { ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr = MemoryBuffer::getFileOrSTDIN(Filename); if (std::error_code EC = MBOrErr.getError()) { llvm::errs() << "Could not open input file '" << Filename << "': " << EC.message() <<"\n"; return true; } std::unique_ptr<llvm::MemoryBuffer> MB = std::move(MBOrErr.get()); // Record the location of the include directory so that the lexer can find it // later. SourceMgr SrcMgr; SrcMgr.setIncludeDirs(IncludeDirs); // Tell SrcMgr about this buffer, which is what Parser will pick up. SrcMgr.AddNewSourceBuffer(std::move(MB), llvm::SMLoc()); LangOptions Opts; Opts.DefaultReal8 = DefaultReal8; Opts.DefaultDouble8 = DefaultDouble8; Opts.DefaultInt8 = DefaultInt8; Opts.ReturnComments = ReturnComments; if(!FreeForm && !FixedForm) { llvm::StringRef Ext = llvm::sys::path::extension(Filename); if(Ext.equals_lower(".f")) { Opts.FixedForm = 1; Opts.FreeForm = 0; } } else if(FixedForm) { Opts.FixedForm = 1; Opts.FreeForm = 0; } TextDiagnosticPrinter TDP(SrcMgr); DiagnosticsEngine Diag(new DiagnosticIDs,&SrcMgr, &TDP, false); // Chain in -verify checker, if requested. if(RunVerifier) Diag.setClient(new VerifyDiagnosticConsumer(Diag)); ASTContext Context(SrcMgr, Opts); Sema SA(Context, Diag); Parser P(SrcMgr, Opts, Diag, SA); Diag.getClient()->BeginSourceFile(Opts, &P.getLexer()); P.ParseProgramUnits(); Diag.getClient()->EndSourceFile(); // Dump if(PrintAST || DumpAST) { auto Dumper = CreateASTDumper(""); Dumper->HandleTranslationUnit(Context); delete Dumper; } // Emit if(!SyntaxOnly && !Diag.hadErrors()) { flang::TargetOptions TargetOptions; TargetOptions.Triple = TargetTriple.empty()? llvm::sys::getDefaultTargetTriple() : TargetTriple; TargetOptions.CPU = llvm::sys::getHostCPUName(); auto CG = CreateLLVMCodeGen(Diag, Filename == ""? std::string("module") : Filename, CodeGenOptions(), TargetOptions, llvm::getGlobalContext()); CG->Initialize(Context); CG->HandleTranslationUnit(Context); BackendAction BA = Backend_EmitObj; if(EmitASM) BA = Backend_EmitAssembly; if(EmitLLVM) BA = Backend_EmitLL; const llvm::Target *TheTarget = 0; std::string Err; TheTarget = llvm::TargetRegistry::lookupTarget(TargetOptions.Triple, Err); CodeGenOpt::Level TMOptLevel = CodeGenOpt::Default; switch(OptLevel) { case 0: TMOptLevel = CodeGenOpt::None; break; case 3: TMOptLevel = CodeGenOpt::Aggressive; break; } llvm::TargetOptions Options; auto TM = TheTarget->createTargetMachine(TargetOptions.Triple, TargetOptions.CPU, "", Options, Reloc::Default, CodeModel::Default, TMOptLevel); if(!(EmitLLVM && OptLevel == 0)) { auto TheModule = CG->GetModule(); auto PM = new llvm::legacy::PassManager(); //llvm::legacy::FunctionPassManager *FPM = new llvm::legacy::FunctionPassManager(TheModule); //FPM->add(new DataLayoutPass()); //PM->add(new llvm::DataLayoutPass()); //TM->addAnalysisPasses(*PM); PM->add(createPromoteMemoryToRegisterPass()); PassManagerBuilder PMBuilder; PMBuilder.OptLevel = OptLevel; PMBuilder.SizeLevel = 0; PMBuilder.LoopVectorize = true; PMBuilder.SLPVectorize = true; unsigned Threshold = 225; if (OptLevel > 2) Threshold = 275; PMBuilder.Inliner = createFunctionInliningPass(Threshold); PMBuilder.populateModulePassManager(*PM); //llvm::legacy::PassManager *MPM = new llvm::legacy::PassManager(); //PMBuilder.populateModulePassManager(*MPM); PM->run(*TheModule); //MPM->run(*TheModule); delete PM; //delete MPM; } if(Interpret) { //const char *Env[] = { "", nullptr }; //Execute(CG->ReleaseModule(), Env); } else if(OutputFile == "-"){ // FIXME: outputting to stdout is broken //EmitFile(llvm::outs(), CG->GetModule(), TM, BA); OutputFiles.push_back(GetOutputName("stdout",BA)); EmitOutputFile(OutputFiles.back(), CG->GetModule(), TM, BA); }else { OutputFiles.push_back(GetOutputName(Filename, BA)); EmitOutputFile(OutputFiles.back(), CG->GetModule(), TM, BA); } delete CG; } return Diag.hadErrors(); }
static bool ExecuteAssembler(AssemblerInvocation &Opts, Diagnostic &Diags) { // Get the target specific parser. std::string Error; const Target *TheTarget(TargetRegistry::lookupTarget(Opts.Triple, Error)); if (!TheTarget) { Diags.Report(diag::err_target_unknown_triple) << Opts.Triple; return false; } MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(Opts.InputFile, &Error); if (Buffer == 0) { Diags.Report(diag::err_fe_error_reading) << Opts.InputFile; return false; } SourceMgr SrcMgr; // Tell SrcMgr about this buffer, which is what the parser will pick up. SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); // Record the location of the include directories so that the lexer can find // it later. SrcMgr.setIncludeDirs(Opts.IncludePaths); OwningPtr<MCAsmInfo> MAI(TheTarget->createAsmInfo(Opts.Triple)); assert(MAI && "Unable to create target asm info!"); MCContext Ctx(*MAI); bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj; formatted_raw_ostream *Out = GetOutputStream(Opts, Diags, IsBinary); if (!Out) return false; // FIXME: We shouldn't need to do this (and link in codegen). OwningPtr<TargetMachine> TM(TheTarget->createTargetMachine(Opts.Triple, "")); if (!TM) { Diags.Report(diag::err_target_unknown_triple) << Opts.Triple; return false; } OwningPtr<MCStreamer> Str; if (Opts.OutputType == AssemblerInvocation::FT_Asm) { MCInstPrinter *IP = TheTarget->createMCInstPrinter(Opts.OutputAsmVariant, *MAI); MCCodeEmitter *CE = 0; if (Opts.ShowEncoding) CE = TheTarget->createCodeEmitter(*TM, Ctx); Str.reset(createAsmStreamer(Ctx, *Out,TM->getTargetData()->isLittleEndian(), /*asmverbose*/true, IP, CE, Opts.ShowInst)); } else if (Opts.OutputType == AssemblerInvocation::FT_Null) { Str.reset(createNullStreamer(Ctx)); } else { assert(Opts.OutputType == AssemblerInvocation::FT_Obj && "Invalid file type!"); MCCodeEmitter *CE = TheTarget->createCodeEmitter(*TM, Ctx); TargetAsmBackend *TAB = TheTarget->createAsmBackend(Opts.Triple); Str.reset(TheTarget->createObjectStreamer(Opts.Triple, Ctx, *TAB, *Out, CE, Opts.RelaxAll)); } OwningPtr<MCAsmParser> Parser(createMCAsmParser(*TheTarget, SrcMgr, Ctx, *Str.get(), *MAI)); OwningPtr<TargetAsmParser> TAP(TheTarget->createAsmParser(*Parser, *TM)); if (!TAP) { Diags.Report(diag::err_target_unknown_triple) << Opts.Triple; return false; } Parser->setTargetParser(*TAP.get()); bool Success = !Parser->Run(Opts.NoInitialTextSection); // Close the output. delete Out; // Delete output on errors. if (!Success && Opts.OutputPath != "-") sys::Path(Opts.OutputPath).eraseFromDisk(); return Success; }
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. 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. if (Opts.CompressDebugSections) MAI->setCompressDebugSections(true); bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj; std::unique_ptr<formatted_raw_ostream> Out( GetOutputStream(Opts, Diags, IsBinary)); if (!Out) return true; // 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); // FIXME: Assembler behavior can change with -static. MOFI->InitMCObjectFileInfo(Opts.Triple, Reloc::Default, CodeModel::Default, 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); if (!Opts.MainFileName.empty()) Ctx.setMainFileName(StringRef(Opts.MainFileName)); Ctx.setDwarfVersion(Opts.DwarfVersion); // 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)); // 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); MCCodeEmitter *CE = nullptr; MCAsmBackend *MAB = nullptr; if (Opts.ShowEncoding) { CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx); MAB = TheTarget->createMCAsmBackend(*MRI, Opts.Triple, Opts.CPU); } Str.reset(TheTarget->createAsmStreamer(Ctx, *Out, /*asmverbose*/true, /*useDwarfDirectory*/ true, IP, CE, MAB, Opts.ShowInst)); } else if (Opts.OutputType == AssemblerInvocation::FT_Null) { Str.reset(createNullStreamer(Ctx)); } else { assert(Opts.OutputType == AssemblerInvocation::FT_Obj && "Invalid file type!"); MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx); MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, Opts.Triple, Opts.CPU); Str.reset(TheTarget->createMCObjectStreamer(Opts.Triple, Ctx, *MAB, *Out, CE, *STI, Opts.RelaxAll)); Str.get()->InitSections(Opts.NoExecStack); if (Opts.EmbedBitcode && Ctx.getObjectFileInfo()->getObjectFileType() == MCObjectFileInfo::IsMachO) { // When -fembed-bitcode is passed to clang_as, a 1-byte marker // is emitted in __LLVM,__asm section to tell the linker to add // the macho object into the bundle const MCSection *AsmLabel = Ctx.getMachOSection("__LLVM", "__asm", MachO::S_REGULAR, 4, SectionKind::getDataNoRel()); Str.get()->SwitchSection(AsmLabel); Str.get()->EmitZeros(1); } } 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; if (!Failed) { Parser->setTargetParser(*TAP.get()); Failed = Parser->Run(Opts.NoInitialTextSection); } // Close the output stream early. Out.reset(); // Delete output file if there were errors. if (Failed && Opts.OutputPath != "-") sys::fs::remove(Opts.OutputPath); return Failed; }
static int AssembleInput(const char *ProgName) { const Target *TheTarget = GetTarget(ProgName); if (!TheTarget) return 1; std::string Error; MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFilename, &Error); if (Buffer == 0) { errs() << ProgName << ": "; if (Error.size()) errs() << Error << "\n"; else errs() << "input file didn't read correctly.\n"; return 1; } SourceMgr SrcMgr; // Tell SrcMgr about this buffer, which is what the parser 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); llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createAsmInfo(TripleName)); assert(MAI && "Unable to create target asm info!"); MCContext Ctx(*MAI); formatted_raw_ostream *Out = GetOutputStream(); if (!Out) return 1; // FIXME: We shouldn't need to do this (and link in codegen). OwningPtr<TargetMachine> TM(TheTarget->createTargetMachine(TripleName, "")); if (!TM) { errs() << ProgName << ": error: could not create target for triple '" << TripleName << "'.\n"; return 1; } OwningPtr<MCCodeEmitter> CE; OwningPtr<MCStreamer> Str; OwningPtr<TargetAsmBackend> TAB; if (FileType == OFT_AssemblyFile) { MCInstPrinter *IP = TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI); if (ShowEncoding) CE.reset(TheTarget->createCodeEmitter(*TM, Ctx)); Str.reset(createAsmStreamer(Ctx, *Out,TM->getTargetData()->isLittleEndian(), /*asmverbose*/true, IP, CE.get(), ShowInst)); } else if (FileType == OFT_Null) { Str.reset(createNullStreamer(Ctx)); } else { assert(FileType == OFT_ObjectFile && "Invalid file type!"); CE.reset(TheTarget->createCodeEmitter(*TM, Ctx)); TAB.reset(TheTarget->createAsmBackend(TripleName)); Str.reset(TheTarget->createObjectStreamer(TripleName, Ctx, *TAB, *Out, CE.get(), RelaxAll)); } if (EnableLogging) { Str.reset(createLoggingStreamer(Str.take(), errs())); } OwningPtr<MCAsmParser> Parser(createMCAsmParser(*TheTarget, SrcMgr, Ctx, *Str.get(), *MAI)); OwningPtr<TargetAsmParser> TAP(TheTarget->createAsmParser(*Parser, *TM)); if (!TAP) { errs() << ProgName << ": error: this target does not support assembly parsing.\n"; return 1; } Parser->setTargetParser(*TAP.get()); int Res = Parser->Run(NoInitialTextSection); delete Out; // Delete output on errors. if (Res && OutputFilename != "-") sys::Path(OutputFilename).eraseFromDisk(); return Res; }
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)); OwningPtr<tool_output_file> Out(GetOutputStream()); if (!Out) return 1; 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: Out->os() << "identifier: " << Lexer.getTok().getString() << '\n'; break; case AsmToken::Integer: Out->os() << "int: " << Lexer.getTok().getString() << '\n'; break; case AsmToken::Real: Out->os() << "real: " << Lexer.getTok().getString() << '\n'; break; case AsmToken::Register: Out->os() << "register: " << Lexer.getTok().getRegVal() << '\n'; break; case AsmToken::String: Out->os() << "string: " << Lexer.getTok().getString() << '\n'; break; case AsmToken::Amp: Out->os() << "Amp\n"; break; case AsmToken::AmpAmp: Out->os() << "AmpAmp\n"; break; case AsmToken::At: Out->os() << "At\n"; break; case AsmToken::Caret: Out->os() << "Caret\n"; break; case AsmToken::Colon: Out->os() << "Colon\n"; break; case AsmToken::Comma: Out->os() << "Comma\n"; break; case AsmToken::Dollar: Out->os() << "Dollar\n"; break; case AsmToken::Dot: Out->os() << "Dot\n"; break; case AsmToken::EndOfStatement: Out->os() << "EndOfStatement\n"; break; case AsmToken::Eof: Out->os() << "Eof\n"; break; case AsmToken::Equal: Out->os() << "Equal\n"; break; case AsmToken::EqualEqual: Out->os() << "EqualEqual\n"; break; case AsmToken::Exclaim: Out->os() << "Exclaim\n"; break; case AsmToken::ExclaimEqual: Out->os() << "ExclaimEqual\n"; break; case AsmToken::Greater: Out->os() << "Greater\n"; break; case AsmToken::GreaterEqual: Out->os() << "GreaterEqual\n"; break; case AsmToken::GreaterGreater: Out->os() << "GreaterGreater\n"; break; case AsmToken::Hash: Out->os() << "Hash\n"; break; case AsmToken::LBrac: Out->os() << "LBrac\n"; break; case AsmToken::LCurly: Out->os() << "LCurly\n"; break; case AsmToken::LParen: Out->os() << "LParen\n"; break; case AsmToken::Less: Out->os() << "Less\n"; break; case AsmToken::LessEqual: Out->os() << "LessEqual\n"; break; case AsmToken::LessGreater: Out->os() << "LessGreater\n"; break; case AsmToken::LessLess: Out->os() << "LessLess\n"; break; case AsmToken::Minus: Out->os() << "Minus\n"; break; case AsmToken::Percent: Out->os() << "Percent\n"; break; case AsmToken::Pipe: Out->os() << "Pipe\n"; break; case AsmToken::PipePipe: Out->os() << "PipePipe\n"; break; case AsmToken::Plus: Out->os() << "Plus\n"; break; case AsmToken::RBrac: Out->os() << "RBrac\n"; break; case AsmToken::RCurly: Out->os() << "RCurly\n"; break; case AsmToken::RParen: Out->os() << "RParen\n"; break; case AsmToken::Slash: Out->os() << "Slash\n"; break; case AsmToken::Star: Out->os() << "Star\n"; break; case AsmToken::Tilde: Out->os() << "Tilde\n"; break; } } // Keep output if no errors. if (Error == 0) Out->keep(); 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. 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. if (Opts.CompressDebugSections) MAI->setCompressDebugSections(DebugCompressionType::DCT_ZlibGnu); MAI->setRelaxELFRelocations(Opts.RelaxELFRelocations); bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj; std::unique_ptr<raw_fd_ostream> FDOS = getOutputStream(Opts, Diags, IsBinary); if (!FDOS) return true; // 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, CodeModel::Default, 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); if (!Opts.MainFileName.empty()) Ctx.setMainFileName(StringRef(Opts.MainFileName)); Ctx.setDwarfVersion(Opts.DwarfVersion); // 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); MCCodeEmitter *CE = nullptr; MCAsmBackend *MAB = nullptr; if (Opts.ShowEncoding) { CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx); MCTargetOptions Options; MAB = TheTarget->createMCAsmBackend(*MRI, Opts.Triple, Opts.CPU, Options); } auto FOut = llvm::make_unique<formatted_raw_ostream>(*Out); Str.reset(TheTarget->createAsmStreamer( Ctx, std::move(FOut), /*asmverbose*/ true, /*useDwarfDirectory*/ true, IP, CE, 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(); } MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx); MCTargetOptions Options; MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, Opts.Triple, Opts.CPU, Options); Triple T(Opts.Triple); Str.reset(TheTarget->createMCObjectStreamer( T, Ctx, *MAB, *Out, CE, *STI, Opts.RelaxAll, Opts.IncrementalLinkerCompatible, /*DWARFMustBeAtTheEnd*/ true)); Str.get()->InitSections(Opts.NoExecStack); } 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; 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 && Opts.OutputPath != "-") sys::fs::remove(Opts.OutputPath); return Failed; }