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