Commit 7eab62325b

Alexandros Naskos <alex_naskos@hotmail.com>
2018-04-24 00:49:22
One step towards @typeInfo
1 parent 89a4c37
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;