One step towards @typeInfo

master
Alexandros Naskos 2018-04-24 01:49:22 +03:00
parent 89a4c373d3
commit 7eab62325b
4 changed files with 217 additions and 0 deletions

View File

@ -1293,6 +1293,7 @@ enum BuiltinFnId {
BuiltinFnIdMemberType, BuiltinFnIdMemberType,
BuiltinFnIdMemberName, BuiltinFnIdMemberName,
BuiltinFnIdField, BuiltinFnIdField,
BuiltinFnIdTypeInfo,
BuiltinFnIdTypeof, BuiltinFnIdTypeof,
BuiltinFnIdAddWithOverflow, BuiltinFnIdAddWithOverflow,
BuiltinFnIdSubWithOverflow, BuiltinFnIdSubWithOverflow,
@ -2037,6 +2038,7 @@ enum IrInstructionId {
IrInstructionIdTagType, IrInstructionIdTagType,
IrInstructionIdFieldParentPtr, IrInstructionIdFieldParentPtr,
IrInstructionIdOffsetOf, IrInstructionIdOffsetOf,
IrInstructionIdTypeInfo,
IrInstructionIdTypeId, IrInstructionIdTypeId,
IrInstructionIdSetEvalBranchQuota, IrInstructionIdSetEvalBranchQuota,
IrInstructionIdPtrTypeOf, IrInstructionIdPtrTypeOf,
@ -2858,6 +2860,12 @@ struct IrInstructionOffsetOf {
IrInstruction *field_name; IrInstruction *field_name;
}; };
struct IrInstructionTypeInfo {
IrInstruction base;
IrInstruction *type_value;
};
struct IrInstructionTypeId { struct IrInstructionTypeId {
IrInstruction base; IrInstruction base;

View File

@ -4502,6 +4502,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdDeclRef: case IrInstructionIdDeclRef:
case IrInstructionIdSwitchVar: case IrInstructionIdSwitchVar:
case IrInstructionIdOffsetOf: case IrInstructionIdOffsetOf:
case IrInstructionIdTypeInfo:
case IrInstructionIdTypeId: case IrInstructionIdTypeId:
case IrInstructionIdSetEvalBranchQuota: case IrInstructionIdSetEvalBranchQuota:
case IrInstructionIdPtrTypeOf: case IrInstructionIdPtrTypeOf:
@ -6125,6 +6126,7 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdMemberType, "memberType", 2); create_builtin_fn(g, BuiltinFnIdMemberType, "memberType", 2);
create_builtin_fn(g, BuiltinFnIdMemberName, "memberName", 2); create_builtin_fn(g, BuiltinFnIdMemberName, "memberName", 2);
create_builtin_fn(g, BuiltinFnIdField, "field", 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, BuiltinFnIdTypeof, "typeOf", 1); // TODO rename to TypeOf
create_builtin_fn(g, BuiltinFnIdAddWithOverflow, "addWithOverflow", 4); create_builtin_fn(g, BuiltinFnIdAddWithOverflow, "addWithOverflow", 4);
create_builtin_fn(g, BuiltinFnIdSubWithOverflow, "subWithOverflow", 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, "};\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, buf_appendf(contents,
"pub const FloatMode = enum {\n" "pub const FloatMode = enum {\n"

View File

@ -615,6 +615,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionOffsetOf *) {
return IrInstructionIdOffsetOf; return IrInstructionIdOffsetOf;
} }
static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeInfo *) {
return IrInstructionIdTypeInfo;
}
static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeId *) { static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeId *) {
return IrInstructionIdTypeId; return IrInstructionIdTypeId;
} }
@ -2440,6 +2444,16 @@ static IrInstruction *ir_build_offset_of(IrBuilder *irb, Scope *scope, AstNode *
return &instruction->base; 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, static IrInstruction *ir_build_type_id(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *type_value) 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); 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: case BuiltinFnIdBreakpoint:
return ir_lval_wrap(irb, scope, ir_build_breakpoint(irb, scope, node), lval); return ir_lval_wrap(irb, scope, ir_build_breakpoint(irb, scope, node), lval);
case BuiltinFnIdReturnAddress: case BuiltinFnIdReturnAddress:
@ -15669,6 +15693,26 @@ static TypeTableEntry *ir_analyze_instruction_offset_of(IrAnalyze *ira,
return ira->codegen->builtin_types.entry_num_lit_int; 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, static TypeTableEntry *ir_analyze_instruction_type_id(IrAnalyze *ira,
IrInstructionTypeId *instruction) 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); return ir_analyze_instruction_field_parent_ptr(ira, (IrInstructionFieldParentPtr *)instruction);
case IrInstructionIdOffsetOf: case IrInstructionIdOffsetOf:
return ir_analyze_instruction_offset_of(ira, (IrInstructionOffsetOf *)instruction); return ir_analyze_instruction_offset_of(ira, (IrInstructionOffsetOf *)instruction);
case IrInstructionIdTypeInfo:
return ir_analyze_instruction_type_info(ira, (IrInstructionTypeInfo *) instruction);
case IrInstructionIdTypeId: case IrInstructionIdTypeId:
return ir_analyze_instruction_type_id(ira, (IrInstructionTypeId *)instruction); return ir_analyze_instruction_type_id(ira, (IrInstructionTypeId *)instruction);
case IrInstructionIdSetEvalBranchQuota: case IrInstructionIdSetEvalBranchQuota:
@ -18821,6 +18867,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdTagName: case IrInstructionIdTagName:
case IrInstructionIdFieldParentPtr: case IrInstructionIdFieldParentPtr:
case IrInstructionIdOffsetOf: case IrInstructionIdOffsetOf:
case IrInstructionIdTypeInfo:
case IrInstructionIdTypeId: case IrInstructionIdTypeId:
case IrInstructionIdAlignCast: case IrInstructionIdAlignCast:
case IrInstructionIdOpaqueType: case IrInstructionIdOpaqueType:

View File

@ -966,6 +966,12 @@ static void ir_print_offset_of(IrPrint *irp, IrInstructionOffsetOf *instruction)
fprintf(irp->f, ")"); 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) { static void ir_print_type_id(IrPrint *irp, IrInstructionTypeId *instruction) {
fprintf(irp->f, "@typeId("); fprintf(irp->f, "@typeId(");
ir_print_other_instruction(irp, instruction->type_value); ir_print_other_instruction(irp, instruction->type_value);
@ -1536,6 +1542,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdOffsetOf: case IrInstructionIdOffsetOf:
ir_print_offset_of(irp, (IrInstructionOffsetOf *)instruction); ir_print_offset_of(irp, (IrInstructionOffsetOf *)instruction);
break; break;
case IrInstructionIdTypeInfo:
ir_print_type_info(irp, (IrInstructionTypeInfo *)instruction);
break;
case IrInstructionIdTypeId: case IrInstructionIdTypeId:
ir_print_type_id(irp, (IrInstructionTypeId *)instruction); ir_print_type_id(irp, (IrInstructionTypeId *)instruction);
break; break;