aboutsummaryrefslogtreecommitdiff
path: root/src/ir.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2019-09-04 11:12:24 -0400
committerAndrew Kelley <andrew@ziglang.org>2019-09-04 11:12:24 -0400
commit53a6aea216d7b1e6b6072d30f2d51ed801d9e0f9 (patch)
tree41809dbfec90af3c6320239cd186f9ede7b8b8e1 /src/ir.cpp
parent77a5f888be664f9ef09e2c93f52338448e992e00 (diff)
parentac7703f65f7acc9137e28ded97659fbaadea4e66 (diff)
downloadzig-53a6aea216d7b1e6b6072d30f2d51ed801d9e0f9.tar.gz
zig-53a6aea216d7b1e6b6072d30f2d51ed801d9e0f9.zip
Merge branch 'marler8997-typeBuiltin'
Diffstat (limited to 'src/ir.cpp')
-rw-r--r--src/ir.cpp187
1 files changed, 181 insertions, 6 deletions
diff --git a/src/ir.cpp b/src/ir.cpp
index 7415a2dd6b..9547b1ec61 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -912,6 +912,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeInfo *) {
return IrInstructionIdTypeInfo;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionType *) {
+ return IrInstructionIdType;
+}
+
static constexpr IrInstructionId ir_instruction_id(IrInstructionHasField *) {
return IrInstructionIdHasField;
}
@@ -2907,6 +2911,15 @@ static IrInstruction *ir_build_type_info(IrBuilder *irb, Scope *scope, AstNode *
return &instruction->base;
}
+static IrInstruction *ir_build_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_info) {
+ IrInstructionType *instruction = ir_build_instruction<IrInstructionType>(irb, scope, source_node);
+ instruction->type_info = type_info;
+
+ ir_ref_instruction(type_info, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_type_id(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *type_value)
{
@@ -5046,6 +5059,16 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
IrInstruction *type_info = ir_build_type_info(irb, scope, node, arg0_value);
return ir_lval_wrap(irb, scope, type_info, lval, result_loc);
}
+ case BuiltinFnIdType:
+ {
+ AstNode *arg_node = node->data.fn_call_expr.params.at(0);
+ IrInstruction *arg = ir_gen_node(irb, arg_node, scope);
+ if (arg == irb->codegen->invalid_instruction)
+ return arg;
+
+ IrInstruction *type = ir_build_type(irb, scope, node, arg);
+ return ir_lval_wrap(irb, scope, type, lval, result_loc);
+ }
case BuiltinFnIdBreakpoint:
return ir_lval_wrap(irb, scope, ir_build_breakpoint(irb, scope, node), lval, result_loc);
case BuiltinFnIdReturnAddress:
@@ -20092,14 +20115,27 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
return ErrorNone;
}
-static uint32_t ptr_len_to_size_enum_index(PtrLen ptr_len) {
+static BuiltinPtrSize ptr_len_to_size_enum_index(PtrLen ptr_len) {
switch (ptr_len) {
case PtrLenSingle:
- return 0;
+ return BuiltinPtrSizeOne;
case PtrLenUnknown:
- return 1;
+ return BuiltinPtrSizeMany;
case PtrLenC:
- return 3;
+ return BuiltinPtrSizeC;
+ }
+ zig_unreachable();
+}
+
+static PtrLen size_enum_index_to_ptr_len(BuiltinPtrSize size_enum_index) {
+ switch (size_enum_index) {
+ case BuiltinPtrSizeOne:
+ return PtrLenSingle;
+ case BuiltinPtrSizeMany:
+ case BuiltinPtrSizeSlice:
+ return PtrLenUnknown;
+ case BuiltinPtrSizeC:
+ return PtrLenC;
}
zig_unreachable();
}
@@ -20107,10 +20143,10 @@ static uint32_t ptr_len_to_size_enum_index(PtrLen ptr_len) {
static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_type_entry) {
Error err;
ZigType *attrs_type;
- uint32_t size_enum_index;
+ BuiltinPtrSize size_enum_index;
if (is_slice(ptr_type_entry)) {
attrs_type = ptr_type_entry->data.structure.fields[slice_ptr_index].type_entry;
- size_enum_index = 2;
+ size_enum_index = BuiltinPtrSizeSlice;
} else if (ptr_type_entry->id == ZigTypeIdPointer) {
attrs_type = ptr_type_entry;
size_enum_index = ptr_len_to_size_enum_index(ptr_type_entry->data.pointer.ptr_len);
@@ -20789,6 +20825,142 @@ static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira,
return result;
}
+static ConstExprValue *get_const_field(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index)
+{
+ ensure_field_index(struct_value->type, name, field_index);
+ assert(struct_value->data.x_struct.fields[field_index].special == ConstValSpecialStatic);
+ return &struct_value->data.x_struct.fields[field_index];
+}
+
+static bool get_const_field_bool(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index)
+{
+ ConstExprValue *value = get_const_field(ira, struct_value, name, field_index);
+ assert(value->type == ira->codegen->builtin_types.entry_bool);
+ return value->data.x_bool;
+}
+
+static BigInt *get_const_field_lit_int(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index)
+{
+ ConstExprValue *value = get_const_field(ira, struct_value, name, field_index);
+ assert(value->type == ira->codegen->builtin_types.entry_num_lit_int);
+ return &value->data.x_bigint;
+}
+
+static ZigType *get_const_field_meta_type(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index)
+{
+ ConstExprValue *value = get_const_field(ira, struct_value, name, field_index);
+ assert(value->type == ira->codegen->builtin_types.entry_type);
+ return value->data.x_type;
+}
+
+static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, ZigTypeId tagTypeId, ConstExprValue *payload) {
+ switch (tagTypeId) {
+ case ZigTypeIdInvalid:
+ zig_unreachable();
+ case ZigTypeIdMetaType:
+ return ira->codegen->builtin_types.entry_type;
+ case ZigTypeIdVoid:
+ return ira->codegen->builtin_types.entry_void;
+ case ZigTypeIdBool:
+ return ira->codegen->builtin_types.entry_bool;
+ case ZigTypeIdUnreachable:
+ return ira->codegen->builtin_types.entry_unreachable;
+ case ZigTypeIdInt:
+ assert(payload->special == ConstValSpecialStatic);
+ assert(payload->type == ir_type_info_get_type(ira, "Int", nullptr));
+ return get_int_type(ira->codegen,
+ get_const_field_bool(ira, payload, "is_signed", 0),
+ bigint_as_u32(get_const_field_lit_int(ira, payload, "bits", 1)));
+ case ZigTypeIdFloat:
+ {
+ assert(payload->special == ConstValSpecialStatic);
+ assert(payload->type == ir_type_info_get_type(ira, "Float", nullptr));
+ uint32_t bits = bigint_as_u32(get_const_field_lit_int(ira, payload, "bits", 0));
+ switch (bits) {
+ case 16: return ira->codegen->builtin_types.entry_f16;
+ case 32: return ira->codegen->builtin_types.entry_f32;
+ case 64: return ira->codegen->builtin_types.entry_f64;
+ case 128: return ira->codegen->builtin_types.entry_f128;
+ }
+ ir_add_error(ira, instruction,
+ buf_sprintf("%d-bit float unsupported", bits));
+ return nullptr;
+ }
+ case ZigTypeIdPointer:
+ {
+ ZigType *type_info_pointer_type = ir_type_info_get_type(ira, "Pointer", nullptr);
+ assert(payload->special == ConstValSpecialStatic);
+ assert(payload->type == type_info_pointer_type);
+ ConstExprValue *size_value = get_const_field(ira, payload, "size", 0);
+ assert(size_value->type == ir_type_info_get_type(ira, "Size", type_info_pointer_type));
+ BuiltinPtrSize size_enum_index = (BuiltinPtrSize)bigint_as_u32(&size_value->data.x_enum_tag);
+ PtrLen ptr_len = size_enum_index_to_ptr_len(size_enum_index);
+ ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen,
+ get_const_field_meta_type(ira, payload, "child", 4),
+ get_const_field_bool(ira, payload, "is_const", 1),
+ get_const_field_bool(ira, payload, "is_volatile", 2),
+ ptr_len,
+ bigint_as_u32(get_const_field_lit_int(ira, payload, "alignment", 3)),
+ 0, // bit_offset_in_host
+ 0, // host_int_bytes
+ get_const_field_bool(ira, payload, "is_allowzero", 5)
+ );
+ if (size_enum_index != 2)
+ return ptr_type;
+ return get_slice_type(ira->codegen, ptr_type);
+ }
+ case ZigTypeIdComptimeFloat:
+ return ira->codegen->builtin_types.entry_num_lit_float;
+ case ZigTypeIdComptimeInt:
+ return ira->codegen->builtin_types.entry_num_lit_int;
+ case ZigTypeIdUndefined:
+ return ira->codegen->builtin_types.entry_undef;
+ case ZigTypeIdNull:
+ return ira->codegen->builtin_types.entry_null;
+ case ZigTypeIdArray:
+ case ZigTypeIdOptional:
+ case ZigTypeIdErrorUnion:
+ case ZigTypeIdErrorSet:
+ case ZigTypeIdEnum:
+ case ZigTypeIdOpaque:
+ case ZigTypeIdFnFrame:
+ case ZigTypeIdAnyFrame:
+ case ZigTypeIdVector:
+ case ZigTypeIdEnumLiteral:
+ ir_add_error(ira, instruction, buf_sprintf(
+ "TODO implement @Type for 'TypeInfo.%s': see https://github.com/ziglang/zig/issues/2907", type_id_name(tagTypeId)));
+ return nullptr;
+ case ZigTypeIdUnion:
+ case ZigTypeIdFn:
+ case ZigTypeIdBoundFn:
+ case ZigTypeIdArgTuple:
+ case ZigTypeIdStruct:
+ ir_add_error(ira, instruction, buf_sprintf(
+ "@Type not availble for 'TypeInfo.%s'", type_id_name(tagTypeId)));
+ return nullptr;
+ }
+ zig_unreachable();
+}
+
+static IrInstruction *ir_analyze_instruction_type(IrAnalyze *ira, IrInstructionType *instruction) {
+ IrInstruction *type_info_ir = instruction->type_info->child;
+ if (type_is_invalid(type_info_ir->value.type))
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *casted_ir = ir_implicit_cast(ira, type_info_ir, ir_type_info_get_type(ira, nullptr, nullptr));
+ if (type_is_invalid(casted_ir->value.type))
+ return ira->codegen->invalid_instruction;
+
+ ConstExprValue *type_info_value = ir_resolve_const(ira, casted_ir, UndefBad);
+ if (!type_info_value)
+ return ira->codegen->invalid_instruction;
+ ZigTypeId typeId = type_id_at_index(bigint_as_usize(&type_info_value->data.x_union.tag));
+ ZigType *type = type_info_to_type(ira, type_info_ir, typeId, type_info_value->data.x_union.payload);
+ if (!type)
+ return ira->codegen->invalid_instruction;
+ return ir_const_type(ira, &instruction->base, type);
+}
+
static IrInstruction *ir_analyze_instruction_type_id(IrAnalyze *ira,
IrInstructionTypeId *instruction)
{
@@ -25295,6 +25467,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
return ir_analyze_instruction_bit_offset_of(ira, (IrInstructionBitOffsetOf *)instruction);
case IrInstructionIdTypeInfo:
return ir_analyze_instruction_type_info(ira, (IrInstructionTypeInfo *) instruction);
+ case IrInstructionIdType:
+ return ir_analyze_instruction_type(ira, (IrInstructionType *)instruction);
case IrInstructionIdHasField:
return ir_analyze_instruction_has_field(ira, (IrInstructionHasField *) instruction);
case IrInstructionIdTypeId:
@@ -25598,6 +25772,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdByteOffsetOf:
case IrInstructionIdBitOffsetOf:
case IrInstructionIdTypeInfo:
+ case IrInstructionIdType:
case IrInstructionIdHasField:
case IrInstructionIdTypeId:
case IrInstructionIdAlignCast: