diff --git a/src/intel/compiler/brw_asm.c b/src/intel/compiler/brw_asm.c new file mode 100644 index 00000000000..10793e94a9d --- /dev/null +++ b/src/intel/compiler/brw_asm.c @@ -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; +} + diff --git a/src/intel/compiler/brw_asm.h b/src/intel/compiler/brw_asm.h index 4f1d94158a4..faf723269f0 100644 --- a/src/intel/compiler/brw_asm.h +++ b/src/intel/compiler/brw_asm.h @@ -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 +#include #include -#include -#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 */ diff --git a/src/intel/compiler/brw_asm_internal.h b/src/intel/compiler/brw_asm_internal.h new file mode 100644 index 00000000000..1f45be7b92e --- /dev/null +++ b/src/intel/compiler/brw_asm_internal.h @@ -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 +#include +#include + +#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 */ + diff --git a/src/intel/compiler/brw_asm_tool.c b/src/intel/compiler/brw_asm_tool.c index e5a0dc9c186..b5d9886bc63 100644 --- a/src/intel/compiler/brw_asm_tool.c +++ b/src/intel/compiler/brw_asm_tool.c @@ -23,9 +23,14 @@ */ #include +#include #include + +#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); diff --git a/src/intel/compiler/brw_gram.y b/src/intel/compiler/brw_gram.y index b747cf21ebc..25daee0d382 100644 --- a/src/intel/compiler/brw_gram.y +++ b/src/intel/compiler/brw_gram.y @@ -26,7 +26,7 @@ #include #include #include -#include "brw_asm.h" +#include "brw_asm_internal.h" #undef yyerror #ifdef YYBYACC diff --git a/src/intel/compiler/brw_lex.l b/src/intel/compiler/brw_lex.l index 63fe5aaaf53..2451f09bad7 100644 --- a/src/intel/compiler/brw_lex.l +++ b/src/intel/compiler/brw_lex.l @@ -2,7 +2,7 @@ %option nounput %{ #include -#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 \ diff --git a/src/intel/compiler/meson.build b/src/intel/compiler/meson.build index 6c792e3b574..344344d2d2d 100644 --- a/src/intel/compiler/meson.build +++ b/src/intel/compiler/meson.build @@ -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',