llvm-mc.cpp revision 8977d087c693fd581db82bcff134d12da0f48bd3
1//===-- llvm-mc.cpp - Machine Code Hacking Driver -------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This utility is a simple driver that allows command line hacking on machine 11// code. 12// 13//===----------------------------------------------------------------------===// 14 15#include "llvm/MC/MCContext.h" 16#include "llvm/MC/MCStreamer.h" 17#include "llvm/ADT/OwningPtr.h" 18#include "llvm/Support/CommandLine.h" 19#include "llvm/Support/ManagedStatic.h" 20#include "llvm/Support/MemoryBuffer.h" 21#include "llvm/Support/PrettyStackTrace.h" 22#include "llvm/Support/SourceMgr.h" 23#include "llvm/Support/raw_ostream.h" 24#include "llvm/System/Signals.h" 25#include "llvm/Target/TargetRegistry.h" 26#include "llvm/Target/TargetSelect.h" 27#include "AsmParser.h" 28using namespace llvm; 29 30static cl::opt<std::string> 31InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-")); 32 33static cl::opt<std::string> 34OutputFilename("o", cl::desc("Output filename"), 35 cl::value_desc("filename")); 36 37static cl::list<std::string> 38IncludeDirs("I", cl::desc("Directory of include files"), 39 cl::value_desc("directory"), cl::Prefix); 40 41static cl::opt<std::string> 42TripleName("triple", cl::desc("Target triple to assemble for," 43 "see -version for available targets"), 44 cl::init(LLVM_HOSTTRIPLE)); 45 46enum ActionType { 47 AC_AsLex, 48 AC_Assemble 49}; 50 51static cl::opt<ActionType> 52Action(cl::desc("Action to perform:"), 53 cl::init(AC_Assemble), 54 cl::values(clEnumValN(AC_AsLex, "as-lex", 55 "Lex tokens from a .s file"), 56 clEnumValN(AC_Assemble, "assemble", 57 "Assemble a .s file (default)"), 58 clEnumValEnd)); 59 60static int AsLexInput(const char *ProgName) { 61 std::string ErrorMessage; 62 MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFilename, 63 &ErrorMessage); 64 if (Buffer == 0) { 65 errs() << ProgName << ": "; 66 if (ErrorMessage.size()) 67 errs() << ErrorMessage << "\n"; 68 else 69 errs() << "input file didn't read correctly.\n"; 70 return 1; 71 } 72 73 SourceMgr SrcMgr; 74 75 // Tell SrcMgr about this buffer, which is what TGParser will pick up. 76 SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); 77 78 // Record the location of the include directories so that the lexer can find 79 // it later. 80 SrcMgr.setIncludeDirs(IncludeDirs); 81 82 AsmLexer Lexer(SrcMgr); 83 84 bool Error = false; 85 86 asmtok::TokKind Tok = Lexer.Lex(); 87 while (Tok != asmtok::Eof) { 88 switch (Tok) { 89 default: 90 Lexer.PrintMessage(Lexer.getLoc(), "unknown token", "warning"); 91 Error = true; 92 break; 93 case asmtok::Error: 94 Error = true; // error already printed. 95 break; 96 case asmtok::Identifier: 97 outs() << "identifier: " << Lexer.getCurStrVal() << '\n'; 98 break; 99 case asmtok::Register: 100 outs() << "register: " << Lexer.getCurStrVal() << '\n'; 101 break; 102 case asmtok::String: 103 outs() << "string: " << Lexer.getCurStrVal() << '\n'; 104 break; 105 case asmtok::IntVal: 106 outs() << "int: " << Lexer.getCurIntVal() << '\n'; 107 break; 108 109 case asmtok::Amp: outs() << "Amp\n"; break; 110 case asmtok::AmpAmp: outs() << "AmpAmp\n"; break; 111 case asmtok::Caret: outs() << "Caret\n"; break; 112 case asmtok::Colon: outs() << "Colon\n"; break; 113 case asmtok::Comma: outs() << "Comma\n"; break; 114 case asmtok::Dollar: outs() << "Dollar\n"; break; 115 case asmtok::EndOfStatement: outs() << "EndOfStatement\n"; break; 116 case asmtok::Eof: outs() << "Eof\n"; break; 117 case asmtok::Equal: outs() << "Equal\n"; break; 118 case asmtok::EqualEqual: outs() << "EqualEqual\n"; break; 119 case asmtok::Exclaim: outs() << "Exclaim\n"; break; 120 case asmtok::ExclaimEqual: outs() << "ExclaimEqual\n"; break; 121 case asmtok::Greater: outs() << "Greater\n"; break; 122 case asmtok::GreaterEqual: outs() << "GreaterEqual\n"; break; 123 case asmtok::GreaterGreater: outs() << "GreaterGreater\n"; break; 124 case asmtok::LParen: outs() << "LParen\n"; break; 125 case asmtok::Less: outs() << "Less\n"; break; 126 case asmtok::LessEqual: outs() << "LessEqual\n"; break; 127 case asmtok::LessGreater: outs() << "LessGreater\n"; break; 128 case asmtok::LessLess: outs() << "LessLess\n"; break; 129 case asmtok::Minus: outs() << "Minus\n"; break; 130 case asmtok::Percent: outs() << "Percent\n"; break; 131 case asmtok::Pipe: outs() << "Pipe\n"; break; 132 case asmtok::PipePipe: outs() << "PipePipe\n"; break; 133 case asmtok::Plus: outs() << "Plus\n"; break; 134 case asmtok::RParen: outs() << "RParen\n"; break; 135 case asmtok::Slash: outs() << "Slash\n"; break; 136 case asmtok::Star: outs() << "Star\n"; break; 137 case asmtok::Tilde: outs() << "Tilde\n"; break; 138 } 139 140 Tok = Lexer.Lex(); 141 } 142 143 return Error; 144} 145 146static int AssembleInput(const char *ProgName) { 147 // Get the target specific parser. 148 std::string Error; 149 const Target *TheTarget = 150 TargetRegistry::lookupTarget(TripleName, 151 /*FallbackToHost=*/true, 152 /*RequireJIT=*/false, 153 Error); 154 if (TheTarget == 0) { 155 errs() << ProgName << ": error: unable to get target for '" << TripleName 156 << "', see --version and --triple.\n"; 157 return 1; 158 } 159 160 TargetAsmParser *TAP = TheTarget->createAsmParser(); 161 if (!TAP) { 162 errs() << ProgName 163 << ": error: this target does not support assembly parsing.\n"; 164 return 1; 165 } 166 167 std::string ErrorMessage; 168 MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFilename, 169 &ErrorMessage); 170 if (Buffer == 0) { 171 errs() << ProgName << ": "; 172 if (ErrorMessage.size()) 173 errs() << ErrorMessage << "\n"; 174 else 175 errs() << "input file didn't read correctly.\n"; 176 return 1; 177 } 178 179 SourceMgr SrcMgr; 180 181 // Tell SrcMgr about this buffer, which is what TGParser will pick up. 182 SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); 183 184 // Record the location of the include directories so that the lexer can find 185 // it later. 186 SrcMgr.setIncludeDirs(IncludeDirs); 187 188 MCContext Ctx; 189 OwningPtr<MCStreamer> Str(createAsmStreamer(Ctx, outs())); 190 191 // FIXME: Target hook & command line option for initial section. 192 Str.get()->SwitchSection(Ctx.GetSection("__TEXT,__text," 193 "regular,pure_instructions")); 194 195 AsmParser Parser(SrcMgr, Ctx, *Str.get(), *TAP); 196 return Parser.Run(); 197} 198 199 200int main(int argc, char **argv) { 201 // Print a stack trace if we signal out. 202 sys::PrintStackTraceOnErrorSignal(); 203 PrettyStackTraceProgram X(argc, argv); 204 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 205 206 // Initialize targets and assembly parsers. 207 llvm::InitializeAllTargetInfos(); 208 llvm::InitializeAllAsmParsers(); 209 210 cl::ParseCommandLineOptions(argc, argv, "llvm machine code playground\n"); 211 212 switch (Action) { 213 default: 214 case AC_AsLex: 215 return AsLexInput(argv[0]); 216 case AC_Assemble: 217 return AssembleInput(argv[0]); 218 } 219 220 return 0; 221} 222 223