2016-12-05 10:06:13 +08:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2016 Andrew Kelley
|
|
|
|
*
|
|
|
|
* This file is part of zig, which is MIT licensed.
|
|
|
|
* See http://opensource.org/licenses/MIT
|
|
|
|
*/
|
|
|
|
|
2016-10-16 14:19:01 +08:00
|
|
|
#include "ir.hpp"
|
2016-10-01 08:12:00 +08:00
|
|
|
#include "ir_print.hpp"
|
|
|
|
|
|
|
|
struct IrPrint {
|
|
|
|
FILE *f;
|
|
|
|
int indent;
|
|
|
|
int indent_size;
|
|
|
|
};
|
|
|
|
|
2016-11-28 15:40:01 +08:00
|
|
|
static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction);
|
|
|
|
|
2016-10-01 08:12:00 +08:00
|
|
|
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);
|
2016-10-16 14:19:01 +08:00
|
|
|
const char *type_name = instruction->type_entry ? buf_ptr(&instruction->type_entry->name) : "(unknown)";
|
|
|
|
const char *ref_count = ir_has_side_effects(instruction) ?
|
|
|
|
"-" : buf_ptr(buf_sprintf("%zu", instruction->ref_count));
|
|
|
|
fprintf(irp->f, "#%-3zu| %-12s| %-2s| ", instruction->debug_id, type_name, ref_count);
|
2016-10-01 08:12:00 +08:00
|
|
|
}
|
|
|
|
|
2016-10-23 12:21:29 +08:00
|
|
|
static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, ConstExprValue *const_val) {
|
2016-10-30 14:46:16 +08:00
|
|
|
switch (const_val->special) {
|
2016-11-17 17:00:02 +08:00
|
|
|
case ConstValSpecialRuntime:
|
|
|
|
zig_unreachable();
|
2016-10-30 14:46:16 +08:00
|
|
|
case ConstValSpecialUndef:
|
|
|
|
fprintf(irp->f, "undefined");
|
|
|
|
return;
|
|
|
|
case ConstValSpecialZeroes:
|
|
|
|
fprintf(irp->f, "zeroes");
|
|
|
|
return;
|
2016-11-17 17:00:02 +08:00
|
|
|
case ConstValSpecialStatic:
|
2016-10-30 14:46:16 +08:00
|
|
|
break;
|
|
|
|
}
|
2016-10-03 11:48:48 +08:00
|
|
|
switch (type_entry->id) {
|
2016-11-28 15:40:01 +08:00
|
|
|
case TypeTableEntryIdTypeDecl:
|
|
|
|
return ir_print_const_value(irp, type_entry->data.type_decl.canonical_type, const_val);
|
2016-10-01 08:12:00 +08:00
|
|
|
case TypeTableEntryIdInvalid:
|
2016-11-20 15:11:36 +08:00
|
|
|
fprintf(irp->f, "(invalid)");
|
2016-11-28 15:40:01 +08:00
|
|
|
return;
|
|
|
|
case TypeTableEntryIdVar:
|
|
|
|
fprintf(irp->f, "(var)");
|
|
|
|
return;
|
2016-10-01 08:12:00 +08:00
|
|
|
case TypeTableEntryIdVoid:
|
2016-10-16 14:19:01 +08:00
|
|
|
fprintf(irp->f, "{}");
|
2016-11-28 15:40:01 +08:00
|
|
|
return;
|
2016-10-03 11:48:48 +08:00
|
|
|
case TypeTableEntryIdNumLitFloat:
|
2016-10-23 12:21:29 +08:00
|
|
|
fprintf(irp->f, "%f", const_val->data.x_bignum.data.x_float);
|
2016-11-28 15:40:01 +08:00
|
|
|
return;
|
2016-10-03 11:48:48 +08:00
|
|
|
case TypeTableEntryIdNumLitInt:
|
|
|
|
{
|
2016-10-23 12:21:29 +08:00
|
|
|
BigNum *bignum = &const_val->data.x_bignum;
|
2016-10-03 11:48:48 +08:00
|
|
|
const char *negative_str = bignum->is_negative ? "-" : "";
|
2016-10-16 14:19:01 +08:00
|
|
|
fprintf(irp->f, "%s%llu", negative_str, bignum->data.x_uint);
|
2016-11-28 15:40:01 +08:00
|
|
|
return;
|
2016-10-03 11:48:48 +08:00
|
|
|
}
|
2016-10-01 08:12:00 +08:00
|
|
|
case TypeTableEntryIdMetaType:
|
2016-10-23 12:21:29 +08:00
|
|
|
fprintf(irp->f, "%s", buf_ptr(&const_val->data.x_type->name));
|
2016-11-28 15:40:01 +08:00
|
|
|
return;
|
2016-10-12 11:45:33 +08:00
|
|
|
case TypeTableEntryIdInt:
|
|
|
|
{
|
2016-10-23 12:21:29 +08:00
|
|
|
BigNum *bignum = &const_val->data.x_bignum;
|
2016-10-12 11:45:33 +08:00
|
|
|
assert(bignum->kind == BigNumKindInt);
|
|
|
|
const char *negative_str = bignum->is_negative ? "-" : "";
|
2016-10-16 14:19:01 +08:00
|
|
|
fprintf(irp->f, "%s%llu", negative_str, bignum->data.x_uint);
|
2016-10-12 11:45:33 +08:00
|
|
|
}
|
2016-11-28 15:40:01 +08:00
|
|
|
return;
|
|
|
|
case TypeTableEntryIdFloat:
|
|
|
|
{
|
|
|
|
BigNum *bignum = &const_val->data.x_bignum;
|
|
|
|
assert(bignum->kind == BigNumKindFloat);
|
|
|
|
fprintf(irp->f, "%f", bignum->data.x_float);
|
|
|
|
}
|
|
|
|
return;
|
2016-10-16 14:19:01 +08:00
|
|
|
case TypeTableEntryIdUnreachable:
|
|
|
|
fprintf(irp->f, "@unreachable()");
|
2016-11-28 15:40:01 +08:00
|
|
|
return;
|
2016-10-01 08:12:00 +08:00
|
|
|
case TypeTableEntryIdBool:
|
2016-10-23 12:21:29 +08:00
|
|
|
{
|
|
|
|
const char *value = const_val->data.x_bool ? "true" : "false";
|
|
|
|
fprintf(irp->f, "%s", value);
|
2016-11-28 15:40:01 +08:00
|
|
|
return;
|
2016-10-23 12:21:29 +08:00
|
|
|
}
|
2016-10-01 08:12:00 +08:00
|
|
|
case TypeTableEntryIdPointer:
|
2016-10-23 12:21:29 +08:00
|
|
|
fprintf(irp->f, "&");
|
2016-11-17 17:00:02 +08:00
|
|
|
ir_print_const_value(irp, type_entry->data.pointer.child_type, const_ptr_pointee(const_val));
|
2016-11-28 15:40:01 +08:00
|
|
|
return;
|
2016-10-27 13:08:06 +08:00
|
|
|
case TypeTableEntryIdFn:
|
|
|
|
{
|
|
|
|
FnTableEntry *fn_entry = const_val->data.x_fn;
|
|
|
|
fprintf(irp->f, "%s", buf_ptr(&fn_entry->symbol_name));
|
2016-11-28 15:40:01 +08:00
|
|
|
return;
|
2016-10-27 13:08:06 +08:00
|
|
|
}
|
2016-11-05 03:36:30 +08:00
|
|
|
case TypeTableEntryIdBlock:
|
|
|
|
{
|
2016-12-06 07:43:16 +08:00
|
|
|
AstNode *node = const_val->data.x_block->source_node;
|
2016-11-05 03:36:30 +08:00
|
|
|
fprintf(irp->f, "(scope:%zu:%zu)", node->line + 1, node->column + 1);
|
2016-11-28 15:40:01 +08:00
|
|
|
return;
|
2016-11-05 03:36:30 +08:00
|
|
|
}
|
2016-11-10 13:41:17 +08:00
|
|
|
case TypeTableEntryIdArray:
|
|
|
|
{
|
|
|
|
uint64_t len = type_entry->data.array.len;
|
|
|
|
fprintf(irp->f, "%s{", buf_ptr(&type_entry->name));
|
|
|
|
for (uint64_t i = 0; i < len; i += 1) {
|
|
|
|
if (i != 0)
|
|
|
|
fprintf(irp->f, ",");
|
2016-11-17 17:00:02 +08:00
|
|
|
ConstExprValue *child_value = &const_val->data.x_array.elements[i];
|
2016-11-10 13:41:17 +08:00
|
|
|
TypeTableEntry *child_type = type_entry->data.array.child_type;
|
|
|
|
ir_print_const_value(irp, child_type, child_value);
|
|
|
|
}
|
|
|
|
fprintf(irp->f, "}");
|
2016-11-28 15:40:01 +08:00
|
|
|
return;
|
2016-11-10 13:41:17 +08:00
|
|
|
}
|
2016-11-19 14:53:14 +08:00
|
|
|
case TypeTableEntryIdNullLit:
|
|
|
|
{
|
|
|
|
fprintf(irp->f, "null");
|
2016-11-28 15:40:01 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
case TypeTableEntryIdUndefLit:
|
|
|
|
{
|
|
|
|
fprintf(irp->f, "undefined");
|
|
|
|
return;
|
2016-11-19 14:53:14 +08:00
|
|
|
}
|
2016-11-19 14:56:48 +08:00
|
|
|
case TypeTableEntryIdMaybe:
|
|
|
|
{
|
|
|
|
if (const_val->data.x_maybe) {
|
|
|
|
ir_print_const_value(irp, type_entry->data.maybe.child_type, const_val->data.x_maybe);
|
|
|
|
} else {
|
|
|
|
fprintf(irp->f, "null");
|
|
|
|
}
|
2016-11-28 15:40:01 +08:00
|
|
|
return;
|
2016-11-19 14:56:48 +08:00
|
|
|
}
|
2016-11-27 09:52:22 +08:00
|
|
|
case TypeTableEntryIdNamespace:
|
|
|
|
{
|
|
|
|
ImportTableEntry *import = const_val->data.x_import;
|
2016-12-11 13:13:43 +08:00
|
|
|
if (import->c_import_node) {
|
|
|
|
fprintf(irp->f, "(namespace from C import)");
|
|
|
|
} else {
|
|
|
|
fprintf(irp->f, "(namespace: %s)", buf_ptr(import->path));
|
|
|
|
}
|
2016-11-28 15:40:01 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
case TypeTableEntryIdBoundFn:
|
|
|
|
{
|
|
|
|
FnTableEntry *fn_entry = const_val->data.x_bound_fn.fn;
|
|
|
|
fprintf(irp->f, "bound %s to ", buf_ptr(&fn_entry->symbol_name));
|
|
|
|
ir_print_other_instruction(irp, const_val->data.x_bound_fn.first_arg);
|
|
|
|
return;
|
2016-11-27 09:52:22 +08:00
|
|
|
}
|
2016-10-01 08:12:00 +08:00
|
|
|
case TypeTableEntryIdStruct:
|
2016-11-28 15:40:01 +08:00
|
|
|
{
|
|
|
|
fprintf(irp->f, "(struct %s constant)", buf_ptr(&type_entry->name));
|
|
|
|
return;
|
|
|
|
}
|
2016-10-01 08:12:00 +08:00
|
|
|
case TypeTableEntryIdEnum:
|
2016-11-28 15:40:01 +08:00
|
|
|
{
|
|
|
|
fprintf(irp->f, "(enum %s constant)", buf_ptr(&type_entry->name));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
case TypeTableEntryIdErrorUnion:
|
|
|
|
{
|
|
|
|
fprintf(irp->f, "(error union %s constant)", buf_ptr(&type_entry->name));
|
|
|
|
return;
|
|
|
|
}
|
2016-10-01 08:12:00 +08:00
|
|
|
case TypeTableEntryIdUnion:
|
2016-11-28 15:40:01 +08:00
|
|
|
{
|
|
|
|
fprintf(irp->f, "(union %s constant)", buf_ptr(&type_entry->name));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
case TypeTableEntryIdPureError:
|
|
|
|
{
|
|
|
|
fprintf(irp->f, "(pure error constant)");
|
|
|
|
return;
|
|
|
|
}
|
2016-10-01 08:12:00 +08:00
|
|
|
}
|
2016-11-28 15:40:01 +08:00
|
|
|
zig_unreachable();
|
2016-10-01 08:12:00 +08:00
|
|
|
}
|
|
|
|
|
2016-10-23 12:21:29 +08:00
|
|
|
static void ir_print_const_instruction(IrPrint *irp, IrInstruction *instruction) {
|
|
|
|
TypeTableEntry *type_entry = instruction->type_entry;
|
|
|
|
ConstExprValue *const_val = &instruction->static_value;
|
|
|
|
ir_print_const_value(irp, type_entry, const_val);
|
|
|
|
}
|
|
|
|
|
2016-10-27 15:28:29 +08:00
|
|
|
static void ir_print_var_instruction(IrPrint *irp, IrInstruction *instruction) {
|
|
|
|
fprintf(irp->f, "#%zu", instruction->debug_id);
|
|
|
|
}
|
|
|
|
|
2016-10-16 14:19:01 +08:00
|
|
|
static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction) {
|
2016-11-17 17:00:02 +08:00
|
|
|
if (instruction->static_value.special != ConstValSpecialRuntime) {
|
2016-10-16 14:19:01 +08:00
|
|
|
ir_print_const_instruction(irp, instruction);
|
|
|
|
} else {
|
2016-10-27 15:28:29 +08:00
|
|
|
ir_print_var_instruction(irp, instruction);
|
2016-10-16 14:19:01 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ir_print_other_block(IrPrint *irp, IrBasicBlock *bb) {
|
|
|
|
fprintf(irp->f, "$%s_%zu", bb->name_hint, bb->debug_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ir_print_return(IrPrint *irp, IrInstructionReturn *return_instruction) {
|
|
|
|
assert(return_instruction->value);
|
|
|
|
fprintf(irp->f, "return ");
|
|
|
|
ir_print_other_instruction(irp, return_instruction->value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction) {
|
|
|
|
ir_print_const_instruction(irp, &const_instruction->base);
|
|
|
|
}
|
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 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) {
|
2016-10-16 14:19:01 +08:00
|
|
|
fprintf(irp->f, "%s ", ir_un_op_id_str(un_op_instruction->op_id));
|
|
|
|
ir_print_other_instruction(irp, un_op_instruction->value);
|
2016-10-12 11:45:33 +08:00
|
|
|
}
|
|
|
|
|
2016-10-03 11:48:48 +08:00
|
|
|
static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction) {
|
2016-10-16 14:19:01 +08:00
|
|
|
ir_print_other_instruction(irp, bin_op_instruction->op1);
|
|
|
|
fprintf(irp->f, " %s ", ir_bin_op_id_str(bin_op_instruction->op_id));
|
|
|
|
ir_print_other_instruction(irp, bin_op_instruction->op2);
|
2016-12-08 15:09:26 +08:00
|
|
|
if (!bin_op_instruction->safety_check_on) {
|
|
|
|
fprintf(irp->f, " // no safety");
|
|
|
|
}
|
2016-10-03 11:48:48 +08:00
|
|
|
}
|
|
|
|
|
2016-10-18 15:00:48 +08:00
|
|
|
static void ir_print_decl_var(IrPrint *irp, IrInstructionDeclVar *decl_var_instruction) {
|
2016-11-04 02:13:57 +08:00
|
|
|
const char *inline_kw = decl_var_instruction->var->is_inline ? "inline " : "";
|
|
|
|
const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var";
|
2016-10-18 15:00:48 +08:00
|
|
|
const char *name = buf_ptr(&decl_var_instruction->var->name);
|
|
|
|
if (decl_var_instruction->var_type) {
|
2016-11-04 02:13:57 +08:00
|
|
|
fprintf(irp->f, "%s%s %s: ", inline_kw, var_or_const, name);
|
2016-10-18 15:00:48 +08:00
|
|
|
ir_print_other_instruction(irp, decl_var_instruction->var_type);
|
|
|
|
fprintf(irp->f, " = ");
|
|
|
|
} else {
|
2016-11-04 02:13:57 +08:00
|
|
|
fprintf(irp->f, "%s%s %s = ", inline_kw, var_or_const, name);
|
2016-10-18 15:00:48 +08:00
|
|
|
}
|
|
|
|
ir_print_other_instruction(irp, decl_var_instruction->init_value);
|
|
|
|
}
|
|
|
|
|
2016-10-09 14:20:01 +08:00
|
|
|
static void ir_print_cast(IrPrint *irp, IrInstructionCast *cast_instruction) {
|
2016-10-16 14:19:01 +08:00
|
|
|
fprintf(irp->f, "cast ");
|
|
|
|
ir_print_other_instruction(irp, cast_instruction->value);
|
2016-11-28 15:40:01 +08:00
|
|
|
fprintf(irp->f, " to %s", buf_ptr(&cast_instruction->dest_type->name));
|
2016-10-09 14:20:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void ir_print_call(IrPrint *irp, IrInstructionCall *call_instruction) {
|
2016-11-28 15:40:01 +08:00
|
|
|
if (call_instruction->fn_entry) {
|
|
|
|
fprintf(irp->f, "%s", buf_ptr(&call_instruction->fn_entry->symbol_name));
|
|
|
|
} else {
|
|
|
|
assert(call_instruction->fn_ref);
|
|
|
|
ir_print_other_instruction(irp, call_instruction->fn_ref);
|
|
|
|
}
|
2016-10-16 14:19:01 +08:00
|
|
|
fprintf(irp->f, "(");
|
2016-10-09 14:20:01 +08:00
|
|
|
for (size_t i = 0; i < call_instruction->arg_count; i += 1) {
|
|
|
|
IrInstruction *arg = call_instruction->args[i];
|
|
|
|
if (i != 0)
|
|
|
|
fprintf(irp->f, ", ");
|
2016-10-16 14:19:01 +08:00
|
|
|
ir_print_other_instruction(irp, arg);
|
2016-10-09 14:20:01 +08:00
|
|
|
}
|
2016-10-16 14:19:01 +08:00
|
|
|
fprintf(irp->f, ")");
|
2016-10-09 14:20:01 +08:00
|
|
|
}
|
|
|
|
|
2016-10-12 11:45:33 +08:00
|
|
|
static void ir_print_cond_br(IrPrint *irp, IrInstructionCondBr *cond_br_instruction) {
|
2016-11-04 02:13:57 +08:00
|
|
|
const char *inline_kw = cond_br_instruction->is_inline ? "inline " : "";
|
|
|
|
fprintf(irp->f, "%sif (", inline_kw);
|
2016-10-16 14:19:01 +08:00
|
|
|
ir_print_other_instruction(irp, cond_br_instruction->condition);
|
|
|
|
fprintf(irp->f, ") ");
|
|
|
|
ir_print_other_block(irp, cond_br_instruction->then_block);
|
|
|
|
fprintf(irp->f, " else ");
|
|
|
|
ir_print_other_block(irp, cond_br_instruction->else_block);
|
2016-10-12 11:45:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void ir_print_br(IrPrint *irp, IrInstructionBr *br_instruction) {
|
2016-11-04 02:13:57 +08:00
|
|
|
const char *inline_kw = br_instruction->is_inline ? "inline " : "";
|
|
|
|
fprintf(irp->f, "%sgoto ", inline_kw);
|
2016-10-16 14:19:01 +08:00
|
|
|
ir_print_other_block(irp, br_instruction->dest_block);
|
2016-10-12 11:45:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void ir_print_phi(IrPrint *irp, IrInstructionPhi *phi_instruction) {
|
2016-11-26 13:25:48 +08:00
|
|
|
assert(phi_instruction->incoming_count != 0);
|
|
|
|
assert(phi_instruction->incoming_count != SIZE_MAX);
|
2016-10-12 11:45:33 +08:00
|
|
|
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, " ");
|
2016-10-16 14:19:01 +08:00
|
|
|
ir_print_other_block(irp, incoming_block);
|
|
|
|
fprintf(irp->f, ":");
|
|
|
|
ir_print_other_instruction(irp, incoming_value);
|
2016-10-12 11:45:33 +08:00
|
|
|
}
|
2016-10-16 14:19:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void ir_print_container_init_list(IrPrint *irp, IrInstructionContainerInitList *instruction) {
|
|
|
|
ir_print_other_instruction(irp, instruction->container_type);
|
|
|
|
fprintf(irp->f, "{");
|
|
|
|
for (size_t i = 0; i < instruction->item_count; i += 1) {
|
|
|
|
IrInstruction *item = instruction->items[i];
|
|
|
|
if (i != 0)
|
|
|
|
fprintf(irp->f, ", ");
|
|
|
|
ir_print_other_instruction(irp, item);
|
|
|
|
}
|
|
|
|
fprintf(irp->f, "}");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ir_print_container_init_fields(IrPrint *irp, IrInstructionContainerInitFields *instruction) {
|
|
|
|
ir_print_other_instruction(irp, instruction->container_type);
|
|
|
|
fprintf(irp->f, "{");
|
|
|
|
for (size_t i = 0; i < instruction->field_count; i += 1) {
|
2016-11-28 15:40:01 +08:00
|
|
|
IrInstructionContainerInitFieldsField *field = &instruction->fields[i];
|
2016-10-16 14:19:01 +08:00
|
|
|
const char *comma = (i == 0) ? "" : ", ";
|
2016-11-28 15:40:01 +08:00
|
|
|
fprintf(irp->f, "%s.%s = ", comma, buf_ptr(field->name));
|
|
|
|
ir_print_other_instruction(irp, field->value);
|
2016-10-16 14:19:01 +08:00
|
|
|
}
|
2016-11-28 15:40:01 +08:00
|
|
|
fprintf(irp->f, "} // container init");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ir_print_struct_init(IrPrint *irp, IrInstructionStructInit *instruction) {
|
|
|
|
fprintf(irp->f, "%s {", buf_ptr(&instruction->struct_type->name));
|
|
|
|
for (size_t i = 0; i < instruction->field_count; i += 1) {
|
|
|
|
IrInstructionStructInitField *field = &instruction->fields[i];
|
|
|
|
Buf *field_name = field->type_struct_field->name;
|
|
|
|
const char *comma = (i == 0) ? "" : ", ";
|
|
|
|
fprintf(irp->f, "%s.%s = ", comma, buf_ptr(field_name));
|
|
|
|
ir_print_other_instruction(irp, field->value);
|
|
|
|
}
|
|
|
|
fprintf(irp->f, "} // struct init");
|
2016-10-16 14:19:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void ir_print_unreachable(IrPrint *irp, IrInstructionUnreachable *instruction) {
|
|
|
|
fprintf(irp->f, "unreachable");
|
2016-10-12 11:45:33 +08:00
|
|
|
}
|
|
|
|
|
2016-10-23 12:21:29 +08:00
|
|
|
static void ir_print_elem_ptr(IrPrint *irp, IrInstructionElemPtr *instruction) {
|
2016-10-28 14:32:36 +08:00
|
|
|
fprintf(irp->f, "&");
|
2016-10-23 12:21:29 +08:00
|
|
|
ir_print_other_instruction(irp, instruction->array_ptr);
|
|
|
|
fprintf(irp->f, "[");
|
|
|
|
ir_print_other_instruction(irp, instruction->elem_index);
|
|
|
|
fprintf(irp->f, "]");
|
2016-11-22 04:01:21 +08:00
|
|
|
if (!instruction->safety_check_on) {
|
|
|
|
fprintf(irp->f, " // no safety");
|
|
|
|
}
|
2016-10-23 12:21:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void ir_print_var_ptr(IrPrint *irp, IrInstructionVarPtr *instruction) {
|
|
|
|
fprintf(irp->f, "&%s", buf_ptr(&instruction->var->name));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) {
|
|
|
|
fprintf(irp->f, "*");
|
|
|
|
ir_print_other_instruction(irp, instruction->ptr);
|
2016-10-18 15:00:48 +08:00
|
|
|
}
|
|
|
|
|
2016-10-23 13:33:23 +08:00
|
|
|
static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) {
|
|
|
|
fprintf(irp->f, "*");
|
2016-10-27 15:28:29 +08:00
|
|
|
ir_print_var_instruction(irp, instruction->ptr);
|
2016-10-23 13:33:23 +08:00
|
|
|
fprintf(irp->f, " = ");
|
|
|
|
ir_print_other_instruction(irp, instruction->value);
|
|
|
|
}
|
|
|
|
|
2016-10-30 14:46:16 +08:00
|
|
|
static void ir_print_typeof(IrPrint *irp, IrInstructionTypeOf *instruction) {
|
|
|
|
fprintf(irp->f, "@typeOf(");
|
|
|
|
ir_print_other_instruction(irp, instruction->value);
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ir_print_to_ptr_type(IrPrint *irp, IrInstructionToPtrType *instruction) {
|
|
|
|
fprintf(irp->f, "@toPtrType(");
|
|
|
|
ir_print_other_instruction(irp, instruction->value);
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ir_print_ptr_type_child(IrPrint *irp, IrInstructionPtrTypeChild *instruction) {
|
|
|
|
fprintf(irp->f, "@ptrTypeChild(");
|
|
|
|
ir_print_other_instruction(irp, instruction->value);
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ir_print_field_ptr(IrPrint *irp, IrInstructionFieldPtr *instruction) {
|
2016-11-28 15:40:01 +08:00
|
|
|
fprintf(irp->f, "fieldptr ");
|
2016-10-30 14:46:16 +08:00
|
|
|
ir_print_other_instruction(irp, instruction->container_ptr);
|
|
|
|
fprintf(irp->f, ".%s", buf_ptr(instruction->field_name));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ir_print_struct_field_ptr(IrPrint *irp, IrInstructionStructFieldPtr *instruction) {
|
|
|
|
fprintf(irp->f, "@StructFieldPtr(&");
|
|
|
|
ir_print_other_instruction(irp, instruction->struct_ptr);
|
|
|
|
fprintf(irp->f, ".%s", buf_ptr(instruction->field->name));
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
|
2016-11-28 15:40:01 +08:00
|
|
|
static void ir_print_enum_field_ptr(IrPrint *irp, IrInstructionEnumFieldPtr *instruction) {
|
|
|
|
fprintf(irp->f, "@EnumFieldPtr(&");
|
|
|
|
ir_print_other_instruction(irp, instruction->enum_ptr);
|
|
|
|
fprintf(irp->f, ".%s", buf_ptr(instruction->field->name));
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
|
2016-11-05 03:36:30 +08:00
|
|
|
static void ir_print_set_fn_test(IrPrint *irp, IrInstructionSetFnTest *instruction) {
|
|
|
|
fprintf(irp->f, "@setFnTest(");
|
|
|
|
ir_print_other_instruction(irp, instruction->fn_value);
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
|
2016-11-22 04:36:25 +08:00
|
|
|
static void ir_print_set_fn_visible(IrPrint *irp, IrInstructionSetFnVisible *instruction) {
|
|
|
|
fprintf(irp->f, "@setFnVisible(");
|
|
|
|
ir_print_other_instruction(irp, instruction->fn_value);
|
|
|
|
fprintf(irp->f, ", ");
|
|
|
|
ir_print_other_instruction(irp, instruction->is_visible);
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
|
2016-11-19 09:57:27 +08:00
|
|
|
static void ir_print_set_debug_safety(IrPrint *irp, IrInstructionSetDebugSafety *instruction) {
|
|
|
|
fprintf(irp->f, "@setDebugSafety(");
|
|
|
|
ir_print_other_instruction(irp, instruction->scope_value);
|
|
|
|
fprintf(irp->f, ", ");
|
|
|
|
ir_print_other_instruction(irp, instruction->debug_safety_on);
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
|
2016-11-08 07:58:01 +08:00
|
|
|
static void ir_print_array_type(IrPrint *irp, IrInstructionArrayType *instruction) {
|
|
|
|
fprintf(irp->f, "[");
|
|
|
|
ir_print_other_instruction(irp, instruction->size);
|
|
|
|
fprintf(irp->f, "]");
|
|
|
|
ir_print_other_instruction(irp, instruction->child_type);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ir_print_slice_type(IrPrint *irp, IrInstructionSliceType *instruction) {
|
|
|
|
const char *const_kw = instruction->is_const ? "const " : "";
|
|
|
|
fprintf(irp->f, "[]%s", const_kw);
|
|
|
|
ir_print_other_instruction(irp, instruction->child_type);
|
|
|
|
}
|
|
|
|
|
2016-11-14 10:07:30 +08:00
|
|
|
static void ir_print_asm(IrPrint *irp, IrInstructionAsm *instruction) {
|
|
|
|
assert(instruction->base.source_node->type == NodeTypeAsmExpr);
|
|
|
|
AstNodeAsmExpr *asm_expr = &instruction->base.source_node->data.asm_expr;
|
|
|
|
const char *volatile_kw = instruction->has_side_effects ? " volatile" : "";
|
|
|
|
fprintf(irp->f, "asm%s (\"%s\") : ", volatile_kw, buf_ptr(asm_expr->asm_template));
|
|
|
|
|
|
|
|
for (size_t i = 0; i < asm_expr->output_list.length; i += 1) {
|
|
|
|
AsmOutput *asm_output = asm_expr->output_list.at(i);
|
|
|
|
if (i != 0) fprintf(irp->f, ", ");
|
|
|
|
|
|
|
|
fprintf(irp->f, "[%s] \"%s\" (",
|
|
|
|
buf_ptr(asm_output->asm_symbolic_name),
|
|
|
|
buf_ptr(asm_output->constraint));
|
|
|
|
if (asm_output->return_type) {
|
|
|
|
fprintf(irp->f, "-> ");
|
|
|
|
ir_print_other_instruction(irp, instruction->output_types[i]);
|
|
|
|
} else {
|
|
|
|
fprintf(irp->f, "%s", buf_ptr(asm_output->variable_name));
|
|
|
|
}
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(irp->f, " : ");
|
|
|
|
for (size_t i = 0; i < asm_expr->input_list.length; i += 1) {
|
|
|
|
AsmInput *asm_input = asm_expr->input_list.at(i);
|
|
|
|
|
|
|
|
if (i != 0) fprintf(irp->f, ", ");
|
|
|
|
fprintf(irp->f, "[%s] \"%s\" (",
|
|
|
|
buf_ptr(asm_input->asm_symbolic_name),
|
|
|
|
buf_ptr(asm_input->constraint));
|
|
|
|
ir_print_other_instruction(irp, instruction->input_list[i]);
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
fprintf(irp->f, " : ");
|
|
|
|
for (size_t i = 0; i < asm_expr->clobber_list.length; i += 1) {
|
|
|
|
Buf *reg_name = asm_expr->clobber_list.at(i);
|
|
|
|
if (i != 0) fprintf(irp->f, ", ");
|
|
|
|
fprintf(irp->f, "\"%s\"", buf_ptr(reg_name));
|
|
|
|
}
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
|
2016-11-19 14:39:51 +08:00
|
|
|
static void ir_print_compile_var(IrPrint *irp, IrInstructionCompileVar *instruction) {
|
|
|
|
fprintf(irp->f, "@compileVar(");
|
|
|
|
ir_print_other_instruction(irp, instruction->name);
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
|
2016-11-20 15:11:36 +08:00
|
|
|
static void ir_print_size_of(IrPrint *irp, IrInstructionSizeOf *instruction) {
|
|
|
|
fprintf(irp->f, "@sizeOf(");
|
|
|
|
ir_print_other_instruction(irp, instruction->type_value);
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
|
2016-11-21 16:08:24 +08:00
|
|
|
static void ir_print_test_null(IrPrint *irp, IrInstructionTestNull *instruction) {
|
|
|
|
fprintf(irp->f, "*");
|
|
|
|
ir_print_other_instruction(irp, instruction->value);
|
|
|
|
fprintf(irp->f, " == null");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ir_print_unwrap_maybe(IrPrint *irp, IrInstructionUnwrapMaybe *instruction) {
|
|
|
|
fprintf(irp->f, "&??*");
|
|
|
|
ir_print_other_instruction(irp, instruction->value);
|
|
|
|
if (!instruction->safety_check_on) {
|
|
|
|
fprintf(irp->f, " // no safety");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-22 02:27:44 +08:00
|
|
|
static void ir_print_clz(IrPrint *irp, IrInstructionClz *instruction) {
|
|
|
|
fprintf(irp->f, "@clz(");
|
|
|
|
ir_print_other_instruction(irp, instruction->value);
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ir_print_ctz(IrPrint *irp, IrInstructionCtz *instruction) {
|
|
|
|
fprintf(irp->f, "@ctz(");
|
|
|
|
ir_print_other_instruction(irp, instruction->value);
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
|
2016-11-26 13:25:48 +08:00
|
|
|
static void ir_print_switch_br(IrPrint *irp, IrInstructionSwitchBr *instruction) {
|
|
|
|
const char *inline_kw = instruction->is_inline ? "inline " : "";
|
|
|
|
fprintf(irp->f, "%sswitch (", inline_kw);
|
|
|
|
ir_print_other_instruction(irp, instruction->target_value);
|
|
|
|
fprintf(irp->f, ") ");
|
|
|
|
for (size_t i = 0; i < instruction->case_count; i += 1) {
|
|
|
|
IrInstructionSwitchBrCase *this_case = &instruction->cases[i];
|
|
|
|
ir_print_other_instruction(irp, this_case->value);
|
|
|
|
fprintf(irp->f, " => ");
|
|
|
|
ir_print_other_block(irp, this_case->block);
|
|
|
|
fprintf(irp->f, ", ");
|
|
|
|
}
|
|
|
|
fprintf(irp->f, "else => ");
|
|
|
|
ir_print_other_block(irp, instruction->else_block);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ir_print_switch_var(IrPrint *irp, IrInstructionSwitchVar *instruction) {
|
|
|
|
fprintf(irp->f, "switchvar ");
|
|
|
|
ir_print_other_instruction(irp, instruction->target_value_ptr);
|
|
|
|
fprintf(irp->f, ", ");
|
|
|
|
ir_print_other_instruction(irp, instruction->prong_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ir_print_switch_target(IrPrint *irp, IrInstructionSwitchTarget *instruction) {
|
|
|
|
fprintf(irp->f, "switchtarget ");
|
|
|
|
ir_print_other_instruction(irp, instruction->target_value_ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ir_print_enum_tag(IrPrint *irp, IrInstructionEnumTag *instruction) {
|
|
|
|
fprintf(irp->f, "enumtag ");
|
|
|
|
ir_print_other_instruction(irp, instruction->value);
|
|
|
|
}
|
|
|
|
|
2016-11-26 17:37:34 +08:00
|
|
|
static void ir_print_static_eval(IrPrint *irp, IrInstructionStaticEval *instruction) {
|
|
|
|
fprintf(irp->f, "@staticEval(");
|
|
|
|
ir_print_other_instruction(irp, instruction->value);
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
|
2016-11-27 09:52:22 +08:00
|
|
|
static void ir_print_import(IrPrint *irp, IrInstructionImport *instruction) {
|
|
|
|
fprintf(irp->f, "@import(");
|
|
|
|
ir_print_other_instruction(irp, instruction->name);
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ir_print_array_len(IrPrint *irp, IrInstructionArrayLen *instruction) {
|
|
|
|
ir_print_other_instruction(irp, instruction->array_value);
|
|
|
|
fprintf(irp->f, ".len");
|
|
|
|
}
|
|
|
|
|
2016-11-27 14:22:30 +08:00
|
|
|
static void ir_print_ref(IrPrint *irp, IrInstructionRef *instruction) {
|
|
|
|
fprintf(irp->f, "ref ");
|
|
|
|
ir_print_other_instruction(irp, instruction->value);
|
|
|
|
}
|
|
|
|
|
2016-12-07 14:23:38 +08:00
|
|
|
static void ir_print_min_value(IrPrint *irp, IrInstructionMinValue *instruction) {
|
|
|
|
fprintf(irp->f, "@minValue(");
|
|
|
|
ir_print_other_instruction(irp, instruction->value);
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ir_print_max_value(IrPrint *irp, IrInstructionMaxValue *instruction) {
|
|
|
|
fprintf(irp->f, "@maxValue(");
|
|
|
|
ir_print_other_instruction(irp, instruction->value);
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
|
2016-12-08 00:29:44 +08:00
|
|
|
static void ir_print_compile_err(IrPrint *irp, IrInstructionCompileErr *instruction) {
|
|
|
|
fprintf(irp->f, "@compileError(");
|
|
|
|
ir_print_other_instruction(irp, instruction->msg);
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
|
2016-12-08 14:52:57 +08:00
|
|
|
static void ir_print_err_name(IrPrint *irp, IrInstructionErrName *instruction) {
|
|
|
|
fprintf(irp->f, "@errorName(");
|
|
|
|
ir_print_other_instruction(irp, instruction->value);
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
|
2016-12-11 13:13:43 +08:00
|
|
|
static void ir_print_c_import(IrPrint *irp, IrInstructionCImport *instruction) {
|
|
|
|
fprintf(irp->f, "@cImport(...)");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ir_print_c_include(IrPrint *irp, IrInstructionCInclude *instruction) {
|
|
|
|
fprintf(irp->f, "@cInclude(");
|
|
|
|
ir_print_other_instruction(irp, instruction->name);
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ir_print_c_define(IrPrint *irp, IrInstructionCDefine *instruction) {
|
|
|
|
fprintf(irp->f, "@cDefine(");
|
|
|
|
ir_print_other_instruction(irp, instruction->name);
|
|
|
|
fprintf(irp->f, ", ");
|
|
|
|
ir_print_other_instruction(irp, instruction->value);
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ir_print_c_undef(IrPrint *irp, IrInstructionCUndef *instruction) {
|
|
|
|
fprintf(irp->f, "@cUndef(");
|
|
|
|
ir_print_other_instruction(irp, instruction->name);
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
|
2016-12-11 13:43:23 +08:00
|
|
|
static void ir_print_embed_file(IrPrint *irp, IrInstructionEmbedFile *instruction) {
|
|
|
|
fprintf(irp->f, "@embedFile(");
|
|
|
|
ir_print_other_instruction(irp, instruction->name);
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
|
2016-12-11 17:06:07 +08:00
|
|
|
static void ir_print_cmpxchg(IrPrint *irp, IrInstructionCmpxchg *instruction) {
|
|
|
|
fprintf(irp->f, "@cmpxchg(");
|
|
|
|
ir_print_other_instruction(irp, instruction->ptr);
|
|
|
|
fprintf(irp->f, ", ");
|
|
|
|
ir_print_other_instruction(irp, instruction->cmp_value);
|
|
|
|
fprintf(irp->f, ", ");
|
|
|
|
ir_print_other_instruction(irp, instruction->new_value);
|
|
|
|
fprintf(irp->f, ", ");
|
|
|
|
ir_print_other_instruction(irp, instruction->success_order_value);
|
|
|
|
fprintf(irp->f, ", ");
|
|
|
|
ir_print_other_instruction(irp, instruction->failure_order_value);
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ir_print_fence(IrPrint *irp, IrInstructionFence *instruction) {
|
|
|
|
fprintf(irp->f, "@fence(");
|
|
|
|
ir_print_other_instruction(irp, instruction->order_value);
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
|
2016-12-12 03:27:37 +08:00
|
|
|
static void ir_print_div_exact(IrPrint *irp, IrInstructionDivExact *instruction) {
|
|
|
|
fprintf(irp->f, "@divExact(");
|
|
|
|
ir_print_other_instruction(irp, instruction->op1);
|
|
|
|
fprintf(irp->f, ", ");
|
|
|
|
ir_print_other_instruction(irp, instruction->op2);
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
|
2016-12-12 04:31:07 +08:00
|
|
|
static void ir_print_truncate(IrPrint *irp, IrInstructionTruncate *instruction) {
|
|
|
|
fprintf(irp->f, "@truncate(");
|
|
|
|
ir_print_other_instruction(irp, instruction->dest_type);
|
|
|
|
fprintf(irp->f, ", ");
|
|
|
|
ir_print_other_instruction(irp, instruction->target);
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
|
2016-12-12 08:43:06 +08:00
|
|
|
static void ir_print_alloca(IrPrint *irp, IrInstructionAlloca *instruction) {
|
|
|
|
fprintf(irp->f, "@alloca(");
|
|
|
|
ir_print_other_instruction(irp, instruction->type_value);
|
|
|
|
fprintf(irp->f, ", ");
|
|
|
|
ir_print_other_instruction(irp, instruction->count);
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
|
2016-12-12 05:30:01 +08:00
|
|
|
static void ir_print_int_type(IrPrint *irp, IrInstructionIntType *instruction) {
|
|
|
|
fprintf(irp->f, "@intType(");
|
|
|
|
ir_print_other_instruction(irp, instruction->is_signed);
|
|
|
|
fprintf(irp->f, ", ");
|
|
|
|
ir_print_other_instruction(irp, instruction->bit_count);
|
|
|
|
fprintf(irp->f, ")");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ir_print_bool_not(IrPrint *irp, IrInstructionBoolNot *instruction) {
|
|
|
|
fprintf(irp->f, "! ");
|
|
|
|
ir_print_other_instruction(irp, instruction->value);
|
|
|
|
}
|
|
|
|
|
2016-10-03 11:48:48 +08:00
|
|
|
static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
2016-10-16 14:19:01 +08:00
|
|
|
ir_print_prefix(irp, instruction);
|
2016-10-03 11:48:48 +08:00
|
|
|
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;
|
2016-10-18 15:00:48 +08:00
|
|
|
case IrInstructionIdDeclVar:
|
|
|
|
ir_print_decl_var(irp, (IrInstructionDeclVar *)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;
|
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;
|
2016-10-16 14:19:01 +08:00
|
|
|
case IrInstructionIdContainerInitList:
|
|
|
|
ir_print_container_init_list(irp, (IrInstructionContainerInitList *)instruction);
|
|
|
|
break;
|
|
|
|
case IrInstructionIdContainerInitFields:
|
|
|
|
ir_print_container_init_fields(irp, (IrInstructionContainerInitFields *)instruction);
|
|
|
|
break;
|
2016-11-28 15:40:01 +08:00
|
|
|
case IrInstructionIdStructInit:
|
|
|
|
ir_print_struct_init(irp, (IrInstructionStructInit *)instruction);
|
|
|
|
break;
|
2016-10-16 14:19:01 +08:00
|
|
|
case IrInstructionIdUnreachable:
|
|
|
|
ir_print_unreachable(irp, (IrInstructionUnreachable *)instruction);
|
|
|
|
break;
|
2016-10-23 12:21:29 +08:00
|
|
|
case IrInstructionIdElemPtr:
|
|
|
|
ir_print_elem_ptr(irp, (IrInstructionElemPtr *)instruction);
|
|
|
|
break;
|
|
|
|
case IrInstructionIdVarPtr:
|
|
|
|
ir_print_var_ptr(irp, (IrInstructionVarPtr *)instruction);
|
|
|
|
break;
|
|
|
|
case IrInstructionIdLoadPtr:
|
|
|
|
ir_print_load_ptr(irp, (IrInstructionLoadPtr *)instruction);
|
2016-10-18 15:00:48 +08:00
|
|
|
break;
|
2016-10-23 12:21:29 +08:00
|
|
|
case IrInstructionIdStorePtr:
|
2016-10-23 13:33:23 +08:00
|
|
|
ir_print_store_ptr(irp, (IrInstructionStorePtr *)instruction);
|
|
|
|
break;
|
2016-10-30 14:46:16 +08:00
|
|
|
case IrInstructionIdTypeOf:
|
|
|
|
ir_print_typeof(irp, (IrInstructionTypeOf *)instruction);
|
|
|
|
break;
|
|
|
|
case IrInstructionIdToPtrType:
|
|
|
|
ir_print_to_ptr_type(irp, (IrInstructionToPtrType *)instruction);
|
|
|
|
break;
|
|
|
|
case IrInstructionIdPtrTypeChild:
|
|
|
|
ir_print_ptr_type_child(irp, (IrInstructionPtrTypeChild *)instruction);
|
|
|
|
break;
|
2016-10-23 12:21:29 +08:00
|
|
|
case IrInstructionIdFieldPtr:
|
2016-10-30 14:46:16 +08:00
|
|
|
ir_print_field_ptr(irp, (IrInstructionFieldPtr *)instruction);
|
|
|
|
break;
|
|
|
|
case IrInstructionIdStructFieldPtr:
|
|
|
|
ir_print_struct_field_ptr(irp, (IrInstructionStructFieldPtr *)instruction);
|
|
|
|
break;
|
2016-11-28 15:40:01 +08:00
|
|
|
case IrInstructionIdEnumFieldPtr:
|
|
|
|
ir_print_enum_field_ptr(irp, (IrInstructionEnumFieldPtr *)instruction);
|
|
|
|
break;
|
2016-11-05 03:36:30 +08:00
|
|
|
case IrInstructionIdSetFnTest:
|
|
|
|
ir_print_set_fn_test(irp, (IrInstructionSetFnTest *)instruction);
|
|
|
|
break;
|
2016-11-22 04:36:25 +08:00
|
|
|
case IrInstructionIdSetFnVisible:
|
|
|
|
ir_print_set_fn_visible(irp, (IrInstructionSetFnVisible *)instruction);
|
|
|
|
break;
|
2016-11-19 09:57:27 +08:00
|
|
|
case IrInstructionIdSetDebugSafety:
|
|
|
|
ir_print_set_debug_safety(irp, (IrInstructionSetDebugSafety *)instruction);
|
|
|
|
break;
|
2016-11-08 07:58:01 +08:00
|
|
|
case IrInstructionIdArrayType:
|
|
|
|
ir_print_array_type(irp, (IrInstructionArrayType *)instruction);
|
|
|
|
break;
|
|
|
|
case IrInstructionIdSliceType:
|
|
|
|
ir_print_slice_type(irp, (IrInstructionSliceType *)instruction);
|
|
|
|
break;
|
2016-11-14 10:07:30 +08:00
|
|
|
case IrInstructionIdAsm:
|
|
|
|
ir_print_asm(irp, (IrInstructionAsm *)instruction);
|
|
|
|
break;
|
2016-11-19 14:39:51 +08:00
|
|
|
case IrInstructionIdCompileVar:
|
|
|
|
ir_print_compile_var(irp, (IrInstructionCompileVar *)instruction);
|
|
|
|
break;
|
2016-11-20 15:11:36 +08:00
|
|
|
case IrInstructionIdSizeOf:
|
|
|
|
ir_print_size_of(irp, (IrInstructionSizeOf *)instruction);
|
|
|
|
break;
|
2016-11-21 16:08:24 +08:00
|
|
|
case IrInstructionIdTestNull:
|
|
|
|
ir_print_test_null(irp, (IrInstructionTestNull *)instruction);
|
|
|
|
break;
|
|
|
|
case IrInstructionIdUnwrapMaybe:
|
|
|
|
ir_print_unwrap_maybe(irp, (IrInstructionUnwrapMaybe *)instruction);
|
|
|
|
break;
|
2016-11-22 02:27:44 +08:00
|
|
|
case IrInstructionIdCtz:
|
|
|
|
ir_print_ctz(irp, (IrInstructionCtz *)instruction);
|
|
|
|
break;
|
|
|
|
case IrInstructionIdClz:
|
|
|
|
ir_print_clz(irp, (IrInstructionClz *)instruction);
|
|
|
|
break;
|
2016-10-30 14:46:16 +08:00
|
|
|
case IrInstructionIdSwitchBr:
|
2016-11-26 13:25:48 +08:00
|
|
|
ir_print_switch_br(irp, (IrInstructionSwitchBr *)instruction);
|
|
|
|
break;
|
2016-11-24 15:44:03 +08:00
|
|
|
case IrInstructionIdSwitchVar:
|
2016-11-26 13:25:48 +08:00
|
|
|
ir_print_switch_var(irp, (IrInstructionSwitchVar *)instruction);
|
|
|
|
break;
|
2016-11-24 15:44:03 +08:00
|
|
|
case IrInstructionIdSwitchTarget:
|
2016-11-26 13:25:48 +08:00
|
|
|
ir_print_switch_target(irp, (IrInstructionSwitchTarget *)instruction);
|
|
|
|
break;
|
|
|
|
case IrInstructionIdEnumTag:
|
|
|
|
ir_print_enum_tag(irp, (IrInstructionEnumTag *)instruction);
|
|
|
|
break;
|
2016-11-26 17:37:34 +08:00
|
|
|
case IrInstructionIdStaticEval:
|
|
|
|
ir_print_static_eval(irp, (IrInstructionStaticEval *)instruction);
|
|
|
|
break;
|
2016-11-27 09:52:22 +08:00
|
|
|
case IrInstructionIdImport:
|
|
|
|
ir_print_import(irp, (IrInstructionImport *)instruction);
|
|
|
|
break;
|
|
|
|
case IrInstructionIdArrayLen:
|
|
|
|
ir_print_array_len(irp, (IrInstructionArrayLen *)instruction);
|
|
|
|
break;
|
2016-11-27 14:22:30 +08:00
|
|
|
case IrInstructionIdRef:
|
|
|
|
ir_print_ref(irp, (IrInstructionRef *)instruction);
|
|
|
|
break;
|
2016-12-07 14:23:38 +08:00
|
|
|
case IrInstructionIdMinValue:
|
|
|
|
ir_print_min_value(irp, (IrInstructionMinValue *)instruction);
|
|
|
|
break;
|
|
|
|
case IrInstructionIdMaxValue:
|
|
|
|
ir_print_max_value(irp, (IrInstructionMaxValue *)instruction);
|
|
|
|
break;
|
2016-12-08 00:29:44 +08:00
|
|
|
case IrInstructionIdCompileErr:
|
|
|
|
ir_print_compile_err(irp, (IrInstructionCompileErr *)instruction);
|
|
|
|
break;
|
2016-12-08 14:52:57 +08:00
|
|
|
case IrInstructionIdErrName:
|
|
|
|
ir_print_err_name(irp, (IrInstructionErrName *)instruction);
|
|
|
|
break;
|
2016-12-11 13:13:43 +08:00
|
|
|
case IrInstructionIdCImport:
|
|
|
|
ir_print_c_import(irp, (IrInstructionCImport *)instruction);
|
|
|
|
break;
|
|
|
|
case IrInstructionIdCInclude:
|
|
|
|
ir_print_c_include(irp, (IrInstructionCInclude *)instruction);
|
|
|
|
break;
|
|
|
|
case IrInstructionIdCDefine:
|
|
|
|
ir_print_c_define(irp, (IrInstructionCDefine *)instruction);
|
|
|
|
break;
|
|
|
|
case IrInstructionIdCUndef:
|
|
|
|
ir_print_c_undef(irp, (IrInstructionCUndef *)instruction);
|
|
|
|
break;
|
2016-12-11 13:43:23 +08:00
|
|
|
case IrInstructionIdEmbedFile:
|
|
|
|
ir_print_embed_file(irp, (IrInstructionEmbedFile *)instruction);
|
|
|
|
break;
|
2016-12-11 17:06:07 +08:00
|
|
|
case IrInstructionIdCmpxchg:
|
|
|
|
ir_print_cmpxchg(irp, (IrInstructionCmpxchg *)instruction);
|
|
|
|
break;
|
|
|
|
case IrInstructionIdFence:
|
|
|
|
ir_print_fence(irp, (IrInstructionFence *)instruction);
|
|
|
|
break;
|
2016-12-12 03:27:37 +08:00
|
|
|
case IrInstructionIdDivExact:
|
|
|
|
ir_print_div_exact(irp, (IrInstructionDivExact *)instruction);
|
|
|
|
break;
|
2016-12-12 04:31:07 +08:00
|
|
|
case IrInstructionIdTruncate:
|
|
|
|
ir_print_truncate(irp, (IrInstructionTruncate *)instruction);
|
|
|
|
break;
|
2016-12-12 08:43:06 +08:00
|
|
|
case IrInstructionIdAlloca:
|
|
|
|
ir_print_alloca(irp, (IrInstructionAlloca *)instruction);
|
|
|
|
break;
|
2016-12-12 05:30:01 +08:00
|
|
|
case IrInstructionIdIntType:
|
|
|
|
ir_print_int_type(irp, (IrInstructionIntType *)instruction);
|
|
|
|
break;
|
|
|
|
case IrInstructionIdBoolNot:
|
|
|
|
ir_print_bool_not(irp, (IrInstructionBoolNot *)instruction);
|
|
|
|
break;
|
2016-10-03 11:48:48 +08:00
|
|
|
}
|
2016-10-16 14:19:01 +08:00
|
|
|
fprintf(irp->f, "\n");
|
2016-10-03 11:48:48 +08:00
|
|
|
}
|
|
|
|
|
2016-10-01 08:12:00 +08:00
|
|
|
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);
|
2016-10-01 08:12:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-12-11 13:13:43 +08:00
|
|
|
|
|
|
|
static void print_tld_var(IrPrint *irp, TldVar *tld_var) {
|
|
|
|
const char *const_or_var = tld_var->var->src_is_const ? "const" : "var";
|
|
|
|
fprintf(irp->f, "%s %s", const_or_var, buf_ptr(tld_var->base.name));
|
|
|
|
bool omit_type = (tld_var->var->type->id == TypeTableEntryIdNumLitFloat ||
|
|
|
|
tld_var->var->type->id == TypeTableEntryIdNumLitInt);
|
|
|
|
if (!omit_type) {
|
|
|
|
fprintf(irp->f, ": %s", buf_ptr(&tld_var->var->type->name));
|
|
|
|
}
|
|
|
|
if (tld_var->var->value) {
|
|
|
|
fprintf(irp->f, " = ");
|
|
|
|
ir_print_const_value(irp, tld_var->var->type, tld_var->var->value);
|
|
|
|
}
|
|
|
|
fprintf(irp->f, ";\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void print_tld_fn(IrPrint *irp, TldFn *tld_fn) {
|
|
|
|
fprintf(irp->f, "// %s = TODO (function)\n", buf_ptr(tld_fn->base.name));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void print_tld_container(IrPrint *irp, TldContainer *tld_container) {
|
|
|
|
fprintf(irp->f, "// %s = TODO (container)\n", buf_ptr(tld_container->base.name));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void print_tld_typedef(IrPrint *irp, TldTypeDef *tld_typedef) {
|
|
|
|
fprintf(irp->f, "// %s = TODO (typedef)\n", buf_ptr(tld_typedef->base.name));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ir_print_decls(FILE *f, ImportTableEntry *import) {
|
|
|
|
IrPrint ir_print = {};
|
|
|
|
IrPrint *irp = &ir_print;
|
|
|
|
irp->f = f;
|
|
|
|
irp->indent = 0;
|
|
|
|
irp->indent_size = 2;
|
|
|
|
|
|
|
|
auto it = import->decls_scope->decl_table.entry_iterator();
|
|
|
|
for (;;) {
|
|
|
|
auto *entry = it.next();
|
|
|
|
if (!entry)
|
|
|
|
break;
|
|
|
|
|
|
|
|
Tld *tld = entry->value;
|
|
|
|
if (!buf_eql_buf(entry->key, tld->name)) {
|
|
|
|
fprintf(f, "// alias: %s = %s\n", buf_ptr(entry->key), buf_ptr(tld->name));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (tld->id) {
|
|
|
|
case TldIdVar:
|
|
|
|
print_tld_var(irp, (TldVar *)tld);
|
|
|
|
continue;
|
|
|
|
case TldIdFn:
|
|
|
|
print_tld_fn(irp, (TldFn *)tld);
|
|
|
|
continue;
|
|
|
|
case TldIdContainer:
|
|
|
|
print_tld_container(irp, (TldContainer *)tld);
|
|
|
|
continue;
|
|
|
|
case TldIdTypeDef:
|
|
|
|
print_tld_typedef(irp, (TldTypeDef *)tld);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
zig_unreachable();
|
|
|
|
}
|
|
|
|
}
|