/** ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** * Copyright 2013 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #include #include #include #include using namespace alloy; using namespace alloy::hir; using namespace alloy::runtime; #define ASSERT_ADDRESS_TYPE(value) #define ASSERT_INTEGER_TYPE(value) #define ASSERT_FLOAT_TYPE(value) #define ASSERT_NON_VECTOR_TYPE(value) #define ASSERT_VECTOR_TYPE(value) #define ASSERT_TYPES_EQUAL(value1, value2) FunctionBuilder::FunctionBuilder() { arena_ = new Arena(); Reset(); } FunctionBuilder::~FunctionBuilder() { Reset(); delete arena_; } void FunctionBuilder::Reset() { attributes_ = 0; next_label_id_ = 0; next_value_ordinal_ = 0; block_head_ = block_tail_ = NULL; current_block_ = NULL; } void FunctionBuilder::DumpValue(StringBuffer* str, Value* value) { if (value->IsConstant()) { switch (value->type) { case INT8_TYPE: str->Append("%X", value->constant.i8); break; case INT16_TYPE: str->Append("%X", value->constant.i16); break; case INT32_TYPE: str->Append("%X", value->constant.i32); break; case INT64_TYPE: str->Append("%X", value->constant.i64); break; case FLOAT32_TYPE: str->Append("%F", value->constant.f32); break; case FLOAT64_TYPE: str->Append("%F", value->constant.f64); break; case VEC128_TYPE: str->Append("(%F,%F,%F,%F)", value->constant.v128.x, value->constant.v128.y, value->constant.v128.z, value->constant.v128.w); break; default: XEASSERTALWAYS(); break; } } else { static const char* type_names[] = { "i8", "i16", "i32", "i64", "f32", "f64", "v128", }; str->Append("v%d.%s", value->ordinal, type_names[value->type]); } } void FunctionBuilder::DumpOp( StringBuffer* str, OpcodeSignatureType sig_type, Instr::Op* op) { switch (sig_type) { case OPCODE_SIG_TYPE_X: break; case OPCODE_SIG_TYPE_L: if (op->label->name) { str->Append(op->label->name); } else { str->Append("label%d", op->label->id); } break; case OPCODE_SIG_TYPE_O: str->Append("+%d", op->offset); break; case OPCODE_SIG_TYPE_S: str->Append(""); break; case OPCODE_SIG_TYPE_V: DumpValue(str, op->value); break; } } void FunctionBuilder::Dump(StringBuffer* str) { if (attributes_) { str->Append("; attributes = %.8X\n", attributes_); } uint32_t block_ordinal = 0; Block* block = block_head_; while (block) { if (block == block_head_) { str->Append(":\n"); } else { str->Append(":\n", block_ordinal); } block_ordinal++; Label* label = block->label_head; while (label) { if (label->name) { str->Append("%s:\n", label->name); } else { str->Append("label%d:\n", label->id); } label = label->next; } Instr* i = block->instr_head; while (i) { if (i->opcode->num == OPCODE_COMMENT) { str->Append(" ; %s\n", (char*)i->src1.offset); i = i->next; continue; } const OpcodeInfo* info = i->opcode; OpcodeSignatureType dest_type = GET_OPCODE_SIG_TYPE_DEST(info->signature); OpcodeSignatureType src1_type = GET_OPCODE_SIG_TYPE_SRC1(info->signature); OpcodeSignatureType src2_type = GET_OPCODE_SIG_TYPE_SRC2(info->signature); OpcodeSignatureType src3_type = GET_OPCODE_SIG_TYPE_SRC3(info->signature); str->Append(" "); if (dest_type) { DumpValue(str, i->dest); str->Append(" = "); } if (i->flags) { str->Append("%s.%d", info->name, i->flags); } else { str->Append("%s", info->name); } if (src1_type) { str->Append(" "); DumpOp(str, src1_type, &i->src1); } if (src2_type) { str->Append(", "); DumpOp(str, src2_type, &i->src2); } if (src3_type) { str->Append(", "); DumpOp(str, src3_type, &i->src3); } str->Append("\n"); i = i->next; } block = block->next; } } Block* FunctionBuilder::current_block() const { return current_block_; } Instr* FunctionBuilder::last_instr() const { if (current_block_ && current_block_->instr_tail) { return current_block_->instr_tail; } else if (block_tail_) { return block_tail_->instr_tail; } return NULL; } Label* FunctionBuilder::NewLabel() { Label* label = arena_->Alloc