| ... | ... | @@ -421,6 +421,8 @@ const Analyze = struct { |
| 421 | 421 | .fntype => return self.analyzeInstFnType(func, old_inst.cast(text.Inst.FnType).?), |
| 422 | 422 | .intcast => return self.analyzeInstIntCast(func, old_inst.cast(text.Inst.IntCast).?), |
| 423 | 423 | .bitcast => return self.analyzeInstBitCast(func, old_inst.cast(text.Inst.BitCast).?), |
| 424 | .elemptr => return self.analyzeInstElemPtr(func, old_inst.cast(text.Inst.ElemPtr).?), |
| 425 | .add => return self.analyzeInstAdd(func, old_inst.cast(text.Inst.Add).?), |
| 424 | 426 | } |
| 425 | 427 | } |
| 426 | 428 | |
| ... | ... | @@ -569,6 +571,67 @@ const Analyze = struct { |
| 569 | 571 | return self.bitcast(func, dest_type, operand); |
| 570 | 572 | } |
| 571 | 573 | |
| 574 | fn analyzeInstElemPtr(self: *Analyze, func: ?*Fn, inst: *text.Inst.ElemPtr) InnerError!*Inst { |
| 575 | const array_ptr = try self.resolveInst(func, inst.positionals.array_ptr); |
| 576 | const uncasted_index = try self.resolveInst(func, inst.positionals.index); |
| 577 | const elem_index = try self.coerce(func, Type.initTag(.usize), uncasted_index); |
| 578 | |
| 579 | if (array_ptr.ty.isSinglePointer() and array_ptr.ty.elemType().zigTypeTag() == .Array) { |
| 580 | if (array_ptr.value()) |array_ptr_val| { |
| 581 | if (elem_index.value()) |index_val| { |
| 582 | // Both array pointer and index are compile-time known. |
| 583 | const index_u64 = index_val.toUnsignedInt(); |
| 584 | // @intCast here because it would have been impossible to construct a value that |
| 585 | // required a larger index. |
| 586 | const elem_val = try array_ptr_val.elemValueAt(&self.arena.allocator, @intCast(usize, index_u64)); |
| 587 | |
| 588 | const ref_payload = try self.arena.allocator.create(Value.Payload.RefVal); |
| 589 | ref_payload.* = .{ .val = elem_val }; |
| 590 | |
| 591 | const type_payload = try self.arena.allocator.create(Type.Payload.SingleConstPointer); |
| 592 | type_payload.* = .{ .pointee_type = array_ptr.ty.elemType().elemType() }; |
| 593 | |
| 594 | return self.constInst(inst.base.src, .{ |
| 595 | .ty = Type.initPayload(&type_payload.base), |
| 596 | .val = Value.initPayload(&ref_payload.base), |
| 597 | }); |
| 598 | } |
| 599 | } |
| 600 | } |
| 601 | |
| 602 | return self.fail(inst.base.src, "TODO implement more analyze elemptr", .{}); |
| 603 | } |
| 604 | |
| 605 | fn analyzeInstAdd(self: *Analyze, func: ?*Fn, inst: *text.Inst.Add) InnerError!*Inst { |
| 606 | const lhs = try self.resolveInst(func, inst.positionals.lhs); |
| 607 | const rhs = try self.resolveInst(func, inst.positionals.rhs); |
| 608 | |
| 609 | if (lhs.ty.zigTypeTag() == .Int and rhs.ty.zigTypeTag() == .Int) { |
| 610 | if (lhs.value()) |lhs_val| { |
| 611 | if (rhs.value()) |rhs_val| { |
| 612 | const lhs_bigint = try lhs_val.toBigInt(&self.arena.allocator); |
| 613 | const rhs_bigint = try rhs_val.toBigInt(&self.arena.allocator); |
| 614 | var result_bigint = try BigInt.init(&self.arena.allocator); |
| 615 | try BigInt.add(&result_bigint, lhs_bigint, rhs_bigint); |
| 616 | |
| 617 | if (!lhs.ty.eql(rhs.ty)) { |
| 618 | return self.fail(inst.base.src, "TODO implement peer type resolution", .{}); |
| 619 | } |
| 620 | |
| 621 | const val_payload = try self.arena.allocator.create(Value.Payload.IntBig); |
| 622 | val_payload.* = .{ .big_int = result_bigint }; |
| 623 | |
| 624 | return self.constInst(inst.base.src, .{ |
| 625 | .ty = lhs.ty, |
| 626 | .val = Value.initPayload(&val_payload.base), |
| 627 | }); |
| 628 | } |
| 629 | } |
| 630 | } |
| 631 | |
| 632 | return self.fail(inst.base.src, "TODO implement more analyze add", .{}); |
| 633 | } |
| 634 | |
| 572 | 635 | fn analyzeInstDeref(self: *Analyze, func: ?*Fn, deref: *text.Inst.Deref) InnerError!*Inst { |
| 573 | 636 | const ptr = try self.resolveInst(func, deref.positionals.ptr); |
| 574 | 637 | const elem_ty = switch (ptr.ty.zigTypeTag()) { |
| ... | ... | @@ -654,7 +717,22 @@ const Analyze = struct { |
| 654 | 717 | return self.constInst(inst.src, .{ .ty = dest_type, .val = val }); |
| 655 | 718 | } |
| 656 | 719 | |
| 657 | | return self.fail(inst.src, "TODO implement type coercion", .{}); |
| 720 | // integer widening |
| 721 | if (inst.ty.zigTypeTag() == .Int and dest_type.zigTypeTag() == .Int) { |
| 722 | const src_info = inst.ty.intInfo(self.target); |
| 723 | const dst_info = dest_type.intInfo(self.target); |
| 724 | if (src_info.signed == dst_info.signed and dst_info.bits >= src_info.bits) { |
| 725 | if (inst.value()) |val| { |
| 726 | return self.constInst(inst.src, .{ .ty = dest_type, .val = val }); |
| 727 | } else { |
| 728 | return self.fail(inst.src, "TODO implement runtime integer widening", .{}); |
| 729 | } |
| 730 | } else { |
| 731 | return self.fail(inst.src, "TODO implement more int widening {} to {}", .{ inst.ty, dest_type }); |
| 732 | } |
| 733 | } |
| 734 | |
| 735 | return self.fail(inst.src, "TODO implement type coercion from {} to {}", .{ inst.ty, dest_type }); |
| 658 | 736 | } |
| 659 | 737 | |
| 660 | 738 | fn bitcast(self: *Analyze, func: ?*Fn, dest_type: Type, inst: *Inst) !*Inst { |