source: driver/cc1.cc@ bdd516a

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors ctor deferred_resn demangler enum forall-pointer-decay gc_noraii jacob/cs343-translation jenkins-sandbox memory new-ast new-ast-unique-expr new-env no_list persistent-indexer pthread-emulation qualifiedEnum resolv-new string stuck-waitfor-destruct with_gc
Last change on this file since bdd516a was bdd516a, checked in by Peter A. Buhr <pabuhr@…>, 11 years ago

fixed sizeof type variable, find lowest cost alternative for sizeof expression, removed unused classes, added compiler flag, remove temporary file for -CFA, formatting

  • Property mode set to 100644
File size: 14.2 KB
Line 
1// -*- Mode: C++ -*-
2//
3// CForall Version 1.0, Copyright (C) Peter A. Buhr 2005
4//
5// cc1.cc --
6//
7// Author : Richard C. Bilson
8// Created On : Fri Aug 26 14:23:51 2005
9// Last Modified By : Peter A. Buhr
10// Last Modified On : Mon Apr 27 23:11:52 2015
11// Update Count : 39
12//
13
14
15#include <iostream>
16using std::cerr;
17using std::endl;
18#include <string>
19using std::string;
20#include <cstdio> // stderr, stdout, perror, fprintf
21#include <cstdlib> // getenv, exit, mkstemp
22#include <unistd.h> // execvp, fork, unlink
23#include <sys/wait.h> // wait
24
25#include "config.h" // configure info
26
27
28//#define __DEBUG_H__
29
30
31string compiler_name( GCC_PATH ); // path/name of C compiler
32
33string D__GCC_BPREFIX__( "-D__GCC_BPREFIX__=" );
34string D__CFA_FLAGPREFIX__( "-D__CFA_FLAG__=" );
35
36char tmpname[] = P_tmpdir "/CFAXXXXXX";
37int tmpfilefd = -1;
38
39
40bool prefix( string arg, string pre ) {
41 return arg.substr( 0, pre.size() ) == pre;
42} // prefix
43
44
45void checkEnv( const char *args[], int &nargs ) {
46 char *value;
47
48 value = getenv( "__COMPILER__" );
49 if ( value != NULL ) {
50 compiler_name = value;
51#ifdef __DEBUG_H__
52 cerr << "env arg:\"" << compiler_name << "\"" << endl;
53#endif // __DEBUG_H__
54 } // if
55
56 value = getenv( "__GCC_MACHINE__" );
57 if ( value != NULL ) {
58 args[nargs] = ( *new string( value ) ).c_str(); // pass the argument along
59#ifdef __DEBUG_H__
60 cerr << "env arg:\"" << args[nargs] << "\"" << endl;
61#endif // __DEBUG_H__
62 nargs += 1;
63 } // if
64
65 value = getenv( "__GCC_VERSION__" );
66 if ( value != NULL ) {
67 args[nargs] = ( *new string( value ) ).c_str(); // pass the argument along
68#ifdef __DEBUG_H__
69 cerr << "env arg:\"" << args[nargs] << "\"" << endl;
70#endif // __DEBUG_H__
71 nargs += 1;
72 } // if
73} // checkEnv
74
75
76void rmtmpfile() {
77 if ( unlink( tmpname ) == -1 ) { // remove tmpname
78 perror ( "CFA Translator error: cpp failed" );
79 exit( EXIT_FAILURE );
80 } // if
81 tmpfilefd = -1; // mark closed
82} // rmtmpfile
83
84
85void sigTermHandler( int signal ) {
86 if ( tmpfilefd != -1 ) { // RACE, file created ?
87 rmtmpfile(); // remove
88 exit( EXIT_FAILURE ); // terminate
89 } // if
90} // sigTermHandler
91
92
93void Stage1( const int argc, const char * const argv[] ) {
94 int code;
95 int i;
96
97 string arg;
98 string bprefix;
99
100 const char *cpp_in = NULL;
101 const char *cpp_out = NULL;
102
103 bool CFA_flag = false;
104 bool cpp_flag = false;
105 const char *o_name = NULL;
106
107 const char *args[argc + 100]; // leave space for 100 additional cpp command line values
108 int nargs = 1; // number of arguments in args list; 0 => command name
109 const char *uargs[20]; // leave space for 20 additional cfa-cpp command line values
110 int nuargs = 1; // 0 => command name
111
112 signal( SIGINT, sigTermHandler );
113 signal( SIGTERM, sigTermHandler );
114
115 // process all the arguments
116
117 checkEnv( args, nargs ); // arguments passed via environment variables
118
119 for ( i = 1; i < argc; i += 1 ) {
120#ifdef __DEBUG_H__
121 cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl;
122#endif // __DEBUG_H__
123 arg = argv[i];
124#ifdef __DEBUG_H__
125 cerr << "arg:\"" << arg << "\"" << endl;
126#endif // __DEBUG_H__
127 if ( prefix( arg, "-" ) ) {
128 // strip g++ flags that are inappropriate or cause duplicates in subsequent passes
129
130 if ( arg == "-quiet" ) {
131 } else if ( arg == "-imultilib" || arg == "-imultiarch" ) {
132 i += 1; // and the argument
133 } else if ( prefix( arg, "-A" ) ) {
134 } else if ( prefix( arg, "-D__GNU" ) ) {
135 //********
136 // GCC 5.6.0 SEPARATED THE -D FROM THE ARGUMENT!
137 //********
138 } else if ( arg == "-D" && prefix( argv[i + 1], "__GNU" ) ) {
139 i += 1; // and the argument
140
141 // strip flags controlling cpp step
142
143 } else if ( arg == "-D__CPP__" ) {
144 cpp_flag = true;
145 } else if ( arg == "-D" && string( argv[i + 1] ) == "__CPP__" ) {
146 i += 1; // and the argument
147 cpp_flag = true;
148 } else if ( arg == "-D__CFA__" ) {
149 CFA_flag = true;
150 } else if ( arg == "-D" && string( argv[i + 1] ) == "__CFA__" ) {
151 i += 1; // and the argument
152 CFA_flag = true;
153 } else if ( prefix( arg, D__CFA_FLAGPREFIX__ ) ) {
154 uargs[nuargs] = ( *new string( arg.substr( D__CFA_FLAGPREFIX__.size() ) ) ).c_str();
155 nuargs += 1;
156 } else if ( arg == "-D" && prefix( argv[i + 1], D__CFA_FLAGPREFIX__.substr(2) ) ) {
157 uargs[nuargs] = ( *new string( string( argv[i + 1] ).substr( D__CFA_FLAGPREFIX__.size() - 2 ) ) ).c_str();
158 nuargs += 1;
159 i += 1; // and the argument
160 } else if ( prefix( arg, D__GCC_BPREFIX__ ) ) {
161 bprefix = arg.substr( D__GCC_BPREFIX__.size() );
162 } else if ( arg == "-D" && prefix( argv[i + 1], D__GCC_BPREFIX__.substr(2) ) ) {
163 bprefix = string( argv[i + 1] ).substr( D__GCC_BPREFIX__.size() - 2 );
164 i += 1; // and the argument
165
166 // all other flags
167
168 } else if ( arg == "-o" ) {
169 i += 1;
170 o_name = argv[i];
171 } else {
172 args[nargs] = argv[i]; // pass the flag along
173 nargs += 1;
174 // CPP flags with an argument
175 if ( arg == "-D" || arg == "-I" || arg == "-MF" || arg == "-MT" || arg == "-MQ" ||
176 arg == "-include" || arg == "-imacros" || arg == "-idirafter" || arg == "-iprefix" ||
177 arg == "-iwithprefix" || arg == "-iwithprefixbefore" || arg == "-isystem" || arg == "-isysroot" ) {
178 i += 1;
179 args[nargs] = argv[i]; // pass the argument along
180 nargs += 1;
181#ifdef __DEBUG_H__
182 cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl;
183#endif // __DEBUG_H__
184 } else if ( arg == "-MD" || arg == "-MMD" ) {
185 args[nargs] = "-MF"; // insert before file
186 nargs += 1;
187 i += 1;
188 args[nargs] = argv[i]; // pass the argument along
189 nargs += 1;
190#ifdef __DEBUG_H__
191 cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl;
192#endif // __DEBUG_H__
193 } // if
194 } // if
195 } else { // obtain input and possibly output files
196 if ( cpp_in == NULL ) {
197 cpp_in = argv[i];
198#ifdef __DEBUG_H__
199 cerr << "cpp_in:\"" << cpp_in << "\"" << endl;
200#endif // __DEBUG_H__
201 } else if ( cpp_out == NULL ) {
202 cpp_out = argv[i];
203#ifdef __DEBUG_H__
204 cerr << "cpp_out:\"" << cpp_out << "\""<< endl;
205#endif // __DEBUG_H__
206 } else {
207 cerr << "Usage: " << argv[0] << " input-file [output-file] [options]" << endl;
208 exit( EXIT_FAILURE );
209 } // if
210 } // if
211 } // for
212
213#ifdef __DEBUG_H__
214 cerr << "args:";
215 for ( i = 1; i < nargs; i += 1 ) {
216 cerr << " " << args[i];
217 } // for
218 if ( cpp_in != NULL ) cerr << " " << cpp_in;
219 if ( cpp_out != NULL ) cerr << " " << cpp_out;
220 cerr << endl;
221#endif // __DEBUG_H__
222
223 if ( cpp_in == NULL ) {
224 cerr << "Usage: " << argv[0] << " input-file [output-file] [options]" << endl;
225 exit( EXIT_FAILURE );
226 } // if
227
228 if ( cpp_flag ) {
229 // The -E flag is specified on the cfa command so only run the preprocessor and output is written to standard
230 // output or -o. The call to cfa has a -E so it does not have to be added to the argument list.
231
232 args[0] = compiler_name.c_str();
233 args[nargs] = cpp_in;
234 nargs += 1;
235 if ( o_name != NULL ) { // location for output
236 args[nargs] = "-o";
237 nargs += 1;
238 args[nargs] = o_name;
239 nargs += 1;
240 } // if
241 args[nargs] = NULL; // terminate argument list
242
243#ifdef __DEBUG_H__
244 cerr << "nargs: " << nargs << endl;
245 for ( i = 0; args[i] != NULL; i += 1 ) {
246 cerr << args[i] << " ";
247 } // for
248 cerr << endl;
249#endif // __DEBUG_H__
250
251 execvp( args[0], (char *const *)args ); // should not return
252 perror( "CFA Translator error: cpp level, execvp" );
253 exit( EXIT_FAILURE );
254 } // if
255
256 // Create a temporary file to store output of the C preprocessor.
257
258 tmpfilefd = mkstemp( tmpname );
259 if ( tmpfilefd == -1 ) {
260 perror( "CFA Translator error: cpp level, mkstemp" );
261 exit( EXIT_FAILURE );
262 } // if
263
264#ifdef __DEBUG_H__
265 cerr << "tmpname:" << tmpname << " tmpfilefd:" << tmpfilefd << endl;
266#endif // __DEBUG_H__
267
268 // Run the C preprocessor and save the output in tmpfile.
269
270 if ( fork() == 0 ) { // child process ?
271 // -o xxx.ii cannot be used to write the output file from cpp because no output file is created if cpp detects
272 // an error (e.g., cannot find include file). Whereas, output is always generated, even when there is an error,
273 // when cpp writes to stdout. Hence, stdout is redirected into the temporary file.
274 if ( freopen( tmpname, "w", stdout ) == NULL ) { // redirect stdout to tmpname
275 perror( "CFA Translator error: cpp level, freopen" );
276 exit( EXIT_FAILURE );
277 } // if
278
279 args[0] = compiler_name.c_str();
280 args[nargs] = cpp_in; // input to cpp
281 nargs += 1;
282 args[nargs] = NULL; // terminate argument list
283
284#ifdef __DEBUG_H__
285 cerr << "cpp nargs: " << nargs << endl;
286 for ( i = 0; args[i] != NULL; i += 1 ) {
287 cerr << args[i] << " ";
288 } // for
289 cerr << endl;
290#endif // __DEBUG_H__
291
292 execvp( args[0], (char *const *)args ); // should not return
293 perror( "CFA Translator error: cpp level, execvp" );
294 exit( EXIT_FAILURE );
295 } // if
296
297 wait( &code ); // wait for child to finish
298
299#ifdef __DEBUG_H__
300 cerr << "return code from cpp:" << WEXITSTATUS(code) << endl;
301#endif // __DEBUG_H__
302
303 if ( WIFSIGNALED(code) != 0 ) { // child failed ?
304 rmtmpfile(); // remove tmpname
305 cerr << "CFA Translator error: cpp failed with signal " << WTERMSIG(code) << endl;
306 exit( EXIT_FAILURE );
307 } // if
308
309 if ( WEXITSTATUS(code) != 0 ) { // child error ?
310 rmtmpfile(); // remove tmpname
311 exit( WEXITSTATUS( code ) ); // do not continue
312 } // if
313
314 // If -CFA flag specified, run the cfa-cpp preprocessor on the temporary file, and output is written to standard
315 // output. Otherwise, run the cfa-cpp preprocessor on the temporary file and save the result into the output file.
316
317 if ( fork() == 0 ) { // child runs CFA
318 uargs[0] = ( *new string( bprefix + "/cfa-cpp" ) ).c_str();
319
320 uargs[nuargs] = "-p";
321 nuargs += 1;
322
323 uargs[nuargs] = tmpname;
324 nuargs += 1;
325 if ( o_name != NULL ) {
326 uargs[nuargs] = o_name;
327 nuargs += 1;
328 } else if ( ! CFA_flag ) { // run cfa-cpp ?
329 uargs[nuargs] = cpp_out;
330 nuargs += 1;
331 } // if
332 uargs[nuargs] = NULL; // terminate argument list
333
334#ifdef __DEBUG_H__
335 cerr << "cfa-cpp nuargs: " << o_name << " " << CFA_flag << " " << nuargs << endl;
336 for ( i = 0; uargs[i] != NULL; i += 1 ) {
337 cerr << uargs[i] << " ";
338 } // for
339 cerr << endl;
340#endif // __DEBUG_H__
341
342 execvp( uargs[0], (char * const *)uargs ); // should not return
343 perror( "CFA Translator error: cpp level, execvp" );
344 exit( EXIT_FAILURE );
345 } // if
346
347 wait( &code ); // wait for child to finish
348
349#ifdef __DEBUG_H__
350 cerr << "return code from cfa-cpp:" << WEXITSTATUS(code) << endl;
351#endif // __DEBUG_H__
352
353 // Must unlink here because file must exist across execvp.
354 rmtmpfile(); // remove tmpname
355
356 if ( WIFSIGNALED(code) ) { // child failed ?
357 cerr << "CFA Translator error: cfa-cpp failed with signal " << WTERMSIG(code) << endl;
358 exit( EXIT_FAILURE );
359 } // if
360
361 exit( WEXITSTATUS(code) );
362} // Stage1
363
364
365void Stage2( const int argc, const char * const * argv ) {
366 int i;
367
368 string arg;
369
370 const char *cpp_in = NULL;
371
372 const char *args[argc + 100]; // leave space for 100 additional cfa command line values
373 int nargs = 1; // number of arguments in args list; 0 => command name
374
375 // process all the arguments
376
377 checkEnv( args, nargs ); // arguments passed via environment variables
378
379 for ( i = 1; i < argc; i += 1 ) {
380#ifdef __DEBUG_H__
381 cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl;
382#endif // __DEBUG_H__
383 arg = argv[i];
384#ifdef __DEBUG_H__
385 cerr << "arg:\"" << arg << "\"" << endl;
386#endif // __DEBUG_H__
387 if ( prefix( arg, "-" ) ) {
388 // strip inappropriate flags
389
390 if ( arg == "-quiet" || arg == "-version" || arg == "-fpreprocessed" ||
391 // Currently CFA does not suppose precompiled .h files.
392 prefix( arg, "--output-pch" ) ) {
393
394 // strip inappropriate flags with an argument
395
396 } else if ( arg == "-auxbase" || arg == "-auxbase-strip" || arg == "-dumpbase" ) {
397 i += 1;
398#ifdef __DEBUG_H__
399 cerr << "arg:\"" << argv[i] << "\"" << endl;
400#endif // __DEBUG_H__
401
402 // all other flags
403
404 } else {
405 args[nargs] = argv[i]; // pass the flag along
406 nargs += 1;
407 if ( arg == "-o" ) {
408 i += 1;
409 args[nargs] = argv[i]; // pass the argument along
410 nargs += 1;
411#ifdef __DEBUG_H__
412 cerr << "arg:\"" << argv[i] << "\"" << endl;
413#endif // __DEBUG_H__
414 } // if
415 } // if
416 } else { // obtain input and possibly output files
417 if ( cpp_in == NULL ) {
418 cpp_in = argv[i];
419#ifdef __DEBUG_H__
420 cerr << "cpp_in:\"" << cpp_in << "\"" << endl;
421#endif // __DEBUG_H__
422 } else {
423 cerr << "Usage: " << argv[0] << " input-file [output-file] [options]" << endl;
424 exit( EXIT_FAILURE );
425 } // if
426 } // if
427 } // for
428
429#ifdef __DEBUG_H__
430 cerr << "args:";
431 for ( i = 1; i < nargs; i += 1 ) {
432 cerr << " " << args[i];
433 } // for
434 cerr << endl;
435 if ( cpp_in != NULL ) cerr << " " << cpp_in;
436#endif // __DEBUG_H__
437
438 args[0] = compiler_name.c_str();
439 args[nargs] = "-S"; // only compile and put assembler output in specified file
440 nargs += 1;
441 args[nargs] = cpp_in;
442 nargs += 1;
443 args[nargs] = NULL; // terminate argument list
444
445#ifdef __DEBUG_H__
446 cerr << "stage2 nargs: " << nargs << endl;
447 for ( i = 0; args[i] != NULL; i += 1 ) {
448 cerr << args[i] << " ";
449 } // for
450 cerr << endl;
451#endif // __DEBUG_H__
452
453 execvp( args[0], (char * const *)args ); // should not return
454 perror( "CFA Translator error: cpp level, execvp" );
455 exit( EXIT_FAILURE ); // tell gcc not to go any further
456} // Stage2
457
458
459int main( const int argc, const char * const argv[], const char * const env[] ) {
460#ifdef __DEBUG_H__
461 for ( int i = 0; env[i] != NULL; i += 1 ) {
462 cerr << env[i] << endl;
463 } // for
464#endif // __DEBUG_H__
465
466 string arg = argv[1];
467
468 // Currently, stage 1 starts with flag -E and stage 2 with flag -fpreprocessed.
469
470 if ( arg == "-E" ) {
471#ifdef __DEBUG_H__
472 cerr << "Stage1" << endl;
473#endif // __DEBUG_H__
474 Stage1( argc, argv );
475 } else if ( arg == "-fpreprocessed" ) {
476#ifdef __DEBUG_H__
477 cerr << "Stage2" << endl;
478#endif // __DEBUG_H__
479 Stage2( argc, argv );
480 } else {
481 cerr << "Usage: " << argv[0] << " input-file [output-file] [options]" << endl;
482 exit( EXIT_FAILURE );
483 } // if
484} // main
485
486
487// Local Variables: //
488// compile-command: "make install" //
489// End: //
Note: See TracBrowser for help on using the repository browser.