* configure.ac (AR_FOR_TARGET, RANLIB_FOR_TARGET): If nvptx-*,
look for them in the gcc build directory.
* configure: Regenerate.
gcc/
* config.gcc (nvptx-*): Define extra_programs.
* config/nvptx/nvptx-as.c: New file.
* config/nvptx/nvptx-ld.c: New file.
* config/nvptx/t-nvptx (nvptx-ld.o, nvptx-as.o, collect-ld$(exeext),
as$(exeext), ar$(exeext), ranlib$(exeext): New rules.
===================================================================
@@ -2154,6 +2154,7 @@ nios2-*-*)
nvptx-*)
tm_file="${tm_file} newlib-stdint.h"
tmake_file="nvptx/t-nvptx"
+ extra_programs="collect-ld\$(exeext) as\$(exeext) ar\$(exeext) ranlib\$(exeext)"
;;
pdp11-*-*)
tm_file="${tm_file} newlib-stdint.h"
===================================================================
@@ -0,0 +1,961 @@
+/* An "assembler" for ptx.
+ Copyright (C) 2014 Free Software Foundation, Inc.
+ Contributed by Nathan Sidwell <nathan@codesourcery.com>
+ Contributed by Bernd Schmidt <bernds@codesourcery.com>
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+/* Munges gcc-generated PTX assembly so that it becomes acceptable for ptxas.
+
+ This is not a complete assembler. We presume the source is well
+ formed from the compiler and can die horribly if it is not. */
+
+#include <getopt.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <wait.h>
+#include <unistd.h>
+#include <errno.h>
+#define obstack_chunk_alloc malloc
+#define obstack_chunk_free free
+#include <obstack.h>
+#define HAVE_DECL_BASENAME 1
+#include <libiberty.h>
+#include <hashtab.h>
+
+#include <list>
+
+static const char *outname = NULL;
+
+static void __attribute__ ((format (printf, 1, 2)))
+fatal_error (const char * cmsgid, ...)
+{
+ va_list ap;
+
+ va_start (ap, cmsgid);
+ fprintf (stderr, "nvptx-as: ");
+ vfprintf (stderr, cmsgid, ap);
+ fprintf (stderr, "\n");
+ va_end (ap);
+
+ unlink (outname);
+ exit (1);
+}
+
+struct Stmt;
+
+class symbol
+{
+ public:
+ symbol (const char *k) : key (k), stmts (0), pending (0), emitted (0)
+ { }
+
+ /* The name of the symbol. */
+ const char *key;
+ /* A linked list of dependencies for the initializer. */
+ std::list<symbol *> deps;
+ /* The statement in which it is defined. */
+ struct Stmt *stmts;
+ bool pending;
+ bool emitted;
+};
+
+/* Hash and comparison functions for these hash tables. */
+
+static int hash_string_eq (const void *, const void *);
+static hashval_t hash_string_hash (const void *);
+
+static int
+hash_string_eq (const void *s1_p, const void *s2_p)
+{
+ const char *const *s1 = (const char *const *) s1_p;
+ const char *s2 = (const char *) s2_p;
+ return strcmp (*s1, s2) == 0;
+}
+
+static hashval_t
+hash_string_hash (const void *s_p)
+{
+ const char *const *s = (const char *const *) s_p;
+ return (*htab_hash_string) (*s);
+}
+
+static htab_t symbol_table;
+
+/* Look up an entry in the symbol hash table. */
+
+static symbol *
+symbol_hash_lookup (const char *string)
+{
+ void **e;
+ e = htab_find_slot_with_hash (symbol_table, string,
+ (*htab_hash_string) (string),
+ INSERT);
+ if (e == NULL)
+ return NULL;
+ if (*e == NULL)
+ *e = new symbol (string);
+
+ return (symbol *) *e;
+}
+
+#define COMMENT_PREFIX "#"
+
+typedef enum Kind
+{
+ /* 0-ff used for single char tokens */
+ K_symbol = 0x100, /* a symbol */
+ K_label, /* a label defn (i.e. symbol:) */
+ K_ident, /* other ident */
+ K_dotted, /* dotted identifier */
+ K_number,
+ K_string,
+ K_comment
+} Kind;
+
+typedef struct Token
+{
+ unsigned short kind : 12;
+ unsigned short space : 1; /* preceded by space */
+ unsigned short end : 1; /* succeeded by end of line */
+ /* Length of token */
+ unsigned short len;
+
+ /* Token itself */
+ char const *ptr;
+} Token;
+
+/* statement info */
+typedef enum Vis
+{
+ V_dot = 0, /* random pseudo */
+ V_var = 1, /* var decl/defn */
+ V_func = 2, /* func decl/defn */
+ V_insn = 3, /* random insn */
+ V_label = 4, /* label defn */
+ V_comment = 5,
+ V_pred = 6, /* predicate */
+ V_mask = 0x7,
+ V_global = 0x08, /* globalize */
+ V_weak = 0x10, /* weakly globalize */
+ V_no_eol = 0x20, /* no end of line */
+ V_prefix_comment = 0x40 /* prefixed comment */
+} Vis;
+
+typedef struct Stmt
+{
+ struct Stmt *next;
+ Token *tokens;
+ symbol *sym;
+ unsigned char vis;
+ unsigned len : 12;
+} Stmt;
+
+struct id_map
+{
+ id_map *next;
+ char *ptx_name;
+};
+
+#define alloc_comment(S,E) alloc_stmt (V_comment, S, E, 0)
+#define append_stmt(V, S) ((S)->next = *(V), *(V) = (S))
+
+static Stmt *decls;
+static Stmt *fns;
+
+static id_map *func_ids, **funcs_tail = &func_ids;
+static id_map *var_ids, **vars_tail = &var_ids;
+
+static void
+record_id (const char *p1, id_map ***where)
+{
+ const char *end = strchr (p1, '\n');
+ if (!end)
+ fatal_error ("malformed ptx file");
+
+ id_map *v = XNEW (id_map);
+ size_t len = end - p1;
+ v->ptx_name = XNEWVEC (char, len + 1);
+ memcpy (v->ptx_name, p1, len);
+ v->ptx_name[len] = '\0';
+ v->next = NULL;
+ id_map **tail = *where;
+ *tail = v;
+ *where = &v->next;
+}
+
+/* Read the whole input file. It will be NUL terminated (but
+ remember, there could be a NUL in the file itself. */
+
+static const char *
+read_file (FILE *stream)
+{
+ size_t alloc = 16384;
+ size_t base = 0;
+ char *buffer;
+
+ if (!fseek (stream, 0, SEEK_END))
+ {
+ /* Get the file size. */
+ long s = ftell (stream);
+ if (s >= 0)
+ alloc = s + 100;
+ fseek (stream, 0, SEEK_SET);
+ }
+ buffer = XNEWVEC (char, alloc);
+
+ for (;;)
+ {
+ size_t n = fread (buffer + base, 1, alloc - base - 1, stream);
+
+ if (!n)
+ break;
+ base += n;
+ if (base + 1 == alloc)
+ {
+ alloc *= 2;
+ buffer = XRESIZEVEC (char, buffer, alloc);
+ }
+ }
+ buffer[base] = 0;
+ return buffer;
+}
+
+/* Read a token, advancing ptr.
+ If we read a comment, append it to the comments block. */
+
+static Token *
+tokenize (const char *ptr)
+{
+ unsigned alloc = 1000;
+ unsigned num = 0;
+ Token *toks = XNEWVEC (Token, alloc);
+ int in_comment = 0;
+ int not_comment = 0;
+
+ for (;; num++)
+ {
+ const char *base;
+ unsigned kind;
+ int ws = 0;
+ int eol = 0;
+
+ again:
+ base = ptr;
+ if (in_comment)
+ goto block_comment;
+ switch (kind = *ptr++)
+ {
+ default:
+ break;
+
+ case '\n':
+ eol = 1;
+ /* Fall through */
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\v':
+ /* White space */
+ ws = not_comment;
+ goto again;
+
+ case '/':
+ {
+ if (*ptr == '/')
+ {
+ /* line comment. Do not include trailing \n */
+ base += 2;
+ for (; *ptr; ptr++)
+ if (*ptr == '\n')
+ break;
+ kind = K_comment;
+ }
+ else if (*ptr == '*')
+ {
+ /* block comment */
+ base += 2;
+ ptr++;
+
+ block_comment:
+ eol = in_comment;
+ in_comment = 1;
+ for (; *ptr; ptr++)
+ {
+ if (*ptr == '\n')
+ {
+ ptr++;
+ break;
+ }
+ if (ptr[0] == '*' && ptr[1] == '/')
+ {
+ in_comment = 2;
+ ptr += 2;
+ break;
+ }
+ }
+ kind = K_comment;
+ }
+ else
+ break;
+ }
+ break;
+
+ case '"':
+ /* quoted string */
+ kind = K_string;
+ while (*ptr)
+ if (*ptr == '"')
+ {
+ ptr++;
+ break;
+ }
+ else if (*ptr++ == '\\')
+ ptr++;
+ break;
+
+ case '.':
+ if (*ptr < '0' || *ptr > '9')
+ {
+ kind = K_dotted;
+ ws = not_comment;
+ goto ident;
+ }
+ /* FALLTHROUGH */
+ case '0'...'9':
+ kind = K_number;
+ goto ident;
+ break;
+
+ case '$': /* local labels. */
+ case '%': /* register names, pseudoes etc */
+ kind = K_ident;
+ goto ident;
+
+ case 'a'...'z':
+ case 'A'...'Z':
+ case '_':
+ kind = K_symbol; /* possible symbol name */
+ ident:
+ for (; *ptr; ptr++)
+ {
+ if (*ptr >= 'A' && *ptr <= 'Z')
+ continue;
+ if (*ptr >= 'a' && *ptr <= 'z')
+ continue;
+ if (*ptr >= '0' && *ptr <= '9')
+ continue;
+ if (*ptr == '_' || *ptr == '$')
+ continue;
+ if (*ptr == '.' && kind != K_dotted)
+ /* Idents starting with a dot, cannot have internal dots. */
+ continue;
+ if ((*ptr == '+' || *ptr == '-')
+ && kind == K_number
+ && (ptr[-1] == 'e' || ptr[-1] == 'E'
+ || ptr[-1] == 'p' || ptr[-1] == 'P'))
+ /* exponent */
+ continue;
+ break;
+ }
+ if (*ptr == ':')
+ {
+ ptr++;
+ kind = K_label;
+ }
+ break;
+ }
+
+ if (alloc == num)
+ {
+ alloc *= 2;
+ toks = XRESIZEVEC (Token, toks, alloc);
+ }
+ Token *tok = toks + num;
+
+ tok->kind = kind;
+ tok->space = ws;
+ tok->end = 0;
+ tok->ptr = base;
+ tok->len = ptr - base - in_comment;
+ in_comment &= 1;
+ not_comment = kind != K_comment;
+ if (eol && num)
+ tok[-1].end = 1;
+ if (!kind)
+ break;
+ }
+
+ return toks;
+}
+
+/* Write an encoded token. */
+
+static void
+write_token (FILE *out, Token const *tok)
+{
+ if (tok->space)
+ fputc (' ', out);
+
+ switch (tok->kind)
+ {
+ case K_string:
+ {
+ const char *c = tok->ptr + 1;
+ size_t len = tok->len - 2;
+
+ fputs ("\"", out);
+ while (len)
+ {
+ const char *bs = (const char *)memchr (c, '\\', len);
+ size_t l = bs ? bs - c : len;
+
+ fprintf (out, "%.*s", (int)l, c);
+ len -= l;
+ c += l;
+ if (bs)
+ {
+ fputs ("\\\\", out);
+ len--, c++;
+ }
+ }
+ fputs ("\"", out);
+ }
+ break;
+
+ default:
+ /* All other tokens shouldn't have anything magic in them */
+ fprintf (out, "%.*s", tok->len, tok->ptr);
+ break;
+ }
+
+ if (tok->end)
+ fputs ("\n", out);
+}
+
+static Stmt *
+alloc_stmt (unsigned vis, Token *tokens, Token *end, symbol *sym)
+{
+ static unsigned alloc = 0;
+ static Stmt *heap = 0;
+
+ if (!alloc)
+ {
+ alloc = 1000;
+ heap = XNEWVEC (Stmt, alloc);
+ }
+
+ Stmt *stmt = heap++;
+ alloc--;
+
+ tokens->space = 0;
+ stmt->next = 0;
+ stmt->vis = vis;
+ stmt->tokens = tokens;
+ stmt->len = end - tokens;
+ stmt->sym = sym;
+
+ return stmt;
+}
+
+static Stmt *
+rev_stmts (Stmt *stmt)
+{
+ Stmt *prev = 0;
+ Stmt *next;
+
+ while (stmt)
+ {
+ next = stmt->next;
+ stmt->next = prev;
+ prev = stmt;
+ stmt = next;
+ }
+
+ return prev;
+}
+
+static void
+write_stmt (FILE *out, const Stmt *stmt)
+{
+ for (int i = 0; i < stmt->len; i++)
+ {
+ if ((stmt->vis & V_mask) == V_comment)
+ fprintf (out, "//");
+ write_token (out, stmt->tokens + i);
+ if ((stmt->vis & V_mask) == V_pred)
+ fputc (' ', out);
+ }
+}
+
+static void
+write_stmts (FILE *out, const Stmt *stmts)
+{
+ for (; stmts; stmts = stmts->next)
+ write_stmt (out, stmts);
+}
+
+static Token *
+parse_insn (Token *tok)
+{
+ unsigned depth = 0;
+
+ do
+ {
+ Stmt *stmt;
+ unsigned s = V_insn;
+ Token *start = tok;
+
+ switch (tok++->kind)
+ {
+ case K_comment:
+ while (tok->kind == K_comment)
+ tok++;
+ stmt = alloc_comment (start, tok);
+ append_stmt (&fns, stmt);
+ continue;
+
+ case '{':
+ depth++;
+ break;
+
+ case '}':
+ depth--;
+ break;
+
+ case K_label:
+ tok[-1].end = 1;
+ s = V_label;
+ break;
+
+ case '@':
+ tok->space = 0;
+ if (tok->kind == '!')
+ tok++;
+ tok++;
+ s = V_pred;
+ break;
+
+ default:
+ for (; tok->kind != ';'; tok++)
+ {
+ if (tok->kind == ',')
+ tok[1].space = 0;
+ }
+ tok++->end = 1;
+ break;
+ }
+
+ stmt = alloc_stmt (s, start, tok, 0);
+ append_stmt (&fns, stmt);
+
+ if (!tok[-1].end && tok[0].kind == K_comment)
+ {
+ stmt->vis |= V_no_eol;
+ stmt = alloc_comment (tok, tok + 1);
+ append_stmt (&fns, stmt);
+ tok++;
+ }
+ }
+ while (depth);
+
+ return tok;
+}
+
+/* comma separated list of tokens */
+
+static Token *
+parse_list_nosemi (Token *tok)
+{
+ Token *start = tok;
+
+ do
+ if (!(++tok)->kind)
+ break;
+ while ((++tok)->kind == ',');
+
+ tok[-1].end = 1;
+ Stmt *stmt = alloc_stmt (V_dot, start, tok, 0);
+ append_stmt (&decls, stmt);
+
+ return tok;
+}
+
+#define is_keyword(T,S) \
+ (sizeof (S) == (T)->len && !memcmp ((T)->ptr + 1, (S), (T)->len - 1))
+
+static Token *
+parse_init (Token *tok, symbol *sym)
+{
+ for (;;)
+ {
+ Token *start = tok;
+ Token *def_tok = 0;
+ Stmt *stmt;
+
+ if (tok->kind == K_comment)
+ {
+ while (tok->kind == K_comment)
+ tok++;
+ stmt = alloc_comment (start, tok);
+ append_stmt (&sym->stmts, stmt);
+ start = tok;
+ }
+
+ if (tok->kind == '{')
+ tok[1].space = 0;
+ /* Find the last symbol before the next comma. This allows us
+ to do the right thing for constructs like "generic (sym)". */
+ for (; tok->kind != ',' && tok->kind != ';'; tok++)
+ if (tok->kind == K_symbol || tok->kind == K_ident)
+ def_tok = tok;
+ if (def_tok)
+ sym->deps.push_back (symbol_hash_lookup (xstrndup (def_tok->ptr,
+ def_tok->len)));
+ tok[1].space = 0;
+ int end = tok++->kind == ';';
+ stmt = alloc_stmt (V_insn, start, tok, 0);
+ append_stmt (&sym->stmts, stmt);
+ if (!tok[-1].end && tok->kind == K_comment)
+ {
+ stmt->vis |= V_no_eol;
+ stmt = alloc_comment (tok, tok + 1);
+ append_stmt (&sym->stmts, stmt);
+ tok++;
+ }
+ if (end)
+ break;
+ }
+ return tok;
+}
+
+static Token *
+parse_file (Token *tok)
+{
+ Stmt *comment = 0;
+
+ if (tok->kind == K_comment)
+ {
+ Token *start = tok;
+
+ while (tok->kind == K_comment)
+ {
+ if (strncmp (tok->ptr, ":VAR_MAP ", 9) == 0)
+ record_id (tok->ptr + 9, &vars_tail);
+ if (strncmp (tok->ptr, ":FUNC_MAP ", 10) == 0)
+ record_id (tok->ptr + 10, &funcs_tail);
+ tok++;
+ }
+ comment = alloc_comment (start, tok);
+ comment->vis |= V_prefix_comment;
+ }
+
+ if (tok->kind == K_dotted)
+ {
+ if (is_keyword (tok, "version")
+ || is_keyword (tok, "target")
+ || is_keyword (tok, "address_size"))
+ {
+ if (comment)
+ append_stmt (&decls, comment);
+ tok = parse_list_nosemi (tok);
+ }
+ else
+ {
+ unsigned vis = 0;
+ symbol *def = 0;
+ unsigned is_decl = 0;
+ Token *start, *def_token = 0;
+
+ for (start = tok;
+ tok->kind && tok->kind != '=' && tok->kind != K_comment
+ && tok->kind != '{' && tok->kind != ';'; tok++)
+ {
+ if (is_keyword (tok, "global")
+ || is_keyword (tok, "const"))
+ vis |= V_var;
+ else if (is_keyword (tok, "func")
+ || is_keyword (tok, "entry"))
+ vis |= V_func;
+ else if (is_keyword (tok, "visible"))
+ vis |= V_global;
+ else if (is_keyword (tok, "extern"))
+ is_decl = 1;
+ else if (is_keyword (tok, "weak"))
+ vis |= V_weak;
+ if (tok->kind == '(')
+ {
+ tok[1].space = 0;
+ tok[0].space = 1;
+ }
+ else if (tok->kind == ')' && tok[1].kind != ';')
+ tok[1].space = 1;
+
+ if (tok->kind == K_symbol || tok->kind == K_ident)
+ def_token = tok;
+ }
+ if (def_token)
+ def = symbol_hash_lookup (xstrndup (def_token->ptr, def_token->len));
+
+ if (!tok->kind)
+ {
+ /* end of file */
+ if (comment)
+ append_stmt (&fns, comment);
+ }
+ else if (tok->kind == '{'
+ || tok->kind == K_comment)
+ {
+ /* function defn */
+ Stmt *stmt = alloc_stmt (vis, start, tok, def);
+ if (comment)
+ {
+ append_stmt (&fns, comment);
+ stmt->vis |= V_prefix_comment;
+ }
+ append_stmt (&fns, stmt);
+ tok = parse_insn (tok);
+ }
+ else
+ {
+ int assign = tok->kind == '=';
+
+ tok++->end = 1;
+ if ((vis & V_mask) == V_var && !is_decl)
+ {
+ /* variable */
+ Stmt *stmt = alloc_stmt (vis, start, tok, def);
+ if (comment)
+ {
+ append_stmt (&def->stmts, comment);
+ stmt->vis |= V_prefix_comment;
+ }
+ append_stmt (&def->stmts, stmt);
+ if (assign)
+ tok = parse_init (tok, def);
+ }
+ else
+ {
+ /* declaration */
+ Stmt *stmt = alloc_stmt (vis, start, tok, 0);
+ if (comment)
+ {
+ append_stmt (&decls, comment);
+ stmt->vis |= V_prefix_comment;
+ }
+ append_stmt (&decls, stmt);
+ }
+ }
+ }
+ }
+ else
+ {
+ /* Something strange. Ignore it. */
+ if (comment)
+ append_stmt (&fns, comment);
+
+ while (tok->kind && !tok->end)
+ tok++;
+ if (tok->kind)
+ tok++;
+ }
+ return tok;
+}
+
+static void
+output_symbol (FILE *out, symbol *e)
+{
+ if (e->emitted)
+ return;
+ if (e->pending)
+ fatal_error ("circular reference in variable initializers");
+ e->pending = true;
+ std::list<symbol *>::iterator i;
+ for (i = e->deps.begin (); i != e->deps.end (); i++)
+ output_symbol (out, *i);
+ e->pending = false;
+ write_stmts (out, rev_stmts (e->stmts));
+ e->emitted = true;
+}
+
+static int
+traverse (void **slot, void *data)
+{
+ symbol *e = *(symbol **)slot;
+ output_symbol ((FILE *)data, e);
+ return 1;
+}
+
+static void
+process (FILE *in, FILE *out)
+{
+ symbol_table = htab_create (500, hash_string_hash, hash_string_eq,
+ NULL);
+
+ const char *input = read_file (in);
+ Token *tok = tokenize (input);
+
+ do
+ tok = parse_file (tok);
+ while (tok->kind);
+
+ write_stmts (out, rev_stmts (decls));
+ htab_traverse (symbol_table, traverse, (void *)out);
+ write_stmts (out, rev_stmts (fns));
+}
+
+/* Wait for a process to finish, and exit if a nonzero status is found. */
+
+int
+collect_wait (const char *prog, struct pex_obj *pex)
+{
+ int status;
+
+ if (!pex_get_status (pex, 1, &status))
+ fatal_error ("can't get program status: %m");
+ pex_free (pex);
+
+ if (status)
+ {
+ if (WIFSIGNALED (status))
+ {
+ int sig = WTERMSIG (status);
+ fatal_error ("%s terminated with signal %d [%s]%s",
+ prog, sig, strsignal(sig),
+ WCOREDUMP(status) ? ", core dumped" : "");
+ }
+
+ if (WIFEXITED (status))
+ return WEXITSTATUS (status);
+ }
+ return 0;
+}
+
+static void
+do_wait (const char *prog, struct pex_obj *pex)
+{
+ int ret = collect_wait (prog, pex);
+ if (ret != 0)
+ {
+ fatal_error ("%s returned %d exit status", prog, ret);
+ }
+}
+
+
+/* Execute a program, and wait for the reply. */
+static void
+fork_execute (const char *prog, char *const *argv)
+{
+ struct pex_obj *pex = pex_init (0, "nvptx-as", NULL);
+ if (pex == NULL)
+ fatal_error ("pex_init failed: %m");
+
+ int err;
+ const char *errmsg;
+
+ errmsg = pex_run (pex, PEX_LAST | PEX_SEARCH, argv[0], argv, NULL,
+ NULL, &err);
+ if (errmsg != NULL)
+ {
+ if (err != 0)
+ {
+ errno = err;
+ fatal_error ("%s: %m", errmsg);
+ }
+ else
+ fatal_error (errmsg);
+ }
+ do_wait (prog, pex);
+}
+
+static struct option long_options[] = {
+ {"traditional-format", no_argument, 0, 0 },
+ {"save-temps", no_argument, 0, 0 },
+ {"no-verify", no_argument, 0, 0 },
+ {0, 0, 0, 0 }
+};
+
+int
+main (int argc, char **argv)
+{
+ FILE *in = stdin;
+ FILE *out = stdout;
+ bool verbose __attribute__((unused)) = false;
+ bool verify = true;
+
+ int o;
+ int option_index = 0;
+ while ((o = getopt_long (argc, argv, "o:I:v", long_options, &option_index)) != -1)
+ {
+ switch (o)
+ {
+ case 0:
+ if (option_index == 2)
+ verify = false;
+ break;
+ case 'v':
+ verbose = true;
+ break;
+ case 'o':
+ if (outname != NULL)
+ {
+ fprintf (stderr, "multiple output files specified\n");
+ exit (1);
+ }
+ outname = optarg;
+ break;
+ case 'I':
+ /* Ignore include paths. */
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (optind + 1 != argc)
+ fatal_error ("not exactly one input file specified");
+
+ out = fopen (outname, "w");
+ if (!out)
+ fatal_error ("cannot open '%s'", outname);
+
+ in = fopen (argv[optind], "r");
+ if (!in)
+ fatal_error ("cannot open input ptx file");
+
+ process (in, out);
+ fclose (out);
+
+ if (verify)
+ {
+ struct obstack argv_obstack;
+ obstack_init (&argv_obstack);
+ obstack_ptr_grow (&argv_obstack, "ptxas");
+ obstack_ptr_grow (&argv_obstack, "-c");
+ obstack_ptr_grow (&argv_obstack, "-o");
+ obstack_ptr_grow (&argv_obstack, "/dev/null");
+ obstack_ptr_grow (&argv_obstack, outname);
+ obstack_ptr_grow (&argv_obstack, "--gpu-name");
+ obstack_ptr_grow (&argv_obstack, "sm_30");
+ obstack_ptr_grow (&argv_obstack, NULL);
+ char *const *new_argv = XOBFINISH (&argv_obstack, char *const *);
+ fork_execute (new_argv[0], new_argv);
+ }
+ return 0;
+}
===================================================================
@@ -0,0 +1,498 @@
+/* An "linker" for ptx.
+ Copyright (C) 2014 Free Software Foundation, Inc.
+ Contributed by Bernd Schmidt <bernds@codesourcery.com>
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <assert.h>
+
+#include "hashtab.h"
+#include "obstack.h"
+#define HAVE_DECL_BASENAME 1
+#include "libiberty.h"
+
+#include <list>
+#include <string>
+#include <iostream>
+
+struct file_hash_entry;
+
+typedef struct symbol_hash_entry
+{
+ /* The name of the symbol. */
+ const char *key;
+ /* A linked list of unresolved referenced symbols. */
+ struct symbol_hash_entry **pprev, *next;
+ /* The file in which it is defined. */
+ struct file_hash_entry *def;
+ int included;
+ int referenced;
+} symbol;
+
+typedef struct file_hash_entry
+{
+ struct file_hash_entry **pprev, *next;
+ const char *name;
+ const char *arname;
+ const char *data;
+ size_t len;
+} file;
+
+/* Hash and comparison functions for these hash tables. */
+
+static int hash_string_eq (const void *, const void *);
+static hashval_t hash_string_hash (const void *);
+
+static int
+hash_string_eq (const void *s1_p, const void *s2_p)
+{
+ const char *const *s1 = (const char *const *) s1_p;
+ const char *s2 = (const char *) s2_p;
+ return strcmp (*s1, s2) == 0;
+}
+
+static hashval_t
+hash_string_hash (const void *s_p)
+{
+ const char *const *s = (const char *const *) s_p;
+ return (*htab_hash_string) (*s);
+}
+
+static htab_t symbol_table;
+
+/* Look up an entry in the symbol hash table. */
+
+static struct symbol_hash_entry *
+symbol_hash_lookup (const char *string, int create)
+{
+ void **e;
+ e = htab_find_slot_with_hash (symbol_table, string,
+ (*htab_hash_string) (string),
+ create ? INSERT : NO_INSERT);
+ if (e == NULL)
+ return NULL;
+ if (*e == NULL)
+ {
+ struct symbol_hash_entry *v;
+ *e = v = XCNEW (struct symbol_hash_entry);
+ v->key = string;
+ }
+ return (struct symbol_hash_entry *) *e;
+}
+
+static struct file_hash_entry *
+file_hash_new (const char *data, size_t len, const char *arname, const char *name)
+{
+ struct file_hash_entry *v = XCNEW (struct file_hash_entry);
+ v->data = data;
+ v->len = len;
+ v->name = xstrdup (name);
+ v->arname = xstrdup (arname);
+ return v;
+}
+
+using namespace std;
+
+#define ARMAG "!<arch>\012" /* For COFF and a.out archives. */
+#define SARMAG 8
+#define ARFMAG "`\012"
+
+struct ar_hdr
+{
+ char ar_name[16]; /* Name of this member. */
+ char ar_date[12]; /* File mtime. */
+ char ar_uid[6]; /* Owner uid; printed as decimal. */
+ char ar_gid[6]; /* Owner gid; printed as decimal. */
+ char ar_mode[8]; /* File mode, printed as octal. */
+ char ar_size[10]; /* File size, printed as decimal. */
+ char ar_fmag[2]; /* Should contain ARFMAG. */
+};
+
+class archive
+{
+ FILE *f;
+ off_t flen;
+ off_t off;
+
+ char name[17];
+ char *contents;
+ size_t len;
+
+ public:
+ archive () : f (NULL), contents (NULL) { }
+ ~archive ()
+ {
+ discard_contents ();
+ }
+ void discard_contents ()
+ {
+ if (contents)
+ delete[] contents;
+ contents = NULL;
+ }
+ bool init (FILE *file)
+ {
+ char magic[SARMAG];
+ if (fread (magic, 1, SARMAG, file) != SARMAG)
+ return false;
+ if (memcmp (magic, ARMAG, SARMAG) != 0)
+ return false;
+ f = file;
+ fseek (f, 0, SEEK_END);
+ flen = ftell (f);
+ fseek (f, SARMAG, SEEK_SET);
+ off = SARMAG;
+
+ struct ar_hdr hdr;
+ if (fread (&hdr, sizeof hdr, 1, f) != 1)
+ return false;
+ if (hdr.ar_name[0] == '/' || hdr.ar_name[0] == ' ')
+ {
+ off += sizeof hdr;
+ long l = atol (hdr.ar_size);
+ if (l < 0 || off + l > flen)
+ return false;
+ off += l;
+ }
+
+ fseek (f, off, SEEK_SET);
+ return true;
+ }
+
+ bool at_end ()
+ {
+ return off == flen;
+ }
+
+ bool next_file ()
+ {
+ discard_contents ();
+
+ struct ar_hdr hdr;
+ if (fread (&hdr, sizeof hdr, 1, f) != 1)
+ return false;
+ off += sizeof hdr;
+ long l = atol (hdr.ar_size);
+ if (l <= 0 || l > flen)
+ return false;
+ size_t read_len = l + (l & 1);
+ len = l;
+ contents = new char[read_len];
+ if (contents == NULL)
+ return false;
+ if (fread (contents, 1, read_len, f) != read_len)
+ return false;
+ off += read_len;
+ memcpy (name, hdr.ar_name, sizeof hdr.ar_name);
+ name[16] = '\0';
+ return true;
+ }
+ const char *get_contents () { return contents; }
+ const char *get_name () { return name; }
+ size_t get_len () { return len; }
+};
+
+FILE *
+path_open (const char *filename, list<string> &paths)
+{
+ FILE *f = fopen (filename, "r");
+ if (f)
+ return f;
+ if (strchr (filename, '/') != NULL)
+ return NULL;
+
+ for (list<string>::const_iterator iterator = paths.begin(), end = paths.end();
+ iterator != end;
+ ++iterator)
+ {
+ string tmp = *iterator;
+ tmp += '/';
+ tmp += filename;
+ FILE *f = fopen (tmp.c_str (), "r");
+ if (f)
+ return f;
+ }
+ return NULL;
+}
+
+static struct symbol_hash_entry *unresolved;
+
+static void
+enqueue_as_unresolved (struct symbol_hash_entry *e)
+{
+ e->pprev = &unresolved;
+ e->next = unresolved;
+ if (e->next)
+ e->next->pprev = &e->next;
+ unresolved = e;
+ e->referenced = true;
+}
+
+static void
+dequeue_unresolved (struct symbol_hash_entry *e)
+{
+ if (e->pprev != NULL)
+ {
+ if (e->next)
+ e->next->pprev = e->pprev;
+ *e->pprev = e->next;
+ }
+ e->pprev = NULL;
+}
+
+static void
+process_refs_defs (file *f, const char *ptx)
+{
+ while (*ptx != '\0')
+ {
+ if (strncmp (ptx, "\n// BEGIN GLOBAL ", 17) == 0)
+ {
+ int type = 0;
+ ptx += 17;
+ if (strncmp (ptx, "VAR DEF: ", 9) == 0)
+ {
+ type = 1;
+ ptx += 9;
+ }
+ else if (strncmp (ptx, "FUNCTION DEF: ", 14) == 0)
+ {
+ type = 1;
+ ptx += 14;
+ }
+ if (strncmp (ptx, "VAR DECL: ", 10) == 0)
+ {
+ type = 2;
+ ptx += 10;
+ }
+ else if (strncmp (ptx, "FUNCTION DECL: ", 15) == 0)
+ {
+ type = 2;
+ ptx += 15;
+ }
+ if (type == 0)
+ continue;
+ const char *end = strchr (ptx, '\n');
+ if (end == 0)
+ end = ptx + strlen (ptx);
+ if ((end - ptx == 6 && memcmp (ptx, "malloc", 6) == 0)
+ || (end - ptx == 4 && memcmp (ptx, "free", 4) == 0)
+ || (end - ptx == 7 && memcmp (ptx, "vprintf", 7) == 0))
+ continue;
+ const char *sym = xstrndup (ptx, end - ptx);
+ struct symbol_hash_entry *e = symbol_hash_lookup (sym, 1);
+
+ if (!e->included)
+ {
+ if (type == 1)
+ {
+ if (f == NULL)
+ {
+ e->included = true;
+ dequeue_unresolved (e);
+ }
+ else
+ e->def = f;
+ }
+ else
+ {
+ if (f == NULL)
+ {
+ if (!e->referenced)
+ enqueue_as_unresolved (e);
+ }
+ }
+ }
+ }
+ ptx++;
+ }
+}
+
+int
+main (int argc, char **argv)
+{
+ const char *outname = NULL;
+ list<string> libraries;
+ list<string> libpaths;
+ bool verbose = false;
+
+ int o;
+ while ((o = getopt (argc, argv, "L:l:o:v")) != -1)
+ {
+ switch (o)
+ {
+ case 'v':
+ verbose = true;
+ break;
+ case 'o':
+ if (outname != NULL)
+ {
+ cerr << "multiple output files specified\n";
+ exit (1);
+ }
+ outname = optarg;
+ break;
+ case 'l':
+ libraries.push_back (optarg);
+ break;
+ case 'L':
+ libpaths.push_back (optarg);
+ break;
+ default:
+ break;
+ }
+ }
+
+ libraries.sort ();
+ libraries.unique ();
+ libpaths.unique ();
+
+ if (outname == NULL)
+ outname = "a.out";
+
+ symbol_table = htab_create (500, hash_string_hash, hash_string_eq,
+ NULL);
+
+ FILE *outfile = fopen (outname, "w");
+ if (outfile == NULL)
+ {
+ cerr << "error opening output file\n";
+ exit (1);
+ }
+ list<string> inputfiles;
+ while (optind < argc)
+ inputfiles.push_back (argv[optind++]);
+
+ int idx = 0;
+ for (list<string>::const_iterator iterator = inputfiles.begin(), end = inputfiles.end();
+ iterator != end;
+ ++iterator)
+ {
+ const string &name = *iterator;
+ FILE *f = path_open (name.c_str (), libpaths);
+ if (f == NULL)
+ {
+ cerr << "error opening " << name << "\n";
+ goto error_out;
+ }
+ fseek (f, 0, SEEK_END);
+ off_t len = ftell (f);
+ fseek (f, 0, SEEK_SET);
+ char *buf = new char[len + 1];
+ fread (buf, 1, len, f);
+ buf[len] = '\0';
+ if (ferror (f))
+ {
+ cerr << "error reading " << name << "\n";
+ goto error_out;
+ }
+ size_t out = fwrite (buf, 1, len, outfile);
+ if (out != len)
+ {
+ cerr << "error writing to output file\n";
+ goto error_out;
+ }
+ process_refs_defs (NULL, buf);
+ free (buf);
+ if (verbose)
+ cout << "Linking " << name << " as " << idx++ << "\n";
+ fputc ('\0', outfile);
+ }
+ for (list<string>::const_iterator iterator = libraries.begin(), end = libraries.end();
+ iterator != end;
+ ++iterator)
+ {
+ const string &name = "lib" + *iterator + ".a";
+ if (verbose)
+ cout << "trying lib " << name << "\n";
+ FILE *f = path_open (name.c_str (), libpaths);
+ if (f == NULL)
+ {
+ cerr << "error opening " << name << "\n";
+ goto error_out;
+ }
+ archive ar;
+ if (!ar.init (f))
+ {
+ cerr << name << " is not a valid archive\n";
+ goto error_out;
+ }
+ while (!ar.at_end ())
+ {
+ if (!ar.next_file ())
+ {
+ cerr << "error reading from archive " << name << "\n";
+ goto error_out;
+ }
+ const char *p = xstrdup (ar.get_contents ());
+ size_t len = ar.get_len ();
+ file *f = file_hash_new (p, len, name.c_str (), ar.get_name ());
+ process_refs_defs (f, p);
+ }
+ }
+
+ while (unresolved)
+ {
+ struct file_hash_entry *to_add = NULL;
+ struct symbol_hash_entry *e;
+ for (e = unresolved; e; e = e->next)
+ {
+ struct file_hash_entry *f = e->def;
+ if (!f)
+ {
+ cerr << "unresolved symbol " << e->key << "\n";
+ goto error_out;
+ }
+ if (verbose)
+ cout << "Resolving " << e->key << "\n";
+ if (!f->pprev)
+ {
+ f->pprev = &to_add;
+ f->next = to_add;
+ to_add = f;
+ }
+ e->included = true;
+ e->pprev = NULL;
+ }
+ unresolved = NULL;
+ assert (to_add != NULL);
+ struct file_hash_entry *f;
+ for (f = to_add; f; f = f->next)
+ {
+ f->pprev = NULL;
+ if (verbose)
+ cout << "Linking " << f->arname << "::" << f->name << " as " << idx++ << "\n";
+ if (fwrite (f->data, 1, f->len, outfile) != f->len)
+ {
+ cerr << "error writing to output file\n";
+ goto error_out;
+ }
+ fputc ('\0', outfile);
+ process_refs_defs (NULL, f->data);
+ }
+ }
+ return 0;
+
+ error_out:
+ fclose (outfile);
+ unlink (outname);
+ return 1;
+}
===================================================================
@@ -1,2 +1,27 @@
#
+nvptx-ld.o: $(srcdir)/config/nvptx/nvptx-ld.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
+
+collect-ld$(exeext): nvptx-ld.o $(LIBIBERTY)
+ +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
+ nvptx-ld.o $(LIBIBERTY)
+
+nvptx-as.o: $(srcdir)/config/nvptx/nvptx-as.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
+
+as$(exeext): nvptx-as.o $(LIBIBERTY)
+ +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
+ nvptx-as.o $(LIBIBERTY)
+
+ar$(exeext):
+ echo -e "#! /bin/sh\n$(AR) \"$$""@\"" >$@
+ chmod a+x $@
+
+ranlib$(exeext):
+ echo -e "#! /bin/sh\n$(RANLIB) \"$$""@\"" >$@
+ chmod a+x $@
+
+
===================================================================
@@ -13607,7 +13607,95 @@ fi
RAW_CXX_FOR_TARGET="$CXX_FOR_TARGET"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the target ar" >&5
+case "${target}" in
+ nvptx-*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the target ar" >&5
+$as_echo_n "checking where to find the target ar... " >&6; }
+if test "x${build}" != "x${host}" ; then
+ if expr "x$AR_FOR_TARGET" : "x/" > /dev/null; then
+ # We already found the complete path
+ ac_dir=`dirname $AR_FOR_TARGET`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed in $ac_dir" >&5
+$as_echo "pre-installed in $ac_dir" >&6; }
+ else
+ # Canadian cross, just use what we found
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed" >&5
+$as_echo "pre-installed" >&6; }
+ fi
+else
+ ok=yes
+ case " ${configdirs} " in
+ *" gcc "*) ;;
+ *) ok=no ;;
+ esac
+
+ if test $ok = yes; then
+ # An in-tree tool is available and we can use it
+ AR_FOR_TARGET='$$r/$(HOST_SUBDIR)/gcc/ar'
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: just compiled" >&5
+$as_echo "just compiled" >&6; }
+ elif expr "x$AR_FOR_TARGET" : "x/" > /dev/null; then
+ # We already found the complete path
+ ac_dir=`dirname $AR_FOR_TARGET`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed in $ac_dir" >&5
+$as_echo "pre-installed in $ac_dir" >&6; }
+ elif test "x$target" = "x$host"; then
+ # We can use an host tool
+ AR_FOR_TARGET='$(AR)'
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: host tool" >&5
+$as_echo "host tool" >&6; }
+ else
+ # We need a cross tool
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed" >&5
+$as_echo "pre-installed" >&6; }
+ fi
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the target ranlib" >&5
+$as_echo_n "checking where to find the target ranlib... " >&6; }
+if test "x${build}" != "x${host}" ; then
+ if expr "x$RANLIB_FOR_TARGET" : "x/" > /dev/null; then
+ # We already found the complete path
+ ac_dir=`dirname $RANLIB_FOR_TARGET`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed in $ac_dir" >&5
+$as_echo "pre-installed in $ac_dir" >&6; }
+ else
+ # Canadian cross, just use what we found
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed" >&5
+$as_echo "pre-installed" >&6; }
+ fi
+else
+ ok=yes
+ case " ${configdirs} " in
+ *" gcc "*) ;;
+ *) ok=no ;;
+ esac
+
+ if test $ok = yes; then
+ # An in-tree tool is available and we can use it
+ RANLIB_FOR_TARGET='$$r/$(HOST_SUBDIR)/gcc/ranlib'
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: just compiled" >&5
+$as_echo "just compiled" >&6; }
+ elif expr "x$RANLIB_FOR_TARGET" : "x/" > /dev/null; then
+ # We already found the complete path
+ ac_dir=`dirname $RANLIB_FOR_TARGET`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed in $ac_dir" >&5
+$as_echo "pre-installed in $ac_dir" >&6; }
+ elif test "x$target" = "x$host"; then
+ # We can use an host tool
+ RANLIB_FOR_TARGET='$(RANLIB)'
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: host tool" >&5
+$as_echo "host tool" >&6; }
+ else
+ # We need a cross tool
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed" >&5
+$as_echo "pre-installed" >&6; }
+ fi
+fi
+
+ ;;
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the target ar" >&5
$as_echo_n "checking where to find the target ar... " >&6; }
if test "x${build}" != "x${host}" ; then
if expr "x$AR_FOR_TARGET" : "x/" > /dev/null; then
@@ -13649,6 +13737,50 @@ $as_echo "pre-installed" >&6; }
fi
fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the target ranlib" >&5
+$as_echo_n "checking where to find the target ranlib... " >&6; }
+if test "x${build}" != "x${host}" ; then
+ if expr "x$RANLIB_FOR_TARGET" : "x/" > /dev/null; then
+ # We already found the complete path
+ ac_dir=`dirname $RANLIB_FOR_TARGET`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed in $ac_dir" >&5
+$as_echo "pre-installed in $ac_dir" >&6; }
+ else
+ # Canadian cross, just use what we found
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed" >&5
+$as_echo "pre-installed" >&6; }
+ fi
+else
+ ok=yes
+ case " ${configdirs} " in
+ *" binutils "*) ;;
+ *) ok=no ;;
+ esac
+
+ if test $ok = yes; then
+ # An in-tree tool is available and we can use it
+ RANLIB_FOR_TARGET='$$r/$(HOST_SUBDIR)/binutils/ranlib'
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: just compiled" >&5
+$as_echo "just compiled" >&6; }
+ elif expr "x$RANLIB_FOR_TARGET" : "x/" > /dev/null; then
+ # We already found the complete path
+ ac_dir=`dirname $RANLIB_FOR_TARGET`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed in $ac_dir" >&5
+$as_echo "pre-installed in $ac_dir" >&6; }
+ elif test "x$target" = "x$host"; then
+ # We can use an host tool
+ RANLIB_FOR_TARGET='$(RANLIB)'
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: host tool" >&5
+$as_echo "host tool" >&6; }
+ else
+ # We need a cross tool
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed" >&5
+$as_echo "pre-installed" >&6; }
+ fi
+fi
+
+ ;;
+esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the target as" >&5
$as_echo_n "checking where to find the target as... " >&6; }
if test "x${build}" != "x${host}" ; then
@@ -14193,48 +14325,6 @@ $as_echo "pre-installed in $ac_dir" >&6;
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: host tool" >&5
$as_echo "host tool" >&6; }
else
- # We need a cross tool
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed" >&5
-$as_echo "pre-installed" >&6; }
- fi
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the target ranlib" >&5
-$as_echo_n "checking where to find the target ranlib... " >&6; }
-if test "x${build}" != "x${host}" ; then
- if expr "x$RANLIB_FOR_TARGET" : "x/" > /dev/null; then
- # We already found the complete path
- ac_dir=`dirname $RANLIB_FOR_TARGET`
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed in $ac_dir" >&5
-$as_echo "pre-installed in $ac_dir" >&6; }
- else
- # Canadian cross, just use what we found
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed" >&5
-$as_echo "pre-installed" >&6; }
- fi
-else
- ok=yes
- case " ${configdirs} " in
- *" binutils "*) ;;
- *) ok=no ;;
- esac
-
- if test $ok = yes; then
- # An in-tree tool is available and we can use it
- RANLIB_FOR_TARGET='$$r/$(HOST_SUBDIR)/binutils/ranlib'
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: just compiled" >&5
-$as_echo "just compiled" >&6; }
- elif expr "x$RANLIB_FOR_TARGET" : "x/" > /dev/null; then
- # We already found the complete path
- ac_dir=`dirname $RANLIB_FOR_TARGET`
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed in $ac_dir" >&5
-$as_echo "pre-installed in $ac_dir" >&6; }
- elif test "x$target" = "x$host"; then
- # We can use an host tool
- RANLIB_FOR_TARGET='$(RANLIB)'
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: host tool" >&5
-$as_echo "host tool" >&6; }
- else
# We need a cross tool
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed" >&5
$as_echo "pre-installed" >&6; }
===================================================================
@@ -3271,7 +3271,16 @@ ACX_CHECK_INSTALLED_TARGET_TOOL(WINDMC_F
RAW_CXX_FOR_TARGET="$CXX_FOR_TARGET"
-GCC_TARGET_TOOL(ar, AR_FOR_TARGET, AR, [binutils/ar])
+case "${target}" in
+ nvptx-*)
+ GCC_TARGET_TOOL(ar, AR_FOR_TARGET, AR, [gcc/ar])
+ GCC_TARGET_TOOL(ranlib, RANLIB_FOR_TARGET, RANLIB, [gcc/ranlib])
+ ;;
+ *)
+ GCC_TARGET_TOOL(ar, AR_FOR_TARGET, AR, [binutils/ar])
+ GCC_TARGET_TOOL(ranlib, RANLIB_FOR_TARGET, RANLIB, [binutils/ranlib])
+ ;;
+esac
GCC_TARGET_TOOL(as, AS_FOR_TARGET, AS, [gas/as-new])
GCC_TARGET_TOOL(cc, CC_FOR_TARGET, CC, [gcc/xgcc -B$$r/$(HOST_SUBDIR)/gcc/])
dnl see comments for CXX_FOR_TARGET_FLAG_TO_PASS
@@ -3293,7 +3302,6 @@ GCC_TARGET_TOOL(ld, LD_FOR_TARGET, LD, [
GCC_TARGET_TOOL(lipo, LIPO_FOR_TARGET, LIPO)
GCC_TARGET_TOOL(nm, NM_FOR_TARGET, NM, [binutils/nm-new])
GCC_TARGET_TOOL(objdump, OBJDUMP_FOR_TARGET, OBJDUMP, [binutils/objdump])
-GCC_TARGET_TOOL(ranlib, RANLIB_FOR_TARGET, RANLIB, [binutils/ranlib])
GCC_TARGET_TOOL(readelf, READELF_FOR_TARGET, READELF, [binutils/readelf])
GCC_TARGET_TOOL(strip, STRIP_FOR_TARGET, STRIP, [binutils/strip-new])
GCC_TARGET_TOOL(windres, WINDRES_FOR_TARGET, WINDRES, [binutils/windres])