blob: 7a639b38cdc6e554fcf4a4c6ecc60895a0eebc2a [file] [log] [blame]
Reid Spencer5c56dc12004-08-13 20:22:43 +00001//===- DriverAction.cpp - Compile Driver Actions ----------------*- C++ -*-===//
2//
3//
4// The LLVM Compiler Infrastructure
5//
6// This file was developed by Reid Spencer and is distributed under the
7// University of Illinois Open Source License. See LICENSE.TXT for details.
8//
9//===----------------------------------------------------------------------===//
10//
11// This file implements support for executable actions in the LLVM Compiler
12// Driver (llvmc).
13//
14//===------------------------------------------------------------------------===
15
16#include "CompilerDriver.h"
17#include <iostream>
18
19using namespace llvm;
20
21namespace {
22 inline std::string RemoveSuffix(const std::string& fullName) {
23 size_t dotpos = fullName.rfind('.',fullName.size());
24 if ( dotpos == std::string::npos ) return fullName;
25 return fullName.substr(0, dotpos);
26 }
27
28 inline std::string GetSuffix(const std::string& fullName) {
29 size_t dotpos = fullName.rfind('.',fullName.size());
30 if ( dotpos = std::string::npos ) return "";
31 return fullName.substr(dotpos+1);
32 }
33 const char OutputSuffix[] = ".o";
34
35}
36
37
38CompilerDriver::CompilerDriver(ConfigDataProvider& confDatProv )
39 : cdp(&confDatProv)
40 , finalPhase(LINKING)
41 , optLevel(OPT_FAST_COMPILE)
42 , isDryRun(false)
43 , isVerbose(false)
44 , isDebug(false)
45 , timeActions(false)
46 , emitRawCode(false)
47 , emitNativeCode(false)
48 , machine()
49 , libPaths()
50{
51 // FIXME: These libraries are platform specific
52 libPaths.push_back("/lib");
53 libPaths.push_back("/usr/lib");
54}
55
56CompilerDriver::~CompilerDriver() {
57 cdp = 0;
58 libPaths.clear();
59}
60
61void CompilerDriver::error( const std::string& errmsg ) {
62 std::cerr << "Error: " << errmsg << ".\n";
63 exit(1);
64}
65
66CompilerDriver::Action* CompilerDriver::GetAction(ConfigData* cd,
67 const std::string& input,
68 const std::string& output,
69 Phases phase)
70{
71 Action* pat = 0;
72 switch (phase) {
73 case PREPROCESSING: pat = &cd->PreProcessor; break;
74 case TRANSLATION: pat = &cd->Translator; break;
75 case OPTIMIZATION: pat = &cd->Optimizer; break;
76 case ASSEMBLY: pat = &cd->Assembler; break;
77 case LINKING: pat = &cd->Linker; break;
78 default:
79 assert(!"Invalid driver phase!");
80 break;
81 }
82 assert(pat != 0 && "Invalid command pattern");
83 Action* a = new Action(*pat);
84 a->args[pat->inputAt] = input;
85 a->args[pat->outputAt] = output;
86 return a;
87}
88
89void CompilerDriver::WriteAction(Action* a) {
90 std::cerr << a->program;
91 std::vector<std::string>::iterator I = a->args.begin();
92 while (I != a->args.end()) {
93 std::cerr << " " + *I;
94 ++I;
95 }
96 std::cerr << "\n";
97}
98
99void CompilerDriver::DoAction(Action*a)
100{
101 if (isVerbose)
102 WriteAction(a);
103 if (!isDryRun) {
104 std::cerr << "execve(\"" << a->program << "\",[\n";
105 std::vector<std::string>::iterator I = a->args.begin();
106 while (I != a->args.end()) {
107 std::cerr << " \"" << *I << "\",\n";
108 ++I;
109 }
110 std::cerr << "],ENV);\n";
111 }
112}
113
114int CompilerDriver::execute(const InputList& InpList,
115 const std::string& Output ) {
116 // Echo the configuration of options if we're running verbose
117 if (isDebug)
118 {
119 std::cerr << "Compiler Driver Options:\n";
120 std::cerr << "DryRun = " << isDryRun << "\n";
121 std::cerr << "Verbose = " << isVerbose << " \n";
122 std::cerr << "TimeActions = " << timeActions << "\n";
123 std::cerr << "EmitRawCode = " << emitRawCode << "\n";
124 std::cerr << "OutputMachine = " << machine << "\n";
125 std::cerr << "EmitNativeCode = " << emitNativeCode << "\n";
126 InputList::const_iterator I = InpList.begin();
127 while ( I != InpList.end() ) {
128 std::cerr << "Input: " << I->first << "(" << I->second << ")\n";
129 ++I;
130 }
131 std::cerr << "Output: " << Output << "\n";
132 }
133
134 // If there's no input, we're done.
135 if (InpList.empty())
136 error("Nothing to compile.");
137
138 // If they are asking for linking and didn't provide an output
139 // file then its an error (no way for us to "make up" a meaningful
140 // file name based on the various linker input files).
141 if (finalPhase == LINKING && Output.empty())
142 error("An output file name must be specified for linker output");
143
144 std::vector<Action*> actions;
145
146 /// PRE-PROCESSING / TRANSLATION / OPTIMIZATION / ASSEMBLY phases
147 // for each input item
148 std::vector<std::string> LinkageItems;
149 InputList::const_iterator I = InpList.begin();
150 while ( I != InpList.end() ) {
151 // Get the suffix of the file name
152 std::string suffix = GetSuffix(I->first);
153
154 // If its a library, bytecode file, or object file, save
155 // it for linking below and short circuit the
156 // pre-processing/translation/assembly phases
157 if (I->second.empty() || suffix == "o" || suffix == "bc") {
158 // We shouldn't get any of these types of files unless we're
159 // later going to link. Enforce this limit now.
160 if (finalPhase != LINKING) {
161 error("Pre-compiled objects found but linking not requested");
162 }
163 LinkageItems.push_back(I->first);
164 continue; // short circuit remainder of loop
165 }
166
167 // At this point, we know its something we need to translate
168 // and/or optimize. See if we can get the configuration data
169 // for this kind of file.
170 ConfigData* cd = cdp->ProvideConfigData(I->second);
171 if (cd == 0)
172 error(std::string("Files of type '") + I->second +
173 "' are not recognized." );
174
175 // We have valid configuration data, now figure out where the output
176 // of compilation should end up.
177 std::string OutFile;
178 if (finalPhase != LINKING) {
179 if (InpList.size() == 1 && !Output.empty())
180 OutFile = Output;
181 else
182 OutFile = RemoveSuffix(I->first) + OutputSuffix;
183 } else {
184 OutFile = Output;
185 }
186
187 /// PRE-PROCESSING PHASE
188 if (finalPhase == PREPROCESSING) {
189 if (cd->PreProcessor.program.empty())
190 error(cd->langName + " does not support pre-processing");
191 else
192 actions.push_back(GetAction(cd,I->first,OutFile,PREPROCESSING));
193 } else if (cd->PreprocessorNeeded && !cd->TranslatorPreprocesses) {
194 if (!cd->PreProcessor.program.empty()) {
195 actions.push_back(GetAction(cd,I->first,OutFile,PREPROCESSING));
196 }
197 }
198
199 // Short-circuit remaining actions if all they want is pre-processing
200 if (finalPhase == PREPROCESSING) { ++I; continue; };
201
202 /// TRANSLATION PHASE
203 actions.push_back(GetAction(cd,I->first,OutFile,TRANSLATION));
204 // Short-circuit remaining actions if all they want is translation
205 if (finalPhase == TRANSLATION) { ++I; continue; }
206
207 /// OPTIMIZATION PHASE
208 actions.push_back(GetAction(cd,I->first,OutFile,OPTIMIZATION));
209 // Short-circuit remaining actions if all they want is optimization
210 if (finalPhase == OPTIMIZATION) { ++I; continue; }
211
212 ++I;
213 }
214
215 /// LINKING PHASE
216
217 /// RUN THE ACTIONS
218 std::vector<Action*>::iterator aIter = actions.begin();
219 while (aIter != actions.end()) {
220 DoAction(*aIter);
221 aIter++;
222 }
223
224 return 0;
225}
226
227// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab