Import pre-release gcc-5.0 to new vendor branch
[dragonfly.git] / contrib / gcc-5.0 / libcc1 / libcc1.cc
1 /* The library used by gdb.
2    Copyright (C) 2014 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3.  If not see
18 <http://www.gnu.org/licenses/>.  */
19
20 #include <cc1plugin-config.h>
21 #include <vector>
22 #include <string>
23 #include <sys/socket.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26 #include <sys/wait.h>
27 #include <stdio.h>
28 #include <errno.h>
29 #include <sys/stat.h>
30 #include <stdlib.h>
31 #include <sstream>
32 #include "rpc.hh"
33 #include "connection.hh"
34 #include "names.hh"
35 #include "callbacks.hh"
36 #include "gcc-interface.h"
37 #include "libiberty.h"
38 #include "xregex.h"
39 #include "findcomp.hh"
40 #include "compiler-name.h"
41
42 struct libcc1;
43
44 class libcc1_connection;
45
46 // The C compiler context that we hand back to our caller.
47 struct libcc1 : public gcc_c_context
48 {
49   libcc1 (const gcc_base_vtable *, const gcc_c_fe_vtable *);
50   ~libcc1 ();
51
52   // A convenience function to print something.
53   void print (const char *str)
54   {
55     this->print_function (this->print_datum, str);
56   }
57
58   libcc1_connection *connection;
59
60   gcc_c_oracle_function *binding_oracle;
61   gcc_c_symbol_address_function *address_oracle;
62   void *oracle_datum;
63
64   void (*print_function) (void *datum, const char *message);
65   void *print_datum;
66
67   std::vector<std::string> args;
68   std::string source_file;
69 };
70
71 // A local subclass of connection that holds a back-pointer to the
72 // gcc_c_context object that we provide to our caller.
73 class libcc1_connection : public cc1_plugin::connection
74 {
75 public:
76
77   libcc1_connection (int fd, int aux_fd, libcc1 *b)
78     : connection (fd, aux_fd),
79       back_ptr (b)
80   {
81   }
82
83   virtual void print (const char *buf)
84   {
85     back_ptr->print (buf);
86   }
87
88   libcc1 *back_ptr;
89 };
90
91 libcc1::libcc1 (const gcc_base_vtable *v,
92                 const gcc_c_fe_vtable *cv)
93   : connection (NULL),
94     binding_oracle (NULL),
95     address_oracle (NULL),
96     oracle_datum (NULL),
97     print_function (NULL),
98     print_datum (NULL),
99     args (),
100     source_file ()
101 {
102   base.ops = v;
103   c_ops = cv;
104 }
105
106 libcc1::~libcc1 ()
107 {
108   delete connection;
109 }
110
111 \f
112
113 // This is a wrapper function that is called by the RPC system and
114 // that then forwards the call to the library user.  Note that the
115 // return value is not used; the type cannot be 'void' due to
116 // limitations in our simple RPC.
117 int
118 call_binding_oracle (cc1_plugin::connection *conn,
119                      enum gcc_c_oracle_request request,
120                      const char *identifier)
121 {
122   libcc1 *self = ((libcc1_connection *) conn)->back_ptr;
123
124   self->binding_oracle (self->oracle_datum, self, request, identifier);
125   return 1;
126 }
127
128 // This is a wrapper function that is called by the RPC system and
129 // that then forwards the call to the library user.
130 gcc_address
131 call_symbol_address (cc1_plugin::connection *conn, const char *identifier)
132 {
133   libcc1 *self = ((libcc1_connection *) conn)->back_ptr;
134
135   return self->address_oracle (self->oracle_datum, self, identifier);
136 }
137
138 \f
139
140 static void
141 set_callbacks (struct gcc_c_context *s,
142                gcc_c_oracle_function *binding_oracle,
143                gcc_c_symbol_address_function *address_oracle,
144                void *datum)
145 {
146   libcc1 *self = (libcc1 *) s;
147
148   self->binding_oracle = binding_oracle;
149   self->address_oracle = address_oracle;
150   self->oracle_datum = datum;
151 }
152
153 // Instances of these rpc<> template functions are installed into the
154 // "c_vtable".  These functions are parameterized by type and method
155 // name and forward the call via the connection.
156
157 template<typename R, const char *&NAME>
158 R rpc (struct gcc_c_context *s)
159 {
160   libcc1 *self = (libcc1 *) s;
161   R result;
162
163   if (!cc1_plugin::call (self->connection, NAME, &result))
164     return 0;
165   return result;
166 }
167
168 template<typename R, const char *&NAME, typename A>
169 R rpc (struct gcc_c_context *s, A arg)
170 {
171   libcc1 *self = (libcc1 *) s;
172   R result;
173
174   if (!cc1_plugin::call (self->connection, NAME, &result, arg))
175     return 0;
176   return result;
177 }
178
179 template<typename R, const char *&NAME, typename A1, typename A2>
180 R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2)
181 {
182   libcc1 *self = (libcc1 *) s;
183   R result;
184
185   if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2))
186     return 0;
187   return result;
188 }
189
190 template<typename R, const char *&NAME, typename A1, typename A2, typename A3>
191 R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2, A3 arg3)
192 {
193   libcc1 *self = (libcc1 *) s;
194   R result;
195
196   if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3))
197     return 0;
198   return result;
199 }
200
201 template<typename R, const char *&NAME, typename A1, typename A2, typename A3,
202          typename A4>
203 R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2, A3 arg3, A4 arg4)
204 {
205   libcc1 *self = (libcc1 *) s;
206   R result;
207
208   if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3,
209                          arg4))
210     return 0;
211   return result;
212 }
213
214 template<typename R, const char *&NAME, typename A1, typename A2, typename A3,
215          typename A4, typename A5>
216 R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5)
217 {
218   libcc1 *self = (libcc1 *) s;
219   R result;
220
221   if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3,
222                          arg4, arg5))
223     return 0;
224   return result;
225 }
226
227 template<typename R, const char *&NAME, typename A1, typename A2, typename A3,
228          typename A4, typename A5, typename A6, typename A7>
229 R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5,
230        A6 arg6, A7 arg7)
231 {
232   libcc1 *self = (libcc1 *) s;
233   R result;
234
235   if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3,
236                          arg4, arg5, arg6, arg7))
237     return 0;
238   return result;
239 }
240
241 static const struct gcc_c_fe_vtable c_vtable =
242 {
243   GCC_C_FE_VERSION_0,
244   set_callbacks,
245
246 #define GCC_METHOD0(R, N) \
247   rpc<R, cc1_plugin::N>,
248 #define GCC_METHOD1(R, N, A) \
249   rpc<R, cc1_plugin::N, A>,
250 #define GCC_METHOD2(R, N, A, B) \
251   rpc<R, cc1_plugin::N, A, B>,
252 #define GCC_METHOD3(R, N, A, B, C) \
253   rpc<R, cc1_plugin::N, A, B, C>,
254 #define GCC_METHOD4(R, N, A, B, C, D) \
255   rpc<R, cc1_plugin::N, A, B, C, D>,
256 #define GCC_METHOD5(R, N, A, B, C, D, E) \
257   rpc<R, cc1_plugin::N, A, B, C, D, E>,
258 #define GCC_METHOD7(R, N, A, B, C, D, E, F, G) \
259   rpc<R, cc1_plugin::N, A, B, C, D, E, F, G>,
260
261 #include "gcc-c-fe.def"
262
263 #undef GCC_METHOD0
264 #undef GCC_METHOD1
265 #undef GCC_METHOD2
266 #undef GCC_METHOD3
267 #undef GCC_METHOD4
268 #undef GCC_METHOD5
269 #undef GCC_METHOD7
270 };
271
272 \f
273
274 // Construct an appropriate regexp to match the compiler name.
275 static std::string
276 make_regexp (const char *triplet_regexp, const char *compiler)
277 {
278   std::stringstream buf;
279
280   buf << "^" << triplet_regexp << "-";
281
282   // Quote the compiler name in case it has something funny in it.
283   for (const char *p = compiler; *p; ++p)
284     {
285       switch (*p)
286         {
287         case '.':
288         case '^':
289         case '$':
290         case '*':
291         case '+':
292         case '?':
293         case '(':
294         case ')':
295         case '[':
296         case '{':
297         case '\\':
298         case '|':
299           buf << '\\';
300           break;
301         }
302       buf << *p;
303     }
304   buf << "$";
305
306   return buf.str ();
307 }
308
309 static char *
310 libcc1_set_arguments (struct gcc_base_context *s,
311                       const char *triplet_regexp,
312                       int argc, char **argv)
313 {
314   libcc1 *self = (libcc1 *) s;
315   regex_t triplet;
316   int code;
317
318   std::string rx = make_regexp (triplet_regexp, COMPILER_NAME);
319   code = regcomp (&triplet, rx.c_str (), REG_EXTENDED | REG_NOSUB);
320   if (code != 0)
321     {
322       size_t len = regerror (code, &triplet, NULL, 0);
323       char err[len];
324
325       regerror (code, &triplet, err, len);
326
327       return concat ("Could not compile regexp \"",
328                      rx.c_str (),
329                      "\": ",
330                      err,
331                      (char *) NULL);
332     }
333
334   std::string compiler;
335   if (!find_compiler (triplet, &compiler))
336     {
337       regfree (&triplet);
338       return concat ("Could not find a compiler matching \"",
339                      rx.c_str (),
340                      "\"",
341                      (char *) NULL);
342     }
343   regfree (&triplet);
344
345   self->args.push_back (compiler);
346
347   for (int i = 0; i < argc; ++i)
348     self->args.push_back (argv[i]);
349
350   return NULL;
351 }
352
353 static void
354 libcc1_set_source_file (struct gcc_base_context *s,
355                         const char *file)
356 {
357   libcc1 *self = (libcc1 *) s;
358
359   self->source_file = file;
360 }
361
362 static void
363 libcc1_set_print_callback (struct gcc_base_context *s,
364                            void (*print_function) (void *datum,
365                                                    const char *message),
366                            void *datum)
367 {
368   libcc1 *self = (libcc1 *) s;
369
370   self->print_function = print_function;
371   self->print_datum = datum;
372 }
373
374 static int
375 fork_exec (libcc1 *self, char **argv, int spair_fds[2], int stderr_fds[2])
376 {
377   pid_t child_pid = fork ();
378
379   if (child_pid == -1)
380     {
381       close (spair_fds[0]);
382       close (spair_fds[1]);
383       close (stderr_fds[0]);
384       close (stderr_fds[1]);
385       return 0;
386     }
387
388   if (child_pid == 0)
389     {
390       // Child.
391       dup2 (stderr_fds[1], 1);
392       dup2 (stderr_fds[1], 2);
393       close (stderr_fds[0]);
394       close (stderr_fds[1]);
395       close (spair_fds[0]);
396
397       execvp (argv[0], argv);
398       _exit (127);
399     }
400   else
401     {
402       // Parent.
403       close (spair_fds[1]);
404       close (stderr_fds[1]);
405
406       cc1_plugin::status result = cc1_plugin::FAIL;
407       if (self->connection->send ('H')
408           && ::cc1_plugin::marshall (self->connection, GCC_C_FE_VERSION_0))
409         result = self->connection->wait_for_query ();
410
411       close (spair_fds[0]);
412       close (stderr_fds[0]);
413
414       while (true)
415         {
416           int status;
417
418           if (waitpid (child_pid, &status, 0) == -1)
419             {
420               if (errno != EINTR)
421                 return 0;
422             }
423
424           if (!WIFEXITED (status) || WEXITSTATUS (status) != 0)
425             return 0;
426           break;
427         }
428
429       if (!result)
430         return 0;
431       return 1;
432     }
433 }
434
435 static int
436 libcc1_compile (struct gcc_base_context *s,
437                 const char *filename,
438                 int verbose)
439 {
440   libcc1 *self = (libcc1 *) s;
441
442   int fds[2];
443   if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) != 0)
444     {
445       self->print ("could not create socketpair\n");
446       return 0;
447     }
448
449   int stderr_fds[2];
450   if (pipe (stderr_fds) != 0)
451     {
452       self->print ("could not create pipe\n");
453       close (fds[0]);
454       close (fds[1]);
455       return 0;
456     }
457
458   self->args.push_back ("-fplugin=libcc1plugin");
459   char buf[100];
460   if (snprintf (buf, sizeof (buf), "-fplugin-arg-libcc1plugin-fd=%d", fds[1])
461       >= (long) sizeof (buf))
462     abort ();
463   self->args.push_back (buf);
464
465   self->args.push_back (self->source_file);
466   self->args.push_back ("-c");
467   self->args.push_back ("-o");
468   self->args.push_back (filename);
469   if (verbose)
470     self->args.push_back ("-v");
471
472   self->connection = new libcc1_connection (fds[0], stderr_fds[0], self);
473
474   cc1_plugin::callback_ftype *fun
475     = cc1_plugin::callback<int,
476                            enum gcc_c_oracle_request,
477                            const char *,
478                            call_binding_oracle>;
479   self->connection->add_callback ("binding_oracle", fun);
480
481   fun = cc1_plugin::callback<gcc_address,
482                              const char *,
483                              call_symbol_address>;
484   self->connection->add_callback ("address_oracle", fun);
485
486   char **argv = new (std::nothrow) char *[self->args.size () + 1];
487   if (argv == NULL)
488     return 0;
489
490   for (unsigned int i = 0; i < self->args.size (); ++i)
491     argv[i] = const_cast<char *> (self->args[i].c_str ());
492   argv[self->args.size ()] = NULL;
493
494   return fork_exec (self, argv, fds, stderr_fds);
495 }
496
497 static void
498 libcc1_destroy (struct gcc_base_context *s)
499 {
500   libcc1 *self = (libcc1 *) s;
501
502   delete self;
503 }
504
505 static const struct gcc_base_vtable vtable =
506 {
507   GCC_FE_VERSION_0,
508   libcc1_set_arguments,
509   libcc1_set_source_file,
510   libcc1_set_print_callback,
511   libcc1_compile,
512   libcc1_destroy
513 };
514
515 extern "C" gcc_c_fe_context_function gcc_c_fe_context;
516
517 #ifdef __GNUC__
518 #pragma GCC visibility push(default)
519 #endif
520
521 extern "C"
522 struct gcc_c_context *
523 gcc_c_fe_context (enum gcc_base_api_version base_version,
524                   enum gcc_c_api_version c_version)
525 {
526   if (base_version != GCC_FE_VERSION_0 || c_version != GCC_C_FE_VERSION_0)
527     return NULL;
528
529   return new libcc1 (&vtable, &c_vtable);
530 }