source: driver/cc1.cc@ bcb14b5

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors deferred_resn enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr no_list persistent-indexer pthread-emulation qualifiedEnum
Last change on this file since bcb14b5 was d6f4488, checked in by Peter A. Buhr <pabuhr@…>, 7 years ago

fix cfa -compiler flag

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