zig/src/ir_print.cpp

311 lines
11 KiB
C++
Raw Normal View History

#include "ir_print.hpp"
struct IrPrint {
FILE *f;
int indent;
int indent_size;
};
static void ir_print_indent(IrPrint *irp) {
for (int i = 0; i < irp->indent; i += 1) {
fprintf(irp->f, " ");
}
}
static void ir_print_prefix(IrPrint *irp, IrInstruction *instruction) {
ir_print_indent(irp);
fprintf(irp->f, "#%-3zu| ", instruction->debug_id);
}
static void ir_print_return(IrPrint *irp, IrInstructionReturn *return_instruction) {
ir_print_prefix(irp, &return_instruction->base);
assert(return_instruction->value);
2016-10-09 14:20:01 +08:00
fprintf(irp->f, "return #%zu\n", return_instruction->value->debug_id);
}
static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction) {
ir_print_prefix(irp, &const_instruction->base);
2016-10-03 11:48:48 +08:00
TypeTableEntry *type_entry = const_instruction->base.type_entry;
fprintf(irp->f, "%s ", buf_ptr(&type_entry->name));
switch (type_entry->id) {
case TypeTableEntryIdInvalid:
zig_unreachable();
case TypeTableEntryIdVoid:
2016-10-03 11:48:48 +08:00
fprintf(irp->f, "%s\n", "void");
break;
2016-10-03 11:48:48 +08:00
case TypeTableEntryIdNumLitFloat:
fprintf(irp->f, "%f\n", const_instruction->base.static_value.data.x_bignum.data.x_float);
break;
case TypeTableEntryIdNumLitInt:
{
BigNum *bignum = &const_instruction->base.static_value.data.x_bignum;
const char *negative_str = bignum->is_negative ? "-" : "";
fprintf(irp->f, "%s%llu\n", negative_str, bignum->data.x_uint);
break;
}
case TypeTableEntryIdMetaType:
2016-10-09 14:20:01 +08:00
fprintf(irp->f, "%s\n", buf_ptr(&const_instruction->base.static_value.data.x_type->name));
break;
2016-10-12 11:45:33 +08:00
case TypeTableEntryIdInt:
{
BigNum *bignum = &const_instruction->base.static_value.data.x_bignum;
assert(bignum->kind == BigNumKindInt);
const char *negative_str = bignum->is_negative ? "-" : "";
fprintf(irp->f, "%s%llu\n", negative_str, bignum->data.x_uint);
}
break;
2016-10-09 14:20:01 +08:00
case TypeTableEntryIdVar:
case TypeTableEntryIdBool:
case TypeTableEntryIdUnreachable:
case TypeTableEntryIdFloat:
case TypeTableEntryIdPointer:
case TypeTableEntryIdArray:
case TypeTableEntryIdStruct:
case TypeTableEntryIdUndefLit:
case TypeTableEntryIdNullLit:
case TypeTableEntryIdMaybe:
case TypeTableEntryIdErrorUnion:
case TypeTableEntryIdPureError:
case TypeTableEntryIdEnum:
case TypeTableEntryIdUnion:
case TypeTableEntryIdFn:
case TypeTableEntryIdTypeDecl:
case TypeTableEntryIdNamespace:
case TypeTableEntryIdBlock:
case TypeTableEntryIdGenericFn:
zig_panic("TODO render more constant types in IR printer");
}
}
2016-10-03 11:48:48 +08:00
static const char *ir_bin_op_id_str(IrBinOp op_id) {
switch (op_id) {
case IrBinOpInvalid:
zig_unreachable();
case IrBinOpBoolOr:
return "BoolOr";
case IrBinOpBoolAnd:
return "BoolAnd";
case IrBinOpCmpEq:
return "==";
case IrBinOpCmpNotEq:
return "!=";
case IrBinOpCmpLessThan:
return "<";
case IrBinOpCmpGreaterThan:
return ">";
case IrBinOpCmpLessOrEq:
return "<=";
case IrBinOpCmpGreaterOrEq:
return ">=";
case IrBinOpBinOr:
return "|";
case IrBinOpBinXor:
return "^";
case IrBinOpBinAnd:
return "&";
case IrBinOpBitShiftLeft:
return "<<";
case IrBinOpBitShiftLeftWrap:
return "<<%";
case IrBinOpBitShiftRight:
return ">>";
case IrBinOpAdd:
return "+";
case IrBinOpAddWrap:
return "+%";
case IrBinOpSub:
return "-";
case IrBinOpSubWrap:
return "-%";
case IrBinOpMult:
return "*";
case IrBinOpMultWrap:
return "*%";
case IrBinOpDiv:
return "/";
case IrBinOpMod:
return "%";
case IrBinOpArrayCat:
return "++";
case IrBinOpArrayMult:
return "**";
}
zig_unreachable();
}
2016-10-12 11:45:33 +08:00
static const char *ir_un_op_id_str(IrUnOp op_id) {
switch (op_id) {
case IrUnOpInvalid:
zig_unreachable();
case IrUnOpBoolNot:
return "!";
case IrUnOpBinNot:
return "~";
case IrUnOpNegation:
return "-";
case IrUnOpNegationWrap:
return "-%";
case IrUnOpAddressOf:
return "&";
case IrUnOpConstAddressOf:
return "&const";
case IrUnOpDereference:
return "*";
case IrUnOpMaybe:
return "?";
case IrUnOpError:
return "%";
case IrUnOpUnwrapError:
return "%%";
case IrUnOpUnwrapMaybe:
return "??";
case IrUnOpMaybeReturn:
return "?return";
case IrUnOpErrorReturn:
return "%return";
}
zig_unreachable();
}
static void ir_print_un_op(IrPrint *irp, IrInstructionUnOp *un_op_instruction) {
ir_print_prefix(irp, &un_op_instruction->base);
fprintf(irp->f, "%s #%zu\n",
ir_un_op_id_str(un_op_instruction->op_id),
un_op_instruction->value->debug_id);
}
2016-10-03 11:48:48 +08:00
static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction) {
ir_print_prefix(irp, &bin_op_instruction->base);
fprintf(irp->f, "#%zu %s #%zu\n",
bin_op_instruction->op1->debug_id,
ir_bin_op_id_str(bin_op_instruction->op_id),
bin_op_instruction->op2->debug_id);
}
static void ir_print_load_var(IrPrint *irp, IrInstructionLoadVar *load_var_instruction) {
ir_print_prefix(irp, &load_var_instruction->base);
fprintf(irp->f, "%s\n",
buf_ptr(&load_var_instruction->var->name));
}
2016-10-09 14:20:01 +08:00
static void ir_print_cast(IrPrint *irp, IrInstructionCast *cast_instruction) {
ir_print_prefix(irp, &cast_instruction->base);
fprintf(irp->f, "cast #%zu to #%zu\n",
cast_instruction->value->debug_id,
cast_instruction->dest_type->debug_id);
}
static void ir_print_call(IrPrint *irp, IrInstructionCall *call_instruction) {
ir_print_prefix(irp, &call_instruction->base);
fprintf(irp->f, "#%zu(", call_instruction->fn->debug_id);
for (size_t i = 0; i < call_instruction->arg_count; i += 1) {
IrInstruction *arg = call_instruction->args[i];
if (i != 0)
fprintf(irp->f, ", ");
fprintf(irp->f, "#%zu", arg->debug_id);
}
fprintf(irp->f, ")\n");
}
2016-10-12 11:45:33 +08:00
static void ir_print_builtin_call(IrPrint *irp, IrInstructionBuiltinCall *call_instruction) {
ir_print_prefix(irp, &call_instruction->base);
fprintf(irp->f, "@%s(", buf_ptr(&call_instruction->fn->name));
for (size_t i = 0; i < call_instruction->fn->param_count; i += 1) {
IrInstruction *arg = call_instruction->args[i];
if (i != 0)
fprintf(irp->f, ", ");
fprintf(irp->f, "#%zu", arg->debug_id);
}
fprintf(irp->f, ")\n");
}
static void ir_print_cond_br(IrPrint *irp, IrInstructionCondBr *cond_br_instruction) {
ir_print_prefix(irp, &cond_br_instruction->base);
fprintf(irp->f, "if #%zu then $%s_%zu else $%s_%zu\n",
cond_br_instruction->condition->debug_id,
cond_br_instruction->then_block->name_hint, cond_br_instruction->then_block->debug_id,
cond_br_instruction->else_block->name_hint, cond_br_instruction->else_block->debug_id);
}
static void ir_print_br(IrPrint *irp, IrInstructionBr *br_instruction) {
ir_print_prefix(irp, &br_instruction->base);
fprintf(irp->f, "goto $%s_%zu\n",
br_instruction->dest_block->name_hint, br_instruction->dest_block->debug_id);
}
static void ir_print_phi(IrPrint *irp, IrInstructionPhi *phi_instruction) {
ir_print_prefix(irp, &phi_instruction->base);
for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) {
IrBasicBlock *incoming_block = phi_instruction->incoming_blocks[i];
IrInstruction *incoming_value = phi_instruction->incoming_values[i];
if (i != 0)
fprintf(irp->f, " ");
fprintf(irp->f, "$%s_%zu:#%zu",
incoming_block->name_hint, incoming_block->debug_id,
incoming_value->debug_id);
}
fprintf(irp->f, "\n");
}
2016-10-03 11:48:48 +08:00
static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
switch (instruction->id) {
case IrInstructionIdInvalid:
zig_unreachable();
case IrInstructionIdReturn:
ir_print_return(irp, (IrInstructionReturn *)instruction);
break;
case IrInstructionIdConst:
ir_print_const(irp, (IrInstructionConst *)instruction);
break;
case IrInstructionIdBinOp:
ir_print_bin_op(irp, (IrInstructionBinOp *)instruction);
break;
case IrInstructionIdLoadVar:
ir_print_load_var(irp, (IrInstructionLoadVar *)instruction);
break;
2016-10-09 14:20:01 +08:00
case IrInstructionIdCast:
ir_print_cast(irp, (IrInstructionCast *)instruction);
break;
case IrInstructionIdCall:
ir_print_call(irp, (IrInstructionCall *)instruction);
break;
2016-10-12 11:45:33 +08:00
case IrInstructionIdUnOp:
ir_print_un_op(irp, (IrInstructionUnOp *)instruction);
break;
2016-10-03 11:48:48 +08:00
case IrInstructionIdCondBr:
2016-10-12 11:45:33 +08:00
ir_print_cond_br(irp, (IrInstructionCondBr *)instruction);
break;
case IrInstructionIdBr:
ir_print_br(irp, (IrInstructionBr *)instruction);
break;
case IrInstructionIdBuiltinCall:
ir_print_builtin_call(irp, (IrInstructionBuiltinCall *)instruction);
break;
2016-10-03 11:48:48 +08:00
case IrInstructionIdPhi:
2016-10-12 11:45:33 +08:00
ir_print_phi(irp, (IrInstructionPhi *)instruction);
break;
case IrInstructionIdSwitchBr:
2016-10-03 11:48:48 +08:00
case IrInstructionIdStoreVar:
zig_panic("TODO print more IR instructions");
}
}
void ir_print(FILE *f, IrExecutable *executable, int indent_size) {
IrPrint ir_print = {};
IrPrint *irp = &ir_print;
irp->f = f;
irp->indent = indent_size;
irp->indent_size = indent_size;
2016-10-06 13:09:01 +08:00
for (size_t bb_i = 0; bb_i < executable->basic_block_list.length; bb_i += 1) {
IrBasicBlock *current_block = executable->basic_block_list.at(bb_i);
2016-10-12 11:45:33 +08:00
fprintf(irp->f, "%s_%zu:\n", current_block->name_hint, current_block->debug_id);
2016-10-06 13:09:01 +08:00
for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) {
IrInstruction *instruction = current_block->instruction_list.at(instr_i);
2016-10-03 11:48:48 +08:00
ir_print_instruction(irp, instruction);
}
}
}