blob: c75c95428bf802180855fb6441ac360162d8563d [file] [log] [blame]
Reid Spencera3f18552004-08-13 20:25:54 +00001//===- CompilerDriver.cpp - The LLVM Compiler Driver ------------*- C++ -*-===//
Reid Spencer5c56dc12004-08-13 20:22:43 +00002//
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//
Reid Spencera3f18552004-08-13 20:25:54 +000011// This file implements the bulk of the LLVM Compiler Driver (llvmc).
Reid Spencer5c56dc12004-08-13 20:22:43 +000012//
13//===------------------------------------------------------------------------===
14
15#include "CompilerDriver.h"
Reid Spencerbf437722004-08-15 08:19:46 +000016#include "ConfigLexer.h"
Reid Spencerbae68252004-08-19 04:49:47 +000017#include "Support/SystemUtils.h"
Reid Spencer5c56dc12004-08-13 20:22:43 +000018#include <iostream>
19
20using namespace llvm;
21
22namespace {
23 inline std::string RemoveSuffix(const std::string& fullName) {
24 size_t dotpos = fullName.rfind('.',fullName.size());
25 if ( dotpos == std::string::npos ) return fullName;
26 return fullName.substr(0, dotpos);
27 }
28
29 inline std::string GetSuffix(const std::string& fullName) {
30 size_t dotpos = fullName.rfind('.',fullName.size());
31 if ( dotpos = std::string::npos ) return "";
32 return fullName.substr(dotpos+1);
33 }
Reid Spencer68fb37a2004-08-14 09:37:15 +000034
Reid Spencer5c56dc12004-08-13 20:22:43 +000035 const char OutputSuffix[] = ".o";
36
Reid Spencerbae68252004-08-19 04:49:47 +000037 void WriteAction(CompilerDriver::Action* action ) {
38 std::cerr << action->program;
39 std::vector<std::string>::iterator I = action->args.begin();
40 while (I != action->args.end()) {
Reid Spencer68fb37a2004-08-14 09:37:15 +000041 std::cerr << " " + *I;
42 ++I;
43 }
44 std::cerr << "\n";
45 }
46
Reid Spencerbae68252004-08-19 04:49:47 +000047 void DumpAction(CompilerDriver::Action* action) {
48 std::cerr << "command = " << action->program;
49 std::vector<std::string>::iterator I = action->args.begin();
50 while (I != action->args.end()) {
Reid Spencerbf437722004-08-15 08:19:46 +000051 std::cerr << " " + *I;
52 ++I;
53 }
54 std::cerr << "\n";
Reid Spencerbae68252004-08-19 04:49:47 +000055 std::cerr << "flags = " << action->flags << "\n";
Reid Spencerbf437722004-08-15 08:19:46 +000056 }
57
Reid Spencer68fb37a2004-08-14 09:37:15 +000058 void DumpConfigData(CompilerDriver::ConfigData* cd, const std::string& type ){
59 std::cerr << "Configuration Data For '" << cd->langName << "' (" << type
60 << ")\n";
Reid Spencer68fb37a2004-08-14 09:37:15 +000061 std::cerr << "PreProcessor: ";
Reid Spencerbf437722004-08-15 08:19:46 +000062 DumpAction(&cd->PreProcessor);
Reid Spencer68fb37a2004-08-14 09:37:15 +000063 std::cerr << "Translator: ";
Reid Spencerbf437722004-08-15 08:19:46 +000064 DumpAction(&cd->Translator);
Reid Spencer68fb37a2004-08-14 09:37:15 +000065 std::cerr << "Optimizer: ";
Reid Spencerbf437722004-08-15 08:19:46 +000066 DumpAction(&cd->Optimizer);
Reid Spencer68fb37a2004-08-14 09:37:15 +000067 std::cerr << "Assembler: ";
Reid Spencerbf437722004-08-15 08:19:46 +000068 DumpAction(&cd->Assembler);
Reid Spencer68fb37a2004-08-14 09:37:15 +000069 std::cerr << "Linker: ";
Reid Spencerbf437722004-08-15 08:19:46 +000070 DumpAction(&cd->Linker);
Reid Spencer68fb37a2004-08-14 09:37:15 +000071 }
Reid Spencer5c56dc12004-08-13 20:22:43 +000072
Reid Spencer2a069fa2004-08-16 07:06:38 +000073 /// This specifies the passes to run for OPT_FAST_COMPILE (-O1)
74 /// which should reduce the volume of code and make compilation
75 /// faster. This is also safe on any llvm module.
Reid Spencerbae68252004-08-19 04:49:47 +000076 static const char* DefaultFastCompileOptimizations[] = {
77 "-simplifycfg", "-mem2reg", "-instcombine"
Reid Spencer2a069fa2004-08-16 07:06:38 +000078 };
79}
Reid Spencer5c56dc12004-08-13 20:22:43 +000080
Reid Spencerbae68252004-08-19 04:49:47 +000081// Stuff in this namespace properly belongs in lib/System and needs
82// to be portable but we're avoiding that for now.
83namespace sys {
Reid Spencer9a8fedd2004-08-20 09:14:05 +000084
85 bool FileReadable(const std::string& fname) {
86 return 0 == access(fname.c_str(), F_OK | R_OK);
87 }
88
89 void CleanupTempFile(const std::string& fname) {
90 if (FileReadable(fname))
91 unlink(fname.c_str());
92 }
93
Reid Spencerbae68252004-08-19 04:49:47 +000094 std::string MakeTemporaryDirectory() {
95 char temp_name[64];
96 strcpy(temp_name,"/tmp/llvm_XXXXXX");
97 if (0 == mkdtemp(temp_name))
98 throw std::string("Can't create temporary directory");
99 return temp_name;
100 }
101
102 std::string FindExecutableInPath(const std::string& program) {
103 // First, just see if the program is already executable
104 if (isExecutableFile(program)) return program;
105
106 // Get the path. If its empty, we can't do anything
107 const char *PathStr = getenv("PATH");
108 if (PathStr == 0) return "";
109
110 // Now we have a colon separated list of directories to search; try them.
111 unsigned PathLen = strlen(PathStr);
112 while (PathLen) {
113 // Find the first colon...
114 const char *Colon = std::find(PathStr, PathStr+PathLen, ':');
115
116 // Check to see if this first directory contains the executable...
117 std::string FilePath = std::string(PathStr, Colon) + '/' + program;
118 if (isExecutableFile(FilePath))
119 return FilePath; // Found the executable!
120
121 // Nope it wasn't in this directory, check the next range!
122 PathLen -= Colon-PathStr;
123 PathStr = Colon;
124
125 // Advance past duplicate coons
126 while (*PathStr == ':') {
127 PathStr++;
128 PathLen--;
129 }
130 }
131
132 // If we fell out, we ran out of directories in PATH to search, return failure
133 return "";
134 }
135}
136
Reid Spencer5c56dc12004-08-13 20:22:43 +0000137CompilerDriver::CompilerDriver(ConfigDataProvider& confDatProv )
138 : cdp(&confDatProv)
139 , finalPhase(LINKING)
140 , optLevel(OPT_FAST_COMPILE)
141 , isDryRun(false)
142 , isVerbose(false)
143 , isDebug(false)
144 , timeActions(false)
145 , emitRawCode(false)
146 , emitNativeCode(false)
Reid Spencerbae68252004-08-19 04:49:47 +0000147 , keepTemps(false)
Reid Spencer5c56dc12004-08-13 20:22:43 +0000148 , machine()
Reid Spencerbf437722004-08-15 08:19:46 +0000149 , LibraryPaths()
Reid Spencerbae68252004-08-19 04:49:47 +0000150 , AdditionalArgs()
151 , TempDir()
Reid Spencer5c56dc12004-08-13 20:22:43 +0000152{
153 // FIXME: These libraries are platform specific
Reid Spencerbf437722004-08-15 08:19:46 +0000154 LibraryPaths.push_back("/lib");
155 LibraryPaths.push_back("/usr/lib");
Reid Spencerbae68252004-08-19 04:49:47 +0000156 AdditionalArgs.reserve(NUM_PHASES);
157 StringVector emptyVec;
158 for (unsigned i = 0; i < NUM_PHASES; ++i)
159 AdditionalArgs.push_back(emptyVec);
Reid Spencer5c56dc12004-08-13 20:22:43 +0000160}
161
162CompilerDriver::~CompilerDriver() {
163 cdp = 0;
Reid Spencerbf437722004-08-15 08:19:46 +0000164 LibraryPaths.clear();
Reid Spencerbae68252004-08-19 04:49:47 +0000165 AdditionalArgs.clear();
166}
167
168CompilerDriver::ConfigData::ConfigData()
169 : langName()
170 , PreProcessor()
171 , Translator()
172 , Optimizer()
173 , Assembler()
174 , Linker()
175{
176 StringVector emptyVec;
177 for (unsigned i = 0; i < NUM_PHASES; ++i)
178 opts.push_back(emptyVec);
Reid Spencer5c56dc12004-08-13 20:22:43 +0000179}
180
181void CompilerDriver::error( const std::string& errmsg ) {
Reid Spencerbae68252004-08-19 04:49:47 +0000182 std::cerr << "llvmc: Error: " << errmsg << ".\n";
Reid Spencer5c56dc12004-08-13 20:22:43 +0000183 exit(1);
184}
185
186CompilerDriver::Action* CompilerDriver::GetAction(ConfigData* cd,
187 const std::string& input,
188 const std::string& output,
189 Phases phase)
190{
Reid Spencerbae68252004-08-19 04:49:47 +0000191 Action* pat = 0; ///< The pattern/template for the action
192 Action* action = new Action; ///< The actual action to execute
193
Reid Spencerbf437722004-08-15 08:19:46 +0000194 // Get the action pattern
Reid Spencer5c56dc12004-08-13 20:22:43 +0000195 switch (phase) {
196 case PREPROCESSING: pat = &cd->PreProcessor; break;
197 case TRANSLATION: pat = &cd->Translator; break;
198 case OPTIMIZATION: pat = &cd->Optimizer; break;
199 case ASSEMBLY: pat = &cd->Assembler; break;
200 case LINKING: pat = &cd->Linker; break;
201 default:
202 assert(!"Invalid driver phase!");
203 break;
204 }
205 assert(pat != 0 && "Invalid command pattern");
Reid Spencerbf437722004-08-15 08:19:46 +0000206
Reid Spencerbae68252004-08-19 04:49:47 +0000207 // Copy over some pattern things that don't need to change
208 action->program = pat->program;
209 action->flags = pat->flags;
Reid Spencerbf437722004-08-15 08:19:46 +0000210
Reid Spencerbae68252004-08-19 04:49:47 +0000211 // Do the substitutions from the pattern to the actual
212 StringVector::iterator PI = pat->args.begin();
213 StringVector::iterator PE = pat->args.end();
214 while (PI != PE) {
Reid Spencer53aa7932004-08-20 22:53:11 +0000215 if ((*PI)[0] == '%') {
216 if (*PI == "%in%") {
Reid Spencerbae68252004-08-19 04:49:47 +0000217 action->args.push_back(input);
Reid Spencer53aa7932004-08-20 22:53:11 +0000218 } else if (*PI == "%out%") {
Reid Spencerbae68252004-08-19 04:49:47 +0000219 action->args.push_back(output);
Reid Spencer53aa7932004-08-20 22:53:11 +0000220 } else if (*PI == "%time%") {
Reid Spencerbae68252004-08-19 04:49:47 +0000221 if (timePasses)
222 action->args.push_back("-time-passes");
Reid Spencer53aa7932004-08-20 22:53:11 +0000223 } else if (*PI == "%stats%") {
Reid Spencerbae68252004-08-19 04:49:47 +0000224 if (showStats)
225 action->args.push_back("-stats");
Reid Spencer53aa7932004-08-20 22:53:11 +0000226 } else if (*PI == "%target%") {
Reid Spencerbae68252004-08-19 04:49:47 +0000227 // FIXME: Ignore for now
Reid Spencer53aa7932004-08-20 22:53:11 +0000228 } else if (*PI == "%opt%") {
Reid Spencerbae68252004-08-19 04:49:47 +0000229 if (!emitRawCode) {
230 if (pat->isSet(GROKS_DASH_O)) {
231 if (optLevel != OPT_NONE) {
232 std::string optArg("-O");
233 switch (optLevel) {
234 case OPT_FAST_COMPILE : optArg.append("1"); break;
235 case OPT_SIMPLE: optArg.append("2"); break;
236 case OPT_AGGRESSIVE: optArg.append("3"); break;
237 case OPT_LINK_TIME: optArg.append("4"); break;
238 case OPT_AGGRESSIVE_LINK_TIME: optArg.append("5"); break;
239 default :
240 assert(!"Invalid optimization argument!");
241 optArg.append("0");
242 break;
243 }
244 action->args.push_back(optArg);
245 }
246 } else {
247 if (cd->opts.size() > static_cast<unsigned>(optLevel) &&
248 !cd->opts[optLevel].empty())
249 action->args.insert(action->args.end(), cd->opts[optLevel].begin(),
250 cd->opts[optLevel].end());
251 }
252 }
253 } else {
254 error("Invalid substitution name");
255 }
256 } else {
257 // Its not a substitution, just put it in the action
258 action->args.push_back(*PI);
259 }
260 PI++;
Reid Spencerbf437722004-08-15 08:19:46 +0000261 }
Reid Spencerbae68252004-08-19 04:49:47 +0000262
263 // Get specific options for each kind of action type
264 StringVector& args = AdditionalArgs[phase];
265
266 // Add specific options for each kind of action type
267 action->args.insert(action->args.end(), args.begin(), args.end());
268
269 // Finally, we're done
270 return action;
Reid Spencer5c56dc12004-08-13 20:22:43 +0000271}
272
Reid Spencerbae68252004-08-19 04:49:47 +0000273bool CompilerDriver::DoAction(Action*action) {
274 assert(action != 0 && "Invalid Action!");
Reid Spencer5c56dc12004-08-13 20:22:43 +0000275 if (isVerbose)
Reid Spencerbae68252004-08-19 04:49:47 +0000276 WriteAction(action);
Reid Spencer5c56dc12004-08-13 20:22:43 +0000277 if (!isDryRun) {
Reid Spencerbae68252004-08-19 04:49:47 +0000278 std::string prog(sys::FindExecutableInPath(action->program));
279 if (prog.empty())
280 error("Can't find program '" + action->program + "'");
281
282 // Get the program's arguments
283 const char* argv[action->args.size() + 1];
284 argv[0] = prog.c_str();
285 unsigned i = 1;
286 for (; i <= action->args.size(); ++i)
287 argv[i] = action->args[i-1].c_str();
288 argv[i] = 0;
289
290 // Invoke the program
291 return !ExecWait(argv, environ);
Reid Spencer5c56dc12004-08-13 20:22:43 +0000292 }
Reid Spencerbae68252004-08-19 04:49:47 +0000293 return true;
Reid Spencer5c56dc12004-08-13 20:22:43 +0000294}
295
296int CompilerDriver::execute(const InputList& InpList,
Reid Spencer2a069fa2004-08-16 07:06:38 +0000297 const std::string& Output ) {
Reid Spencer5c56dc12004-08-13 20:22:43 +0000298 // Echo the configuration of options if we're running verbose
299 if (isDebug)
300 {
301 std::cerr << "Compiler Driver Options:\n";
302 std::cerr << "DryRun = " << isDryRun << "\n";
303 std::cerr << "Verbose = " << isVerbose << " \n";
304 std::cerr << "TimeActions = " << timeActions << "\n";
305 std::cerr << "EmitRawCode = " << emitRawCode << "\n";
306 std::cerr << "OutputMachine = " << machine << "\n";
307 std::cerr << "EmitNativeCode = " << emitNativeCode << "\n";
308 InputList::const_iterator I = InpList.begin();
309 while ( I != InpList.end() ) {
310 std::cerr << "Input: " << I->first << "(" << I->second << ")\n";
311 ++I;
312 }
313 std::cerr << "Output: " << Output << "\n";
314 }
315
316 // If there's no input, we're done.
317 if (InpList.empty())
318 error("Nothing to compile.");
319
320 // If they are asking for linking and didn't provide an output
321 // file then its an error (no way for us to "make up" a meaningful
322 // file name based on the various linker input files).
323 if (finalPhase == LINKING && Output.empty())
324 error("An output file name must be specified for linker output");
325
Reid Spencerbf437722004-08-15 08:19:46 +0000326 // This vector holds all the resulting actions of the following loop.
Reid Spencer5c56dc12004-08-13 20:22:43 +0000327 std::vector<Action*> actions;
328
Reid Spencerbf437722004-08-15 08:19:46 +0000329 // Create a temporary directory for our temporary files
Reid Spencerbae68252004-08-19 04:49:47 +0000330 std::string TempDir(sys::MakeTemporaryDirectory());
331 std::string TempPreprocessorOut(TempDir + "/preproc.o");
332 std::string TempTranslatorOut(TempDir + "/trans.o");
333 std::string TempOptimizerOut(TempDir + "/opt.o");
334 std::string TempAssemblerOut(TempDir + "/asm.o");
Reid Spencerbf437722004-08-15 08:19:46 +0000335
Reid Spencer5c56dc12004-08-13 20:22:43 +0000336 /// PRE-PROCESSING / TRANSLATION / OPTIMIZATION / ASSEMBLY phases
337 // for each input item
338 std::vector<std::string> LinkageItems;
339 InputList::const_iterator I = InpList.begin();
340 while ( I != InpList.end() ) {
341 // Get the suffix of the file name
342 std::string suffix = GetSuffix(I->first);
343
344 // If its a library, bytecode file, or object file, save
345 // it for linking below and short circuit the
346 // pre-processing/translation/assembly phases
347 if (I->second.empty() || suffix == "o" || suffix == "bc") {
348 // We shouldn't get any of these types of files unless we're
349 // later going to link. Enforce this limit now.
350 if (finalPhase != LINKING) {
351 error("Pre-compiled objects found but linking not requested");
352 }
353 LinkageItems.push_back(I->first);
354 continue; // short circuit remainder of loop
355 }
356
357 // At this point, we know its something we need to translate
358 // and/or optimize. See if we can get the configuration data
359 // for this kind of file.
360 ConfigData* cd = cdp->ProvideConfigData(I->second);
361 if (cd == 0)
362 error(std::string("Files of type '") + I->second +
363 "' are not recognized." );
Reid Spencer68fb37a2004-08-14 09:37:15 +0000364 if (isDebug)
365 DumpConfigData(cd,I->second);
Reid Spencer5c56dc12004-08-13 20:22:43 +0000366
367 // We have valid configuration data, now figure out where the output
368 // of compilation should end up.
369 std::string OutFile;
370 if (finalPhase != LINKING) {
371 if (InpList.size() == 1 && !Output.empty())
372 OutFile = Output;
373 else
374 OutFile = RemoveSuffix(I->first) + OutputSuffix;
375 } else {
376 OutFile = Output;
377 }
378
Reid Spencerbae68252004-08-19 04:49:47 +0000379 // Initialize the input file
380 std::string InFile(I->first);
381
Reid Spencerbf437722004-08-15 08:19:46 +0000382 // PRE-PROCESSING PHASE
Reid Spencerbae68252004-08-19 04:49:47 +0000383 Action& action = cd->PreProcessor;
Reid Spencer5c56dc12004-08-13 20:22:43 +0000384
Reid Spencerbf437722004-08-15 08:19:46 +0000385 // Get the preprocessing action, if needed, or error if appropriate
Reid Spencerbae68252004-08-19 04:49:47 +0000386 if (!action.program.empty()) {
387 if (action.isSet(REQUIRED_FLAG) || finalPhase == PREPROCESSING) {
388 if (finalPhase == PREPROCESSING)
389 actions.push_back(GetAction(cd,InFile,OutFile,PREPROCESSING));
390 else {
391 actions.push_back(GetAction(cd,InFile,TempPreprocessorOut,
392 PREPROCESSING));
393 InFile = TempPreprocessorOut;
394 }
Reid Spencerbf437722004-08-15 08:19:46 +0000395 }
396 } else if (finalPhase == PREPROCESSING) {
397 error(cd->langName + " does not support pre-processing");
Reid Spencerbae68252004-08-19 04:49:47 +0000398 } else if (action.isSet(REQUIRED_FLAG)) {
Reid Spencerbf437722004-08-15 08:19:46 +0000399 error(std::string("Don't know how to pre-process ") +
400 cd->langName + " files");
401 }
Reid Spencerbae68252004-08-19 04:49:47 +0000402
Reid Spencer5c56dc12004-08-13 20:22:43 +0000403 // Short-circuit remaining actions if all they want is pre-processing
404 if (finalPhase == PREPROCESSING) { ++I; continue; };
405
406 /// TRANSLATION PHASE
Reid Spencerbae68252004-08-19 04:49:47 +0000407 action = cd->Translator;
Reid Spencerbf437722004-08-15 08:19:46 +0000408
409 // Get the translation action, if needed, or error if appropriate
Reid Spencerbae68252004-08-19 04:49:47 +0000410 if (!action.program.empty()) {
411 if (action.isSet(REQUIRED_FLAG) || finalPhase == TRANSLATION) {
412 if (finalPhase == TRANSLATION)
413 actions.push_back(GetAction(cd,InFile,OutFile,TRANSLATION));
414 else {
415 actions.push_back(GetAction(cd,InFile,TempTranslatorOut,TRANSLATION));
416 InFile = TempTranslatorOut;
417 }
418
419 // ll -> bc Helper
420 if (action.isSet(OUTPUT_IS_ASM_FLAG)) {
421 /// The output of the translator is an LLVM Assembly program
422 /// We need to translate it to bytecode
423 Action* action = new Action();
424 action->program = "llvm-as";
425 action->args.push_back(InFile);
426 action->args.push_back("-o");
427 InFile += ".bc";
428 action->args.push_back(InFile);
429 actions.push_back(action);
430 }
Reid Spencerbf437722004-08-15 08:19:46 +0000431 }
432 } else if (finalPhase == TRANSLATION) {
433 error(cd->langName + " does not support translation");
Reid Spencerbae68252004-08-19 04:49:47 +0000434 } else if (action.isSet(REQUIRED_FLAG)) {
Reid Spencerbf437722004-08-15 08:19:46 +0000435 error(std::string("Don't know how to translate ") +
436 cd->langName + " files");
437 }
Reid Spencerbae68252004-08-19 04:49:47 +0000438
Reid Spencer5c56dc12004-08-13 20:22:43 +0000439 // Short-circuit remaining actions if all they want is translation
440 if (finalPhase == TRANSLATION) { ++I; continue; }
441
442 /// OPTIMIZATION PHASE
Reid Spencerbae68252004-08-19 04:49:47 +0000443 action = cd->Optimizer;
Reid Spencerbf437722004-08-15 08:19:46 +0000444
445 // Get the optimization action, if needed, or error if appropriate
Reid Spencerbae68252004-08-19 04:49:47 +0000446 if (!action.program.empty() && !emitRawCode) {
447 if (action.isSet(REQUIRED_FLAG) || finalPhase == OPTIMIZATION) {
448 if (finalPhase == OPTIMIZATION)
449 actions.push_back(GetAction(cd,InFile,OutFile,OPTIMIZATION));
450 else {
451 actions.push_back(GetAction(cd,InFile,TempOptimizerOut,OPTIMIZATION));
452 InFile = TempOptimizerOut;
453 }
454 // ll -> bc Helper
455 if (action.isSet(OUTPUT_IS_ASM_FLAG)) {
456 /// The output of the translator is an LLVM Assembly program
457 /// We need to translate it to bytecode
458 Action* action = new Action();
459 action->program = "llvm-as";
460 action->args.push_back(InFile);
Reid Spencer9a8fedd2004-08-20 09:14:05 +0000461 action->args.push_back("-f");
Reid Spencerbae68252004-08-19 04:49:47 +0000462 action->args.push_back("-o");
463 InFile += ".bc";
464 action->args.push_back(InFile);
465 actions.push_back(action);
466 }
467 }
Reid Spencerbf437722004-08-15 08:19:46 +0000468 } else if (finalPhase == OPTIMIZATION) {
469 error(cd->langName + " does not support optimization");
Reid Spencerbae68252004-08-19 04:49:47 +0000470 } else if (action.isSet(REQUIRED_FLAG)) {
Reid Spencerbf437722004-08-15 08:19:46 +0000471 error(std::string("Don't know how to optimize ") +
472 cd->langName + " files");
473 }
Reid Spencerbae68252004-08-19 04:49:47 +0000474
Reid Spencer5c56dc12004-08-13 20:22:43 +0000475 // Short-circuit remaining actions if all they want is optimization
476 if (finalPhase == OPTIMIZATION) { ++I; continue; }
477
Reid Spencerbae68252004-08-19 04:49:47 +0000478 /// ASSEMBLY PHASE
Reid Spencer9a8fedd2004-08-20 09:14:05 +0000479 action = cd->Assembler;
480
481 if (finalPhase == ASSEMBLY) {
482 if (emitNativeCode) {
483 if (action.program.empty()) {
484 error(std::string("Native Assembler not specified for ") +
485 cd->langName + " files");
486 } else {
487 actions.push_back(GetAction(cd,InFile,OutFile,ASSEMBLY));
488 }
489 } else {
490 // Just convert back to llvm assembly with llvm-dis
491 Action* action = new Action();
492 action->program = "llvm-dis";
493 action->args.push_back(InFile);
494 action->args.push_back("-f");
495 action->args.push_back("-o");
496 action->args.push_back(OutFile);
497 actions.push_back(action);
498 }
Reid Spencerbae68252004-08-19 04:49:47 +0000499 }
500
501 // Go to next file to be processed
Reid Spencer5c56dc12004-08-13 20:22:43 +0000502 ++I;
503 }
504
505 /// LINKING PHASE
Reid Spencer9a8fedd2004-08-20 09:14:05 +0000506 if (finalPhase == LINKING) {
507 if (emitNativeCode) {
508 } else {
509 }
Reid Spencerbae68252004-08-19 04:49:47 +0000510 }
Reid Spencer5c56dc12004-08-13 20:22:43 +0000511
512 /// RUN THE ACTIONS
513 std::vector<Action*>::iterator aIter = actions.begin();
514 while (aIter != actions.end()) {
Reid Spencerbae68252004-08-19 04:49:47 +0000515 if (!DoAction(*aIter))
516 error("Action failed");
Reid Spencer5c56dc12004-08-13 20:22:43 +0000517 aIter++;
518 }
519
Reid Spencerbae68252004-08-19 04:49:47 +0000520 if (!keepTemps) {
521 // Cleanup files
Reid Spencer9a8fedd2004-08-20 09:14:05 +0000522 ::sys::CleanupTempFile(TempPreprocessorOut);
523 ::sys::CleanupTempFile(TempTranslatorOut);
524 ::sys::CleanupTempFile(TempOptimizerOut);
Reid Spencer2a069fa2004-08-16 07:06:38 +0000525
Reid Spencerbae68252004-08-19 04:49:47 +0000526 // Cleanup temporary directory we created
Reid Spencer9a8fedd2004-08-20 09:14:05 +0000527 if (::sys::FileReadable(TempDir))
Reid Spencerbae68252004-08-19 04:49:47 +0000528 rmdir(TempDir.c_str());
529 }
Reid Spencerbf437722004-08-15 08:19:46 +0000530
Reid Spencer5c56dc12004-08-13 20:22:43 +0000531 return 0;
532}
533
534// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab