@@ -692,8 +692,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionFieldParentPtr *
692
692
return IrInstructionIdFieldParentPtr;
693
693
}
694
694
695
- static constexpr IrInstructionId ir_instruction_id(IrInstructionOffsetOf *) {
696
- return IrInstructionIdOffsetOf;
695
+ static constexpr IrInstructionId ir_instruction_id(IrInstructionByteOffsetOf *) {
696
+ return IrInstructionIdByteOffsetOf;
697
+ }
698
+
699
+ static constexpr IrInstructionId ir_instruction_id(IrInstructionBitOffsetOf *) {
700
+ return IrInstructionIdBitOffsetOf;
697
701
}
698
702
699
703
static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeInfo *) {
@@ -2609,10 +2613,23 @@ static IrInstruction *ir_build_field_parent_ptr(IrBuilder *irb, Scope *scope, As
2609
2613
return &instruction->base;
2610
2614
}
2611
2615
2612
- static IrInstruction *ir_build_offset_of(IrBuilder *irb, Scope *scope, AstNode *source_node,
2616
+ static IrInstruction *ir_build_byte_offset_of(IrBuilder *irb, Scope *scope, AstNode *source_node,
2617
+ IrInstruction *type_value, IrInstruction *field_name)
2618
+ {
2619
+ IrInstructionByteOffsetOf *instruction = ir_build_instruction<IrInstructionByteOffsetOf>(irb, scope, source_node);
2620
+ instruction->type_value = type_value;
2621
+ instruction->field_name = field_name;
2622
+
2623
+ ir_ref_instruction(type_value, irb->current_basic_block);
2624
+ ir_ref_instruction(field_name, irb->current_basic_block);
2625
+
2626
+ return &instruction->base;
2627
+ }
2628
+
2629
+ static IrInstruction *ir_build_bit_offset_of(IrBuilder *irb, Scope *scope, AstNode *source_node,
2613
2630
IrInstruction *type_value, IrInstruction *field_name)
2614
2631
{
2615
- IrInstructionOffsetOf *instruction = ir_build_instruction<IrInstructionOffsetOf >(irb, scope, source_node);
2632
+ IrInstructionBitOffsetOf *instruction = ir_build_instruction<IrInstructionBitOffsetOf >(irb, scope, source_node);
2616
2633
instruction->type_value = type_value;
2617
2634
instruction->field_name = field_name;
2618
2635
@@ -4644,7 +4661,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4644
4661
IrInstruction *field_parent_ptr = ir_build_field_parent_ptr(irb, scope, node, arg0_value, arg1_value, arg2_value, nullptr);
4645
4662
return ir_lval_wrap(irb, scope, field_parent_ptr, lval);
4646
4663
}
4647
- case BuiltinFnIdOffsetOf :
4664
+ case BuiltinFnIdByteOffsetOf :
4648
4665
{
4649
4666
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4650
4667
IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
@@ -4656,7 +4673,22 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4656
4673
if (arg1_value == irb->codegen->invalid_instruction)
4657
4674
return arg1_value;
4658
4675
4659
- IrInstruction *offset_of = ir_build_offset_of(irb, scope, node, arg0_value, arg1_value);
4676
+ IrInstruction *offset_of = ir_build_byte_offset_of(irb, scope, node, arg0_value, arg1_value);
4677
+ return ir_lval_wrap(irb, scope, offset_of, lval);
4678
+ }
4679
+ case BuiltinFnIdBitOffsetOf:
4680
+ {
4681
+ AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4682
+ IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4683
+ if (arg0_value == irb->codegen->invalid_instruction)
4684
+ return arg0_value;
4685
+
4686
+ AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4687
+ IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
4688
+ if (arg1_value == irb->codegen->invalid_instruction)
4689
+ return arg1_value;
4690
+
4691
+ IrInstruction *offset_of = ir_build_bit_offset_of(irb, scope, node, arg0_value, arg1_value);
4660
4692
return ir_lval_wrap(irb, scope, offset_of, lval);
4661
4693
}
4662
4694
case BuiltinFnIdInlineCall:
@@ -16705,10 +16737,55 @@ static TypeTableEntry *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira,
16705
16737
return result_type;
16706
16738
}
16707
16739
16708
- static TypeTableEntry *ir_analyze_instruction_offset_of(IrAnalyze *ira,
16709
- IrInstructionOffsetOf *instruction)
16740
+ static TypeTableEntry *ir_analyze_instruction_byte_offset_of(IrAnalyze *ira,
16741
+ IrInstructionByteOffsetOf *instruction)
16742
+ {
16743
+ IrInstruction *type_value = instruction->type_value->other;
16744
+ TypeTableEntry *container_type = ir_resolve_type(ira, type_value);
16745
+ if (type_is_invalid(container_type))
16746
+ return ira->codegen->builtin_types.entry_invalid;
16747
+
16748
+ ensure_complete_type(ira->codegen, container_type);
16749
+ if (type_is_invalid(container_type))
16750
+ return ira->codegen->builtin_types.entry_invalid;
16751
+
16752
+ IrInstruction *field_name_value = instruction->field_name->other;
16753
+ Buf *field_name = ir_resolve_str(ira, field_name_value);
16754
+ if (!field_name)
16755
+ return ira->codegen->builtin_types.entry_invalid;
16756
+
16757
+ if (container_type->id != TypeTableEntryIdStruct) {
16758
+ ir_add_error(ira, type_value,
16759
+ buf_sprintf("expected struct type, found '%s'", buf_ptr(&container_type->name)));
16760
+ return ira->codegen->builtin_types.entry_invalid;
16761
+ }
16762
+
16763
+ TypeStructField *field = find_struct_type_field(container_type, field_name);
16764
+ if (field == nullptr) {
16765
+ ir_add_error(ira, field_name_value,
16766
+ buf_sprintf("struct '%s' has no field '%s'",
16767
+ buf_ptr(&container_type->name), buf_ptr(field_name)));
16768
+ return ira->codegen->builtin_types.entry_invalid;
16769
+ }
16770
+
16771
+ if (!type_has_bits(field->type_entry)) {
16772
+ ir_add_error(ira, field_name_value,
16773
+ buf_sprintf("zero-bit field '%s' in struct '%s' has no offset",
16774
+ buf_ptr(field_name), buf_ptr(&container_type->name)));
16775
+ return ira->codegen->builtin_types.entry_invalid;
16776
+ }
16777
+
16778
+ size_t byte_offset = LLVMOffsetOfElement(ira->codegen->target_data_ref, container_type->type_ref, field->gen_index);
16779
+ ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
16780
+ bigint_init_unsigned(&out_val->data.x_bigint, byte_offset);
16781
+ return ira->codegen->builtin_types.entry_num_lit_int;
16782
+ }
16783
+
16784
+ static TypeTableEntry *ir_analyze_instruction_bit_offset_of(IrAnalyze *ira,
16785
+ IrInstructionBitOffsetOf *instruction)
16710
16786
{
16711
16787
IrInstruction *type_value = instruction->type_value->other;
16788
+
16712
16789
TypeTableEntry *container_type = ir_resolve_type(ira, type_value);
16713
16790
if (type_is_invalid(container_type))
16714
16791
return ira->codegen->builtin_types.entry_invalid;
@@ -16742,6 +16819,7 @@ static TypeTableEntry *ir_analyze_instruction_offset_of(IrAnalyze *ira,
16742
16819
buf_ptr(field_name), buf_ptr(&container_type->name)));
16743
16820
return ira->codegen->builtin_types.entry_invalid;
16744
16821
}
16822
+
16745
16823
size_t byte_offset = LLVMOffsetOfElement(ira->codegen->target_data_ref, container_type->type_ref, field->gen_index);
16746
16824
ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
16747
16825
bigint_init_unsigned(&out_val->data.x_bigint, byte_offset);
@@ -21089,8 +21167,10 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
21089
21167
return ir_analyze_instruction_enum_tag_name(ira, (IrInstructionTagName *)instruction);
21090
21168
case IrInstructionIdFieldParentPtr:
21091
21169
return ir_analyze_instruction_field_parent_ptr(ira, (IrInstructionFieldParentPtr *)instruction);
21092
- case IrInstructionIdOffsetOf:
21093
- return ir_analyze_instruction_offset_of(ira, (IrInstructionOffsetOf *)instruction);
21170
+ case IrInstructionIdByteOffsetOf:
21171
+ return ir_analyze_instruction_byte_offset_of(ira, (IrInstructionByteOffsetOf *)instruction);
21172
+ case IrInstructionIdBitOffsetOf:
21173
+ return ir_analyze_instruction_bit_offset_of(ira, (IrInstructionBitOffsetOf *)instruction);
21094
21174
case IrInstructionIdTypeInfo:
21095
21175
return ir_analyze_instruction_type_info(ira, (IrInstructionTypeInfo *) instruction);
21096
21176
case IrInstructionIdTypeId:
@@ -21368,7 +21448,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
21368
21448
case IrInstructionIdTypeName:
21369
21449
case IrInstructionIdTagName:
21370
21450
case IrInstructionIdFieldParentPtr:
21371
- case IrInstructionIdOffsetOf:
21451
+ case IrInstructionIdByteOffsetOf:
21452
+ case IrInstructionIdBitOffsetOf:
21372
21453
case IrInstructionIdTypeInfo:
21373
21454
case IrInstructionIdTypeId:
21374
21455
case IrInstructionIdAlignCast:
0 commit comments