From patchwork Sat Nov 1 12:11:29 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bernd Schmidt X-Patchwork-Id: 405789 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 502C81400B6 for ; Sat, 1 Nov 2014 23:12:03 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; q= dns; s=default; b=NtDLCx4FP3uiEghAMtgoLloZ0atW63P+DxJ7oMASUb5ce0 hjVNIm8A8NYr/TOSCJ680twAKL+hzZ/4uD3IylwYRClR3XczHMlhOVh9iRSAq984 kqhW8icVxrsHSjpMmxmQf4b7ACqtMBAfhKUXsHdrMjoQFB5FxpMtm5C3fD5O8= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; s= default; bh=7WQAbsu/L9ISgE/PsCo/EvMhLVc=; b=xHYt1lpxMABdc17SlYLm /6WtX053xYeRw/B/9Iyr84zPAMPyGKpexYxlhg6Hq3xV00GW8/YwAkFKxvJeUa4s HtDlnBdHZP3Q85ZMudfDmdhIDD6QvZz9sHSPeXzynsa5SAv8gdyl3E7UZNcqodya +/Qzge7aECA4SWfPx60ISU4= Received: (qmail 29571 invoked by alias); 1 Nov 2014 12:11:55 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 29562 invoked by uid 89); 1 Nov 2014 12:11:54 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.8 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_NONE, WEIRD_QUOTING autolearn=ham version=3.3.2 X-HELO: relay1.mentorg.com Received: from relay1.mentorg.com (HELO relay1.mentorg.com) (192.94.38.131) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 01 Nov 2014 12:11:51 +0000 Received: from nat-ies.mentorg.com ([192.94.31.2] helo=SVR-IES-FEM-01.mgc.mentorg.com) by relay1.mentorg.com with esmtp id 1XkXX1-0005Ly-JY from Bernd_Schmidt@mentor.com for gcc-patches@gcc.gnu.org; Sat, 01 Nov 2014 05:11:48 -0700 Received: from [127.0.0.1] (137.202.0.76) by SVR-IES-FEM-01.mgc.mentorg.com (137.202.0.104) with Microsoft SMTP Server id 14.3.181.6; Sat, 1 Nov 2014 12:11:45 +0000 Message-ID: <5454CDF1.3070307@codesourcery.com> Date: Sat, 1 Nov 2014 13:11:29 +0100 From: Bernd Schmidt User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.8.0 MIME-Version: 1.0 To: GCC Patches Subject: nvptx offloading patches [4/n] I'm sending this for reference more than anything else - this is the patch that adds the target support for offloading to the nvptx port. It depends on the other offloading patches Ilya is currently submitting. I actually expect this to change a little in the near future; the nvptx mkoffload duplicates some of the logic that we have in nvptx-as and I'm thinking of making some improvements. But I figure it would be good to show the entire picture, as it is as of now. Bernd Index: git/gcc/config/nvptx/mkoffload.c =================================================================== --- /dev/null +++ git/gcc/config/nvptx/mkoffload.c @@ -0,0 +1,889 @@ +/* Offload image generation tool for ptx + + Nathan Sidwell + Bernd Schmidt + + Munges PTX assembly into a C source file defining the PTX code as a + string. + + 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 "config.h" +#include "system.h" +#include "coretypes.h" +#include "intl.h" +#include +#include "obstack.h" +#include "diagnostic-core.h" +#include "collect-utils.h" + +const char tool_name[] = "nvptx mkoffload"; + +#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; + unsigned char vis; + unsigned len : 12; + unsigned sym : 12; +} Stmt; + +struct id_map +{ + id_map *next; + char *ptx_name; +}; + +static const char *read_file (FILE *); +static Token *tokenize (const char *); + +static void write_token (FILE *, const Token *); +static void write_tokens (FILE *, const Token *, unsigned, int); + +static Stmt *alloc_stmt (unsigned, Token *, Token *, const Token *); +#define alloc_comment(S,E) alloc_stmt (V_comment, S, E, 0) +#define append_stmt(V, S) ((S)->next = *(V), *(V) = (S)) +static Stmt *rev_stmts (Stmt *); +static void write_stmt (FILE *, const Stmt *); +static void write_stmts (FILE *, const Stmt *); + +static Token *parse_insn (Token *); +static Token *parse_list_nosemi (Token *); +static Token *parse_init (Token *); +static Token *parse_file (Token *); + +static Stmt *decls; +static Stmt *vars; +static Stmt *fns; + +static id_map *func_ids, **funcs_tail = &func_ids; +static id_map *var_ids, **vars_tail = &var_ids; + +/* Files to unlink. */ +static const char *ptx_name; +static const char *ptx_cfile_name; + +/* Delete tempfiles. */ + +/* Unlink a temporary file unless requested otherwise. */ + +void +maybe_unlink (const char *file) +{ + if (! debug) + { + if (unlink_if_ordinary (file) + && errno != ENOENT) + fatal_error ("deleting file %s: %m", file); + } + else + fprintf (stderr, "[Leaving %s]\n", file); +} + +void +tool_cleanup (bool) +{ +} + +/* Add or change the value of an environment variable, outputting the + change to standard error if in verbose mode. */ +static void +xputenv (const char *string) +{ + if (verbose) + fprintf (stderr, "%s\n", string); + putenv (CONST_CAST (char *, string)); +} + + +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 void +write_tokens (FILE *out, Token const *toks, unsigned len, int spc) +{ + fputs ("\t\"", out); + for (; len--; toks++) + write_token (out, toks); + if (spc) + fputs (" ", out); + fputs ("\"", out); +} + +static Stmt * +alloc_stmt (unsigned vis, Token *tokens, Token *end, Token const *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 ? sym - tokens : ~0; + + 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) +{ + if ((stmt->vis & V_mask) != V_comment) + { + write_tokens (out, stmt->tokens, stmt->len, + (stmt->vis & V_mask) == V_pred); + fputs (stmt->vis & V_no_eol ? "\t" : "\n", 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; + Token *sym = 0; + 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: + if (tok[-1].ptr[0] != '$') + sym = tok - 1; + tok[-1].end = 1; + s = V_label; + break; + + case '@': + tok->space = 0; + if (tok->kind == '!') + tok++; + if (tok->kind == K_symbol) + sym = tok; + tok++; + s = V_pred; + break; + + default: + for (; tok->kind != ';'; tok++) + { + if (tok->kind == ',') + tok[1].space = 0; + else if (tok->kind == K_symbol) + sym = tok; + } + tok++->end = 1; + break; + } + + stmt = alloc_stmt (s, start, tok, sym); + 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) +{ + for (;;) + { + Token *start = tok; + Token const *sym = 0; + Stmt *stmt; + + if (tok->kind == K_comment) + { + while (tok->kind == K_comment) + tok++; + stmt = alloc_comment (start, tok); + append_stmt (&vars, stmt); + start = tok; + } + + if (tok->kind == '{') + tok[1].space = 0; + for (; tok->kind != ',' && tok->kind != ';'; tok++) + if (tok->kind == K_symbol) + sym = tok; + tok[1].space = 0; + int end = tok++->kind == ';'; + stmt = alloc_stmt (V_insn, start, tok, sym); + append_stmt (&vars, stmt); + if (!tok[-1].end && tok->kind == K_comment) + { + stmt->vis |= V_no_eol; + stmt = alloc_comment (tok, tok + 1); + append_stmt (&vars, 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; + const Token *def = 0; + unsigned is_decl = 0; + Token *start; + + 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) + def = tok; + } + + 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 (&vars, comment); + stmt->vis |= V_prefix_comment; + } + append_stmt (&vars, stmt); + if (assign) + tok = parse_init (tok); + } + 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++; + } + return tok; +} + +static void +process (FILE *in, FILE *out) +{ + const char *input = read_file (in); + Token *tok = tokenize (input); + + do + tok = parse_file (tok); + while (tok->kind); + + fprintf (out, "static const char ptx_code[] = \n"); + write_stmts (out, rev_stmts (decls)); + write_stmts (out, rev_stmts (vars)); + write_stmts (out, rev_stmts (fns)); + fprintf (out, ";\n\n"); + fprintf (out, "static const char *var_mappings[] = {\n"); + for (id_map *id = var_ids; id; id = id->next) + fprintf (out, "\t\"%s\"%s\n", id->ptx_name, id->next ? "," : ""); + fprintf (out, "};\n\n"); + fprintf (out, "static const char *func_mappings[] = {\n"); + for (id_map *id = func_ids; id; id = id->next) + fprintf (out, "\t\"%s\"%s\n", id->ptx_name, id->next ? "," : ""); + fprintf (out, "};\n\n"); + + fprintf (out, "static const void *target_data[] = {\n"); + fprintf (out, " ptx_code, var_mappings, func_mappings\n"); + fprintf (out, "};\n\n"); + + fprintf (out, "extern void GOMP_offload_register (const void *, int, void *);\n"); + + fprintf (out, "extern void *__OPENMP_TARGET__[];\n\n"); + fprintf (out, "#define PTX_ID 1\n"); + fprintf (out, "static __attribute__((constructor)) void init (void)\n{\n"); + fprintf (out, " GOMP_offload_register (__OPENMP_TARGET__, PTX_ID,\n"); + fprintf (out, " &target_data);\n"); + fprintf (out, "};\n"); +} + +static void +compile_native (const char *infile, const char *outfile, const char *compiler) +{ + const char *collect_gcc_options = getenv ("COLLECT_GCC_OPTIONS"); + if (!collect_gcc_options) + fatal_error ("environment variable COLLECT_GCC_OPTIONS must be set"); + + struct obstack argv_obstack; + obstack_init (&argv_obstack); + obstack_ptr_grow (&argv_obstack, compiler); + obstack_ptr_grow (&argv_obstack, infile); + obstack_ptr_grow (&argv_obstack, "-c"); + obstack_ptr_grow (&argv_obstack, "-o"); + obstack_ptr_grow (&argv_obstack, outfile); + obstack_ptr_grow (&argv_obstack, NULL); + + const char **new_argv = XOBFINISH (&argv_obstack, const char **); + fork_execute (new_argv[0], CONST_CAST (char **, new_argv), true); + obstack_free (&argv_obstack, NULL); +} + +int +main (int argc, char **argv) +{ + FILE *in = stdin; + FILE *out = stdout; + const char *outname = 0; + + char *collect_gcc = getenv ("COLLECT_GCC"); + if (collect_gcc == NULL) + fatal_error ("COLLECT_GCC must be set."); + const char *gcc_path = dirname (ASTRDUP (collect_gcc)); + const char *gcc_exec = basename (ASTRDUP (collect_gcc)); + + size_t len = (strlen (gcc_path) + 1 + + strlen (GCC_INSTALL_NAME) + + 1); + char *driver = XALLOCAVEC (char, len); + + if (strcmp (gcc_exec, collect_gcc) == 0) + /* collect_gcc has no path, so it was found in PATH. Make sure we also + find accel-gcc in PATH. */ + gcc_path = NULL; + + int driver_used = 0; + if (gcc_path != NULL) + driver_used = sprintf (driver, "%s/", gcc_path); + sprintf (driver + driver_used, "%s", GCC_INSTALL_NAME); + + /* We may be called with all the arguments stored in some file and + passed with @file. Expand them into argv before processing. */ + expandargv (&argc, &argv); + + struct obstack argv_obstack; + obstack_init (&argv_obstack); + obstack_ptr_grow (&argv_obstack, driver); + obstack_ptr_grow (&argv_obstack, "-xlto"); + obstack_ptr_grow (&argv_obstack, "-m64"); + obstack_ptr_grow (&argv_obstack, "-S"); + + for (int ix = 1; ix != argc; ix++) + { + if (!strcmp (argv[ix], "-o") && ix + 1 != argc) + outname = argv[++ix]; + else + obstack_ptr_grow (&argv_obstack, argv[ix]); + } + + ptx_name = make_temp_file (".mkoffload"); + obstack_ptr_grow (&argv_obstack, "-o"); + obstack_ptr_grow (&argv_obstack, ptx_name); + obstack_ptr_grow (&argv_obstack, NULL); + const char **new_argv = XOBFINISH (&argv_obstack, const char **); + + char *execpath = getenv ("GCC_EXEC_PREFIX"); + char *cpath = getenv ("COMPILER_PATH"); + char *lpath = getenv ("LIBRARY_PATH"); + unsetenv ("GCC_EXEC_PREFIX"); + unsetenv ("COMPILER_PATH"); + unsetenv ("LIBRARY_PATH"); + + fork_execute (new_argv[0], CONST_CAST (char **, new_argv), true); + obstack_free (&argv_obstack, NULL); + + xputenv (concat ("GCC_EXEC_PREFIX=", execpath, NULL)); + xputenv (concat ("COMPILER_PATH=", cpath, NULL)); + xputenv (concat ("LIBRARY_PATH=", lpath, NULL)); + + in = fopen (ptx_name, "r"); + if (!in) + fatal_error ("cannot open intermediate ptx file"); + + ptx_cfile_name = make_temp_file (".c"); + + out = fopen (ptx_cfile_name, "w"); + if (!out) + fatal_error ("cannot open '%s'", ptx_cfile_name); + + process (in, out); + fclose (out); + + compile_native (ptx_cfile_name, outname, collect_gcc); + + utils_cleanup (false); + + return 0; +} Index: git/gcc/config.gcc =================================================================== --- git.orig/gcc/config.gcc +++ git/gcc/config.gcc @@ -2155,6 +2155,9 @@ nvptx-*) tm_file="${tm_file} newlib-stdint.h" tmake_file="nvptx/t-nvptx" extra_programs="collect-ld\$(exeext) as\$(exeext) ar\$(exeext) ranlib\$(exeext)" + if test x$enable_as_accelerator = xyes; then + extra_programs="${extra_programs} mkoffload\$(exeext)" + fi ;; pdp11-*-*) tm_file="${tm_file} newlib-stdint.h" Index: git/gcc/config/nvptx/t-nvptx =================================================================== --- git.orig/gcc/config/nvptx/t-nvptx +++ git/gcc/config/nvptx/t-nvptx @@ -1,5 +1,15 @@ # +CFLAGS-mkoffload.o += $(DRIVER_DEFINES) \ + -DGCC_INSTALL_NAME=\"$(GCC_INSTALL_NAME)\" +mkoffload.o: $(srcdir)/config/nvptx/mkoffload.c + $(COMPILE) $< + $(POSTCOMPILE) + +mkoffload$(exeext): mkoffload.o collect-utils.o libcommon-target.a $(LIBIBERTY) $(LIBDEPS) + +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \ + mkoffload.o collect-utils.o libcommon-target.a $(LIBIBERTY) $(LIBS) + nvptx-ld.o: $(srcdir)/config/nvptx/nvptx-ld.c $(COMPILE) $< $(POSTCOMPILE) @@ -23,5 +33,3 @@ ar$(exeext): ranlib$(exeext): echo -e "#! /bin/sh\n$(RANLIB) \"$$""@\"" >$@ chmod a+x $@ - - Index: git/gcc/config/nvptx/nvptx.c =================================================================== --- git.orig/gcc/config/nvptx/nvptx.c +++ git/gcc/config/nvptx/nvptx.c @@ -1990,6 +1990,16 @@ nvptx_vector_alignment (const_tree type) return MIN (align, BIGGEST_ALIGNMENT); } +/* Record a symbol for mkoffload to enter into the mapping table. */ + +static void +nvptx_record_offload_symbol (tree decl) +{ + fprintf (asm_out_file, "//:%s_MAP %s\n", + TREE_CODE (decl) == VAR_DECL ? "VAR" : "FUNC", + IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); +} + /* Implement TARGET_ASM_FILE_START. Write the kinds of things ptxas expects at the start of a file. */ @@ -2101,6 +2111,9 @@ nvptx_file_end (void) #undef TARGET_NO_REGISTER_ALLOCATION #define TARGET_NO_REGISTER_ALLOCATION true +#undef TARGET_RECORD_OFFLOAD_SYMBOL +#define TARGET_RECORD_OFFLOAD_SYMBOL nvptx_record_offload_symbol + #undef TARGET_VECTOR_ALIGNMENT #define TARGET_VECTOR_ALIGNMENT nvptx_vector_alignment