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; }
bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM) { PatternLoc = SMLoc::getFromPointer(PatternStr.data()); // Ignore trailing whitespace. while (!PatternStr.empty() && (PatternStr.back() == ' ' || PatternStr.back() == '\t')) PatternStr = PatternStr.substr(0, PatternStr.size()-1); // Check that there is something on the line. if (PatternStr.empty()) { SM.PrintMessage(PatternLoc, "found empty check string with prefix '" + CheckPrefix+":'", "error"); return true; } // Check to see if this is a fixed string, or if it has regex pieces. if (PatternStr.size() < 2 || (PatternStr.find("{{") == StringRef::npos && PatternStr.find("[[") == StringRef::npos)) { FixedStr = PatternStr; return false; } // Paren value #0 is for the fully matched string. Any new parenthesized // values add from their. unsigned CurParen = 1; // Otherwise, there is at least one regex piece. Build up the regex pattern // by escaping scary characters in fixed strings, building up one big regex. while (!PatternStr.empty()) { // RegEx matches. if (PatternStr.size() >= 2 && PatternStr[0] == '{' && PatternStr[1] == '{') { // Otherwise, this is the start of a regex match. Scan for the }}. size_t End = PatternStr.find("}}"); if (End == StringRef::npos) { SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()), "found start of regex string with no end '}}'", "error"); return true; } if (AddRegExToRegEx(PatternStr.substr(2, End-2), CurParen, SM)) return true; PatternStr = PatternStr.substr(End+2); continue; } // Named RegEx matches. These are of two forms: [[foo:.*]] which matches .* // (or some other regex) and assigns it to the FileCheck variable 'foo'. The // second form is [[foo]] which is a reference to foo. The variable name // itself must be of the form "[a-zA-Z_][0-9a-zA-Z_]*", otherwise we reject // it. This is to catch some common errors. if (PatternStr.size() >= 2 && PatternStr[0] == '[' && PatternStr[1] == '[') { // Verify that it is terminated properly. size_t End = PatternStr.find("]]"); if (End == StringRef::npos) { SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()), "invalid named regex reference, no ]] found", "error"); return true; } StringRef MatchStr = PatternStr.substr(2, End-2); PatternStr = PatternStr.substr(End+2); // Get the regex name (e.g. "foo"). size_t NameEnd = MatchStr.find(':'); StringRef Name = MatchStr.substr(0, NameEnd); if (Name.empty()) { SM.PrintMessage(SMLoc::getFromPointer(Name.data()), "invalid name in named regex: empty name", "error"); return true; } // Verify that the name is well formed. for (unsigned i = 0, e = Name.size(); i != e; ++i) if (Name[i] != '_' && (Name[i] < 'a' || Name[i] > 'z') && (Name[i] < 'A' || Name[i] > 'Z') && (Name[i] < '0' || Name[i] > '9')) { SM.PrintMessage(SMLoc::getFromPointer(Name.data()+i), "invalid name in named regex", "error"); return true; } // Name can't start with a digit. if (isdigit(Name[0])) { SM.PrintMessage(SMLoc::getFromPointer(Name.data()), "invalid name in named regex", "error"); return true; } // Handle [[foo]]. if (NameEnd == StringRef::npos) { VariableUses.push_back(std::make_pair(Name, RegExStr.size())); continue; } // Handle [[foo:.*]]. VariableDefs.push_back(std::make_pair(Name, CurParen)); RegExStr += '('; ++CurParen; if (AddRegExToRegEx(MatchStr.substr(NameEnd+1), CurParen, SM)) return true; RegExStr += ')'; } // Handle fixed string matches. // Find the end, which is the start of the next regex. size_t FixedMatchEnd = PatternStr.find("{{"); FixedMatchEnd = std::min(FixedMatchEnd, PatternStr.find("[[")); AddFixedStringToRegEx(PatternStr.substr(0, FixedMatchEnd), RegExStr); PatternStr = PatternStr.substr(FixedMatchEnd); continue; } return false; }
/// ReadCheckFile - Read the check file, which specifies the sequence of /// expected strings. The strings are added to the CheckStrings vector. static bool ReadCheckFile(SourceMgr &SM, std::vector<CheckString> &CheckStrings) { // Open the check file, and tell SourceMgr about it. std::string ErrorStr; MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(CheckFilename.c_str(), &ErrorStr); if (F == 0) { errs() << "Could not open check file '" << CheckFilename << "': " << ErrorStr << '\n'; return true; } // If we want to canonicalize whitespace, strip excess whitespace from the // buffer containing the CHECK lines. if (!NoCanonicalizeWhiteSpace) F = CanonicalizeInputFile(F); SM.AddNewSourceBuffer(F, SMLoc()); // Find all instances of CheckPrefix followed by : in the file. StringRef Buffer = F->getBuffer(); std::vector<std::pair<SMLoc, Pattern> > NotMatches; while (1) { // See if Prefix occurs in the memory buffer. Buffer = Buffer.substr(Buffer.find(CheckPrefix)); // If we didn't find a match, we're done. if (Buffer.empty()) break; const char *CheckPrefixStart = Buffer.data(); // When we find a check prefix, keep track of whether we find CHECK: or // CHECK-NEXT: bool IsCheckNext = false, IsCheckNot = false; // Verify that the : is present after the prefix. if (Buffer[CheckPrefix.size()] == ':') { Buffer = Buffer.substr(CheckPrefix.size()+1); } else if (Buffer.size() > CheckPrefix.size()+6 && memcmp(Buffer.data()+CheckPrefix.size(), "-NEXT:", 6) == 0) { Buffer = Buffer.substr(CheckPrefix.size()+7); IsCheckNext = true; } else if (Buffer.size() > CheckPrefix.size()+5 && memcmp(Buffer.data()+CheckPrefix.size(), "-NOT:", 5) == 0) { Buffer = Buffer.substr(CheckPrefix.size()+6); IsCheckNot = true; } else { Buffer = Buffer.substr(1); continue; } // Okay, we found the prefix, yay. Remember the rest of the line, but // ignore leading and trailing whitespace. Buffer = Buffer.substr(Buffer.find_first_not_of(" \t")); // Scan ahead to the end of line. size_t EOL = Buffer.find_first_of("\n\r"); // Remember the location of the start of the pattern, for diagnostics. SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data()); // Parse the pattern. Pattern P; if (P.ParsePattern(Buffer.substr(0, EOL), SM)) return true; Buffer = Buffer.substr(EOL); // Verify that CHECK-NEXT lines have at least one CHECK line before them. if (IsCheckNext && CheckStrings.empty()) { SM.PrintMessage(SMLoc::getFromPointer(CheckPrefixStart), "found '"+CheckPrefix+"-NEXT:' without previous '"+ CheckPrefix+ ": line", "error"); return true; } // Handle CHECK-NOT. if (IsCheckNot) { NotMatches.push_back(std::make_pair(SMLoc::getFromPointer(Buffer.data()), P)); continue; } // Okay, add the string we captured to the output vector and move on. CheckStrings.push_back(CheckString(P, PatternLoc, IsCheckNext)); std::swap(NotMatches, CheckStrings.back().NotStrings); } if (CheckStrings.empty()) { errs() << "error: no check strings found with prefix '" << CheckPrefix << ":'\n"; return true; } if (!NotMatches.empty()) { errs() << "error: '" << CheckPrefix << "-NOT:' not supported after last check line.\n"; return true; } return false; }
/// EmitInlineAsm - Emit a blob of inline asm to the output streamer. void AsmPrinter::EmitInlineAsm(StringRef Str, const MDNode *LocMDNode, InlineAsm::AsmDialect Dialect) const { assert(!Str.empty() && "Can't emit empty inline asm block"); // Remember if the buffer is nul terminated or not so we can avoid a copy. bool isNullTerminated = Str.back() == 0; if (isNullTerminated) Str = Str.substr(0, Str.size()-1); // If the output streamer does not have mature MC support or the integrated // assembler has been disabled, just emit the blob textually. // Otherwise parse the asm and emit it via MC support. // This is useful in case the asm parser doesn't handle something but the // system assembler does. const MCAsmInfo *MCAI = TM.getMCAsmInfo(); assert(MCAI && "No MCAsmInfo"); if (!MCAI->useIntegratedAssembler() && !OutStreamer.isIntegratedAssemblerRequired()) { OutStreamer.EmitRawText(Str); emitInlineAsmEnd(TM.getSubtarget<MCSubtargetInfo>(), 0); return; } SourceMgr SrcMgr; SrcMgrDiagInfo DiagInfo; // If the current LLVMContext has an inline asm handler, set it in SourceMgr. LLVMContext &LLVMCtx = MMI->getModule()->getContext(); bool HasDiagHandler = false; if (LLVMCtx.getInlineAsmDiagnosticHandler() != 0) { // If the source manager has an issue, we arrange for srcMgrDiagHandler // to be invoked, getting DiagInfo passed into it. DiagInfo.LocInfo = LocMDNode; DiagInfo.DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler(); DiagInfo.DiagContext = LLVMCtx.getInlineAsmDiagnosticContext(); SrcMgr.setDiagHandler(srcMgrDiagHandler, &DiagInfo); HasDiagHandler = true; } MemoryBuffer *Buffer; if (isNullTerminated) Buffer = MemoryBuffer::getMemBuffer(Str, "<inline asm>"); else Buffer = MemoryBuffer::getMemBufferCopy(Str, "<inline asm>"); // Tell SrcMgr about this buffer, it takes ownership of the buffer. SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); std::unique_ptr<MCAsmParser> Parser( createMCAsmParser(SrcMgr, OutContext, OutStreamer, *MAI)); // Initialize the parser with a fresh subtarget info. It is better to use a // new STI here because the parser may modify it and we do not want those // modifications to persist after parsing the inlineasm. The modifications // made by the parser will be seen by the code emitters because it passes // the current STI down to the EncodeInstruction() method. std::unique_ptr<MCSubtargetInfo> STI(TM.getTarget().createMCSubtargetInfo( TM.getTargetTriple(), TM.getTargetCPU(), TM.getTargetFeatureString())); // Preserve a copy of the original STI because the parser may modify it. For // example, when switching between arm and thumb mode. If the target needs to // emit code to return to the original state it can do so in // emitInlineAsmEnd(). MCSubtargetInfo STIOrig = *STI; std::unique_ptr<MCTargetAsmParser> TAP( TM.getTarget().createMCAsmParser(*STI, *Parser, *MII)); if (!TAP) report_fatal_error("Inline asm not supported by this streamer because" " we don't have an asm parser for this target\n"); Parser->setAssemblerDialect(Dialect); Parser->setTargetParser(*TAP.get()); // Don't implicitly switch to the text section before the asm. int Res = Parser->Run(/*NoInitialTextSection*/ true, /*NoFinalize*/ true); emitInlineAsmEnd(STIOrig, STI.get()); if (Res && !HasDiagHandler) report_fatal_error("Error parsing inline asm\n"); }
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; OwningPtr<MemoryBuffer> BufferPtr; if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, BufferPtr)) { errs() << ProgName << ": " << ec.message() << '\n'; return 1; } 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(IncludeDirs); llvm::OwningPtr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); assert(MRI && "Unable to create target register info!"); llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TripleName)); assert(MAI && "Unable to create target asm info!"); // 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.get(), MRI.get(), MOFI.get(), &SrcMgr); MOFI->InitMCObjectFileInfo(TripleName, RelocModel, CMModel, Ctx); if (SaveTempLabels) Ctx.setAllowTemporaryLabels(false); Ctx.setGenDwarfForAssembly(GenDwarfForAssembly); 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(); } OwningPtr<tool_output_file> Out(GetOutputStream()); if (!Out) return 1; formatted_raw_ostream FOS(Out->os()); OwningPtr<MCStreamer> Str; OwningPtr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); OwningPtr<MCSubtargetInfo> STI(TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr)); MCInstPrinter *IP = NULL; if (FileType == OFT_AssemblyFile) { IP = TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI, *MCII, *MRI, *STI); MCCodeEmitter *CE = 0; MCAsmBackend *MAB = 0; if (ShowEncoding) { CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx); MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU); } bool UseCFI = !DisableCFI; Str.reset(TheTarget->createAsmStreamer( Ctx, FOS, /*asmverbose*/ true, UseCFI, /*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_HDisassemble: assert(IP && "Expected assembly output"); IP->setPrintImmHex(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 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); } // 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 = 1; // 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; }
void PrintWarning(const char *Loc, const Twine &Msg) { SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), SourceMgr::DK_Warning, Msg); }
int Disassembler::disassemble(const Target &T, const std::string &Triple, MCSubtargetInfo &STI, MCStreamer &Streamer, MemoryBuffer &Buffer, SourceMgr &SM, raw_ostream &Out) { std::unique_ptr<const MCRegisterInfo> MRI(T.createMCRegInfo(Triple)); if (!MRI) { errs() << "error: no register info for target " << Triple << "\n"; return -1; } std::unique_ptr<const MCAsmInfo> MAI(T.createMCAsmInfo(*MRI, Triple)); if (!MAI) { errs() << "error: no assembly info for target " << Triple << "\n"; return -1; } // Set up the MCContext for creating symbols and MCExpr's. MCContext Ctx(MAI.get(), MRI.get(), nullptr); std::unique_ptr<const MCDisassembler> DisAsm( T.createMCDisassembler(STI, Ctx)); if (!DisAsm) { errs() << "error: no disassembler for target " << Triple << "\n"; return -1; } // Set up initial section manually here Streamer.InitSections(false); bool ErrorOccurred = false; // Convert the input to a vector for disassembly. ByteArrayTy ByteArray; StringRef Str = Buffer.getBuffer(); bool InAtomicBlock = false; while (SkipToToken(Str)) { ByteArray.first.clear(); ByteArray.second.clear(); if (Str[0] == '[') { if (InAtomicBlock) { SM.PrintMessage(SMLoc::getFromPointer(Str.data()), SourceMgr::DK_Error, "nested atomic blocks make no sense"); ErrorOccurred = true; } InAtomicBlock = true; Str = Str.drop_front(); continue; } else if (Str[0] == ']') { if (!InAtomicBlock) { SM.PrintMessage(SMLoc::getFromPointer(Str.data()), SourceMgr::DK_Error, "attempt to close atomic block without opening"); ErrorOccurred = true; } InAtomicBlock = false; Str = Str.drop_front(); continue; } // It's a real token, get the bytes and emit them ErrorOccurred |= ByteArrayFromString(ByteArray, Str, SM); if (!ByteArray.first.empty()) ErrorOccurred |= PrintInsts(*DisAsm, ByteArray, SM, Out, Streamer, InAtomicBlock, STI); } if (InAtomicBlock) { SM.PrintMessage(SMLoc::getFromPointer(Str.data()), SourceMgr::DK_Error, "unclosed atomic block"); ErrorOccurred = true; } return ErrorOccurred; }
static int AsLexInput(SourceMgr &SrcMgr, MCAsmInfo &MAI, raw_ostream &OS) { AsmLexer Lexer(MAI); Lexer.setBuffer(SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())->getBuffer()); bool Error = false; while (Lexer.Lex().isNot(AsmToken::Eof)) { const AsmToken &Tok = Lexer.getTok(); switch (Tok.getKind()) { default: SrcMgr.PrintMessage(Lexer.getLoc(), SourceMgr::DK_Warning, "unknown token"); Error = true; break; case AsmToken::Error: Error = true; // error already printed. break; case AsmToken::Identifier: OS << "identifier: " << Lexer.getTok().getString(); break; case AsmToken::Integer: OS << "int: " << Lexer.getTok().getString(); break; case AsmToken::Real: OS << "real: " << Lexer.getTok().getString(); break; case AsmToken::String: OS << "string: " << Lexer.getTok().getString(); break; case AsmToken::Amp: OS << "Amp"; break; case AsmToken::AmpAmp: OS << "AmpAmp"; break; case AsmToken::At: OS << "At"; break; case AsmToken::Caret: OS << "Caret"; break; case AsmToken::Colon: OS << "Colon"; break; case AsmToken::Comma: OS << "Comma"; break; case AsmToken::Dollar: OS << "Dollar"; break; case AsmToken::Dot: OS << "Dot"; break; case AsmToken::EndOfStatement: OS << "EndOfStatement"; break; case AsmToken::Eof: OS << "Eof"; break; case AsmToken::Equal: OS << "Equal"; break; case AsmToken::EqualEqual: OS << "EqualEqual"; break; case AsmToken::Exclaim: OS << "Exclaim"; break; case AsmToken::ExclaimEqual: OS << "ExclaimEqual"; break; case AsmToken::Greater: OS << "Greater"; break; case AsmToken::GreaterEqual: OS << "GreaterEqual"; break; case AsmToken::GreaterGreater: OS << "GreaterGreater"; break; case AsmToken::Hash: OS << "Hash"; break; case AsmToken::LBrac: OS << "LBrac"; break; case AsmToken::LCurly: OS << "LCurly"; break; case AsmToken::LParen: OS << "LParen"; break; case AsmToken::Less: OS << "Less"; break; case AsmToken::LessEqual: OS << "LessEqual"; break; case AsmToken::LessGreater: OS << "LessGreater"; break; case AsmToken::LessLess: OS << "LessLess"; break; case AsmToken::Minus: OS << "Minus"; break; case AsmToken::Percent: OS << "Percent"; break; case AsmToken::Pipe: OS << "Pipe"; break; case AsmToken::PipePipe: OS << "PipePipe"; break; case AsmToken::Plus: OS << "Plus"; break; case AsmToken::RBrac: OS << "RBrac"; break; case AsmToken::RCurly: OS << "RCurly"; break; case AsmToken::RParen: OS << "RParen"; break; case AsmToken::Slash: OS << "Slash"; break; case AsmToken::Star: OS << "Star"; break; case AsmToken::Tilde: OS << "Tilde"; break; case AsmToken::PercentCall16: OS << "PercentCall16"; break; case AsmToken::PercentCall_Hi: OS << "PercentCall_Hi"; break; case AsmToken::PercentCall_Lo: OS << "PercentCall_Lo"; break; case AsmToken::PercentDtprel_Hi: OS << "PercentDtprel_Hi"; break; case AsmToken::PercentDtprel_Lo: OS << "PercentDtprel_Lo"; break; case AsmToken::PercentGot: OS << "PercentGot"; break; case AsmToken::PercentGot_Disp: OS << "PercentGot_Disp"; break; case AsmToken::PercentGot_Hi: OS << "PercentGot_Hi"; break; case AsmToken::PercentGot_Lo: OS << "PercentGot_Lo"; break; case AsmToken::PercentGot_Ofst: OS << "PercentGot_Ofst"; break; case AsmToken::PercentGot_Page: OS << "PercentGot_Page"; break; case AsmToken::PercentGottprel: OS << "PercentGottprel"; break; case AsmToken::PercentGp_Rel: OS << "PercentGp_Rel"; break; case AsmToken::PercentHi: OS << "PercentHi"; break; case AsmToken::PercentHigher: OS << "PercentHigher"; break; case AsmToken::PercentHighest: OS << "PercentHighest"; break; case AsmToken::PercentLo: OS << "PercentLo"; break; case AsmToken::PercentNeg: OS << "PercentNeg"; break; case AsmToken::PercentPcrel_Hi: OS << "PercentPcrel_Hi"; break; case AsmToken::PercentPcrel_Lo: OS << "PercentPcrel_Lo"; break; case AsmToken::PercentTlsgd: OS << "PercentTlsgd"; break; case AsmToken::PercentTlsldm: OS << "PercentTlsldm"; break; case AsmToken::PercentTprel_Hi: OS << "PercentTprel_Hi"; break; case AsmToken::PercentTprel_Lo: OS << "PercentTprel_Lo"; break; } // Print the token string. OS << " (\""; OS.write_escaped(Tok.getString()); OS << "\")\n"; } return Error; }
int EDDisassembler::parseInst(SmallVectorImpl<MCParsedAsmOperand*> &operands, SmallVectorImpl<AsmToken> &tokens, const std::string &str) { int ret = 0; switch (Key.Arch) { default: return -1; case Triple::x86: case Triple::x86_64: case Triple::arm: case Triple::thumb: break; } const char *cStr = str.c_str(); MemoryBuffer *buf = MemoryBuffer::getMemBuffer(cStr, cStr + strlen(cStr)); StringRef instName; SMLoc instLoc; SourceMgr sourceMgr; sourceMgr.AddNewSourceBuffer(buf, SMLoc()); // ownership of buf handed over MCContext context(*AsmInfo, NULL); OwningPtr<MCStreamer> streamer(createNullStreamer(context)); OwningPtr<MCAsmParser> genericParser(createMCAsmParser(*Tgt, sourceMgr, context, *streamer, *AsmInfo)); OwningPtr<TargetAsmParser> TargetParser(Tgt->createAsmParser(*genericParser, *TargetMachine)); AsmToken OpcodeToken = genericParser->Lex(); AsmToken NextToken = genericParser->Lex(); // consume next token, because specificParser expects us to if (OpcodeToken.is(AsmToken::Identifier)) { instName = OpcodeToken.getString(); instLoc = OpcodeToken.getLoc(); if (NextToken.isNot(AsmToken::Eof) && TargetParser->ParseInstruction(instName, instLoc, operands)) ret = -1; } else { ret = -1; } ParserMutex.acquire(); if (!ret) { GenericAsmLexer->setBuffer(buf); while (SpecificAsmLexer->Lex(), SpecificAsmLexer->isNot(AsmToken::Eof) && SpecificAsmLexer->isNot(AsmToken::EndOfStatement)) { if (SpecificAsmLexer->is(AsmToken::Error)) { ret = -1; break; } tokens.push_back(SpecificAsmLexer->getTok()); } } ParserMutex.release(); return ret; }
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<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(Opts.Triple)); assert(MRI && "Unable to create target register info!"); OwningPtr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, Opts.Triple)); assert(MAI && "Unable to create target asm 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.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)); // 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]; } OwningPtr<MCStreamer> Str; OwningPtr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); OwningPtr<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, /*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(*MRI, Opts.Triple, Opts.CPU); 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::fs::remove(Opts.OutputPath); return Success; }
/// EmitInlineAsm - Emit a blob of inline asm to the output streamer. void AsmPrinter::EmitInlineAsm(StringRef Str, const MDNode *LocMDNode, InlineAsm::AsmDialect Dialect) const { assert(!Str.empty() && "Can't emit empty inline asm block"); // Remember if the buffer is nul terminated or not so we can avoid a copy. bool isNullTerminated = Str.back() == 0; if (isNullTerminated) Str = Str.substr(0, Str.size()-1); // If the output streamer is actually a .s file, just emit the blob textually. // This is useful in case the asm parser doesn't handle something but the // system assembler does. if (OutStreamer.hasRawTextSupport()) { OutStreamer.EmitRawText(Str); return; } SourceMgr SrcMgr; SrcMgrDiagInfo DiagInfo; // If the current LLVMContext has an inline asm handler, set it in SourceMgr. LLVMContext &LLVMCtx = MMI->getModule()->getContext(); bool HasDiagHandler = false; if (LLVMCtx.getInlineAsmDiagnosticHandler() != 0) { // If the source manager has an issue, we arrange for srcMgrDiagHandler // to be invoked, getting DiagInfo passed into it. DiagInfo.LocInfo = LocMDNode; DiagInfo.DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler(); DiagInfo.DiagContext = LLVMCtx.getInlineAsmDiagnosticContext(); SrcMgr.setDiagHandler(srcMgrDiagHandler, &DiagInfo); HasDiagHandler = true; } MemoryBuffer *Buffer; if (isNullTerminated) Buffer = MemoryBuffer::getMemBuffer(Str, "<inline asm>"); else Buffer = MemoryBuffer::getMemBufferCopy(Str, "<inline asm>"); // Tell SrcMgr about this buffer, it takes ownership of the buffer. SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); OwningPtr<MCAsmParser> Parser(createMCAsmParser(SrcMgr, OutContext, OutStreamer, *MAI)); // FIXME: It would be nice if we can avoid createing a new instance of // MCSubtargetInfo here given TargetSubtargetInfo is available. However, // we have to watch out for asm directives which can change subtarget // state. e.g. .code 16, .code 32. OwningPtr<MCSubtargetInfo> STI(TM.getTarget().createMCSubtargetInfo(TM.getTargetTriple(), TM.getTargetCPU(), TM.getTargetFeatureString())); OwningPtr<MCTargetAsmParser> TAP(TM.getTarget().createMCAsmParser(*STI, *Parser, *MII)); if (!TAP) report_fatal_error("Inline asm not supported by this streamer because" " we don't have an asm parser for this target\n"); Parser->setAssemblerDialect(Dialect); Parser->setTargetParser(*TAP.get()); // Don't implicitly switch to the text section before the asm. int Res = Parser->Run(/*NoInitialTextSection*/ true, /*NoFinalize*/ true); if (Res && !HasDiagHandler) report_fatal_error("Error parsing inline asm\n"); }
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(Opts.OutputAsmVariant, *MAI, *MCII, *MRI, *STI); 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); Triple T(Opts.Triple); Str.reset(TheTarget->createMCObjectStreamer(T, Ctx, *MAB, *Out, CE, *STI, Opts.RelaxAll, /*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 the output stream early. Out.reset(); // Delete output file if there were errors. if (Failed && Opts.OutputPath != "-") sys::fs::remove(Opts.OutputPath); return Failed; }
// 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); 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, CodeModel::Default, MCCtx); RecordStreamer Streamer(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)); } }
static int AsLexInput(const char *ProgName) { std::string ErrorMessage; MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFilename, &ErrorMessage); if (Buffer == 0) { errs() << ProgName << ": "; if (ErrorMessage.size()) errs() << ErrorMessage << "\n"; else errs() << "input file didn't read correctly.\n"; return 1; } SourceMgr SrcMgr; // Tell SrcMgr about this buffer, which is what TGParser will pick up. SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); // Record the location of the include directories so that the lexer can find // it later. SrcMgr.setIncludeDirs(IncludeDirs); const Target *TheTarget = GetTarget(ProgName); if (!TheTarget) return 1; llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createAsmInfo(TripleName)); assert(MAI && "Unable to create target asm info!"); AsmLexer Lexer(*MAI); Lexer.setBuffer(SrcMgr.getMemoryBuffer(0)); bool Error = false; while (Lexer.Lex().isNot(AsmToken::Eof)) { switch (Lexer.getKind()) { default: SrcMgr.PrintMessage(Lexer.getLoc(), "unknown token", "warning"); Error = true; break; case AsmToken::Error: Error = true; // error already printed. break; case AsmToken::Identifier: outs() << "identifier: " << Lexer.getTok().getString() << '\n'; break; case AsmToken::String: outs() << "string: " << Lexer.getTok().getString() << '\n'; break; case AsmToken::Integer: outs() << "int: " << Lexer.getTok().getString() << '\n'; break; case AsmToken::Amp: outs() << "Amp\n"; break; case AsmToken::AmpAmp: outs() << "AmpAmp\n"; break; case AsmToken::Caret: outs() << "Caret\n"; break; case AsmToken::Colon: outs() << "Colon\n"; break; case AsmToken::Comma: outs() << "Comma\n"; break; case AsmToken::Dollar: outs() << "Dollar\n"; break; case AsmToken::EndOfStatement: outs() << "EndOfStatement\n"; break; case AsmToken::Eof: outs() << "Eof\n"; break; case AsmToken::Equal: outs() << "Equal\n"; break; case AsmToken::EqualEqual: outs() << "EqualEqual\n"; break; case AsmToken::Exclaim: outs() << "Exclaim\n"; break; case AsmToken::ExclaimEqual: outs() << "ExclaimEqual\n"; break; case AsmToken::Greater: outs() << "Greater\n"; break; case AsmToken::GreaterEqual: outs() << "GreaterEqual\n"; break; case AsmToken::GreaterGreater: outs() << "GreaterGreater\n"; break; case AsmToken::LParen: outs() << "LParen\n"; break; case AsmToken::Less: outs() << "Less\n"; break; case AsmToken::LessEqual: outs() << "LessEqual\n"; break; case AsmToken::LessGreater: outs() << "LessGreater\n"; break; case AsmToken::LessLess: outs() << "LessLess\n"; break; case AsmToken::Minus: outs() << "Minus\n"; break; case AsmToken::Percent: outs() << "Percent\n"; break; case AsmToken::Pipe: outs() << "Pipe\n"; break; case AsmToken::PipePipe: outs() << "PipePipe\n"; break; case AsmToken::Plus: outs() << "Plus\n"; break; case AsmToken::RParen: outs() << "RParen\n"; break; case AsmToken::Slash: outs() << "Slash\n"; break; case AsmToken::Star: outs() << "Star\n"; break; case AsmToken::Tilde: outs() << "Tilde\n"; break; } } return Error; }
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::None) { if (!zlib::isAvailable()) { errs() << ProgName << ": build tools with zlib to enable -compress-debug-sections"; return 1; } MAI->setCompressDebugSections(CompressDebugSections); } MAI->setPreserveAsmComments(PreserveComments); // 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 > 5) { 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); if (!IP) { errs() << "error: unable to create instruction printer for target triple '" << TheTriple.normalize() << "' with assembly variant " << OutputAsmVariant << ".\n"; return 1; } // 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, MCOptions); } 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, MCOptions); 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); 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 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 void parseMCMarkup(StringRef Filename) { OwningPtr<MemoryBuffer> BufferPtr; if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, BufferPtr)) { errs() << ToolName << ": " << ec.message() << '\n'; return; } MemoryBuffer *Buffer = BufferPtr.take(); SourceMgr SrcMgr; // Tell SrcMgr about this buffer, which is what the parser will pick up. SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); StringRef InputSource = Buffer->getBuffer(); MarkupLexer Lex(InputSource); MarkupParser Parser(Lex, SrcMgr); SmallVector<MarkupTag, 4> TagStack; for (int CurChar = Lex.getNextChar(); CurChar != EOF; CurChar = Lex.getNextChar()) { switch (CurChar) { case '<': { // A "<<" is output as a literal '<' and does not start a markup tag. if (Lex.peekNextChar() == '<') { (void)Lex.getNextChar(); break; } // Parse the markup entry. TagStack.push_back(Parser.parseTag()); // Do any special handling for the start of a tag. processStartTag(TagStack.back()); continue; } case '>': { SMLoc Loc = SMLoc::getFromPointer(Lex.getPosition() - 1); // A ">>" is output as a literal '>' and does not end a markup tag. if (Lex.peekNextChar() == '>') { (void)Lex.getNextChar(); break; } // Close out the innermost tag. if (TagStack.empty()) Parser.FatalError(Loc, "'>' without matching '<'"); // Do any special handling for the end of a tag. processEndTag(TagStack.back()); TagStack.pop_back(); continue; } default: break; } // For anything else, just echo the character back out. if (!DumpTags && CurChar != EOF) outs() << (char)CurChar; } // If there are any unterminated markup tags, issue diagnostics for them. while (!TagStack.empty()) { MarkupTag &Tag = TagStack.back(); SrcMgr.PrintMessage(Tag.getLoc(), SourceMgr::DK_Error, "unterminated markup tag"); TagStack.pop_back(); } }
void jl_dump_function_asm(void* Fptr, size_t Fsize, std::vector<JITEvent_EmittedFunctionDetails::LineStart> lineinfo, formatted_raw_ostream &stream) { // Initialize targets and assembly printers/parsers. // Avoids hard-coded targets - will generally be only host CPU anyway. llvm::InitializeNativeTargetAsmParser(); llvm::InitializeNativeTargetDisassembler(); // Get the host information std::string TripleName; if (TripleName.empty()) TripleName = sys::getDefaultTargetTriple(); Triple TheTriple(Triple::normalize(TripleName)); std::string MCPU = sys::getHostCPUName(); SubtargetFeatures Features; Features.getDefaultSubtargetFeatures(TheTriple); std::string err; const Target* TheTarget = TargetRegistry::lookupTarget(TripleName, err); // Set up required helpers and streamer OwningPtr<MCStreamer> Streamer; SourceMgr SrcMgr; #ifdef LLVM34 llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*TheTarget->createMCRegInfo(TripleName),TripleName)); #else llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TripleName)); #endif assert(MAI && "Unable to create target asm info!"); llvm::OwningPtr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); assert(MRI && "Unable to create target register info!"); OwningPtr<MCObjectFileInfo> MOFI(new MCObjectFileInfo()); #ifdef LLVM34 MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &SrcMgr); #else MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr); #endif MOFI->InitMCObjectFileInfo(TripleName, Reloc::Default, CodeModel::Default, Ctx); // Set up Subtarget and Disassembler OwningPtr<MCSubtargetInfo> STI(TheTarget->createMCSubtargetInfo(TripleName, MCPU, Features.getString())); #ifdef LLVM35 OwningPtr<const MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI, Ctx)); #else OwningPtr<const MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI)); #endif if (!DisAsm) { JL_PRINTF(JL_STDERR, "error: no disassembler for target", TripleName.c_str(), "\n"); return; } unsigned OutputAsmVariant = 1; bool ShowEncoding = false; bool ShowInst = false; OwningPtr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); MCInstPrinter* IP = TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI, *MCII, *MRI, *STI); MCCodeEmitter *CE = 0; MCAsmBackend *MAB = 0; if (ShowEncoding) { CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx); #ifdef LLVM34 MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU); #else MAB = TheTarget->createMCAsmBackend(TripleName, MCPU); #endif } Streamer.reset(TheTarget->createAsmStreamer(Ctx, stream, /*asmverbose*/true, #ifndef LLVM35 /*useLoc*/ true, /*useCFI*/ true, #endif /*useDwarfDirectory*/ true, IP, CE, MAB, ShowInst)); Streamer->InitSections(); // Make the MemoryObject wrapper FuncMCView memoryObject(Fptr, Fsize); uint64_t Size; uint64_t Index; uint64_t absAddr; // Set up the line info typedef std::vector<JITEvent_EmittedFunctionDetails::LineStart> LInfoVec; LInfoVec::iterator lineIter = lineinfo.begin(); lineIter = lineinfo.begin(); uint64_t nextLineAddr = -1; DISubprogram debugscope; if (lineIter != lineinfo.end()) { nextLineAddr = (*lineIter).Address; debugscope = DISubprogram((*lineIter).Loc.getScope(jl_LLVMContext)); stream << "Filename: " << debugscope.getFilename().data() << "\n"; stream << "Source line: " << (*lineIter).Loc.getLine() << "\n"; } // Do the disassembly for (Index = 0, absAddr = (uint64_t)Fptr; Index < memoryObject.getExtent(); Index += Size, absAddr += Size) { if (nextLineAddr != (uint64_t)-1 && absAddr == nextLineAddr) { stream << "Source line: " << (*lineIter).Loc.getLine() << "\n"; nextLineAddr = (*++lineIter).Address; } MCInst Inst; MCDisassembler::DecodeStatus S; S = DisAsm->getInstruction(Inst, Size, memoryObject, Index, /*REMOVE*/ nulls(), nulls()); switch (S) { case MCDisassembler::Fail: SrcMgr.PrintMessage(SMLoc::getFromPointer(memoryObject[Index]), SourceMgr::DK_Warning, "invalid instruction encoding"); if (Size == 0) Size = 1; // skip illegible bytes break; case MCDisassembler::SoftFail: SrcMgr.PrintMessage(SMLoc::getFromPointer(memoryObject[Index]), SourceMgr::DK_Warning, "potentially undefined instruction encoding"); // Fall through case MCDisassembler::Success: #ifdef LLVM35 Streamer->EmitInstruction(Inst, *STI); #else Streamer->EmitInstruction(Inst); #endif break; } } }
void PrintError(const char *Loc, const Twine &Msg) { SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), SourceMgr::DK_Error, Msg); }
int Disassembler::disassemble(const Target &T, const std::string &Triple, const std::string &Cpu, const std::string &FeaturesStr, MemoryBuffer &Buffer, raw_ostream &Out) { // Set up disassembler. OwningPtr<const MCAsmInfo> AsmInfo(T.createMCAsmInfo(Triple)); if (!AsmInfo) { errs() << "error: no assembly info for target " << Triple << "\n"; return -1; } OwningPtr<const MCSubtargetInfo> STI(T.createMCSubtargetInfo(Triple, Cpu, FeaturesStr)); if (!STI) { errs() << "error: no subtarget info for target " << Triple << "\n"; return -1; } OwningPtr<const MCDisassembler> DisAsm(T.createMCDisassembler(*STI)); if (!DisAsm) { errs() << "error: no disassembler for target " << Triple << "\n"; return -1; } OwningPtr<const MCRegisterInfo> MRI(T.createMCRegInfo(Triple)); if (!MRI) { errs() << "error: no register info for target " << Triple << "\n"; return -1; } OwningPtr<const MCInstrInfo> MII(T.createMCInstrInfo()); if (!MII) { errs() << "error: no instruction info for target " << Triple << "\n"; return -1; } int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); OwningPtr<MCInstPrinter> IP(T.createMCInstPrinter(AsmPrinterVariant, *AsmInfo, *MII, *MRI, *STI)); if (!IP) { errs() << "error: no instruction printer for target " << Triple << '\n'; return -1; } bool ErrorOccurred = false; SourceMgr SM; SM.AddNewSourceBuffer(&Buffer, SMLoc()); // Convert the input to a vector for disassembly. ByteArrayTy ByteArray; StringRef Str = Buffer.getBuffer(); ErrorOccurred |= ByteArrayFromString(ByteArray, Str, SM); if (!ByteArray.empty()) ErrorOccurred |= PrintInsts(*DisAsm, *IP, ByteArray, SM, Out); return ErrorOccurred; }
static int AsLexInput(SourceMgr &SrcMgr, MCAsmInfo &MAI, tool_output_file *Out) { AsmLexer Lexer(MAI); Lexer.setBuffer(SrcMgr.getMemoryBuffer(0)); bool Error = false; while (Lexer.Lex().isNot(AsmToken::Eof)) { AsmToken Tok = Lexer.getTok(); switch (Tok.getKind()) { default: SrcMgr.PrintMessage(Lexer.getLoc(), SourceMgr::DK_Warning, "unknown token"); Error = true; break; case AsmToken::Error: Error = true; // error already printed. break; case AsmToken::Identifier: Out->os() << "identifier: " << Lexer.getTok().getString(); break; case AsmToken::Integer: Out->os() << "int: " << Lexer.getTok().getString(); break; case AsmToken::Real: Out->os() << "real: " << Lexer.getTok().getString(); break; case AsmToken::String: Out->os() << "string: " << Lexer.getTok().getString(); break; case AsmToken::Amp: Out->os() << "Amp"; break; case AsmToken::AmpAmp: Out->os() << "AmpAmp"; break; case AsmToken::At: Out->os() << "At"; break; case AsmToken::Caret: Out->os() << "Caret"; break; case AsmToken::Colon: Out->os() << "Colon"; break; case AsmToken::Comma: Out->os() << "Comma"; break; case AsmToken::Dollar: Out->os() << "Dollar"; break; case AsmToken::Dot: Out->os() << "Dot"; break; case AsmToken::EndOfStatement: Out->os() << "EndOfStatement"; break; case AsmToken::Eof: Out->os() << "Eof"; break; case AsmToken::Equal: Out->os() << "Equal"; break; case AsmToken::EqualEqual: Out->os() << "EqualEqual"; break; case AsmToken::Exclaim: Out->os() << "Exclaim"; break; case AsmToken::ExclaimEqual: Out->os() << "ExclaimEqual"; break; case AsmToken::Greater: Out->os() << "Greater"; break; case AsmToken::GreaterEqual: Out->os() << "GreaterEqual"; break; case AsmToken::GreaterGreater: Out->os() << "GreaterGreater"; break; case AsmToken::Hash: Out->os() << "Hash"; break; case AsmToken::LBrac: Out->os() << "LBrac"; break; case AsmToken::LCurly: Out->os() << "LCurly"; break; case AsmToken::LParen: Out->os() << "LParen"; break; case AsmToken::Less: Out->os() << "Less"; break; case AsmToken::LessEqual: Out->os() << "LessEqual"; break; case AsmToken::LessGreater: Out->os() << "LessGreater"; break; case AsmToken::LessLess: Out->os() << "LessLess"; break; case AsmToken::Minus: Out->os() << "Minus"; break; case AsmToken::Percent: Out->os() << "Percent"; break; case AsmToken::Pipe: Out->os() << "Pipe"; break; case AsmToken::PipePipe: Out->os() << "PipePipe"; break; case AsmToken::Plus: Out->os() << "Plus"; break; case AsmToken::RBrac: Out->os() << "RBrac"; break; case AsmToken::RCurly: Out->os() << "RCurly"; break; case AsmToken::RParen: Out->os() << "RParen"; break; case AsmToken::Slash: Out->os() << "Slash"; break; case AsmToken::Star: Out->os() << "Star"; break; case AsmToken::Tilde: Out->os() << "Tilde"; break; } // Print the token string. Out->os() << " (\""; Out->os().write_escaped(Tok.getString()); Out->os() << "\")\n"; } return Error; }
int Disassembler::disassembleEnhanced(const std::string &TS, MemoryBuffer &Buffer, raw_ostream &Out) { ByteArrayTy ByteArray; StringRef Str = Buffer.getBuffer(); SourceMgr SM; SM.AddNewSourceBuffer(&Buffer, SMLoc()); if (ByteArrayFromString(ByteArray, Str, SM)) { return -1; } Triple T(TS); EDDisassembler::AssemblySyntax AS; switch (T.getArch()) { default: errs() << "error: no default assembly syntax for " << TS.c_str() << "\n"; return -1; case Triple::arm: case Triple::thumb: AS = EDDisassembler::kEDAssemblySyntaxARMUAL; break; case Triple::x86: case Triple::x86_64: AS = EDDisassembler::kEDAssemblySyntaxX86ATT; break; } OwningPtr<EDDisassembler> disassembler(EDDisassembler::getDisassembler(TS.c_str(), AS)); if (disassembler == 0) { errs() << "error: couldn't get disassembler for " << TS << '\n'; return -1; } while (ByteArray.size()) { OwningPtr<EDInst> inst(disassembler->createInst(byteArrayReader, 0, &ByteArray)); if (inst == 0) { errs() << "error: Didn't get an instruction\n"; return -1; } ByteArray.erase (ByteArray.begin(), ByteArray.begin() + inst->byteSize()); unsigned numTokens = inst->numTokens(); if ((int)numTokens < 0) { errs() << "error: couldn't count the instruction's tokens\n"; return -1; } for (unsigned tokenIndex = 0; tokenIndex != numTokens; ++tokenIndex) { EDToken *token; if (inst->getToken(token, tokenIndex)) { errs() << "error: Couldn't get token\n"; return -1; } const char *buf; if (token->getString(buf)) { errs() << "error: Couldn't get string for token\n"; return -1; } Out << '['; int operandIndex = token->operandID(); if (operandIndex >= 0) Out << operandIndex << "-"; switch (token->type()) { case EDToken::kTokenWhitespace: Out << "w"; break; case EDToken::kTokenPunctuation: Out << "p"; break; case EDToken::kTokenOpcode: Out << "o"; break; case EDToken::kTokenLiteral: Out << "l"; break; case EDToken::kTokenRegister: Out << "r"; break; } Out << ":" << buf; if (token->type() == EDToken::kTokenLiteral) { Out << "="; if (token->literalSign()) Out << "-"; uint64_t absoluteValue; if (token->literalAbsoluteValue(absoluteValue)) { errs() << "error: Couldn't get the value of a literal token\n"; return -1; } Out << absoluteValue; } else if (token->type() == EDToken::kTokenRegister) { Out << "="; unsigned regID; if (token->registerID(regID)) { errs() << "error: Couldn't get the ID of a register token\n"; return -1; } Out << "r" << regID; } Out << "]"; } Out << " "; if (inst->isBranch()) Out << "<br> "; if (inst->isMove()) Out << "<mov> "; unsigned numOperands = inst->numOperands(); if ((int)numOperands < 0) { errs() << "error: Couldn't count operands\n"; return -1; } for (unsigned operandIndex = 0; operandIndex != numOperands; ++operandIndex) { Out << operandIndex << ":"; EDOperand *operand; if (inst->getOperand(operand, operandIndex)) { errs() << "error: couldn't get operand\n"; return -1; } uint64_t evaluatedResult; void *Arg[] = { disassembler.get(), &Out }; if (operand->evaluate(evaluatedResult, verboseEvaluator, Arg)) { errs() << "error: Couldn't evaluate an operand\n"; return -1; } Out << "=" << evaluatedResult << " "; } Out << '\n'; } return 0; }
/// EmitInlineAsm - Emit a blob of inline asm to the output streamer. void AsmPrinter::EmitInlineAsm(StringRef Str, const MCSubtargetInfo &STI, const MDNode *LocMDNode, InlineAsm::AsmDialect Dialect) const { assert(!Str.empty() && "Can't emit empty inline asm block"); // Remember if the buffer is nul terminated or not so we can avoid a copy. bool isNullTerminated = Str.back() == 0; if (isNullTerminated) Str = Str.substr(0, Str.size()-1); // If the output streamer does not have mature MC support or the integrated // assembler has been disabled, just emit the blob textually. // Otherwise parse the asm and emit it via MC support. // This is useful in case the asm parser doesn't handle something but the // system assembler does. const MCAsmInfo *MCAI = TM.getMCAsmInfo(); assert(MCAI && "No MCAsmInfo"); if (!MCAI->useIntegratedAssembler() && !OutStreamer->isIntegratedAssemblerRequired()) { emitInlineAsmStart(); OutStreamer->EmitRawText(Str); emitInlineAsmEnd(STI, nullptr); return; } SourceMgr SrcMgr; SrcMgrDiagInfo DiagInfo; // If the current LLVMContext has an inline asm handler, set it in SourceMgr. LLVMContext &LLVMCtx = MMI->getModule()->getContext(); bool HasDiagHandler = false; if (LLVMCtx.getInlineAsmDiagnosticHandler() != nullptr) { // If the source manager has an issue, we arrange for srcMgrDiagHandler // to be invoked, getting DiagInfo passed into it. DiagInfo.LocInfo = LocMDNode; DiagInfo.DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler(); DiagInfo.DiagContext = LLVMCtx.getInlineAsmDiagnosticContext(); SrcMgr.setDiagHandler(srcMgrDiagHandler, &DiagInfo); HasDiagHandler = true; } std::unique_ptr<MemoryBuffer> Buffer; if (isNullTerminated) Buffer = MemoryBuffer::getMemBuffer(Str, "<inline asm>"); else Buffer = MemoryBuffer::getMemBufferCopy(Str, "<inline asm>"); // Tell SrcMgr about this buffer, it takes ownership of the buffer. SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc()); std::unique_ptr<MCAsmParser> Parser( createMCAsmParser(SrcMgr, OutContext, *OutStreamer, *MAI)); // Create a temporary copy of the original STI because the parser may modify // it. For example, when switching between arm and thumb mode. If the target // needs to emit code to return to the original state it can do so in // emitInlineAsmEnd(). MCSubtargetInfo TmpSTI = STI; // We create a new MCInstrInfo here since we might be at the module level // and not have a MachineFunction to initialize the TargetInstrInfo from and // we only need MCInstrInfo for asm parsing. We create one unconditionally // because it's not subtarget dependent. std::unique_ptr<MCInstrInfo> MII(TM.getTarget().createMCInstrInfo()); std::unique_ptr<MCTargetAsmParser> TAP(TM.getTarget().createMCAsmParser( TmpSTI, *Parser, *MII, TM.Options.MCOptions)); if (!TAP) report_fatal_error("Inline asm not supported by this streamer because" " we don't have an asm parser for this target\n"); Parser->setAssemblerDialect(Dialect); Parser->setTargetParser(*TAP.get()); if (MF) { const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); TAP->SetFrameRegister(TRI->getFrameRegister(*MF)); } emitInlineAsmStart(); // Don't implicitly switch to the text section before the asm. int Res = Parser->Run(/*NoInitialTextSection*/ true, /*NoFinalize*/ true); emitInlineAsmEnd(STI, &TmpSTI); if (Res && !HasDiagHandler) report_fatal_error("Error parsing inline asm\n"); }
bool MIRParserImpl::initializeMachineFunction(const yaml::MachineFunction &YamlMF, MachineFunction &MF) { // TODO: Recreate the machine function. initNames2RegClasses(MF); initNames2RegBanks(MF); if (YamlMF.Alignment) MF.setAlignment(YamlMF.Alignment); MF.setExposesReturnsTwice(YamlMF.ExposesReturnsTwice); if (YamlMF.Legalized) MF.getProperties().set(MachineFunctionProperties::Property::Legalized); if (YamlMF.RegBankSelected) MF.getProperties().set( MachineFunctionProperties::Property::RegBankSelected); if (YamlMF.Selected) MF.getProperties().set(MachineFunctionProperties::Property::Selected); PerFunctionMIParsingState PFS(MF, SM, IRSlots, Names2RegClasses, Names2RegBanks); if (parseRegisterInfo(PFS, YamlMF)) return true; if (!YamlMF.Constants.empty()) { auto *ConstantPool = MF.getConstantPool(); assert(ConstantPool && "Constant pool must be created"); if (initializeConstantPool(PFS, *ConstantPool, YamlMF)) return true; } StringRef BlockStr = YamlMF.Body.Value.Value; SMDiagnostic Error; SourceMgr BlockSM; BlockSM.AddNewSourceBuffer( MemoryBuffer::getMemBuffer(BlockStr, "",/*RequiresNullTerminator=*/false), SMLoc()); PFS.SM = &BlockSM; if (parseMachineBasicBlockDefinitions(PFS, BlockStr, Error)) { reportDiagnostic( diagFromBlockStringDiag(Error, YamlMF.Body.Value.SourceRange)); return true; } PFS.SM = &SM; // Initialize the frame information after creating all the MBBs so that the // MBB references in the frame information can be resolved. if (initializeFrameInfo(PFS, YamlMF)) return true; // Initialize the jump table after creating all the MBBs so that the MBB // references can be resolved. if (!YamlMF.JumpTableInfo.Entries.empty() && initializeJumpTableInfo(PFS, YamlMF.JumpTableInfo)) return true; // Parse the machine instructions after creating all of the MBBs so that the // parser can resolve the MBB references. StringRef InsnStr = YamlMF.Body.Value.Value; SourceMgr InsnSM; InsnSM.AddNewSourceBuffer( MemoryBuffer::getMemBuffer(InsnStr, "", /*RequiresNullTerminator=*/false), SMLoc()); PFS.SM = &InsnSM; if (parseMachineInstructions(PFS, InsnStr, Error)) { reportDiagnostic( diagFromBlockStringDiag(Error, YamlMF.Body.Value.SourceRange)); return true; } PFS.SM = &SM; if (setupRegisterInfo(PFS, YamlMF)) return true; computeFunctionProperties(MF); MF.verify(); return false; }
void Pattern::PrintFailureInfo(const SourceMgr &SM, StringRef Buffer, const StringMap<StringRef> &VariableTable) const{ // If this was a regular expression using variables, print the current // variable values. if (!VariableUses.empty()) { for (unsigned i = 0, e = VariableUses.size(); i != e; ++i) { StringRef Var = VariableUses[i].first; StringMap<StringRef>::const_iterator it = VariableTable.find(Var); SmallString<256> Msg; raw_svector_ostream OS(Msg); // Check for undefined variable references. if (it == VariableTable.end()) { OS << "uses undefined variable \""; OS.write_escaped(Var) << "\"";; } else { OS << "with variable \""; OS.write_escaped(Var) << "\" equal to \""; OS.write_escaped(it->second) << "\""; } SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), OS.str(), "note", /*ShowLine=*/false); } } // Attempt to find the closest/best fuzzy match. Usually an error happens // because some string in the output didn't exactly match. In these cases, we // would like to show the user a best guess at what "should have" matched, to // save them having to actually check the input manually. size_t NumLinesForward = 0; size_t Best = StringRef::npos; double BestQuality = 0; // Use an arbitrary 4k limit on how far we will search. for (size_t i = 0, e = std::min(size_t(4096), Buffer.size()); i != e; ++i) { if (Buffer[i] == '\n') ++NumLinesForward; // Patterns have leading whitespace stripped, so skip whitespace when // looking for something which looks like a pattern. if (Buffer[i] == ' ' || Buffer[i] == '\t') continue; // Compute the "quality" of this match as an arbitrary combination of the // match distance and the number of lines skipped to get to this match. unsigned Distance = ComputeMatchDistance(Buffer.substr(i), VariableTable); double Quality = Distance + (NumLinesForward / 100.); if (Quality < BestQuality || Best == StringRef::npos) { Best = i; BestQuality = Quality; } } // Print the "possible intended match here" line if we found something // reasonable and not equal to what we showed in the "scanning from here" // line. if (Best && Best != StringRef::npos && BestQuality < 50) { SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + Best), "possible intended match here", "note"); // FIXME: If we wanted to be really friendly we would show why the match // failed, as it can be hard to spot simple one character differences. } }
void jl_dump_function_asm(const char *Fptr, size_t Fsize, #ifndef USE_MCJIT std::vector<JITEvent_EmittedFunctionDetails::LineStart> lineinfo, #else object::ObjectFile *objectfile, #endif formatted_raw_ostream &stream) { // Initialize targets and assembly printers/parsers. // Avoids hard-coded targets - will generally be only host CPU anyway. llvm::InitializeNativeTargetAsmParser(); llvm::InitializeNativeTargetDisassembler(); // Get the host information std::string TripleName; if (TripleName.empty()) TripleName = sys::getDefaultTargetTriple(); Triple TheTriple(Triple::normalize(TripleName)); std::string MCPU = sys::getHostCPUName(); SubtargetFeatures Features; Features.getDefaultSubtargetFeatures(TheTriple); std::string err; const Target* TheTarget = TargetRegistry::lookupTarget(TripleName, err); // Set up required helpers and streamer #ifdef LLVM35 std::unique_ptr<MCStreamer> Streamer; #else OwningPtr<MCStreamer> Streamer; #endif SourceMgr SrcMgr; #ifdef LLVM35 std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*TheTarget->createMCRegInfo(TripleName),TripleName)); #elif defined(LLVM34) llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*TheTarget->createMCRegInfo(TripleName),TripleName)); #else llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TripleName)); #endif assert(MAI && "Unable to create target asm info!"); #ifdef LLVM35 std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); #else llvm::OwningPtr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); #endif assert(MRI && "Unable to create target register info!"); #ifdef LLVM35 std::unique_ptr<MCObjectFileInfo> MOFI(new MCObjectFileInfo()); #else OwningPtr<MCObjectFileInfo> MOFI(new MCObjectFileInfo()); #endif #ifdef LLVM34 MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &SrcMgr); #else MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr); #endif MOFI->InitMCObjectFileInfo(TripleName, Reloc::Default, CodeModel::Default, Ctx); // Set up Subtarget and Disassembler #ifdef LLVM35 std::unique_ptr<MCSubtargetInfo> STI(TheTarget->createMCSubtargetInfo(TripleName, MCPU, Features.getString())); std::unique_ptr<const MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI, Ctx)); #else OwningPtr<MCSubtargetInfo> STI(TheTarget->createMCSubtargetInfo(TripleName, MCPU, Features.getString())); OwningPtr<MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI)); #endif if (!DisAsm) { JL_PRINTF(JL_STDERR, "error: no disassembler for target", TripleName.c_str(), "\n"); return; } unsigned OutputAsmVariant = 1; bool ShowEncoding = false; bool ShowInst = false; #ifdef LLVM35 std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); #else OwningPtr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); OwningPtr<MCInstrAnalysis> MCIA(TheTarget->createMCInstrAnalysis(MCII.get())); #endif MCInstPrinter* IP = TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI, *MCII, *MRI, *STI); MCCodeEmitter *CE = 0; MCAsmBackend *MAB = 0; if (ShowEncoding) { CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx); #ifdef LLVM34 MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU); #else MAB = TheTarget->createMCAsmBackend(TripleName, MCPU); #endif } Streamer.reset(TheTarget->createAsmStreamer(Ctx, stream, /*asmverbose*/true, #ifndef LLVM35 /*useLoc*/ true, /*useCFI*/ true, #endif /*useDwarfDirectory*/ true, IP, CE, MAB, ShowInst)); #ifdef LLVM36 Streamer->InitSections(true); #else Streamer->InitSections(); #endif #ifndef USE_MCJIT // LLVM33 version // Make the MemoryObject wrapper #ifdef LLVM36 ArrayRef<uint8_t> memoryObject((uint8_t*)Fptr,Fsize); #else FuncMCView memoryObject(Fptr, Fsize); #endif SymbolTable DisInfo(Ctx, memoryObject); // Take two passes: In the first pass we record all branch labels, // in the second we actually perform the output for (int pass = 0; pass < 2; ++ pass) { DisInfo.setPass(pass); if (pass != 0) { // Switch to symbolic disassembly. We cannot do this // before the first pass, because this changes branch // targets from immediate values (constants) to // expressions, which are not handled correctly by // MCIA->evaluateBranch. (It should be possible to rewrite // this routine to handle this case correctly as well.) // Could add OpInfoLookup here DisAsm->setupForSymbolicDisassembly (OpInfoLookup, SymbolLookup, &DisInfo, &Ctx); } uint64_t Size = 0; uint64_t Index = 0; uint64_t absAddr = 0; // Set up the line info typedef std::vector<JITEvent_EmittedFunctionDetails::LineStart> LInfoVec; LInfoVec::iterator lineIter = lineinfo.begin(); LInfoVec::iterator lineEnd = lineinfo.end(); uint64_t nextLineAddr = -1; DISubprogram debugscope; if (lineIter != lineEnd) { nextLineAddr = (*lineIter).Address; debugscope = DISubprogram((*lineIter).Loc.getScope(jl_LLVMContext)); if (pass != 0) { stream << "Filename: " << debugscope.getFilename() << "\n"; stream << "Source line: " << (*lineIter).Loc.getLine() << "\n"; } } // Do the disassembly for (Index = 0, absAddr = (uint64_t)Fptr; Index < memoryObject.getExtent(); Index += Size, absAddr += Size) { if (nextLineAddr != (uint64_t)-1 && absAddr == nextLineAddr) { if (pass != 0) stream << "Source line: " << (*lineIter).Loc.getLine() << "\n"; nextLineAddr = (*++lineIter).Address; } if (pass != 0) { // Uncomment this to output addresses for all instructions // stream << Index << ": "; const char *symbolName = DisInfo.lookupSymbol(Index); if (symbolName) stream << symbolName << ":"; } MCInst Inst; MCDisassembler::DecodeStatus S; S = DisAsm->getInstruction(Inst, Size, memoryObject, Index, /*REMOVE*/ nulls(), nulls()); switch (S) { case MCDisassembler::Fail: if (pass != 0) SrcMgr.PrintMessage(SMLoc::getFromPointer(memoryObject[Index]), SourceMgr::DK_Warning, "invalid instruction encoding"); if (Size == 0) Size = 1; // skip illegible bytes break; case MCDisassembler::SoftFail: if (pass != 0) SrcMgr.PrintMessage(SMLoc::getFromPointer(memoryObject[Index]), SourceMgr::DK_Warning, "potentially undefined instruction encoding"); // Fall through case MCDisassembler::Success: #ifdef LLVM35 if (pass != 0) Streamer->EmitInstruction(Inst, *STI); #else if (pass == 0) { // Pass 0: Record all branch targets if (MCIA->isBranch(Inst)) { uint64_t addr = MCIA->evaluateBranch(Inst, Index, Size); if (addr != uint64_t(-1)) DisInfo.insertAddress(addr); } } else { // Pass 1: Output instruction Streamer->EmitInstruction(Inst); } #endif break; } } if (pass == 0) DisInfo.createSymbols(); } #else // MCJIT version #ifdef LLVM36 ArrayRef<uint8_t> memoryObject((uint8_t*)Fptr,Fsize); #else FuncMCView memoryObject(Fptr, Fsize); // MemoryObject wrapper #endif if (!objectfile) return; #ifdef LLVM36 DIContext *di_ctx = DIContext::getDWARFContext(*objectfile); #else DIContext *di_ctx = DIContext::getDWARFContext(objectfile); #endif if (di_ctx == NULL) return; DILineInfoTable lineinfo = di_ctx->getLineInfoForAddressRange((size_t)Fptr, Fsize); // Set up the line info DILineInfoTable::iterator lineIter = lineinfo.begin(); DILineInfoTable::iterator lineEnd = lineinfo.end(); uint64_t nextLineAddr = -1; if (lineIter != lineEnd) { nextLineAddr = lineIter->first; #ifdef LLVM35 stream << "Filename: " << lineIter->second.FileName << "\n"; #else stream << "Filename: " << lineIter->second.getFileName() << "\n"; #endif } uint64_t Index = 0; uint64_t absAddr = 0; uint64_t insSize = 0; // Do the disassembly for (Index = 0, absAddr = (uint64_t)Fptr; Index < Fsize; Index += insSize, absAddr += insSize) { if (nextLineAddr != (uint64_t)-1 && absAddr == nextLineAddr) { #ifdef LLVM35 stream << "Source line: " << lineIter->second.Line << "\n"; #else stream << "Source line: " << lineIter->second.getLine() << "\n"; #endif nextLineAddr = (++lineIter)->first; } MCInst Inst; MCDisassembler::DecodeStatus S; S = DisAsm->getInstruction(Inst, insSize, memoryObject, Index, /*REMOVE*/ nulls(), nulls()); switch (S) { case MCDisassembler::Fail: SrcMgr.PrintMessage(SMLoc::getFromPointer(Fptr + Index), SourceMgr::DK_Warning, "invalid instruction encoding"); if (insSize == 0) insSize = 1; // skip illegible bytes break; case MCDisassembler::SoftFail: SrcMgr.PrintMessage(SMLoc::getFromPointer(Fptr + Index), SourceMgr::DK_Warning, "potentially undefined instruction encoding"); // Fall through case MCDisassembler::Success: #ifdef LLVM35 Streamer->EmitInstruction(Inst, *STI); #else Streamer->EmitInstruction(Inst); #endif break; } } #endif }
int main(int argc, char **argv) { sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); cl::ParseCommandLineOptions(argc, argv); SourceMgr SM; // Read the expected strings from the check file. std::vector<CheckString> CheckStrings; if (ReadCheckFile(SM, CheckStrings)) return 2; // Open the file to check and add it to SourceMgr. std::string ErrorStr; MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), &ErrorStr); if (F == 0) { errs() << "Could not open input file '" << InputFilename << "': " << ErrorStr << '\n'; return true; } // Remove duplicate spaces in the input file if requested. if (!NoCanonicalizeWhiteSpace) F = CanonicalizeInputFile(F); SM.AddNewSourceBuffer(F, SMLoc()); /// VariableTable - This holds all the current filecheck variables. StringMap<StringRef> VariableTable; // Check that we have all of the expected strings, in order, in the input // file. StringRef Buffer = F->getBuffer(); const char *LastMatch = Buffer.data(); for (unsigned StrNo = 0, e = CheckStrings.size(); StrNo != e; ++StrNo) { const CheckString &CheckStr = CheckStrings[StrNo]; StringRef SearchFrom = Buffer; // Find StrNo in the file. size_t MatchLen = 0; Buffer = Buffer.substr(CheckStr.Pat.Match(Buffer, MatchLen, VariableTable)); // If we didn't find a match, reject the input. if (Buffer.empty()) { PrintCheckFailed(SM, CheckStr, SearchFrom, VariableTable); return 1; } StringRef SkippedRegion(LastMatch, Buffer.data()-LastMatch); // If this check is a "CHECK-NEXT", verify that the previous match was on // the previous line (i.e. that there is one newline between them). if (CheckStr.IsCheckNext) { // Count the number of newlines between the previous match and this one. assert(LastMatch != F->getBufferStart() && "CHECK-NEXT can't be the first check in a file"); unsigned NumNewLines = CountNumNewlinesBetween(SkippedRegion); if (NumNewLines == 0) { SM.PrintMessage(CheckStr.Loc, CheckPrefix+"-NEXT: is on the same line as previous match", "error"); SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), "'next' match was here", "note"); SM.PrintMessage(SMLoc::getFromPointer(LastMatch), "previous match was here", "note"); return 1; } if (NumNewLines != 1) { SM.PrintMessage(CheckStr.Loc, CheckPrefix+ "-NEXT: is not on the line after the previous match", "error"); SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), "'next' match was here", "note"); SM.PrintMessage(SMLoc::getFromPointer(LastMatch), "previous match was here", "note"); return 1; } } // If this match had "not strings", verify that they don't exist in the // skipped region. for (unsigned ChunkNo = 0, e = CheckStr.NotStrings.size(); ChunkNo != e; ++ChunkNo) { size_t MatchLen = 0; size_t Pos = CheckStr.NotStrings[ChunkNo].second.Match(SkippedRegion, MatchLen, VariableTable); if (Pos == StringRef::npos) continue; SM.PrintMessage(SMLoc::getFromPointer(LastMatch+Pos), CheckPrefix+"-NOT: string occurred!", "error"); SM.PrintMessage(CheckStr.NotStrings[ChunkNo].first, CheckPrefix+"-NOT: pattern specified here", "note"); return 1; } // Otherwise, everything is good. Step over the matched text and remember // the position after the match as the end of the last match. Buffer = Buffer.substr(MatchLen); LastMatch = Buffer.data(); } return 0; }
int LLVMTargetMachineAssembleToOutputStream(LLVMTargetMachineRef TM, LLVMMemoryBufferRef Mem, void *JOStream, LLVMBool RelaxAll, LLVMBool NoExecStack, char **ErrorMessage) { *ErrorMessage = NULL; #if !defined(WIN32) locale_t loc = newlocale(LC_ALL_MASK, "C", 0); locale_t oldLoc = uselocale(loc); #endif TargetMachine *TheTargetMachine = unwrap(TM); const Target *TheTarget = &(TheTargetMachine->getTarget()); std::string TripleName = TheTargetMachine->getTargetTriple().str(); std::string MCPU = TheTargetMachine->getTargetCPU().str(); std::string FeaturesStr = TheTargetMachine->getTargetFeatureString().str(); Reloc::Model RelocModel = TheTargetMachine->getRelocationModel(); CodeModel::Model CMModel = TheTargetMachine->getCodeModel(); std::unique_ptr<MemoryBuffer> Buffer(unwrap(Mem)); std::string DiagStr; raw_string_ostream DiagStream(DiagStr); SourceMgr SrcMgr; SrcMgr.setDiagHandler(assembleDiagHandler, &DiagStream); // 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(IncludeDirs); std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TripleName)); std::unique_ptr<MCObjectFileInfo> MOFI(new MCObjectFileInfo()); MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &SrcMgr); MOFI->InitMCObjectFileInfo(TripleName, RelocModel, CMModel, Ctx); std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); std::unique_ptr<MCSubtargetInfo> STI(TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr)); raw_java_ostream& Out = *((raw_java_ostream*) JOStream); std::unique_ptr<MCStreamer> Str; MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx); MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU); Str.reset(TheTarget->createMCObjectStreamer(TripleName, Ctx, *MAB, Out, CE, *STI, RelaxAll != 0)); if (NoExecStack != 0) Str->InitSections(true); MCTargetOptions MCOptions; std::unique_ptr<MCAsmParser> Parser(createMCAsmParser(SrcMgr, Ctx, *Str, *MAI)); std::unique_ptr<MCTargetAsmParser> TAP(TheTarget->createMCAsmParser(*STI, *Parser, *MCII, MCOptions)); if (!TAP) { *ErrorMessage = strdup("this target does not support assembly parsing"); goto done; } Parser->setTargetParser(*TAP.get()); if (Parser->Run(false)) { *ErrorMessage = strdup(DiagStream.str().c_str()); goto done; } Out.flush(); done: #if !defined(WIN32) uselocale(oldLoc); freelocale(loc); #endif return *ErrorMessage ? 1 : 0; }