Commit 7eab62325b
Changed files (4)
src/all_types.hpp
@@ -1293,6 +1293,7 @@ enum BuiltinFnId {
BuiltinFnIdMemberType,
BuiltinFnIdMemberName,
BuiltinFnIdField,
+ BuiltinFnIdTypeInfo,
BuiltinFnIdTypeof,
BuiltinFnIdAddWithOverflow,
BuiltinFnIdSubWithOverflow,
@@ -2037,6 +2038,7 @@ enum IrInstructionId {
IrInstructionIdTagType,
IrInstructionIdFieldParentPtr,
IrInstructionIdOffsetOf,
+ IrInstructionIdTypeInfo,
IrInstructionIdTypeId,
IrInstructionIdSetEvalBranchQuota,
IrInstructionIdPtrTypeOf,
@@ -2858,6 +2860,12 @@ struct IrInstructionOffsetOf {
IrInstruction *field_name;
};
+struct IrInstructionTypeInfo {
+ IrInstruction base;
+
+ IrInstruction *type_value;
+};
+
struct IrInstructionTypeId {
IrInstruction base;
src/codegen.cpp
@@ -4502,6 +4502,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdDeclRef:
case IrInstructionIdSwitchVar:
case IrInstructionIdOffsetOf:
+ case IrInstructionIdTypeInfo:
case IrInstructionIdTypeId:
case IrInstructionIdSetEvalBranchQuota:
case IrInstructionIdPtrTypeOf:
@@ -6125,6 +6126,7 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdMemberType, "memberType", 2);
create_builtin_fn(g, BuiltinFnIdMemberName, "memberName", 2);
create_builtin_fn(g, BuiltinFnIdField, "field", 2);
+ create_builtin_fn(g, BuiltinFnIdTypeInfo, "typeInfo", 1);
create_builtin_fn(g, BuiltinFnIdTypeof, "typeOf", 1); // TODO rename to TypeOf
create_builtin_fn(g, BuiltinFnIdAddWithOverflow, "addWithOverflow", 4);
create_builtin_fn(g, BuiltinFnIdSubWithOverflow, "subWithOverflow", 4);
@@ -6344,6 +6346,157 @@ static void define_builtin_compile_vars(CodeGen *g) {
}
buf_appendf(contents, "};\n\n");
}
+ {
+ buf_appendf(contents,
+ "pub const IntInfo = struct {\n"
+ " is_signed: bool,\n"
+ " bits: u8,\n"
+ "};\n"
+ "\n"
+ "pub const FloatInfo = struct {\n"
+ " bits: u8,\n"
+ "};\n"
+ "\n"
+ "pub const PointerInfo = struct {\n"
+ " is_const: bool,\n"
+ " is_volatile: bool,\n"
+ " alignment: u32,\n"
+ " child: &TypeInfo,\n"
+ "};\n"
+ "\n"
+ "pub const ArrayInfo = struct {\n"
+ " len: u64,\n"
+ " child: &TypeInfo,\n"
+ "};\n"
+ "\n"
+ "pub const ContainerLayout = enum {\n"
+ " Auto,\n"
+ " Extern,\n"
+ " Packed,\n"
+ "};\n"
+ "\n"
+ "pub const StructFieldInfo = struct {\n"
+ " name: []const u8,\n"
+ " offset: usize,\n"
+ " type_info: TypeInfo,\n"
+ "};\n"
+ "\n"
+ "pub const StructInfo = struct {\n"
+ " layout: ContainerLayout,\n"
+ " fields: []StructFieldInfo,\n"
+ "};\n"
+ "\n"
+ "pub const NullableInfo = struct {\n"
+ " child: &TypeInfo,\n"
+ "};\n"
+ "\n"
+ "pub const ErrorUnionInfo = struct {\n"
+ " error_set: ErrorSetInfo,\n"
+ " payload: &TypeInfo,\n"
+ "};\n"
+ "\n"
+ "pub const ErrorInfo = struct {\n"
+ " name: []const u8,\n"
+ " value: usize,\n"
+ "};\n"
+ "\n"
+ "pub const ErrorSetInfo = struct {\n"
+ " errors: []ErrorInfo,\n"
+ "};\n"
+ "\n"
+ "pub const EnumFieldInfo = struct {\n"
+ " name: []const u8,\n"
+ " value: usize,\n"
+ "};\n"
+ "\n"
+ "pub const EnumInfo = struct {\n"
+ " layout: ContainerLayout,\n"
+ " tag_type: IntInfo,\n"
+ " fields: []EnumFieldInfo,\n"
+ "};\n"
+ "\n"
+ "pub const UnionFieldInfo = struct {\n"
+ " name: []const u8,\n"
+ " enum_field: EnumFieldInfo,\n"
+ " type_info: TypeInfo,\n"
+ "};\n"
+ "\n"
+ "pub const UnionInfo = struct {\n"
+ " layout: ContainerLayout,\n"
+ " tag_type: ?EnumInfo,\n"
+ " fields: []UnionFieldInfo,\n"
+ "};\n"
+ "\n"
+ "pub const CallingConvention = enum {\n"
+ " Unspecified,\n"
+ " C,\n"
+ " Cold,\n"
+ " Naked,\n"
+ " Stdcall,\n"
+ " Async,\n"
+ "};\n"
+ "\n"
+ "pub const FnArgInfo = struct {\n"
+ " is_comptime: bool,\n"
+ " name: []const u8,\n"
+ " type_info: TypeInfo,\n"
+ "};\n"
+ "\n"
+ "pub const FnInfo = struct {\n"
+ " calling_convention: CallingConvention,\n"
+ " is_generic: bool,\n"
+ " is_varargs: bool,\n"
+ " return_type: &TypeInfo,\n"
+ " args: []FnArgInfo,\n"
+ "};\n"
+ "\n"
+ "pub const BoundFnInfo = struct {\n"
+ " bound_type: &TypeInfo,\n"
+ " fn_info: FnInfo,\n"
+ "};\n"
+ "\n"
+ "pub const PromiseInfo = struct {\n"
+ " child: ?&TypeInfo,\n"
+ "};\n"
+ "\n"
+ "pub const TypeInfo = union(TypeId) {\n"
+ " Type: void,\n"
+ " Void: void,\n"
+ " Bool: void,\n"
+ " NoReturn: void,\n"
+ " Int: IntInfo,\n"
+ " Float: FloatInfo,\n"
+ " Pointer: PointerInfo,\n"
+ " Array: ArrayInfo,\n"
+ " Struct: StructInfo,\n"
+ " FloatLiteral: void,\n"
+ " IntLiteral: void,\n"
+ " UndefinedLiteral: void,\n"
+ " NullLiteral: void,\n"
+ " Nullable: NullableInfo,\n"
+ " ErrorUnion: ErrorUnionInfo,\n"
+ " ErrorSet: ErrorSetInfo,\n"
+ " Enum: EnumInfo,\n"
+ " Union: UnionInfo,\n"
+ " Fn: FnInfo,\n"
+ " Namespace: void,\n"
+ " Block: void,\n"
+ " BoundFn: BoundFnInfo,\n"
+ " ArgTuple: void,\n"
+ " Opaque: void,\n"
+ " Promise: PromiseInfo,\n"
+ "};\n\n");
+ assert(ContainerLayoutAuto == 0);
+ assert(ContainerLayoutExtern == 1);
+ assert(ContainerLayoutPacked == 2);
+
+ assert(CallingConventionUnspecified == 0);
+ assert(CallingConventionC == 1);
+ assert(CallingConventionCold == 2);
+ assert(CallingConventionNaked == 3);
+ assert(CallingConventionStdcall == 4);
+ assert(CallingConventionAsync == 5);
+ }
{
buf_appendf(contents,
"pub const FloatMode = enum {\n"
src/ir.cpp
@@ -615,6 +615,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionOffsetOf *) {
return IrInstructionIdOffsetOf;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeInfo *) {
+ return IrInstructionIdTypeInfo;
+}
+
static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeId *) {
return IrInstructionIdTypeId;
}
@@ -2440,6 +2444,16 @@ static IrInstruction *ir_build_offset_of(IrBuilder *irb, Scope *scope, AstNode *
return &instruction->base;
}
+static IrInstruction *ir_build_type_info(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *type_value) {
+ IrInstructionTypeInfo *instruction = ir_build_instruction<IrInstructionTypeInfo>(irb, scope, source_node);
+ instruction->type_value = type_value;
+
+ ir_ref_instruction(type_value, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_type_id(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *type_value)
{
@@ -4080,6 +4094,16 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return ir_build_load_ptr(irb, scope, node, ptr_instruction);
}
+ case BuiltinFnIdTypeInfo:
+ {
+ 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;
+
+ IrInstruction *type_info = ir_build_type_info(irb, scope, node, arg0_value);
+ return ir_lval_wrap(irb, scope, type_info, lval);
+ }
case BuiltinFnIdBreakpoint:
return ir_lval_wrap(irb, scope, ir_build_breakpoint(irb, scope, node), lval);
case BuiltinFnIdReturnAddress:
@@ -15669,6 +15693,26 @@ static TypeTableEntry *ir_analyze_instruction_offset_of(IrAnalyze *ira,
return ira->codegen->builtin_types.entry_num_lit_int;
}
+static TypeTableEntry *ir_analyze_instruction_type_info(IrAnalyze *ira,
+ IrInstructionTypeInfo *instruction)
+{
+ IrInstruction *type_value = instruction->type_value->other;
+ TypeTableEntry *type_entry = ir_resolve_type(ira, type_value);
+ if (type_is_invalid(type_entry))
+ return ira->codegen->builtin_types.entry_invalid;
+
+ ConstExprValue *var_value = get_builtin_value(ira->codegen, "TypeInfo");
+ assert(var_value->type->id == TypeTableEntryIdMetaType);
+ TypeTableEntry *result_type = var_value->data.x_type;
+
+ // TODO: Check if we need to explicitely make a &const TypeInfo here, I think we don't.
+ ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
+ out_val->data.x_struct.fields = create_const_vals(1);
+ // TODO: Fill the struct
+ zig_panic("Building TypeInfo...");
+ return result_type;
+}
+
static TypeTableEntry *ir_analyze_instruction_type_id(IrAnalyze *ira,
IrInstructionTypeId *instruction)
{
@@ -18555,6 +18599,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
return ir_analyze_instruction_field_parent_ptr(ira, (IrInstructionFieldParentPtr *)instruction);
case IrInstructionIdOffsetOf:
return ir_analyze_instruction_offset_of(ira, (IrInstructionOffsetOf *)instruction);
+ case IrInstructionIdTypeInfo:
+ return ir_analyze_instruction_type_info(ira, (IrInstructionTypeInfo *) instruction);
case IrInstructionIdTypeId:
return ir_analyze_instruction_type_id(ira, (IrInstructionTypeId *)instruction);
case IrInstructionIdSetEvalBranchQuota:
@@ -18821,6 +18867,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdTagName:
case IrInstructionIdFieldParentPtr:
case IrInstructionIdOffsetOf:
+ case IrInstructionIdTypeInfo:
case IrInstructionIdTypeId:
case IrInstructionIdAlignCast:
case IrInstructionIdOpaqueType:
src/ir_print.cpp
@@ -966,6 +966,12 @@ static void ir_print_offset_of(IrPrint *irp, IrInstructionOffsetOf *instruction)
fprintf(irp->f, ")");
}
+static void ir_print_type_info(IrPrint *irp, IrInstructionTypeInfo *instruction) {
+ fprintf(irp->f, "@typeInfo(");
+ ir_print_other_instruction(irp, instruction->type_value);
+ fprintf(irp->f, ")");
+}
+
static void ir_print_type_id(IrPrint *irp, IrInstructionTypeId *instruction) {
fprintf(irp->f, "@typeId(");
ir_print_other_instruction(irp, instruction->type_value);
@@ -1536,6 +1542,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdOffsetOf:
ir_print_offset_of(irp, (IrInstructionOffsetOf *)instruction);
break;
+ case IrInstructionIdTypeInfo:
+ ir_print_type_info(irp, (IrInstructionTypeInfo *)instruction);
+ break;
case IrInstructionIdTypeId:
ir_print_type_id(irp, (IrInstructionTypeId *)instruction);
break;