mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-21 18:00:13 +01:00
For each label store its offset and two lists of uses (for JIP and UIP). Because the parser itself already restricts what opcodes can use labels (and which ones), don't re-validate them. Reviewed-by: Sagar Ghuge <sagar.ghuge@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33522>
174 lines
4.4 KiB
C
174 lines
4.4 KiB
C
/*
|
|
* Copyright © 2018 Intel Corporation
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#include "brw_asm.h"
|
|
#include "brw_asm_internal.h"
|
|
#include "brw_disasm_info.h"
|
|
#include "util/hash_table.h"
|
|
#include "util/u_dynarray.h"
|
|
|
|
/* TODO: Check if we can use bison/flex without globals. */
|
|
|
|
extern FILE *yyin;
|
|
|
|
struct brw_codegen *p;
|
|
const char *input_filename;
|
|
int errors;
|
|
bool compaction_warning_given;
|
|
|
|
/*
|
|
* Label tracking.
|
|
*/
|
|
static struct hash_table *brw_asm_labels;
|
|
|
|
typedef struct {
|
|
char *name;
|
|
int offset; /* -1 for unset */
|
|
struct util_dynarray jip_uses;
|
|
struct util_dynarray uip_uses;
|
|
} brw_asm_label;
|
|
|
|
static brw_asm_label *
|
|
brw_asm_label_lookup(const char *name)
|
|
{
|
|
uint32_t h = _mesa_hash_string(name);
|
|
struct hash_entry *entry =
|
|
_mesa_hash_table_search_pre_hashed(brw_asm_labels, h, name);
|
|
if (!entry) {
|
|
void *mem_ctx = brw_asm_labels;
|
|
brw_asm_label *label = rzalloc(mem_ctx, brw_asm_label);
|
|
label->name = ralloc_strdup(mem_ctx, name);
|
|
label->offset = -1;
|
|
util_dynarray_init(&label->jip_uses, mem_ctx);
|
|
util_dynarray_init(&label->uip_uses, mem_ctx);
|
|
entry = _mesa_hash_table_insert_pre_hashed(brw_asm_labels,
|
|
h, name, label);
|
|
}
|
|
assert(entry);
|
|
return entry->data;
|
|
}
|
|
|
|
void
|
|
brw_asm_label_set(const char *name)
|
|
{
|
|
brw_asm_label *label = brw_asm_label_lookup(name);
|
|
label->offset = p->next_insn_offset;
|
|
}
|
|
|
|
void
|
|
brw_asm_label_use_jip(const char *name)
|
|
{
|
|
brw_asm_label *label = brw_asm_label_lookup(name);
|
|
int offset = p->next_insn_offset - sizeof(brw_eu_inst);
|
|
util_dynarray_append(&label->jip_uses, int, offset);
|
|
}
|
|
|
|
void
|
|
brw_asm_label_use_uip(const char *name)
|
|
{
|
|
brw_asm_label *label = brw_asm_label_lookup(name);
|
|
int offset = p->next_insn_offset - sizeof(brw_eu_inst);
|
|
util_dynarray_append(&label->uip_uses, int, offset);
|
|
}
|
|
|
|
static bool
|
|
brw_postprocess_labels()
|
|
{
|
|
unsigned unknown = 0;
|
|
void *store = p->store;
|
|
|
|
hash_table_foreach(brw_asm_labels, entry) {
|
|
brw_asm_label *label = entry->data;
|
|
|
|
if (label->offset == -1) {
|
|
fprintf(stderr, "Unknown label '%s'\n", label->name);
|
|
unknown++;
|
|
continue;
|
|
}
|
|
|
|
util_dynarray_foreach(&label->jip_uses, int, use_offset) {
|
|
brw_eu_inst *inst = store + *use_offset;
|
|
brw_eu_inst_set_jip(p->devinfo, inst, label->offset - *use_offset);
|
|
}
|
|
|
|
util_dynarray_foreach(&label->uip_uses, int, use_offset) {
|
|
brw_eu_inst *inst = store + *use_offset;
|
|
brw_eu_inst_set_uip(p->devinfo, inst, label->offset - *use_offset);
|
|
}
|
|
}
|
|
|
|
return unknown == 0;
|
|
}
|
|
|
|
/* TODO: Would be nice to make this operate on string instead on a FILE. */
|
|
|
|
brw_assemble_result
|
|
brw_assemble(void *mem_ctx, const struct intel_device_info *devinfo,
|
|
FILE *f, const char *filename, brw_assemble_flags flags)
|
|
{
|
|
brw_assemble_result result = {0};
|
|
|
|
void *tmp_ctx = ralloc_context(mem_ctx);
|
|
brw_asm_labels = _mesa_string_hash_table_create(tmp_ctx);
|
|
|
|
struct brw_isa_info isa;
|
|
brw_init_isa_info(&isa, devinfo);
|
|
|
|
p = rzalloc(mem_ctx, struct brw_codegen);
|
|
brw_init_codegen(&isa, p, p);
|
|
|
|
yyin = f;
|
|
input_filename = filename;
|
|
|
|
compaction_warning_given = false;
|
|
int err = yyparse();
|
|
if (err || errors)
|
|
goto end;
|
|
|
|
if (!brw_postprocess_labels())
|
|
goto end;
|
|
|
|
struct disasm_info *disasm_info = disasm_initialize(p->isa, NULL);
|
|
if (!disasm_info) {
|
|
ralloc_free(disasm_info);
|
|
fprintf(stderr, "Unable to initialize disasm_info struct instance\n");
|
|
goto end;
|
|
}
|
|
|
|
/* Add "inst groups" so validation errors can be recorded. */
|
|
for (int i = 0; i <= p->next_insn_offset; i += 16)
|
|
disasm_new_inst_group(disasm_info, i);
|
|
|
|
if (!brw_validate_instructions(p->isa, p->store, 0,
|
|
p->next_insn_offset, disasm_info)) {
|
|
dump_assembly(p->store, 0, p->next_insn_offset, disasm_info, NULL);
|
|
ralloc_free(disasm_info);
|
|
fprintf(stderr, "Invalid instructions.\n");
|
|
goto end;
|
|
}
|
|
|
|
if ((flags & BRW_ASSEMBLE_COMPACT) != 0)
|
|
brw_compact_instructions(p, 0, disasm_info);
|
|
|
|
result.bin = p->store;
|
|
result.bin_size = p->next_insn_offset;
|
|
|
|
if ((flags & BRW_ASSEMBLE_DUMP) != 0)
|
|
dump_assembly(p->store, 0, p->next_insn_offset, disasm_info, NULL);
|
|
|
|
ralloc_free(disasm_info);
|
|
|
|
end:
|
|
/* Reset internal state. */
|
|
yyin = NULL;
|
|
input_filename = NULL;
|
|
p = NULL;
|
|
brw_asm_labels = NULL;
|
|
|
|
ralloc_free(tmp_ctx);
|
|
|
|
return result;
|
|
}
|
|
|