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; }
int main(int argc, char **argv) { InitLLVM X(argc, argv); // Initialize targets and assembly parsers. InitializeAllTargetInfos(); InitializeAllTargetMCs(); InitializeAllAsmParsers(); // Enable printing of available targets when flag --version is specified. cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion); cl::HideUnrelatedOptions({&ToolOptions, &ViewOptions}); // Parse flags and initialize target options. cl::ParseCommandLineOptions(argc, argv, "llvm machine code performance analyzer.\n"); // Get the target from the triple. If a triple is not specified, then select // the default triple for the host. If the triple doesn't correspond to any // registered target, then exit with an error message. const char *ProgName = argv[0]; const Target *TheTarget = getTarget(ProgName); if (!TheTarget) return 1; // GetTarget() may replaced TripleName with a default triple. // For safety, reconstruct the Triple object. Triple TheTriple(TripleName); ErrorOr<std::unique_ptr<MemoryBuffer>> BufferPtr = MemoryBuffer::getFileOrSTDIN(InputFilename); if (std::error_code EC = BufferPtr.getError()) { WithColor::error() << InputFilename << ": " << EC.message() << '\n'; return 1; } // Apply overrides to llvm-mca specific options. processViewOptions(); SourceMgr SrcMgr; // Tell SrcMgr about this buffer, which is what the parser will pick up. SrcMgr.AddNewSourceBuffer(std::move(*BufferPtr), SMLoc()); 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!"); MCObjectFileInfo MOFI; MCContext Ctx(MAI.get(), MRI.get(), &MOFI, &SrcMgr); MOFI.InitMCObjectFileInfo(TheTriple, /* PIC= */ false, Ctx); std::unique_ptr<buffer_ostream> BOS; std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); std::unique_ptr<MCInstrAnalysis> MCIA( TheTarget->createMCInstrAnalysis(MCII.get())); if (!MCPU.compare("native")) MCPU = llvm::sys::getHostCPUName(); std::unique_ptr<MCSubtargetInfo> STI( TheTarget->createMCSubtargetInfo(TripleName, MCPU, /* FeaturesStr */ "")); if (!STI->isCPUStringValid(MCPU)) return 1; if (!PrintInstructionTables && !STI->getSchedModel().isOutOfOrder()) { WithColor::error() << "please specify an out-of-order cpu. '" << MCPU << "' is an in-order cpu.\n"; return 1; } if (!STI->getSchedModel().hasInstrSchedModel()) { WithColor::error() << "unable to find instruction-level scheduling information for" << " target triple '" << TheTriple.normalize() << "' and cpu '" << MCPU << "'.\n"; if (STI->getSchedModel().InstrItineraries) WithColor::note() << "cpu '" << MCPU << "' provides itineraries. However, " << "instruction itineraries are currently unsupported.\n"; return 1; } // Parse the input and create CodeRegions that llvm-mca can analyze. mca::AsmCodeRegionGenerator CRG(*TheTarget, SrcMgr, Ctx, *MAI, *STI, *MCII); Expected<const mca::CodeRegions &> RegionsOrErr = CRG.parseCodeRegions(); if (!RegionsOrErr) { if (auto Err = handleErrors(RegionsOrErr.takeError(), [](const StringError &E) { WithColor::error() << E.getMessage() << '\n'; })) { // Default case. WithColor::error() << toString(std::move(Err)) << '\n'; } return 1; } const mca::CodeRegions &Regions = *RegionsOrErr; if (Regions.empty()) { WithColor::error() << "no assembly instructions found.\n"; return 1; } // Now initialize the output file. auto OF = getOutputStream(); if (std::error_code EC = OF.getError()) { WithColor::error() << EC.message() << '\n'; return 1; } unsigned AssemblerDialect = CRG.getAssemblerDialect(); if (OutputAsmVariant >= 0) AssemblerDialect = static_cast<unsigned>(OutputAsmVariant); std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter( Triple(TripleName), AssemblerDialect, *MAI, *MCII, *MRI)); if (!IP) { WithColor::error() << "unable to create instruction printer for target triple '" << TheTriple.normalize() << "' with assembly variant " << AssemblerDialect << ".\n"; return 1; } std::unique_ptr<ToolOutputFile> TOF = std::move(*OF); const MCSchedModel &SM = STI->getSchedModel(); // Create an instruction builder. mca::InstrBuilder IB(*STI, *MCII, *MRI, MCIA.get()); // Create a context to control ownership of the pipeline hardware. mca::Context MCA(*MRI, *STI); mca::PipelineOptions PO(MicroOpQueue, DecoderThroughput, DispatchWidth, RegisterFileSize, LoadQueueSize, StoreQueueSize, AssumeNoAlias, EnableBottleneckAnalysis); // Number each region in the sequence. unsigned RegionIdx = 0; for (const std::unique_ptr<mca::CodeRegion> &Region : Regions) { // Skip empty code regions. if (Region->empty()) continue; // Don't print the header of this region if it is the default region, and // it doesn't have an end location. if (Region->startLoc().isValid() || Region->endLoc().isValid()) { TOF->os() << "\n[" << RegionIdx++ << "] Code Region"; StringRef Desc = Region->getDescription(); if (!Desc.empty()) TOF->os() << " - " << Desc; TOF->os() << "\n\n"; } // Lower the MCInst sequence into an mca::Instruction sequence. ArrayRef<MCInst> Insts = Region->getInstructions(); std::vector<std::unique_ptr<mca::Instruction>> LoweredSequence; for (const MCInst &MCI : Insts) { Expected<std::unique_ptr<mca::Instruction>> Inst = IB.createInstruction(MCI); if (!Inst) { if (auto NewE = handleErrors( Inst.takeError(), [&IP, &STI](const mca::InstructionError<MCInst> &IE) { std::string InstructionStr; raw_string_ostream SS(InstructionStr); WithColor::error() << IE.Message << '\n'; IP->printInst(&IE.Inst, SS, "", *STI); SS.flush(); WithColor::note() << "instruction: " << InstructionStr << '\n'; })) { // Default case. WithColor::error() << toString(std::move(NewE)); } return 1; } LoweredSequence.emplace_back(std::move(Inst.get())); } mca::SourceMgr S(LoweredSequence, PrintInstructionTables ? 1 : Iterations); if (PrintInstructionTables) { // Create a pipeline, stages, and a printer. auto P = llvm::make_unique<mca::Pipeline>(); P->appendStage(llvm::make_unique<mca::EntryStage>(S)); P->appendStage(llvm::make_unique<mca::InstructionTables>(SM)); mca::PipelinePrinter Printer(*P); // Create the views for this pipeline, execute, and emit a report. if (PrintInstructionInfoView) { Printer.addView(llvm::make_unique<mca::InstructionInfoView>( *STI, *MCII, Insts, *IP)); } Printer.addView( llvm::make_unique<mca::ResourcePressureView>(*STI, *IP, Insts)); if (!runPipeline(*P)) return 1; Printer.printReport(TOF->os()); continue; } // Create a basic pipeline simulating an out-of-order backend. auto P = MCA.createDefaultPipeline(PO, IB, S); mca::PipelinePrinter Printer(*P); if (PrintSummaryView) Printer.addView(llvm::make_unique<mca::SummaryView>( SM, Insts, DispatchWidth)); if (EnableBottleneckAnalysis) Printer.addView(llvm::make_unique<mca::BottleneckAnalysis>(SM)); if (PrintInstructionInfoView) Printer.addView( llvm::make_unique<mca::InstructionInfoView>(*STI, *MCII, Insts, *IP)); if (PrintDispatchStats) Printer.addView(llvm::make_unique<mca::DispatchStatistics>()); if (PrintSchedulerStats) Printer.addView(llvm::make_unique<mca::SchedulerStatistics>(*STI)); if (PrintRetireStats) Printer.addView(llvm::make_unique<mca::RetireControlUnitStatistics>(SM)); if (PrintRegisterFileStats) Printer.addView(llvm::make_unique<mca::RegisterFileStatistics>(*STI)); if (PrintResourcePressureView) Printer.addView( llvm::make_unique<mca::ResourcePressureView>(*STI, *IP, Insts)); if (PrintTimelineView) { unsigned TimelineIterations = TimelineMaxIterations ? TimelineMaxIterations : 10; Printer.addView(llvm::make_unique<mca::TimelineView>( *STI, *IP, Insts, std::min(TimelineIterations, S.getNumIterations()), TimelineMaxCycles)); } if (!runPipeline(*P)) return 1; Printer.printReport(TOF->os()); // Clear the InstrBuilder internal state in preparation for another round. IB.clear(); } TOF->keep(); return 0; }
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; }
IRObjectFile::IRObjectFile(MemoryBufferRef Object, std::unique_ptr<Module> Mod) : SymbolicFile(Binary::ID_IR, Object), M(std::move(Mod)) { Mang.reset(new Mangler()); const std::string &InlineAsm = M->getModuleInlineAsm(); if (InlineAsm.empty()) return; Triple TT(M->getTargetTriple()); std::string Err; const Target *T = TargetRegistry::lookupTarget(TT.str(), Err); if (!T) return; std::unique_ptr<MCRegisterInfo> MRI(T->createMCRegInfo(TT.str())); if (!MRI) return; std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, TT.str())); if (!MAI) return; std::unique_ptr<MCSubtargetInfo> STI( T->createMCSubtargetInfo(TT.str(), "", "")); if (!STI) return; std::unique_ptr<MCInstrInfo> MCII(T->createMCInstrInfo()); if (!MCII) return; MCObjectFileInfo MOFI; MCContext MCCtx(MAI.get(), MRI.get(), &MOFI); MOFI.InitMCObjectFileInfo(TT, Reloc::Default, CodeModel::Default, MCCtx); std::unique_ptr<RecordStreamer> Streamer(new RecordStreamer(MCCtx)); T->createNullTargetStreamer(*Streamer); std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer(InlineAsm)); SourceMgr SrcMgr; SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc()); std::unique_ptr<MCAsmParser> Parser( createMCAsmParser(SrcMgr, MCCtx, *Streamer, *MAI)); MCTargetOptions MCOptions; std::unique_ptr<MCTargetAsmParser> TAP( T->createMCAsmParser(*STI, *Parser, *MCII, MCOptions)); if (!TAP) return; Parser->setTargetParser(*TAP); if (Parser->Run(false)) return; for (auto &KV : *Streamer) { StringRef Key = KV.first(); RecordStreamer::State Value = KV.second; uint32_t Res = BasicSymbolRef::SF_None; switch (Value) { case RecordStreamer::NeverSeen: llvm_unreachable("foo"); case RecordStreamer::DefinedGlobal: Res |= BasicSymbolRef::SF_Global; break; case RecordStreamer::Defined: break; case RecordStreamer::Global: case RecordStreamer::Used: Res |= BasicSymbolRef::SF_Undefined; Res |= BasicSymbolRef::SF_Global; break; } AsmSymbols.push_back( std::make_pair<std::string, uint32_t>(Key, std::move(Res))); } }
// Parse inline ASM and collect the list of symbols that are not defined in // the current module. This is inspired from IRObjectFile. void IRObjectFile::CollectAsmUndefinedRefs( const Triple &TT, StringRef InlineAsm, function_ref<void(StringRef, BasicSymbolRef::Flags)> AsmUndefinedRefs) { if (InlineAsm.empty()) return; std::string Err; const Target *T = TargetRegistry::lookupTarget(TT.str(), Err); if (!T) return; std::unique_ptr<MCRegisterInfo> MRI(T->createMCRegInfo(TT.str())); if (!MRI) return; std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, TT.str())); if (!MAI) return; std::unique_ptr<MCSubtargetInfo> STI( T->createMCSubtargetInfo(TT.str(), "", "")); if (!STI) return; std::unique_ptr<MCInstrInfo> MCII(T->createMCInstrInfo()); if (!MCII) return; MCObjectFileInfo MOFI; MCContext MCCtx(MAI.get(), MRI.get(), &MOFI); MOFI.InitMCObjectFileInfo(TT, /*PIC*/ false, CodeModel::Default, MCCtx); std::unique_ptr<RecordStreamer> Streamer(new RecordStreamer(MCCtx)); T->createNullTargetStreamer(*Streamer); std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer(InlineAsm)); SourceMgr SrcMgr; SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc()); std::unique_ptr<MCAsmParser> Parser( createMCAsmParser(SrcMgr, MCCtx, *Streamer, *MAI)); MCTargetOptions MCOptions; std::unique_ptr<MCTargetAsmParser> TAP( T->createMCAsmParser(*STI, *Parser, *MCII, MCOptions)); if (!TAP) return; Parser->setTargetParser(*TAP); if (Parser->Run(false)) return; for (auto &KV : *Streamer) { StringRef Key = KV.first(); RecordStreamer::State Value = KV.second; uint32_t Res = BasicSymbolRef::SF_None; switch (Value) { case RecordStreamer::NeverSeen: llvm_unreachable("NeverSeen should have been replaced earlier"); case RecordStreamer::DefinedGlobal: Res |= BasicSymbolRef::SF_Global; break; case RecordStreamer::Defined: break; case RecordStreamer::Global: case RecordStreamer::Used: Res |= BasicSymbolRef::SF_Undefined; Res |= BasicSymbolRef::SF_Global; break; case RecordStreamer::DefinedWeak: Res |= BasicSymbolRef::SF_Weak; Res |= BasicSymbolRef::SF_Global; break; case RecordStreamer::UndefinedWeak: Res |= BasicSymbolRef::SF_Weak; Res |= BasicSymbolRef::SF_Undefined; } AsmUndefinedRefs(Key, BasicSymbolRef::Flags(Res)); } }
int main(int argc, char **argv) { ParseCommandLineOptions(argc, argv, "merge split dwarf (.dwo) files"); llvm::InitializeAllTargetInfos(); llvm::InitializeAllTargetMCs(); llvm::InitializeAllTargets(); llvm::InitializeAllAsmPrinters(); std::string ErrorStr; StringRef Context = "dwarf streamer init"; Triple TheTriple("x86_64-linux-gnu"); // Get the target. const Target *TheTarget = TargetRegistry::lookupTarget("", TheTriple, ErrorStr); if (!TheTarget) return error(ErrorStr, Context); std::string TripleName = TheTriple.getTriple(); // Create all the MC Objects. std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); if (!MRI) return error(Twine("no register info for target ") + TripleName, Context); std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TripleName)); if (!MAI) return error("no asm info for target " + TripleName, Context); MCObjectFileInfo MOFI; MCContext MC(MAI.get(), MRI.get(), &MOFI); MOFI.InitMCObjectFileInfo(TheTriple, Reloc::Default, CodeModel::Default, MC); auto MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, ""); if (!MAB) return error("no asm backend for target " + TripleName, Context); std::unique_ptr<MCInstrInfo> MII(TheTarget->createMCInstrInfo()); if (!MII) return error("no instr info info for target " + TripleName, Context); std::unique_ptr<MCSubtargetInfo> MSTI( TheTarget->createMCSubtargetInfo(TripleName, "", "")); if (!MSTI) return error("no subtarget info for target " + TripleName, Context); MCCodeEmitter *MCE = TheTarget->createMCCodeEmitter(*MII, *MRI, MC); if (!MCE) return error("no code emitter for target " + TripleName, Context); // Create the output file. std::error_code EC; raw_fd_ostream OutFile(OutputFilename, EC, sys::fs::F_None); if (EC) return error(Twine(OutputFilename) + ": " + EC.message(), Context); MCTargetOptions MCOptions = InitMCTargetOptionsFromFlags(); std::unique_ptr<MCStreamer> MS(TheTarget->createMCObjectStreamer( TheTriple, MC, *MAB, OutFile, MCE, *MSTI, MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible, /*DWARFMustBeAtTheEnd*/ false)); if (!MS) return error("no object streamer for target " + TripleName, Context); if (auto Err = write(*MS, InputFiles)) return error(Err.message(), "Writing DWP file"); MS->Finish(); }
void ModuleSymbolTable::CollectAsmSymbols( const Module &M, function_ref<void(StringRef, BasicSymbolRef::Flags)> AsmSymbol) { StringRef InlineAsm = M.getModuleInlineAsm(); if (InlineAsm.empty()) return; std::string Err; const Triple TT(M.getTargetTriple()); const Target *T = TargetRegistry::lookupTarget(TT.str(), Err); assert(T && T->hasMCAsmParser()); std::unique_ptr<MCRegisterInfo> MRI(T->createMCRegInfo(TT.str())); if (!MRI) return; std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, TT.str())); if (!MAI) return; std::unique_ptr<MCSubtargetInfo> STI( T->createMCSubtargetInfo(TT.str(), "", "")); if (!STI) return; std::unique_ptr<MCInstrInfo> MCII(T->createMCInstrInfo()); if (!MCII) return; MCObjectFileInfo MOFI; MCContext MCCtx(MAI.get(), MRI.get(), &MOFI); MOFI.InitMCObjectFileInfo(TT, /*PIC*/ false, MCCtx); RecordStreamer Streamer(MCCtx, M); T->createNullTargetStreamer(Streamer); std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer(InlineAsm)); SourceMgr SrcMgr; SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc()); std::unique_ptr<MCAsmParser> Parser( createMCAsmParser(SrcMgr, MCCtx, Streamer, *MAI)); MCTargetOptions MCOptions; std::unique_ptr<MCTargetAsmParser> TAP( T->createMCAsmParser(*STI, *Parser, *MCII, MCOptions)); if (!TAP) return; Parser->setTargetParser(*TAP); if (Parser->Run(false)) return; Streamer.flushSymverDirectives(); for (auto &KV : Streamer) { StringRef Key = KV.first(); RecordStreamer::State Value = KV.second; // FIXME: For now we just assume that all asm symbols are executable. uint32_t Res = BasicSymbolRef::SF_Executable; switch (Value) { case RecordStreamer::NeverSeen: llvm_unreachable("NeverSeen should have been replaced earlier"); case RecordStreamer::DefinedGlobal: Res |= BasicSymbolRef::SF_Global; break; case RecordStreamer::Defined: break; case RecordStreamer::Global: case RecordStreamer::Used: Res |= BasicSymbolRef::SF_Undefined; Res |= BasicSymbolRef::SF_Global; break; case RecordStreamer::DefinedWeak: Res |= BasicSymbolRef::SF_Weak; Res |= BasicSymbolRef::SF_Global; break; case RecordStreamer::UndefinedWeak: Res |= BasicSymbolRef::SF_Weak; Res |= BasicSymbolRef::SF_Undefined; } AsmSymbol(Key, BasicSymbolRef::Flags(Res)); } }
int main(int ac, char **av) { SourceMgr SrcMgr; //LLVMInitializeX86TargetInfo(); llvm::InitializeAllTargetInfos(); //LLVMInitializeX86AsmParser(); llvm::InitializeAllTargetMCs(); //LLVMInitializeX86TargetMC(); llvm::InitializeAllAsmParsers(); //LLVMInitializeX86AsmParser(); llvm::InitializeAllDisassemblers(); //LLVMInitializeX86Disassembler(); // arg0: // llvm::Target encapsulating the "x86_64-apple-darwin14.5.0" information // see /lib/Support/Triple.cpp for the details //spec = llvm::sys::getDefaultTargetTriple(); //std::string machSpec = "x86_64-apple-windows"; // will produce a COFF //std::string machSpec = "x86_64-apple-darwin14.5.0"; // will produce a Mach-O std::string machSpec = "arm-none-none-eabi"; // //std::string machSpec = "x86_64-apple-darwin"; //std::string machSpec = "x86_64-thumb-linux-gnu"; //std::string machSpec = "x86_64-unknown-linux-gnu"; printf("machine spec: %s\n", machSpec.c_str()); machSpec = Triple::normalize(machSpec); printf("machine spec (normalized): %s\n", machSpec.c_str()); Triple TheTriple(machSpec); // Get the target specific parser. std::string Error; const Target *TheTarget = TargetRegistry::lookupTarget(/*arch*/"", TheTriple, Error); if (!TheTarget) { errs() << Error; return -1; } machSpec = TheTriple.getTriple(); printf("machine spec (returned): %s\n", machSpec.c_str()); printf("Target.getName(): %s\n", TheTarget->getName()); printf("Target.getShortDescription(): %s\n", TheTarget->getShortDescription()); /* from the target we get almost everything */ std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(machSpec)); std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, machSpec)); std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); /* describes target instruction set */ MCSubtargetInfo *STI = TheTarget->createMCSubtargetInfo(machSpec, "", ""); /* subtarget instr set */ MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, machSpec, /* specific CPU */ ""); // arg0: // llvm::SourceMgr (Support/SourceMgr.h) that holds assembler source // has vector of llvm::SrcBuffer encaps (Support/MemoryBuffer.h) and vector of include dirs //std::string asmSrc = ".org 0x100, 0xAA\nfoo:\nxor %eax, %ebx\npush %rbp\njmp foo\nrdtsc\n"; //std::string asmSrc = ".text\n" "ldr pc, data_foo\n" "\n" "data_foo:\n" " .int 0x8\n" "\n" "loop:\n" "b loop\n"; //std::string asmSrc = ".text\n" "mov r2, r1\n"; std::string asmSrc = ".text\n" "ldr pc, data_foo\n" "data_foo:\n" ".int 0x8\n" "loop:\n" "b loop\n"; std::unique_ptr<MemoryBuffer> memBuf = MemoryBuffer::getMemBuffer(asmSrc); SrcMgr.AddNewSourceBuffer(std::move(memBuf), SMLoc()); // arg1: the machine code context MCObjectFileInfo MOFI; MCContext Ctx(MAI.get(), MRI.get(), &MOFI, &SrcMgr); MOFI.InitMCObjectFileInfo(TheTriple, Reloc::Default, CodeModel::Default, Ctx); // this is the assembler interface // -methods per .s statements (emit bytes, handle directive, etc.) // -remembers current section // -implementations that write a .s, or .o in various formats // // 1. the output stream ... a formatted_raw_ostream wraps a raw_ostream to provide // tracking of line and column position for padding and shit // // but raw_ostream is abstract and is implemented by raw_fd_ostream, raw_string_ostream, etc. /* output stream: raw_svector_ostream is a raw_pwrite_stream is a raw_ostream since a SmallString is SmallVector (svector) we can use this and retrieve bytes later with its .data() method */ SmallString<1024> smallString; raw_svector_ostream rso(smallString); /* code emitter needs 1) instruction set info 2) register info */ MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx); MCStreamer *as = TheTarget->createMCObjectStreamer( TheTriple, /* Triple */ Ctx, /* the MCContext */ *MAB, /* the AsmBackend, (fixups, relaxation, objs and elfs) */ rso, /* output stream raw_pwrite_stream */ CE, /* code emitter */ *STI, /* subtarget info */ true, /* relax all fixups */ true, /* incremental linker compatible */ false /* DWARFMustBeAtTheEnd */ ); std::string abi = "none"; MCTargetOptions toptions; toptions.MCUseDwarfDirectory = false; toptions.ABIName = abi; printf("trying to assemble, let's go..\n"); AssembleInput(TheTarget, SrcMgr, Ctx, *as, *MAI, *STI, *MCII, toptions); printf("done with AssembleInput()\n"); /* dump to file for debugging */ FILE *fp; fp = fopen("out.bin", "wb"); fwrite(smallString.data(), 1, smallString.size(), fp); fclose(fp); //int n = smallString.size(); int codeOffset=0, codeSize = 0; char *data = smallString.data(); if(*(uint32_t *)data == 0xFEEDFACF) { unsigned int idx = 0; idx += 0x20; /* skip mach_header_64 to first command */ idx += 0x48; /* advance into segment_command_64 to first section */ idx += 0x28; /* advance into section_64 to size */ uint64_t scn_size = *(uint64_t *)(data + idx); idx += 0x8; /* advance into section_64 to offset */ uint64_t scn_offset = *(uint64_t *)(data + idx); codeOffset = scn_offset; codeSize = scn_size; } else if(0==memcmp(data, "\x7F" "ELF\x01\x01\x01\x00", 8)) { /* assume four sections: NULL, .strtab, .text, .symtab */ uint32_t e_shoff = *(uint32_t *)(data + 0x20); uint32_t sh_offset = *(uint32_t *)(data + e_shoff + 2*0x28 + 0x10); /* second shdr */ uint32_t sh_size = *(uint32_t *)(data + e_shoff + 2*0x28 + 0x14); /* second shdr */ codeOffset = sh_offset; codeSize = sh_size; } else { printf("ERROR: couldn't identify type of output file\n"); } dump_bytes((unsigned char *)data + codeOffset, codeSize, 0); return 0; }
int main(int argc, char **argv) { InitLLVM X(argc, argv); // Initialize targets and assembly parsers. llvm::InitializeAllTargetInfos(); llvm::InitializeAllTargetMCs(); llvm::InitializeAllAsmParsers(); // Enable printing of available targets when flag --version is specified. cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion); cl::HideUnrelatedOptions({&ToolOptions, &ViewOptions}); // Parse flags and initialize target options. cl::ParseCommandLineOptions(argc, argv, "llvm machine code performance analyzer.\n"); MCTargetOptions MCOptions; MCOptions.PreserveAsmComments = false; // Get the target from the triple. If a triple is not specified, then select // the default triple for the host. If the triple doesn't correspond to any // registered target, then exit with an error message. const char *ProgName = argv[0]; const Target *TheTarget = getTarget(ProgName); if (!TheTarget) return 1; // GetTarget() may replaced TripleName with a default triple. // For safety, reconstruct the Triple object. Triple TheTriple(TripleName); ErrorOr<std::unique_ptr<MemoryBuffer>> BufferPtr = MemoryBuffer::getFileOrSTDIN(InputFilename); if (std::error_code EC = BufferPtr.getError()) { WithColor::error() << InputFilename << ": " << EC.message() << '\n'; return 1; } // Apply overrides to llvm-mca specific options. processViewOptions(); SourceMgr SrcMgr; // Tell SrcMgr about this buffer, which is what the parser will pick up. SrcMgr.AddNewSourceBuffer(std::move(*BufferPtr), SMLoc()); 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!"); MCObjectFileInfo MOFI; MCContext Ctx(MAI.get(), MRI.get(), &MOFI, &SrcMgr); MOFI.InitMCObjectFileInfo(TheTriple, /* PIC= */ false, Ctx); std::unique_ptr<buffer_ostream> BOS; mca::CodeRegions Regions(SrcMgr); MCStreamerWrapper Str(Ctx, Regions); std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); std::unique_ptr<MCInstrAnalysis> MCIA( TheTarget->createMCInstrAnalysis(MCII.get())); if (!MCPU.compare("native")) MCPU = llvm::sys::getHostCPUName(); std::unique_ptr<MCSubtargetInfo> STI( TheTarget->createMCSubtargetInfo(TripleName, MCPU, /* FeaturesStr */ "")); if (!STI->isCPUStringValid(MCPU)) return 1; if (!PrintInstructionTables && !STI->getSchedModel().isOutOfOrder()) { WithColor::error() << "please specify an out-of-order cpu. '" << MCPU << "' is an in-order cpu.\n"; return 1; } if (!STI->getSchedModel().hasInstrSchedModel()) { WithColor::error() << "unable to find instruction-level scheduling information for" << " target triple '" << TheTriple.normalize() << "' and cpu '" << MCPU << "'.\n"; if (STI->getSchedModel().InstrItineraries) WithColor::note() << "cpu '" << MCPU << "' provides itineraries. However, " << "instruction itineraries are currently unsupported.\n"; return 1; } std::unique_ptr<MCAsmParser> P(createMCAsmParser(SrcMgr, Ctx, Str, *MAI)); MCAsmLexer &Lexer = P->getLexer(); MCACommentConsumer CC(Regions); Lexer.setCommentConsumer(&CC); if (AssembleInput(ProgName, *P, TheTarget, *STI, *MCII, MCOptions)) return 1; if (Regions.empty()) { WithColor::error() << "no assembly instructions found.\n"; return 1; } // Now initialize the output file. auto OF = getOutputStream(); if (std::error_code EC = OF.getError()) { WithColor::error() << EC.message() << '\n'; return 1; } unsigned AssemblerDialect = P->getAssemblerDialect(); if (OutputAsmVariant >= 0) AssemblerDialect = static_cast<unsigned>(OutputAsmVariant); std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter( Triple(TripleName), AssemblerDialect, *MAI, *MCII, *MRI)); if (!IP) { WithColor::error() << "unable to create instruction printer for target triple '" << TheTriple.normalize() << "' with assembly variant " << AssemblerDialect << ".\n"; return 1; } std::unique_ptr<llvm::ToolOutputFile> TOF = std::move(*OF); const MCSchedModel &SM = STI->getSchedModel(); unsigned Width = SM.IssueWidth; if (DispatchWidth) Width = DispatchWidth; // Create an instruction builder. mca::InstrBuilder IB(*STI, *MCII, *MRI, *MCIA, *IP); // Create a context to control ownership of the pipeline hardware. mca::Context MCA(*MRI, *STI); mca::PipelineOptions PO(Width, RegisterFileSize, LoadQueueSize, StoreQueueSize, AssumeNoAlias); // Number each region in the sequence. unsigned RegionIdx = 0; for (const std::unique_ptr<mca::CodeRegion> &Region : Regions) { // Skip empty code regions. if (Region->empty()) continue; // Don't print the header of this region if it is the default region, and // it doesn't have an end location. if (Region->startLoc().isValid() || Region->endLoc().isValid()) { TOF->os() << "\n[" << RegionIdx++ << "] Code Region"; StringRef Desc = Region->getDescription(); if (!Desc.empty()) TOF->os() << " - " << Desc; TOF->os() << "\n\n"; } mca::SourceMgr S(Region->getInstructions(), PrintInstructionTables ? 1 : Iterations); if (PrintInstructionTables) { // Create a pipeline, stages, and a printer. auto P = llvm::make_unique<mca::Pipeline>(); P->appendStage(llvm::make_unique<mca::FetchStage>(IB, S)); P->appendStage(llvm::make_unique<mca::InstructionTables>(SM, IB)); mca::PipelinePrinter Printer(*P); // Create the views for this pipeline, execute, and emit a report. if (PrintInstructionInfoView) { Printer.addView( llvm::make_unique<mca::InstructionInfoView>(*STI, *MCII, S, *IP)); } Printer.addView( llvm::make_unique<mca::ResourcePressureView>(*STI, *IP, S)); P->run(); Printer.printReport(TOF->os()); continue; } // Create a basic pipeline simulating an out-of-order backend. auto P = MCA.createDefaultPipeline(PO, IB, S); mca::PipelinePrinter Printer(*P); if (PrintSummaryView) Printer.addView(llvm::make_unique<mca::SummaryView>(SM, S, Width)); if (PrintInstructionInfoView) Printer.addView( llvm::make_unique<mca::InstructionInfoView>(*STI, *MCII, S, *IP)); if (PrintDispatchStats) Printer.addView(llvm::make_unique<mca::DispatchStatistics>()); if (PrintSchedulerStats) Printer.addView(llvm::make_unique<mca::SchedulerStatistics>(*STI)); if (PrintRetireStats) Printer.addView(llvm::make_unique<mca::RetireControlUnitStatistics>()); if (PrintRegisterFileStats) Printer.addView(llvm::make_unique<mca::RegisterFileStatistics>(*STI)); if (PrintResourcePressureView) Printer.addView( llvm::make_unique<mca::ResourcePressureView>(*STI, *IP, S)); if (PrintTimelineView) { Printer.addView(llvm::make_unique<mca::TimelineView>( *STI, *IP, S, TimelineMaxIterations, TimelineMaxCycles)); } P->run(); Printer.printReport(TOF->os()); // Clear the InstrBuilder internal state in preparation for another round. IB.clear(); } TOF->keep(); return 0; }