intel/brw: Split off assembler logic into library

Reviewed-by: Sagar Ghuge <sagar.ghuge@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30006>
This commit is contained in:
Caio Oliveira 2024-07-02 11:57:39 -07:00 committed by Marge Bot
parent 1f906f8715
commit f48b3bee31
7 changed files with 317 additions and 237 deletions

View file

@ -0,0 +1,149 @@
/*
* Copyright © 2018 Intel Corporation
* SPDX-License-Identifier: MIT
*/
#include "brw_asm.h"
#include "brw_asm_internal.h"
#include "brw_disasm_info.h"
/* TODO: Check if we can use bison/flex without globals. */
extern FILE *yyin;
struct list_head instr_labels;
struct list_head target_labels;
struct brw_codegen *p;
const char *input_filename;
int errors;
static bool
i965_postprocess_labels()
{
void *store = p->store;
struct target_label *tlabel;
struct instr_label *ilabel, *s;
const unsigned to_bytes_scale = brw_jump_scale(p->devinfo);
LIST_FOR_EACH_ENTRY(tlabel, &target_labels, link) {
LIST_FOR_EACH_ENTRY_SAFE(ilabel, s, &instr_labels, link) {
if (!strcmp(tlabel->name, ilabel->name)) {
brw_inst *inst = store + ilabel->offset;
int relative_offset = (tlabel->offset - ilabel->offset) / sizeof(brw_inst);
relative_offset *= to_bytes_scale;
unsigned opcode = brw_inst_opcode(p->isa, inst);
if (ilabel->type == INSTR_LABEL_JIP) {
switch (opcode) {
case BRW_OPCODE_IF:
case BRW_OPCODE_ELSE:
case BRW_OPCODE_ENDIF:
case BRW_OPCODE_WHILE:
brw_inst_set_jip(p->devinfo, inst, relative_offset);
break;
case BRW_OPCODE_BREAK:
case BRW_OPCODE_HALT:
case BRW_OPCODE_CONTINUE:
brw_inst_set_jip(p->devinfo, inst, relative_offset);
break;
default:
fprintf(stderr, "Unknown opcode %d with JIP label\n", opcode);
return false;
}
} else {
switch (opcode) {
case BRW_OPCODE_IF:
case BRW_OPCODE_ELSE:
brw_inst_set_uip(p->devinfo, inst, relative_offset);
break;
case BRW_OPCODE_WHILE:
case BRW_OPCODE_ENDIF:
fprintf(stderr, "WHILE/ENDIF cannot have UIP offset\n");
return false;
case BRW_OPCODE_BREAK:
case BRW_OPCODE_CONTINUE:
case BRW_OPCODE_HALT:
brw_inst_set_uip(p->devinfo, inst, relative_offset);
break;
default:
fprintf(stderr, "Unknown opcode %d with UIP label\n", opcode);
return false;
}
}
list_del(&ilabel->link);
}
}
}
LIST_FOR_EACH_ENTRY(ilabel, &instr_labels, link) {
fprintf(stderr, "Unknown label '%s'\n", ilabel->name);
}
return list_is_empty(&instr_labels);
}
/* 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};
list_inithead(&instr_labels);
list_inithead(&target_labels);
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;
int err = yyparse();
if (err || errors)
goto end;
if (!i965_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;
}
if (!brw_validate_instructions(p->isa, p->store, 0,
p->next_insn_offset, disasm_info)) {
ralloc_free(disasm_info);
fprintf(stderr, "Invalid instructions\n");
goto end;
}
result.bin = p->store;
result.inst_count = p->next_insn_offset / 16;
if ((flags & BRW_ASSEMBLE_COMPACT) != 0)
brw_compact_instructions(p, 0, disasm_info);
ralloc_free(disasm_info);
end:
/* Reset internal state. */
yyin = NULL;
input_filename = NULL;
p = NULL;
list_inithead(&instr_labels);
list_inithead(&target_labels);
return result;
}

View file

@ -1,122 +1,27 @@
/*
* Copyright © 2018 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* SPDX-License-Identifier: MIT
*/
#ifndef BRW_ASM_H
#define BRW_ASM_H
#include <inttypes.h>
#include <stdio.h>
#include <stdbool.h>
#include <assert.h>
#include "compiler/brw_reg.h"
#include "compiler/brw_reg_type.h"
#include "compiler/brw_eu_defines.h"
#include "compiler/brw_inst.h"
#include "compiler/brw_eu.h"
#include "dev/intel_device_info.h"
#include "util/list.h"
struct intel_device_info;
/* glibc < 2.27 defines OVERFLOW in /usr/include/math.h. */
#undef OVERFLOW
typedef struct {
void *bin;
int inst_count;
} brw_assemble_result;
int yyparse(void);
int yylex(void);
char *lex_text(void);
typedef enum {
BRW_ASSEMBLE_COMPACT = 1 << 0,
} brw_assemble_flags;
extern struct brw_codegen *p;
extern int errors;
extern char *input_filename;
extern struct list_head instr_labels;
extern struct list_head target_labels;
struct condition {
unsigned cond_modifier:4;
unsigned flag_reg_nr:1;
unsigned flag_subreg_nr:1;
};
struct predicate {
unsigned pred_control:4;
unsigned pred_inv:1;
unsigned flag_reg_nr:1;
unsigned flag_subreg_nr:1;
};
enum instoption_type {
INSTOPTION_FLAG,
INSTOPTION_DEP_INFO,
INSTOPTION_CHAN_OFFSET,
};
struct instoption {
enum instoption_type type;
union {
unsigned uint_value;
struct tgl_swsb depinfo_value;
};
};
struct options {
uint8_t chan_offset;
unsigned access_mode:1;
unsigned compression_control:2;
unsigned thread_control:2;
unsigned no_dd_check:1; // Dependency control
unsigned no_dd_clear:1; // Dependency control
unsigned mask_control:1;
unsigned debug_control:1;
unsigned acc_wr_control:1;
unsigned end_of_thread:1;
unsigned compaction:1;
unsigned is_compr:1;
struct tgl_swsb depinfo;
};
struct msgdesc {
unsigned ex_bso:1;
unsigned src1_len:5;
};
enum instr_label_type {
INSTR_LABEL_JIP,
INSTR_LABEL_UIP,
};
struct instr_label {
struct list_head link;
char *name;
int offset;
enum instr_label_type type;
};
struct target_label {
struct list_head link;
char *name;
int offset;
};
brw_assemble_result brw_assemble(
void *mem_ctx, const struct intel_device_info *devinfo,
FILE *f, const char *filename, brw_assemble_flags flags);
#endif /* BRW_ASM_H */

View file

@ -0,0 +1,106 @@
/*
* Copyright © 2018 Intel Corporation
* SPDX-License-Identifier: MIT
*/
#ifndef BRW_ASM_INTERNAL_H
#define BRW_ASM_INTERNAL_H
/* Assembler internal state and definitions used by the brw_gram/brw_lex. */
#include <inttypes.h>
#include <stdbool.h>
#include <assert.h>
#include "compiler/brw_reg.h"
#include "compiler/brw_reg_type.h"
#include "compiler/brw_eu_defines.h"
#include "compiler/brw_inst.h"
#include "compiler/brw_eu.h"
#include "dev/intel_device_info.h"
#include "util/list.h"
/* glibc < 2.27 defines OVERFLOW in /usr/include/math.h. */
#undef OVERFLOW
int yyparse(void);
int yylex(void);
char *lex_text(void);
extern struct brw_codegen *p;
extern int errors;
extern const char *input_filename;
extern struct list_head instr_labels;
extern struct list_head target_labels;
struct condition {
unsigned cond_modifier:4;
unsigned flag_reg_nr:1;
unsigned flag_subreg_nr:1;
};
struct predicate {
unsigned pred_control:4;
unsigned pred_inv:1;
unsigned flag_reg_nr:1;
unsigned flag_subreg_nr:1;
};
enum instoption_type {
INSTOPTION_FLAG,
INSTOPTION_DEP_INFO,
INSTOPTION_CHAN_OFFSET,
};
struct instoption {
enum instoption_type type;
union {
unsigned uint_value;
struct tgl_swsb depinfo_value;
};
};
struct options {
uint8_t chan_offset;
unsigned access_mode:1;
unsigned compression_control:2;
unsigned thread_control:2;
unsigned no_dd_check:1; // Dependency control
unsigned no_dd_clear:1; // Dependency control
unsigned mask_control:1;
unsigned debug_control:1;
unsigned acc_wr_control:1;
unsigned end_of_thread:1;
unsigned compaction:1;
unsigned is_compr:1;
struct tgl_swsb depinfo;
};
struct msgdesc {
unsigned ex_bso:1;
unsigned src1_len:5;
};
enum instr_label_type {
INSTR_LABEL_JIP,
INSTR_LABEL_UIP,
};
struct instr_label {
struct list_head link;
char *name;
int offset;
enum instr_label_type type;
};
struct target_label {
struct list_head link;
char *name;
int offset;
};
#endif /* BRW_ASM_H */

View file

@ -23,9 +23,14 @@
*/
#include <stdio.h>
#include <string.h>
#include <getopt.h>
#include "util/ralloc.h"
#include "compiler/brw_inst.h"
#include "dev/intel_device_info.h"
#include "brw_asm.h"
#include "intel/compiler/brw_disasm_info.h"
enum opt_output_type {
OPT_OUTPUT_HEX,
@ -33,14 +38,7 @@ enum opt_output_type {
OPT_OUTPUT_BIN,
};
extern FILE *yyin;
struct brw_codegen *p;
static enum opt_output_type output_type = OPT_OUTPUT_BIN;
char *input_filename = NULL;
int errors;
struct list_head instr_labels;
struct list_head target_labels;
static void
print_help(const char *progname, FILE *file)
@ -127,91 +125,20 @@ i965_asm_init(uint16_t pci_id)
return devinfo;
}
static bool
i965_postprocess_labels()
{
void *store = p->store;
struct target_label *tlabel;
struct instr_label *ilabel, *s;
const unsigned to_bytes_scale = brw_jump_scale(p->devinfo);
LIST_FOR_EACH_ENTRY(tlabel, &target_labels, link) {
LIST_FOR_EACH_ENTRY_SAFE(ilabel, s, &instr_labels, link) {
if (!strcmp(tlabel->name, ilabel->name)) {
brw_inst *inst = store + ilabel->offset;
int relative_offset = (tlabel->offset - ilabel->offset) / sizeof(brw_inst);
relative_offset *= to_bytes_scale;
unsigned opcode = brw_inst_opcode(p->isa, inst);
if (ilabel->type == INSTR_LABEL_JIP) {
switch (opcode) {
case BRW_OPCODE_IF:
case BRW_OPCODE_ELSE:
case BRW_OPCODE_ENDIF:
case BRW_OPCODE_WHILE:
brw_inst_set_jip(p->devinfo, inst, relative_offset);
break;
case BRW_OPCODE_BREAK:
case BRW_OPCODE_HALT:
case BRW_OPCODE_CONTINUE:
brw_inst_set_jip(p->devinfo, inst, relative_offset);
break;
default:
fprintf(stderr, "Unknown opcode %d with JIP label\n", opcode);
return false;
}
} else {
switch (opcode) {
case BRW_OPCODE_IF:
case BRW_OPCODE_ELSE:
brw_inst_set_uip(p->devinfo, inst, relative_offset);
break;
case BRW_OPCODE_WHILE:
case BRW_OPCODE_ENDIF:
fprintf(stderr, "WHILE/ENDIF cannot have UIP offset\n");
return false;
case BRW_OPCODE_BREAK:
case BRW_OPCODE_CONTINUE:
case BRW_OPCODE_HALT:
brw_inst_set_uip(p->devinfo, inst, relative_offset);
break;
default:
fprintf(stderr, "Unknown opcode %d with UIP label\n", opcode);
return false;
}
}
list_del(&ilabel->link);
}
}
}
LIST_FOR_EACH_ENTRY(ilabel, &instr_labels, link) {
fprintf(stderr, "Unknown label '%s'\n", ilabel->name);
}
return list_is_empty(&instr_labels);
}
int main(int argc, char **argv)
{
void *mem_ctx = ralloc_context(NULL);
FILE *input_file = NULL;
char *output_file = NULL;
char c;
FILE *output = stdout;
bool help = false, compact = false;
void *store;
uint64_t pci_id = 0;
int offset = 0, err;
int start_offset = 0;
struct disasm_info *disasm_info;
int offset = 0;
struct intel_device_info *devinfo = NULL;
int result = EXIT_FAILURE;
list_inithead(&instr_labels);
list_inithead(&target_labels);
const struct option i965_asm_opts[] = {
{ "help", no_argument, (int *) &help, true },
@ -279,11 +206,11 @@ int main(int argc, char **argv)
goto end;
}
input_filename = strdup(argv[optind]);
yyin = fopen(input_filename, "r");
if (!yyin) {
const char *filename = argv[optind];
input_file = fopen(filename, "r");
if (!input_file) {
fprintf(stderr, "Unable to read input file : %s\n",
input_filename);
filename);
goto end;
}
@ -302,43 +229,19 @@ int main(int argc, char **argv)
goto end;
}
struct brw_isa_info isa;
brw_init_isa_info(&isa, devinfo);
p = rzalloc(NULL, struct brw_codegen);
brw_init_codegen(&isa, p, p);
err = yyparse();
if (err || errors)
brw_assemble_result r = brw_assemble(mem_ctx, devinfo, input_file, filename,
compact ? BRW_ASSEMBLE_COMPACT : 0);
if (!r.bin)
goto end;
if (!i965_postprocess_labels())
goto end;
store = p->store;
disasm_info = disasm_initialize(p->isa, NULL);
if (!disasm_info) {
fprintf(stderr, "Unable to initialize disasm_info struct instance\n");
goto end;
}
if (output_type == OPT_OUTPUT_C_LITERAL)
fprintf(output, "{\n");
brw_validate_instructions(p->isa, p->store, 0,
p->next_insn_offset, disasm_info);
const int nr_insn = (p->next_insn_offset - start_offset) / 16;
if (compact)
brw_compact_instructions(p, start_offset, disasm_info);
for (int i = 0; i < nr_insn; i++) {
const brw_inst *insn = store + offset;
for (int i = 0; i < r.inst_count; i++) {
const brw_inst *insn = r.bin + offset;
bool compacted = false;
if (compact && brw_inst_cmpt_control(p->devinfo, insn)) {
if (compact && brw_inst_cmpt_control(devinfo, insn)) {
offset += 8;
compacted = true;
} else {
@ -348,8 +251,6 @@ int main(int argc, char **argv)
print_instruction(output, compacted, insn);
}
ralloc_free(disasm_info);
if (output_type == OPT_OUTPUT_C_LITERAL)
fprintf(output, "}");
@ -357,17 +258,15 @@ int main(int argc, char **argv)
goto end;
end:
free(input_filename);
free(output_file);
if (yyin)
fclose(yyin);
if (input_file)
fclose(input_file);
if (output)
fclose(output);
if (p)
ralloc_free(p);
ralloc_free(mem_ctx);
if (devinfo)
free(devinfo);

View file

@ -26,7 +26,7 @@
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "brw_asm.h"
#include "brw_asm_internal.h"
#undef yyerror
#ifdef YYBYACC

View file

@ -2,7 +2,7 @@
%option nounput
%{
#include <string.h>
#include "brw_asm.h"
#include "brw_asm_internal.h"
#undef ALIGN16
#include "brw_gram.tab.h"
@ -10,7 +10,7 @@
int yycolumn = 1;
int saved_state = 0;
extern char *input_filename;
extern const char *input_filename;
#define YY_NO_INPUT
#define YY_USER_ACTION \

View file

@ -242,11 +242,32 @@ brw_lex_yy_c = custom_target(
command : [prog_flex, '-o', '@OUTPUT@', '@INPUT@']
)
brw_asm_deps = [
dep_thread,
idep_intel_compiler_brw,
idep_intel_dev,
idep_mesautil,
]
brw_asm = static_library(
'brw_asm',
['brw_asm.c', brw_gram_tab[0], brw_gram_tab[1], brw_lex_yy_c],
dependencies : brw_asm_deps,
include_directories : [inc_include, inc_src, inc_intel],
c_args : [no_override_init_args],
gnu_symbol_visibility : 'hidden',
build_by_default : false,
)
idep_brw_asm = declare_dependency(
link_with : brw_asm,
dependencies : brw_asm_deps,
)
brw_asm_tool = executable(
'brw_asm',
['brw_asm_tool.c', brw_gram_tab[0], brw_gram_tab[1], brw_lex_yy_c],
dependencies : [idep_mesautil, dep_thread, idep_intel_dev,
idep_intel_compiler_brw],
['brw_asm_tool.c'],
dependencies : idep_brw_asm,
include_directories : [inc_include, inc_src, inc_intel],
c_args : [no_override_init_args],
gnu_symbol_visibility : 'hidden',