blob: 1f8bd12680ec30910d49b67ab68c0c763a6d2b79 [file] [log] [blame]
/*
* Copyright (C) 2018-2019 Alyssa Rosenzweig <alyssa@rosenzweig.io>
*
* 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.
*/
#include "compiler.h"
#include "helpers.h"
#include "midgard_ops.h"
/* Pretty printer for Midgard IR, for use debugging compiler-internal
* passes like register allocation. The output superficially resembles
* Midgard assembly, with the exception that unit information and such is
* (normally) omitted, and generic indices are usually used instead of
* registers */
static void
mir_print_index(int source)
{
if (source < 0) {
printf("_");
return;
}
if (source >= SSA_FIXED_MINIMUM) {
/* Specific register */
int reg = SSA_REG_FROM_FIXED(source);
/* TODO: Moving threshold */
if (reg > 16 && reg < 24)
printf("u%d", 23 - reg);
else
printf("r%d", reg);
} else {
printf("%d", source);
}
}
static const char components[16] = "xyzwefghijklmnop";
static void
mir_print_mask(unsigned mask)
{
printf(".");
for (unsigned i = 0; i < 16; ++i) {
if (mask & (1 << i))
putchar(components[i]);
}
}
static const char *
mir_get_unit(unsigned unit)
{
switch (unit) {
case ALU_ENAB_VEC_MUL:
return "vmul";
case ALU_ENAB_SCAL_ADD:
return "sadd";
case ALU_ENAB_VEC_ADD:
return "vadd";
case ALU_ENAB_SCAL_MUL:
return "smul";
case ALU_ENAB_VEC_LUT:
return "lut";
case ALU_ENAB_BR_COMPACT:
return "br";
case ALU_ENAB_BRANCH:
return "brx";
default:
return "???";
}
}
void
mir_print_instruction(midgard_instruction *ins)
{
printf("\t");
switch (ins->type) {
case TAG_ALU_4: {
midgard_alu_op op = ins->alu.op;
const char *name = alu_opcode_props[op].name;
if (ins->unit)
printf("%s.", mir_get_unit(ins->unit));
printf("%s", name ? name : "??");
break;
}
case TAG_LOAD_STORE_4: {
midgard_load_store_op op = ins->load_store.op;
const char *name = load_store_opcode_names[op];
assert(name);
printf("%s", name);
break;
}
case TAG_TEXTURE_4: {
printf("texture");
break;
}
default:
assert(0);
}
if (ins->invert)
printf(".not");
ssa_args *args = &ins->ssa_args;
printf(" ");
mir_print_index(args->dest);
if (ins->mask != 0xF)
mir_print_mask(ins->mask);
printf(", ");
mir_print_index(args->src[0]);
printf(", ");
if (args->inline_constant)
printf("#%d", ins->inline_constant);
else
mir_print_index(args->src[1]);
printf(", ");
mir_print_index(args->src[2]);
if (ins->has_constants)
printf(" <%f, %f, %f, %f>", ins->constants[0], ins->constants[1], ins->constants[2], ins->constants[3]);
if (ins->no_spill)
printf(" /* no spill */");
printf("\n");
}
/* Dumps MIR for a block or entire shader respective */
void
mir_print_block(midgard_block *block)
{
printf("block%d: {\n", block->source_id);
mir_foreach_instr_in_block(block, ins) {
mir_print_instruction(ins);
}
printf("}");
if (block->nr_successors) {
printf(" -> ");
for (unsigned i = 0; i < block->nr_successors; ++i) {
printf("block%d%s", block->successors[i]->source_id,
(i + 1) != block->nr_successors ? ", " : "");
}
}
printf(" from { ");
mir_foreach_predecessor(block, pred)
printf("block%d ", pred->source_id);
printf("}");
printf("\n\n");
}
void
mir_print_shader(compiler_context *ctx)
{
mir_foreach_block(ctx, block) {
mir_print_block(block);
}
}
void
mir_print_bundle(midgard_bundle *bundle)
{
printf("[\n");
for (unsigned i = 0; i < bundle->instruction_count; ++i) {
midgard_instruction *ins = bundle->instructions[i];
mir_print_instruction(ins);
}
printf("]\n");
}