source: driver/cc1.cc @ bdd516a

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsctordeferred_resndemanglerenumforall-pointer-decaygc_noraiijacob/cs343-translationjenkins-sandboxmemorynew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newstringwith_gc
Last change on this file since bdd516a was bdd516a, checked in by Peter A. Buhr <pabuhr@…>, 9 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.