blob: 7021dd110a25857049bfba5458e5a03be465f327 [file] [log] [blame]
Chris Lattner767a1e42003-11-23 18:01:26 +00001//===--- stkrc.cpp --- The Stacker Compiler -------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Reid Spencer and donated to the LLVM research
6// group and is distributed under the University of Illinois Open Source
7// License. See LICENSE.TXT for details.
8//
9//===----------------------------------------------------------------------===//
10//
11// This is the "main" program for the Stacker Compiler. It is simply a utility
12// that invokes the StackerCompiler::compile method (see StackerCompiler.cpp)
13//
14// To get help using this utility, you can invoke it with:
15// stkrc --help - Output information about command line switches
16//
17//
18//===------------------------------------------------------------------------===
19
20#include "../../lib/compiler/StackerCompiler.h"
21#include "llvm/Assembly/Parser.h"
22#include "llvm/Bytecode/Writer.h"
23#include "llvm/Analysis/Verifier.h"
Reid Spencer551ccae2004-09-01 22:55:40 +000024#include "llvm/Support/CommandLine.h"
Chris Lattner6f9e6072004-05-27 05:37:32 +000025#include "llvm/System/Signals.h"
Chris Lattner767a1e42003-11-23 18:01:26 +000026#include <fstream>
Reid Spencer321f8312004-07-04 12:22:14 +000027#include <iostream>
Chris Lattner767a1e42003-11-23 18:01:26 +000028#include <memory>
29
30using namespace llvm;
31
32static cl::opt<std::string>
33InputFilename(cl::Positional, cl::desc("<input .st file>"), cl::init("-"));
34
35static cl::opt<std::string>
36OutputFilename("o", cl::desc("Override output filename"),
37 cl::value_desc("filename"));
38
39static cl::opt<bool>
40Force("f", cl::desc("Overwrite output files"));
41
Chris Lattner767a1e42003-11-23 18:01:26 +000042static cl::opt<uint32_t>
43StackSize("s", cl::desc("Specify program maximum stack size"),
Reid Spencer6220aa82004-07-10 23:35:46 +000044 cl::init(1024), cl::value_desc("stack size"));
45
46static cl::opt<bool>
47DumpAsm("d", cl::desc("Print LLVM Assembly as parsed"), cl::Hidden);
Chris Lattner767a1e42003-11-23 18:01:26 +000048
49#ifdef PARSE_DEBUG
50static cl::opt<bool>
51ParseDebug("g", cl::desc("Turn on Bison Debugging"), cl::Hidden);
52#endif
53
54#ifdef FLEX_DEBUG
55static cl::opt<bool>
56FlexDebug("x", cl::desc("Turn on Flex Debugging"), cl::Hidden);
57#endif
58
59static cl::opt<bool>
Reid Spencer6220aa82004-07-10 23:35:46 +000060EchoSource("e", cl::desc("Print Stacker Source as parsed"), cl::Hidden);
Chris Lattner767a1e42003-11-23 18:01:26 +000061
Reid Spencer2c711572004-09-04 19:05:53 +000062enum OptLev {
63 None = 0,
64 One = 1,
65 Two = 2,
66 Three = 3,
67 Four = 4,
68 Five = 5
69};
70
71static cl::opt<OptLev> OptLevel(
72 cl::desc("Choose optimization level to apply:"),
73 cl::init(One),
74 cl::values(
75 clEnumValN(None,"O0","An alias for the -O1 option"),
76 clEnumValN(One,"O1","Optimize for compilation speed"),
77 clEnumValN(Two,"O2","Perform simple optimizations to reduce code size"),
78 clEnumValN(Three,"O3","More aggressive optimizations"),
79 clEnumValN(Four,"O4","High level of optimization"),
80 clEnumValN(Five,"O5","An alias for the -O4 option"),
81 clEnumValEnd
82 ));
83
Chris Lattner767a1e42003-11-23 18:01:26 +000084int main(int argc, char **argv)
85{
86 cl::ParseCommandLineOptions(argc, argv, " stacker .st -> .bc compiler\n");
87
88 std::ostream *Out = 0;
Reid Spencer2c711572004-09-04 19:05:53 +000089 try {
90 StackerCompiler compiler;
91 try
Chris Lattner767a1e42003-11-23 18:01:26 +000092 {
Reid Spencer2c711572004-09-04 19:05:53 +000093#ifdef PARSE_DEBUG
94 {
95 extern int Stackerdebug;
96 Stackerdebug = ParseDebug;
97 }
Chris Lattner767a1e42003-11-23 18:01:26 +000098#endif
99#ifdef FLEX_DEBUG
Reid Spencer2c711572004-09-04 19:05:53 +0000100 {
101 extern int Stacker_flex_debug;
102 Stacker_flex_debug = FlexDebug;
103 }
Chris Lattner767a1e42003-11-23 18:01:26 +0000104#endif
Reid Spencer2c711572004-09-04 19:05:53 +0000105 // Parse the file now...
106
107 std::auto_ptr<Module> M (
108 compiler.compile(InputFilename,EchoSource,OptLevel,StackSize));
109 if (M.get() == 0) {
110 throw std::string("program didn't parse correctly.");
111 }
112
113 if (verifyModule(*M.get())) {
114 throw std::string("program parsed, but does not verify as correct!");
115 }
Chris Lattner767a1e42003-11-23 18:01:26 +0000116
Reid Spencer2c711572004-09-04 19:05:53 +0000117 if (DumpAsm)
118 std::cerr << "Here's the assembly:" << M.get();
Chris Lattner767a1e42003-11-23 18:01:26 +0000119
Reid Spencer2c711572004-09-04 19:05:53 +0000120 if (OutputFilename != "") { // Specified an output filename?
121 if (OutputFilename != "-") { // Not stdout?
122 if (!Force && std::ifstream(OutputFilename.c_str())) {
123 // If force is not specified, make sure not to overwrite a file!
124 throw std::string("error opening '") + OutputFilename +
125 "': file exists!\n" +
126 "Use -f command line argument to force output";
127 return 1;
128 }
129 Out = new std::ofstream(OutputFilename.c_str());
130 } else { // Specified stdout
131 Out = &std::cout;
Chris Lattner767a1e42003-11-23 18:01:26 +0000132 }
Chris Lattner767a1e42003-11-23 18:01:26 +0000133 } else {
Reid Spencer2c711572004-09-04 19:05:53 +0000134 if (InputFilename == "-") {
135 OutputFilename = "-";
136 Out = &std::cout;
Chris Lattner767a1e42003-11-23 18:01:26 +0000137 } else {
Reid Spencer2c711572004-09-04 19:05:53 +0000138 std::string IFN = InputFilename;
139 int Len = IFN.length();
140 if (IFN[Len-3] == '.' && IFN[Len-2] == 's' && IFN[Len-1] == 't') {
141 // Source ends in .ll
142 OutputFilename = std::string(IFN.begin(), IFN.end()-3);
143 } else {
144 OutputFilename = IFN; // Append a .bc to it
145 }
146 OutputFilename += ".bc";
Chris Lattner767a1e42003-11-23 18:01:26 +0000147
Reid Spencer2c711572004-09-04 19:05:53 +0000148 if (!Force && std::ifstream(OutputFilename.c_str())) {
149 // If force is not specified, make sure not to overwrite a file!
150 throw std::string("error opening '") + OutputFilename +
151 "': file exists!\n" +
152 "Use -f command line argument to force output\n";
153 }
154
155 Out = new std::ofstream(OutputFilename.c_str());
156 // Make sure that the Out file gets unlinked from the disk if we get a
157 // SIGINT
158 sys::RemoveFileOnSignal(OutputFilename);
Chris Lattner767a1e42003-11-23 18:01:26 +0000159 }
Chris Lattner767a1e42003-11-23 18:01:26 +0000160 }
Reid Spencer2c711572004-09-04 19:05:53 +0000161
162 if (!Out->good()) {
163 throw std::string("error opening ") + OutputFilename + "!";
164 }
165
166 WriteBytecodeToFile(M.get(), *Out);
167 } catch (const ParseException &E) {
168 std::cerr << argv[0] << ": " << E.getMessage() << "\n";
Chris Lattner767a1e42003-11-23 18:01:26 +0000169 return 1;
170 }
Reid Spencer2c711572004-09-04 19:05:53 +0000171 }
172 catch (const std::string& msg ) {
173 std::cerr << argv[0] << ": " << msg << "\n";
Chris Lattner767a1e42003-11-23 18:01:26 +0000174 return 1;
175 }
176
177 if (Out != &std::cout) delete Out;
178 return 0;
179}