| ... | @@ -553,6 +553,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionFieldParentPtr * | ... | @@ -553,6 +553,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionFieldParentPtr * |
| 553 | return IrInstructionIdFieldParentPtr; | 553 | return IrInstructionIdFieldParentPtr; |
| 554 | } | 554 | } |
| 555 | | 555 | |
| | 556 | static constexpr IrInstructionId ir_instruction_id(IrInstructionOffsetOf *) { |
| | 557 | return IrInstructionIdOffsetOf; |
| | 558 | } |
| | 559 | |
| 556 | template<typename T> | 560 | template<typename T> |
| 557 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { | 561 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 558 | T *special_instruction = allocate<T>(1); | 562 | T *special_instruction = allocate<T>(1); |
| ... | @@ -2183,6 +2187,19 @@ static IrInstruction *ir_build_field_parent_ptr(IrBuilder *irb, Scope *scope, As | ... | @@ -2183,6 +2187,19 @@ static IrInstruction *ir_build_field_parent_ptr(IrBuilder *irb, Scope *scope, As |
| 2183 | return &instruction->base; | 2187 | return &instruction->base; |
| 2184 | } | 2188 | } |
| 2185 | | 2189 | |
| | 2190 | static IrInstruction *ir_build_offset_of(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| | 2191 | IrInstruction *type_value, IrInstruction *field_name) |
| | 2192 | { |
| | 2193 | IrInstructionOffsetOf *instruction = ir_build_instruction<IrInstructionOffsetOf>(irb, scope, source_node); |
| | 2194 | instruction->type_value = type_value; |
| | 2195 | instruction->field_name = field_name; |
| | 2196 | |
| | 2197 | ir_ref_instruction(type_value, irb->current_basic_block); |
| | 2198 | ir_ref_instruction(field_name, irb->current_basic_block); |
| | 2199 | |
| | 2200 | return &instruction->base; |
| | 2201 | } |
| | 2202 | |
| 2186 | static IrInstruction *ir_instruction_br_get_dep(IrInstructionBr *instruction, size_t index) { | 2203 | static IrInstruction *ir_instruction_br_get_dep(IrInstructionBr *instruction, size_t index) { |
| 2187 | return nullptr; | 2204 | return nullptr; |
| 2188 | } | 2205 | } |
| ... | @@ -2863,6 +2880,13 @@ static IrInstruction *ir_instruction_fieldparentptr_get_dep(IrInstructionFieldPa | ... | @@ -2863,6 +2880,13 @@ static IrInstruction *ir_instruction_fieldparentptr_get_dep(IrInstructionFieldPa |
| 2863 | } | 2880 | } |
| 2864 | } | 2881 | } |
| 2865 | | 2882 | |
| | 2883 | static IrInstruction *ir_instruction_offsetof_get_dep(IrInstructionOffsetOf *instruction, size_t index) { |
| | 2884 | switch (index) { |
| | 2885 | case 0: return instruction->type_value; |
| | 2886 | case 1: return instruction->field_name; |
| | 2887 | default: return nullptr; |
| | 2888 | } |
| | 2889 | } |
| 2866 | | 2890 | |
| 2867 | static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t index) { | 2891 | static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t index) { |
| 2868 | switch (instruction->id) { | 2892 | switch (instruction->id) { |
| ... | @@ -3058,6 +3082,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t | ... | @@ -3058,6 +3082,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t |
| 3058 | return ir_instruction_setfnrefinline_get_dep((IrInstructionSetFnRefInline *) instruction, index); | 3082 | return ir_instruction_setfnrefinline_get_dep((IrInstructionSetFnRefInline *) instruction, index); |
| 3059 | case IrInstructionIdFieldParentPtr: | 3083 | case IrInstructionIdFieldParentPtr: |
| 3060 | return ir_instruction_fieldparentptr_get_dep((IrInstructionFieldParentPtr *) instruction, index); | 3084 | return ir_instruction_fieldparentptr_get_dep((IrInstructionFieldParentPtr *) instruction, index); |
| | 3085 | case IrInstructionIdOffsetOf: |
| | 3086 | return ir_instruction_offsetof_get_dep((IrInstructionOffsetOf *) instruction, index); |
| 3061 | } | 3087 | } |
| 3062 | zig_unreachable(); | 3088 | zig_unreachable(); |
| 3063 | } | 3089 | } |
| ... | @@ -4384,6 +4410,20 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo | ... | @@ -4384,6 +4410,20 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4384 | | 4410 | |
| 4385 | return ir_build_field_parent_ptr(irb, scope, node, arg0_value, arg1_value, arg2_value, nullptr); | 4411 | return ir_build_field_parent_ptr(irb, scope, node, arg0_value, arg1_value, arg2_value, nullptr); |
| 4386 | } | 4412 | } |
| | 4413 | case BuiltinFnIdOffsetOf: |
| | 4414 | { |
| | 4415 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); |
| | 4416 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); |
| | 4417 | if (arg0_value == irb->codegen->invalid_instruction) |
| | 4418 | return arg0_value; |
| | 4419 | |
| | 4420 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); |
| | 4421 | IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); |
| | 4422 | if (arg1_value == irb->codegen->invalid_instruction) |
| | 4423 | return arg1_value; |
| | 4424 | |
| | 4425 | return ir_build_offset_of(irb, scope, node, arg0_value, arg1_value); |
| | 4426 | } |
| 4387 | } | 4427 | } |
| 4388 | zig_unreachable(); | 4428 | zig_unreachable(); |
| 4389 | } | 4429 | } |
| ... | @@ -11401,6 +11441,41 @@ static TypeTableEntry *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira, | ... | @@ -11401,6 +11441,41 @@ static TypeTableEntry *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira, |
| 11401 | return result_type; | 11441 | return result_type; |
| 11402 | } | 11442 | } |
| 11403 | | 11443 | |
| | 11444 | static TypeTableEntry *ir_analyze_instruction_offset_of(IrAnalyze *ira, |
| | 11445 | IrInstructionOffsetOf *instruction) |
| | 11446 | { |
| | 11447 | IrInstruction *type_value = instruction->type_value->other; |
| | 11448 | TypeTableEntry *container_type = ir_resolve_type(ira, type_value); |
| | 11449 | if (type_is_invalid(container_type)) |
| | 11450 | return ira->codegen->builtin_types.entry_invalid; |
| | 11451 | |
| | 11452 | ensure_complete_type(ira->codegen, container_type); |
| | 11453 | |
| | 11454 | IrInstruction *field_name_value = instruction->field_name->other; |
| | 11455 | Buf *field_name = ir_resolve_str(ira, field_name_value); |
| | 11456 | if (!field_name) |
| | 11457 | return ira->codegen->builtin_types.entry_invalid; |
| | 11458 | |
| | 11459 | if (container_type->id != TypeTableEntryIdStruct) { |
| | 11460 | ir_add_error(ira, type_value, |
| | 11461 | buf_sprintf("expected struct type, found '%s'", buf_ptr(&container_type->name))); |
| | 11462 | return ira->codegen->builtin_types.entry_invalid; |
| | 11463 | } |
| | 11464 | |
| | 11465 | TypeStructField *field = find_struct_type_field(container_type, field_name); |
| | 11466 | if (field == nullptr) { |
| | 11467 | ir_add_error(ira, field_name_value, |
| | 11468 | buf_sprintf("struct '%s' has no field '%s'", |
| | 11469 | buf_ptr(&container_type->name), buf_ptr(field_name))); |
| | 11470 | return ira->codegen->builtin_types.entry_invalid; |
| | 11471 | } |
| | 11472 | |
| | 11473 | size_t byte_offset = LLVMOffsetOfElement(ira->codegen->target_data_ref, container_type->type_ref, field->gen_index); |
| | 11474 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); |
| | 11475 | bignum_init_unsigned(&out_val->data.x_bignum, byte_offset); |
| | 11476 | return ira->codegen->builtin_types.entry_num_lit_int; |
| | 11477 | } |
| | 11478 | |
| 11404 | static TypeTableEntry *ir_analyze_instruction_type_name(IrAnalyze *ira, IrInstructionTypeName *instruction) { | 11479 | static TypeTableEntry *ir_analyze_instruction_type_name(IrAnalyze *ira, IrInstructionTypeName *instruction) { |
| 11405 | IrInstruction *type_value = instruction->type_value->other; | 11480 | IrInstruction *type_value = instruction->type_value->other; |
| 11406 | TypeTableEntry *type_entry = ir_resolve_type(ira, type_value); | 11481 | TypeTableEntry *type_entry = ir_resolve_type(ira, type_value); |
| ... | @@ -12921,6 +12996,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -12921,6 +12996,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 12921 | return ir_analyze_instruction_set_fn_ref_inline(ira, (IrInstructionSetFnRefInline *)instruction); | 12996 | return ir_analyze_instruction_set_fn_ref_inline(ira, (IrInstructionSetFnRefInline *)instruction); |
| 12922 | case IrInstructionIdFieldParentPtr: | 12997 | case IrInstructionIdFieldParentPtr: |
| 12923 | return ir_analyze_instruction_field_parent_ptr(ira, (IrInstructionFieldParentPtr *)instruction); | 12998 | return ir_analyze_instruction_field_parent_ptr(ira, (IrInstructionFieldParentPtr *)instruction); |
| | 12999 | case IrInstructionIdOffsetOf: |
| | 13000 | return ir_analyze_instruction_offset_of(ira, (IrInstructionOffsetOf *)instruction); |
| 12924 | case IrInstructionIdMaybeWrap: | 13001 | case IrInstructionIdMaybeWrap: |
| 12925 | case IrInstructionIdErrWrapCode: | 13002 | case IrInstructionIdErrWrapCode: |
| 12926 | case IrInstructionIdErrWrapPayload: | 13003 | case IrInstructionIdErrWrapPayload: |
| ... | @@ -13108,6 +13185,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -13108,6 +13185,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 13108 | case IrInstructionIdEnumTagName: | 13185 | case IrInstructionIdEnumTagName: |
| 13109 | case IrInstructionIdSetFnRefInline: | 13186 | case IrInstructionIdSetFnRefInline: |
| 13110 | case IrInstructionIdFieldParentPtr: | 13187 | case IrInstructionIdFieldParentPtr: |
| | 13188 | case IrInstructionIdOffsetOf: |
| 13111 | return false; | 13189 | return false; |
| 13112 | case IrInstructionIdAsm: | 13190 | case IrInstructionIdAsm: |
| 13113 | { | 13191 | { |