PR target/65871
[official-gcc.git] / libcc1 / libcc1.cc
blob7d7d2c190c7fcad124e53fedc208a04e0a07575e
1 /* The library used by gdb.
2 Copyright (C) 2014 Free Software Foundation, Inc.
4 This file is part of GCC.
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.
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.
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/>. */
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"
42 struct libcc1;
44 class libcc1_connection;
46 // The C compiler context that we hand back to our caller.
47 struct libcc1 : public gcc_c_context
49 libcc1 (const gcc_base_vtable *, const gcc_c_fe_vtable *);
50 ~libcc1 ();
52 // A convenience function to print something.
53 void print (const char *str)
55 this->print_function (this->print_datum, str);
58 libcc1_connection *connection;
60 gcc_c_oracle_function *binding_oracle;
61 gcc_c_symbol_address_function *address_oracle;
62 void *oracle_datum;
64 void (*print_function) (void *datum, const char *message);
65 void *print_datum;
67 std::vector<std::string> args;
68 std::string source_file;
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
75 public:
77 libcc1_connection (int fd, int aux_fd, libcc1 *b)
78 : connection (fd, aux_fd),
79 back_ptr (b)
83 virtual void print (const char *buf)
85 back_ptr->print (buf);
88 libcc1 *back_ptr;
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 ()
102 base.ops = v;
103 c_ops = cv;
106 libcc1::~libcc1 ()
108 delete connection;
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.
118 call_binding_oracle (cc1_plugin::connection *conn,
119 enum gcc_c_oracle_request request,
120 const char *identifier)
122 libcc1 *self = ((libcc1_connection *) conn)->back_ptr;
124 self->binding_oracle (self->oracle_datum, self, request, identifier);
125 return 1;
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)
133 libcc1 *self = ((libcc1_connection *) conn)->back_ptr;
135 return self->address_oracle (self->oracle_datum, self, identifier);
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)
146 libcc1 *self = (libcc1 *) s;
148 self->binding_oracle = binding_oracle;
149 self->address_oracle = address_oracle;
150 self->oracle_datum = datum;
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.
157 template<typename R, const char *&NAME>
158 R rpc (struct gcc_c_context *s)
160 libcc1 *self = (libcc1 *) s;
161 R result;
163 if (!cc1_plugin::call (self->connection, NAME, &result))
164 return 0;
165 return result;
168 template<typename R, const char *&NAME, typename A>
169 R rpc (struct gcc_c_context *s, A arg)
171 libcc1 *self = (libcc1 *) s;
172 R result;
174 if (!cc1_plugin::call (self->connection, NAME, &result, arg))
175 return 0;
176 return result;
179 template<typename R, const char *&NAME, typename A1, typename A2>
180 R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2)
182 libcc1 *self = (libcc1 *) s;
183 R result;
185 if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2))
186 return 0;
187 return result;
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)
193 libcc1 *self = (libcc1 *) s;
194 R result;
196 if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3))
197 return 0;
198 return result;
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)
205 libcc1 *self = (libcc1 *) s;
206 R result;
208 if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3,
209 arg4))
210 return 0;
211 return result;
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)
218 libcc1 *self = (libcc1 *) s;
219 R result;
221 if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3,
222 arg4, arg5))
223 return 0;
224 return result;
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)
232 libcc1 *self = (libcc1 *) s;
233 R result;
235 if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3,
236 arg4, arg5, arg6, arg7))
237 return 0;
238 return result;
241 static const struct gcc_c_fe_vtable c_vtable =
243 GCC_C_FE_VERSION_0,
244 set_callbacks,
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>,
261 #include "gcc-c-fe.def"
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
274 // Construct an appropriate regexp to match the compiler name.
275 static std::string
276 make_regexp (const char *triplet_regexp, const char *compiler)
278 std::stringstream buf;
280 buf << "^" << triplet_regexp << "-";
282 // Quote the compiler name in case it has something funny in it.
283 for (const char *p = compiler; *p; ++p)
285 switch (*p)
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;
302 buf << *p;
304 buf << "$";
306 return buf.str ();
309 static char *
310 libcc1_set_arguments (struct gcc_base_context *s,
311 const char *triplet_regexp,
312 int argc, char **argv)
314 libcc1 *self = (libcc1 *) s;
315 regex_t triplet;
316 int code;
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)
322 size_t len = regerror (code, &triplet, NULL, 0);
323 char err[len];
325 regerror (code, &triplet, err, len);
327 return concat ("Could not compile regexp \"",
328 rx.c_str (),
329 "\": ",
330 err,
331 (char *) NULL);
334 std::string compiler;
335 if (!find_compiler (triplet, &compiler))
337 regfree (&triplet);
338 return concat ("Could not find a compiler matching \"",
339 rx.c_str (),
340 "\"",
341 (char *) NULL);
343 regfree (&triplet);
345 self->args.push_back (compiler);
347 for (int i = 0; i < argc; ++i)
348 self->args.push_back (argv[i]);
350 return NULL;
353 static void
354 libcc1_set_source_file (struct gcc_base_context *s,
355 const char *file)
357 libcc1 *self = (libcc1 *) s;
359 self->source_file = file;
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)
368 libcc1 *self = (libcc1 *) s;
370 self->print_function = print_function;
371 self->print_datum = datum;
374 static int
375 fork_exec (libcc1 *self, char **argv, int spair_fds[2], int stderr_fds[2])
377 pid_t child_pid = fork ();
379 if (child_pid == -1)
381 close (spair_fds[0]);
382 close (spair_fds[1]);
383 close (stderr_fds[0]);
384 close (stderr_fds[1]);
385 return 0;
388 if (child_pid == 0)
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]);
397 execvp (argv[0], argv);
398 _exit (127);
400 else
402 // Parent.
403 close (spair_fds[1]);
404 close (stderr_fds[1]);
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 ();
411 close (spair_fds[0]);
412 close (stderr_fds[0]);
414 while (true)
416 int status;
418 if (waitpid (child_pid, &status, 0) == -1)
420 if (errno != EINTR)
421 return 0;
424 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0)
425 return 0;
426 break;
429 if (!result)
430 return 0;
431 return 1;
435 static int
436 libcc1_compile (struct gcc_base_context *s,
437 const char *filename,
438 int verbose)
440 libcc1 *self = (libcc1 *) s;
442 int fds[2];
443 if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) != 0)
445 self->print ("could not create socketpair\n");
446 return 0;
449 int stderr_fds[2];
450 if (pipe (stderr_fds) != 0)
452 self->print ("could not create pipe\n");
453 close (fds[0]);
454 close (fds[1]);
455 return 0;
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);
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");
472 self->connection = new libcc1_connection (fds[0], stderr_fds[0], self);
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);
481 fun = cc1_plugin::callback<gcc_address,
482 const char *,
483 call_symbol_address>;
484 self->connection->add_callback ("address_oracle", fun);
486 char **argv = new (std::nothrow) char *[self->args.size () + 1];
487 if (argv == NULL)
488 return 0;
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;
494 return fork_exec (self, argv, fds, stderr_fds);
497 static void
498 libcc1_destroy (struct gcc_base_context *s)
500 libcc1 *self = (libcc1 *) s;
502 delete self;
505 static const struct gcc_base_vtable vtable =
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
515 extern "C" gcc_c_fe_context_function gcc_c_fe_context;
517 #ifdef __GNUC__
518 #pragma GCC visibility push(default)
519 #endif
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)
526 if (base_version != GCC_FE_VERSION_0 || c_version != GCC_C_FE_VERSION_0)
527 return NULL;
529 return new libcc1 (&vtable, &c_vtable);