llvm-mc.cpp revision 16cdcb38b2a5c5cdc216f9abafabd20e1ef7a254
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/TargetAsmParser.h" 26#include "llvm/Target/TargetRegistry.h" 27#include "llvm/Target/TargetSelect.h" 28#include "AsmParser.h" 29using namespace llvm; 30 31static cl::opt<std::string> 32InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-")); 33 34static cl::opt<std::string> 35OutputFilename("o", cl::desc("Output filename"), 36 cl::value_desc("filename")); 37 38static cl::list<std::string> 39IncludeDirs("I", cl::desc("Directory of include files"), 40 cl::value_desc("directory"), cl::Prefix); 41 42static cl::opt<std::string> 43TripleName("triple", cl::desc("Target triple to assemble for," 44 "see -version for available targets"), 45 cl::init(LLVM_HOSTTRIPLE)); 46 47enum ActionType { 48 AC_AsLex, 49 AC_Assemble 50}; 51 52static cl::opt<ActionType> 53Action(cl::desc("Action to perform:"), 54 cl::init(AC_Assemble), 55 cl::values(clEnumValN(AC_AsLex, "as-lex", 56 "Lex tokens from a .s file"), 57 clEnumValN(AC_Assemble, "assemble", 58 "Assemble a .s file (default)"), 59 clEnumValEnd)); 60 61static int AsLexInput(const char *ProgName) { 62 std::string ErrorMessage; 63 MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFilename, 64 &ErrorMessage); 65 if (Buffer == 0) { 66 errs() << ProgName << ": "; 67 if (ErrorMessage.size()) 68 errs() << ErrorMessage << "\n"; 69 else 70 errs() << "input file didn't read correctly.\n"; 71 return 1; 72 } 73 74 SourceMgr SrcMgr; 75 76 // Tell SrcMgr about this buffer, which is what TGParser will pick up. 77 SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); 78 79 // Record the location of the include directories so that the lexer can find 80 // it later. 81 SrcMgr.setIncludeDirs(IncludeDirs); 82 83 AsmLexer Lexer(SrcMgr); 84 85 bool Error = false; 86 87 while (Lexer.Lex().isNot(AsmToken::Eof)) { 88 switch (Lexer.getKind()) { 89 default: 90 Lexer.PrintMessage(Lexer.getLoc(), "unknown token", "warning"); 91 Error = true; 92 break; 93 case AsmToken::Error: 94 Error = true; // error already printed. 95 break; 96 case AsmToken::Identifier: 97 outs() << "identifier: " << Lexer.getTok().getString() << '\n'; 98 break; 99 case AsmToken::Register: 100 outs() << "register: " << Lexer.getTok().getString() << '\n'; 101 break; 102 case AsmToken::String: 103 outs() << "string: " << Lexer.getTok().getString() << '\n'; 104 break; 105 case AsmToken::Integer: 106 outs() << "int: " << Lexer.getTok().getString() << '\n'; 107 break; 108 109 case AsmToken::Amp: outs() << "Amp\n"; break; 110 case AsmToken::AmpAmp: outs() << "AmpAmp\n"; break; 111 case AsmToken::Caret: outs() << "Caret\n"; break; 112 case AsmToken::Colon: outs() << "Colon\n"; break; 113 case AsmToken::Comma: outs() << "Comma\n"; break; 114 case AsmToken::Dollar: outs() << "Dollar\n"; break; 115 case AsmToken::EndOfStatement: outs() << "EndOfStatement\n"; break; 116 case AsmToken::Eof: outs() << "Eof\n"; break; 117 case AsmToken::Equal: outs() << "Equal\n"; break; 118 case AsmToken::EqualEqual: outs() << "EqualEqual\n"; break; 119 case AsmToken::Exclaim: outs() << "Exclaim\n"; break; 120 case AsmToken::ExclaimEqual: outs() << "ExclaimEqual\n"; break; 121 case AsmToken::Greater: outs() << "Greater\n"; break; 122 case AsmToken::GreaterEqual: outs() << "GreaterEqual\n"; break; 123 case AsmToken::GreaterGreater: outs() << "GreaterGreater\n"; break; 124 case AsmToken::LParen: outs() << "LParen\n"; break; 125 case AsmToken::Less: outs() << "Less\n"; break; 126 case AsmToken::LessEqual: outs() << "LessEqual\n"; break; 127 case AsmToken::LessGreater: outs() << "LessGreater\n"; break; 128 case AsmToken::LessLess: outs() << "LessLess\n"; break; 129 case AsmToken::Minus: outs() << "Minus\n"; break; 130 case AsmToken::Percent: outs() << "Percent\n"; break; 131 case AsmToken::Pipe: outs() << "Pipe\n"; break; 132 case AsmToken::PipePipe: outs() << "PipePipe\n"; break; 133 case AsmToken::Plus: outs() << "Plus\n"; break; 134 case AsmToken::RParen: outs() << "RParen\n"; break; 135 case AsmToken::Slash: outs() << "Slash\n"; break; 136 case AsmToken::Star: outs() << "Star\n"; break; 137 case AsmToken::Tilde: outs() << "Tilde\n"; break; 138 } 139 } 140 141 return Error; 142} 143 144static TargetAsmParser *GetTargetAsmParser(const char *ProgName, 145 MCAsmParser &Parser) { 146 // Get the target specific parser. 147 std::string Error; 148 const Target *TheTarget = 149 TargetRegistry::lookupTarget(TripleName, 150 /*FallbackToHost=*/true, 151 /*RequireJIT=*/false, 152 Error); 153 if (TheTarget == 0) { 154 errs() << ProgName << ": error: unable to get target for '" << TripleName 155 << "', see --version and --triple.\n"; 156 return 0; 157 } 158 159 if (TargetAsmParser *TAP = TheTarget->createAsmParser(Parser)) 160 return TAP; 161 162 errs() << ProgName 163 << ": error: this target does not support assembly parsing.\n"; 164 return 0; 165} 166 167static int AssembleInput(const char *ProgName) { 168 std::string Error; 169 MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFilename, &Error); 170 if (Buffer == 0) { 171 errs() << ProgName << ": "; 172 if (Error.size()) 173 errs() << Error << "\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()); 196 OwningPtr<TargetAsmParser> TAP(GetTargetAsmParser(ProgName, Parser)); 197 if (!TAP) 198 return 1; 199 Parser.setTargetParser(*TAP.get()); 200 return Parser.Run(); 201} 202 203 204int main(int argc, char **argv) { 205 // Print a stack trace if we signal out. 206 sys::PrintStackTraceOnErrorSignal(); 207 PrettyStackTraceProgram X(argc, argv); 208 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 209 210 // Initialize targets and assembly parsers. 211 llvm::InitializeAllTargetInfos(); 212 llvm::InitializeAllAsmParsers(); 213 214 cl::ParseCommandLineOptions(argc, argv, "llvm machine code playground\n"); 215 216 switch (Action) { 217 default: 218 case AC_AsLex: 219 return AsLexInput(argv[0]); 220 case AC_Assemble: 221 return AssembleInput(argv[0]); 222 } 223 224 return 0; 225} 226 227