process_asm (FILE *in, FILE *out, FILE *cfile)
{
int fn_count = 0, var_count = 0, dims_count = 0, regcount_count = 0;
- struct obstack fns_os, vars_os, varsizes_os, dims_os, regcounts_os;
+ struct obstack fns_os, dims_os, regcounts_os;
obstack_init (&fns_os);
- obstack_init (&vars_os);
- obstack_init (&varsizes_os);
obstack_init (&dims_os);
obstack_init (®counts_os);
unsigned varsize;
if (sscanf (buf, " .8byte %ms\n", &varname))
{
- obstack_ptr_grow (&vars_os, varname);
+ fputs (buf, out);
fgets (buf, sizeof (buf), in);
if (!sscanf (buf, " .8byte %u\n", &varsize))
abort ();
- obstack_int_grow (&varsizes_os, varsize);
var_count++;
-
- /* The HSA Runtime cannot locate the symbol if it is not
- exported from the kernel. */
- fprintf (out, "\t.global %s\n", varname);
}
break;
}
char dummy;
if (sscanf (buf, " .section .gnu.offload_vars%c", &dummy) > 0)
- state = IN_VARS;
+ {
+ state = IN_VARS;
+
+ /* Add a global symbol to allow plugin-gcn.c to locate the table
+ at runtime. It can't use the "offload_var_table.N" emitted by
+ the compiler because a) they're not global, and b) there's one
+ for each input file combined into the binary. */
+ fputs (buf, out);
+ fputs ("\t.global .offload_var_table\n"
+ "\t.type .offload_var_table, @object\n"
+ ".offload_var_table:\n",
+ out);
+ }
else if (sscanf (buf, " .section .gnu.offload_funcs%c", &dummy) > 0)
state = IN_FUNCS;
else if (sscanf (buf, " .amdgpu_metadata%c", &dummy) > 0)
regcount.sgpr_count = regcount.vgpr_count = -1;
}
- if (state == IN_CODE || state == IN_METADATA)
+ if (state == IN_CODE || state == IN_METADATA || state == IN_VARS)
fputs (buf, out);
}
fprintf (cfile, "#include <stdlib.h>\n");
fprintf (cfile, "#include <stdbool.h>\n\n");
- char **vars = XOBFINISH (&vars_os, char **);
- unsigned *varsizes = XOBFINISH (&varsizes_os, unsigned *);
- fprintf (cfile,
- "static const struct global_var_info {\n"
- " const char *name;\n"
- " void *address;\n"
- "} vars[] = {\n");
- int i;
- for (i = 0; i < var_count; ++i)
- {
- const char *sep = i < var_count - 1 ? "," : " ";
- fprintf (cfile, " { \"%s\", NULL }%s /* size: %u */\n", vars[i], sep,
- varsizes[i]);
- }
- fprintf (cfile, "};\n\n");
-
- obstack_free (&vars_os, NULL);
- obstack_free (&varsizes_os, NULL);
+ fprintf (cfile, "static const int gcn_num_vars = %d;\n\n", var_count);
/* Dump out function idents. */
fprintf (cfile, "static const struct hsa_kernel_description {\n"
"} gcn_kernels[] = {\n ");
dim.d[0] = dim.d[1] = dim.d[2] = 0;
const char *comma;
+ int i;
for (comma = "", i = 0; i < fn_count; comma = ",\n ", i++)
{
/* Find if we recorded dimensions for this function. */
" unsigned kernel_count;\n"
" const struct hsa_kernel_description *kernel_infos;\n"
" unsigned global_variable_count;\n"
- " const struct global_var_info *global_variables;\n"
"} target_data = {\n"
" &gcn_image,\n"
" sizeof (gcn_kernels) / sizeof (gcn_kernels[0]),\n"
" gcn_kernels,\n"
- " sizeof (vars) / sizeof (vars[0]),\n"
- " vars\n"
+ " gcn_num_vars\n"
"};\n\n");
fprintf (cfile,
const unsigned kernel_count;
struct hsa_kernel_description *kernel_infos;
const unsigned global_variable_count;
- struct global_var_info *global_variables;
};
/* This enum mirrors the corresponding LLVM enum's values for all ISAs that we
if (!create_and_finalize_hsa_program (agent))
return -1;
- for (unsigned i = 0; i < var_count; i++)
+ if (var_count > 0)
{
- struct global_var_info *v = &image_desc->global_variables[i];
- GCN_DEBUG ("Looking for variable %s\n", v->name);
-
hsa_status_t status;
hsa_executable_symbol_t var_symbol;
status = hsa_fns.hsa_executable_get_symbol_fn (agent->executable, NULL,
- v->name, agent->id,
+ ".offload_var_table",
+ agent->id,
0, &var_symbol);
if (status != HSA_STATUS_SUCCESS)
hsa_fatal ("Could not find symbol for variable in the code object",
status);
- uint64_t var_addr;
- uint32_t var_size;
+ uint64_t var_table_addr;
status = hsa_fns.hsa_executable_symbol_get_info_fn
- (var_symbol, HSA_EXECUTABLE_SYMBOL_INFO_VARIABLE_ADDRESS, &var_addr);
+ (var_symbol, HSA_EXECUTABLE_SYMBOL_INFO_VARIABLE_ADDRESS,
+ &var_table_addr);
if (status != HSA_STATUS_SUCCESS)
hsa_fatal ("Could not extract a variable from its symbol", status);
- status = hsa_fns.hsa_executable_symbol_get_info_fn
- (var_symbol, HSA_EXECUTABLE_SYMBOL_INFO_VARIABLE_SIZE, &var_size);
- if (status != HSA_STATUS_SUCCESS)
- hsa_fatal ("Could not extract a variable size from its symbol", status);
- pair->start = var_addr;
- pair->end = var_addr + var_size;
- GCN_DEBUG ("Found variable %s at %p with size %u\n", v->name,
- (void *)var_addr, var_size);
- pair++;
+ struct {
+ uint64_t addr;
+ uint64_t size;
+ } var_table[var_count];
+ GOMP_OFFLOAD_dev2host (agent->device_id, var_table,
+ (void*)var_table_addr, sizeof (var_table));
+
+ for (unsigned i = 0; i < var_count; i++)
+ {
+ pair->start = var_table[i].addr;
+ pair->end = var_table[i].addr + var_table[i].size;
+ GCN_DEBUG ("Found variable at %p with size %lu\n",
+ (void *)var_table[i].addr, var_table[i].size);
+ pair++;
+ }
}
GCN_DEBUG ("Looking for variable %s\n", STRINGX (GOMP_DEVICE_NUM_VAR));