mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
IR: implement intType builtin
and int type field access and fix compile time bool not
This commit is contained in:
parent
3429639e84
commit
9b17c0ff7f
@ -1411,6 +1411,8 @@ enum IrInstructionId {
|
||||
IrInstructionIdFence,
|
||||
IrInstructionIdDivExact,
|
||||
IrInstructionIdTruncate,
|
||||
IrInstructionIdIntType,
|
||||
IrInstructionIdBoolNot,
|
||||
};
|
||||
|
||||
struct IrInstruction {
|
||||
@ -1481,7 +1483,6 @@ struct IrInstructionPhi {
|
||||
|
||||
enum IrUnOp {
|
||||
IrUnOpInvalid,
|
||||
IrUnOpBoolNot,
|
||||
IrUnOpBinNot,
|
||||
IrUnOpNegation,
|
||||
IrUnOpNegationWrap,
|
||||
@ -1900,6 +1901,19 @@ struct IrInstructionTruncate {
|
||||
IrInstruction *target;
|
||||
};
|
||||
|
||||
struct IrInstructionIntType {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *is_signed;
|
||||
IrInstruction *bit_count;
|
||||
};
|
||||
|
||||
struct IrInstructionBoolNot {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *value;
|
||||
};
|
||||
|
||||
enum LValPurpose {
|
||||
LValPurposeNone,
|
||||
LValPurposeAssign,
|
||||
|
||||
@ -2809,3 +2809,14 @@ ConstExprValue *create_const_enum_tag(uint64_t tag) {
|
||||
init_const_enum_tag(const_val, tag);
|
||||
return const_val;
|
||||
}
|
||||
|
||||
void init_const_bool(ConstExprValue *const_val, bool value) {
|
||||
const_val->special = ConstValSpecialStatic;
|
||||
const_val->data.x_bool = value;
|
||||
}
|
||||
|
||||
ConstExprValue *create_const_bool(bool value) {
|
||||
ConstExprValue *const_val = allocate<ConstExprValue>(1);
|
||||
init_const_bool(const_val, value);
|
||||
return const_val;
|
||||
}
|
||||
|
||||
@ -98,4 +98,7 @@ ConstExprValue *create_const_float(double value);
|
||||
void init_const_enum_tag(ConstExprValue *const_val, uint64_t tag);
|
||||
ConstExprValue *create_const_enum_tag(uint64_t tag);
|
||||
|
||||
void init_const_bool(ConstExprValue *const_val, bool value);
|
||||
ConstExprValue *create_const_bool(bool value);
|
||||
|
||||
#endif
|
||||
|
||||
@ -1230,11 +1230,6 @@ static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInst
|
||||
zig_unreachable();
|
||||
}
|
||||
}
|
||||
case IrUnOpBoolNot:
|
||||
{
|
||||
LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(expr));
|
||||
return LLVMBuildICmp(g->builder, LLVMIntEQ, expr, zero, "");
|
||||
}
|
||||
case IrUnOpBinNot:
|
||||
return LLVMBuildNot(g->builder, expr, "");
|
||||
case IrUnOpAddressOf:
|
||||
@ -1339,6 +1334,12 @@ static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInst
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutable *executable, IrInstructionBoolNot *instruction) {
|
||||
LLVMValueRef value = ir_llvm_value(g, instruction->value);
|
||||
LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(value));
|
||||
return LLVMBuildICmp(g->builder, LLVMIntEQ, value, zero, "");
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionDeclVar *decl_var_instruction)
|
||||
{
|
||||
@ -1927,6 +1928,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
||||
case IrInstructionIdCDefine:
|
||||
case IrInstructionIdCUndef:
|
||||
case IrInstructionIdEmbedFile:
|
||||
case IrInstructionIdIntType:
|
||||
zig_unreachable();
|
||||
case IrInstructionIdReturn:
|
||||
return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
|
||||
@ -1984,6 +1986,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
||||
return ir_render_div_exact(g, executable, (IrInstructionDivExact *)instruction);
|
||||
case IrInstructionIdTruncate:
|
||||
return ir_render_truncate(g, executable, (IrInstructionTruncate *)instruction);
|
||||
case IrInstructionIdBoolNot:
|
||||
return ir_render_bool_not(g, executable, (IrInstructionBoolNot *)instruction);
|
||||
case IrInstructionIdSwitchVar:
|
||||
case IrInstructionIdContainerInitList:
|
||||
case IrInstructionIdStructInit:
|
||||
|
||||
245
src/ir.cpp
245
src/ir.cpp
@ -363,6 +363,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTruncate *) {
|
||||
return IrInstructionIdTruncate;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionIntType *) {
|
||||
return IrInstructionIdIntType;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionBoolNot *) {
|
||||
return IrInstructionIdBoolNot;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {
|
||||
T *special_instruction = allocate<T>(1);
|
||||
@ -1455,6 +1463,32 @@ static IrInstruction *ir_build_truncate_from(IrBuilder *irb, IrInstruction *old_
|
||||
return new_instruction;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_int_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *is_signed, IrInstruction *bit_count) {
|
||||
IrInstructionIntType *instruction = ir_build_instruction<IrInstructionIntType>(irb, scope, source_node);
|
||||
instruction->is_signed = is_signed;
|
||||
instruction->bit_count = bit_count;
|
||||
|
||||
ir_ref_instruction(is_signed);
|
||||
ir_ref_instruction(bit_count);
|
||||
|
||||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_bool_not(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
|
||||
IrInstructionBoolNot *instruction = ir_build_instruction<IrInstructionBoolNot>(irb, scope, source_node);
|
||||
instruction->value = value;
|
||||
|
||||
ir_ref_instruction(value);
|
||||
|
||||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_bool_not_from(IrBuilder *irb, IrInstruction *old_instruction, IrInstruction *value) {
|
||||
IrInstruction *new_instruction = ir_build_bool_not(irb, old_instruction->scope, old_instruction->source_node, value);
|
||||
ir_link_new_instruction(new_instruction, old_instruction);
|
||||
return new_instruction;
|
||||
}
|
||||
|
||||
static void ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope,
|
||||
bool gen_error_defers, bool gen_maybe_defers)
|
||||
{
|
||||
@ -2262,6 +2296,20 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
|
||||
|
||||
return ir_build_truncate(irb, scope, node, arg0_value, arg1_value);
|
||||
}
|
||||
case BuiltinFnIdIntType:
|
||||
{
|
||||
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
|
||||
IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
|
||||
if (arg0_value == irb->codegen->invalid_instruction)
|
||||
return arg0_value;
|
||||
|
||||
AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
|
||||
IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
|
||||
if (arg1_value == irb->codegen->invalid_instruction)
|
||||
return arg1_value;
|
||||
|
||||
return ir_build_int_type(irb, scope, node, arg0_value, arg1_value);
|
||||
}
|
||||
case BuiltinFnIdMemcpy:
|
||||
case BuiltinFnIdMemset:
|
||||
case BuiltinFnIdAlignof:
|
||||
@ -2273,7 +2321,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
|
||||
case BuiltinFnIdBreakpoint:
|
||||
case BuiltinFnIdReturnAddress:
|
||||
case BuiltinFnIdFrameAddress:
|
||||
case BuiltinFnIdIntType:
|
||||
zig_panic("TODO IR gen more builtin functions");
|
||||
}
|
||||
zig_unreachable();
|
||||
@ -2379,6 +2426,28 @@ static IrInstruction *ir_gen_prefix_op_unwrap_maybe(IrBuilder *irb, Scope *scope
|
||||
return unwrapped_ptr;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_gen_bool_not(IrBuilder *irb, Scope *scope, AstNode *node) {
|
||||
assert(node->type == NodeTypePrefixOpExpr);
|
||||
AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
|
||||
|
||||
IrInstruction *value = ir_gen_node(irb, expr_node, scope);
|
||||
if (value == irb->codegen->invalid_instruction)
|
||||
return irb->codegen->invalid_instruction;
|
||||
|
||||
return ir_build_bool_not(irb, scope, node, value);
|
||||
}
|
||||
|
||||
static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LValPurpose lval) {
|
||||
if (lval == LValPurposeNone)
|
||||
return value;
|
||||
if (value == irb->codegen->invalid_instruction)
|
||||
return value;
|
||||
|
||||
// We needed a pointer to a value, but we got a value. So we create
|
||||
// an instruction which just makes a const pointer of it.
|
||||
return ir_build_ref(irb, scope, value->source_node, value);
|
||||
}
|
||||
|
||||
static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) {
|
||||
assert(node->type == NodeTypePrefixOpExpr);
|
||||
|
||||
@ -2388,7 +2457,7 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod
|
||||
case PrefixOpInvalid:
|
||||
zig_unreachable();
|
||||
case PrefixOpBoolNot:
|
||||
return ir_gen_prefix_op_id(irb, scope, node, IrUnOpBoolNot);
|
||||
return ir_lval_wrap(irb, scope, ir_gen_bool_not(irb, scope, node), lval);
|
||||
case PrefixOpBinNot:
|
||||
return ir_gen_prefix_op_id(irb, scope, node, IrUnOpBinNot);
|
||||
case PrefixOpNegation:
|
||||
@ -3124,17 +3193,6 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *scope, AstNode *nod
|
||||
return ir_build_br(irb, scope, node, dest_block, is_inline);
|
||||
}
|
||||
|
||||
static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LValPurpose lval) {
|
||||
if (lval == LValPurposeNone)
|
||||
return value;
|
||||
if (value == irb->codegen->invalid_instruction)
|
||||
return value;
|
||||
|
||||
// We needed a pointer to a value, but we got a value. So we create
|
||||
// an instruction which just makes a const pointer of it.
|
||||
return ir_build_ref(irb, scope, value->source_node, value);
|
||||
}
|
||||
|
||||
static IrInstruction *ir_gen_type_literal(IrBuilder *irb, Scope *scope, AstNode *node) {
|
||||
assert(node->type == NodeTypeTypeLiteral);
|
||||
return ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_type);
|
||||
@ -5136,31 +5194,6 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction
|
||||
}
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_unary_bool_not(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
|
||||
IrInstruction *value = un_op_instruction->value->other;
|
||||
if (value->type_entry->id == TypeTableEntryIdInvalid)
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
TypeTableEntry *bool_type = ira->codegen->builtin_types.entry_bool;
|
||||
|
||||
IrInstruction *casted_value = ir_get_casted_value(ira, value, bool_type);
|
||||
if (casted_value->type_entry->id == TypeTableEntryIdInvalid)
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
ConstExprValue *operand_val = &casted_value->static_value;
|
||||
if (operand_val->special != ConstValSpecialRuntime) {
|
||||
ConstExprValue *result_val = &un_op_instruction->base.static_value;
|
||||
result_val->special = ConstValSpecialStatic;
|
||||
result_val->depends_on_compile_var = operand_val->depends_on_compile_var;
|
||||
result_val->data.x_bool = !operand_val->data.x_bool;
|
||||
return bool_type;
|
||||
}
|
||||
|
||||
ir_build_un_op_from(&ira->new_irb, &un_op_instruction->base, IrUnOpBoolNot, casted_value);
|
||||
|
||||
return bool_type;
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_unary_prefix_op_err(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
|
||||
assert(un_op_instruction->op_id == IrUnOpError);
|
||||
IrInstruction *value = un_op_instruction->value->other;
|
||||
@ -5425,8 +5458,6 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio
|
||||
switch (op_id) {
|
||||
case IrUnOpInvalid:
|
||||
zig_unreachable();
|
||||
case IrUnOpBoolNot:
|
||||
return ir_analyze_unary_bool_not(ira, un_op_instruction);
|
||||
case IrUnOpBinNot:
|
||||
zig_panic("TODO analyze PrefixOpBinNot");
|
||||
//{
|
||||
@ -5961,9 +5992,22 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
|
||||
buf_sprintf("use of undeclared error value '%s'", buf_ptr(field_name)));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
} else if (child_type->id == TypeTableEntryIdInt) {
|
||||
zig_panic("TODO integer type field");
|
||||
if (buf_eql_str(field_name, "bit_count")) {
|
||||
return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
|
||||
create_const_unsigned_negative(child_type->data.integral.bit_count, false),
|
||||
ira->codegen->builtin_types.entry_num_lit_int, depends_on_compile_var, ConstPtrSpecialNone);
|
||||
} else if (buf_eql_str(field_name, "is_signed")) {
|
||||
return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
|
||||
create_const_bool(child_type->data.integral.is_signed),
|
||||
ira->codegen->builtin_types.entry_bool, depends_on_compile_var, ConstPtrSpecialNone);
|
||||
} else {
|
||||
ir_add_error(ira, &field_ptr_instruction->base,
|
||||
buf_sprintf("type '%s' has no member called '%s'",
|
||||
buf_ptr(&child_type->name), buf_ptr(field_name)));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
} else {
|
||||
add_node_error(ira->codegen, source_node,
|
||||
ir_add_error(ira, &field_ptr_instruction->base,
|
||||
buf_sprintf("type '%s' does not support field access", buf_ptr(&container_type->name)));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
@ -7620,6 +7664,47 @@ static TypeTableEntry *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruc
|
||||
return dest_type;
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_instruction_int_type(IrAnalyze *ira, IrInstructionIntType *instruction) {
|
||||
IrInstruction *is_signed_value = instruction->is_signed->other;
|
||||
bool is_signed;
|
||||
if (!ir_resolve_bool(ira, is_signed_value, &is_signed))
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
IrInstruction *bit_count_value = instruction->bit_count->other;
|
||||
uint64_t bit_count;
|
||||
if (!ir_resolve_usize(ira, bit_count_value, &bit_count))
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
bool depends_on_compile_var = is_signed_value->static_value.depends_on_compile_var ||
|
||||
bit_count_value->static_value.depends_on_compile_var;
|
||||
|
||||
ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, depends_on_compile_var);
|
||||
out_val->data.x_type = get_int_type(ira->codegen, is_signed, bit_count);
|
||||
return ira->codegen->builtin_types.entry_type;
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_instruction_bool_not(IrAnalyze *ira, IrInstructionBoolNot *instruction) {
|
||||
IrInstruction *value = instruction->value->other;
|
||||
if (value->type_entry->id == TypeTableEntryIdInvalid)
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
TypeTableEntry *bool_type = ira->codegen->builtin_types.entry_bool;
|
||||
|
||||
IrInstruction *casted_value = ir_get_casted_value(ira, value, bool_type);
|
||||
if (casted_value->type_entry->id == TypeTableEntryIdInvalid)
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
if (casted_value->static_value.special != ConstValSpecialRuntime) {
|
||||
bool depends_on_compile_var = casted_value->static_value.depends_on_compile_var;
|
||||
ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, depends_on_compile_var);
|
||||
out_val->data.x_bool = !casted_value->static_value.data.x_bool;
|
||||
return bool_type;
|
||||
}
|
||||
|
||||
ir_build_bool_not_from(&ira->new_irb, &instruction->base, casted_value);
|
||||
return bool_type;
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
|
||||
switch (instruction->id) {
|
||||
case IrInstructionIdInvalid:
|
||||
@ -7730,6 +7815,10 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
|
||||
return ir_analyze_instruction_div_exact(ira, (IrInstructionDivExact *)instruction);
|
||||
case IrInstructionIdTruncate:
|
||||
return ir_analyze_instruction_truncate(ira, (IrInstructionTruncate *)instruction);
|
||||
case IrInstructionIdIntType:
|
||||
return ir_analyze_instruction_int_type(ira, (IrInstructionIntType *)instruction);
|
||||
case IrInstructionIdBoolNot:
|
||||
return ir_analyze_instruction_bool_not(ira, (IrInstructionBoolNot *)instruction);
|
||||
case IrInstructionIdCast:
|
||||
case IrInstructionIdStructFieldPtr:
|
||||
case IrInstructionIdEnumFieldPtr:
|
||||
@ -7869,6 +7958,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
|
||||
case IrInstructionIdEmbedFile:
|
||||
case IrInstructionIdDivExact:
|
||||
case IrInstructionIdTruncate:
|
||||
case IrInstructionIdIntType:
|
||||
case IrInstructionIdBoolNot:
|
||||
return false;
|
||||
case IrInstructionIdAsm:
|
||||
{
|
||||
@ -7880,45 +7971,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
|
||||
}
|
||||
|
||||
// TODO port over all this commented out code into new IR way of doing things
|
||||
//static TypeTableEntry *analyze_int_type(CodeGen *g, ImportTableEntry *import,
|
||||
// BlockContext *context, AstNode *node)
|
||||
//{
|
||||
// AstNode **is_signed_node = &node->data.fn_call_expr.params.at(0);
|
||||
// AstNode **bit_count_node = &node->data.fn_call_expr.params.at(1);
|
||||
//
|
||||
// TypeTableEntry *bool_type = g->builtin_types.entry_bool;
|
||||
// TypeTableEntry *usize_type = g->builtin_types.entry_usize;
|
||||
// TypeTableEntry *is_signed_type = analyze_expression(g, import, context, bool_type, *is_signed_node);
|
||||
// TypeTableEntry *bit_count_type = analyze_expression(g, import, context, usize_type, *bit_count_node);
|
||||
//
|
||||
// if (is_signed_type->id == TypeTableEntryIdInvalid ||
|
||||
// bit_count_type->id == TypeTableEntryIdInvalid)
|
||||
// {
|
||||
// return g->builtin_types.entry_invalid;
|
||||
// }
|
||||
//
|
||||
// ConstExprValue *is_signed_val = &get_resolved_expr(*is_signed_node)->const_val;
|
||||
// ConstExprValue *bit_count_val = &get_resolved_expr(*bit_count_node)->const_val;
|
||||
//
|
||||
// AstNode *bad_node = nullptr;
|
||||
// if (!is_signed_val->ok) {
|
||||
// bad_node = *is_signed_node;
|
||||
// } else if (!bit_count_val->ok) {
|
||||
// bad_node = *bit_count_node;
|
||||
// }
|
||||
// if (bad_node) {
|
||||
// add_node_error(g, bad_node, buf_sprintf("unable to evaluate constant expression"));
|
||||
// return g->builtin_types.entry_invalid;
|
||||
// }
|
||||
//
|
||||
// bool depends_on_compile_var = is_signed_val->depends_on_compile_var || bit_count_val->depends_on_compile_var;
|
||||
//
|
||||
// TypeTableEntry *int_type = get_int_type(g, is_signed_val->data.x_bool,
|
||||
// bit_count_val->data.x_bignum.data.x_uint);
|
||||
// return resolve_expr_const_val_as_type(g, node, int_type, depends_on_compile_var);
|
||||
//
|
||||
//}
|
||||
//
|
||||
//static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
||||
// TypeTableEntry *expected_type, AstNode *node)
|
||||
//{
|
||||
@ -8049,8 +8101,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
|
||||
// case BuiltinFnIdFrameAddress:
|
||||
// mark_impure_fn(g, context, node);
|
||||
// return builtin_fn->return_type;
|
||||
// case BuiltinFnIdIntType:
|
||||
// return analyze_int_type(g, import, context, node);
|
||||
// }
|
||||
// zig_unreachable();
|
||||
//}
|
||||
@ -8215,34 +8265,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
|
||||
// return return_type;
|
||||
//}
|
||||
//
|
||||
//static TypeTableEntry *analyze_logic_bin_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
||||
// AstNode *node)
|
||||
//{
|
||||
// assert(node->type == NodeTypeBinOpExpr);
|
||||
// BinOpType bin_op_type = node->data.bin_op_expr.bin_op;
|
||||
//
|
||||
// AstNode *op1 = node->data.bin_op_expr.op1;
|
||||
// AstNode *op2 = node->data.bin_op_expr.op2;
|
||||
// TypeTableEntry *op1_type = analyze_expression(g, import, context, g->builtin_types.entry_bool, op1);
|
||||
// TypeTableEntry *op2_type = analyze_expression(g, import, context, g->builtin_types.entry_bool, op2);
|
||||
//
|
||||
// if (op1_type->id == TypeTableEntryIdInvalid ||
|
||||
// op2_type->id == TypeTableEntryIdInvalid)
|
||||
// {
|
||||
// return g->builtin_types.entry_invalid;
|
||||
// }
|
||||
//
|
||||
// ConstExprValue *op1_val = &get_resolved_expr(op1)->const_val;
|
||||
// ConstExprValue *op2_val = &get_resolved_expr(op2)->const_val;
|
||||
// if (!op1_val->ok || !op2_val->ok) {
|
||||
// return g->builtin_types.entry_bool;
|
||||
// }
|
||||
//
|
||||
// ConstExprValue *out_val = &get_resolved_expr(node)->const_val;
|
||||
// eval_const_expr_bin_op(op1_val, op1_type, bin_op_type, op2_val, op2_type, out_val);
|
||||
// return g->builtin_types.entry_bool;
|
||||
//}
|
||||
//
|
||||
//static TypeTableEntry *analyze_array_mult(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
||||
// TypeTableEntry *expected_type, AstNode *node)
|
||||
//{
|
||||
@ -8402,7 +8424,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
|
||||
// switch (builtin_fn->id) {
|
||||
// case BuiltinFnIdInvalid:
|
||||
// case BuiltinFnIdTypeof:
|
||||
// case BuiltinFnIdIntType:
|
||||
// zig_unreachable();
|
||||
// case BuiltinFnIdAddWithOverflow:
|
||||
// case BuiltinFnIdSubWithOverflow:
|
||||
|
||||
@ -279,8 +279,6 @@ 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:
|
||||
@ -755,6 +753,19 @@ static void ir_print_truncate(IrPrint *irp, IrInstructionTruncate *instruction)
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||
ir_print_prefix(irp, instruction);
|
||||
switch (instruction->id) {
|
||||
@ -931,6 +942,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||
case IrInstructionIdTruncate:
|
||||
ir_print_truncate(irp, (IrInstructionTruncate *)instruction);
|
||||
break;
|
||||
case IrInstructionIdIntType:
|
||||
ir_print_int_type(irp, (IrInstructionIntType *)instruction);
|
||||
break;
|
||||
case IrInstructionIdBoolNot:
|
||||
ir_print_bool_not(irp, (IrInstructionBoolNot *)instruction);
|
||||
break;
|
||||
}
|
||||
fprintf(irp->f, "\n");
|
||||
}
|
||||
|
||||
@ -299,6 +299,35 @@ fn testTruncate(x: u32) -> u8 {
|
||||
@truncate(u8, x)
|
||||
}
|
||||
|
||||
fn intTypeBuiltin() {
|
||||
assert(@intType(true, 8) == i8);
|
||||
assert(@intType(true, 16) == i16);
|
||||
assert(@intType(true, 32) == i32);
|
||||
assert(@intType(true, 64) == i64);
|
||||
|
||||
assert(@intType(false, 8) == u8);
|
||||
assert(@intType(false, 16) == u16);
|
||||
assert(@intType(false, 32) == u32);
|
||||
assert(@intType(false, 64) == u64);
|
||||
|
||||
assert(i8.bit_count == 8);
|
||||
assert(i16.bit_count == 16);
|
||||
assert(i32.bit_count == 32);
|
||||
assert(i64.bit_count == 64);
|
||||
|
||||
assert(i8.is_signed);
|
||||
assert(i16.is_signed);
|
||||
assert(i32.is_signed);
|
||||
assert(i64.is_signed);
|
||||
assert(isize.is_signed);
|
||||
|
||||
assert(!u8.is_signed);
|
||||
assert(!u16.is_signed);
|
||||
assert(!u32.is_signed);
|
||||
assert(!u64.is_signed);
|
||||
assert(!usize.is_signed);
|
||||
|
||||
}
|
||||
|
||||
fn assert(ok: bool) {
|
||||
if (!ok)
|
||||
@ -331,6 +360,7 @@ fn runAllTests() {
|
||||
fence();
|
||||
exactDivision();
|
||||
truncate();
|
||||
intTypeBuiltin();
|
||||
}
|
||||
|
||||
export nakedcc fn _start() -> unreachable {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user