| ... | @@ -421,6 +421,8 @@ const Analyze = struct { | ... | @@ -421,6 +421,8 @@ const Analyze = struct { |
| 421 | .fntype => return self.analyzeInstFnType(func, old_inst.cast(text.Inst.FnType).?), | 421 | .fntype => return self.analyzeInstFnType(func, old_inst.cast(text.Inst.FnType).?), |
| 422 | .intcast => return self.analyzeInstIntCast(func, old_inst.cast(text.Inst.IntCast).?), | 422 | .intcast => return self.analyzeInstIntCast(func, old_inst.cast(text.Inst.IntCast).?), |
| 423 | .bitcast => return self.analyzeInstBitCast(func, old_inst.cast(text.Inst.BitCast).?), | 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,6 +571,67 @@ const Analyze = struct { |
| 569 | return self.bitcast(func, dest_type, operand); | 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 | fn analyzeInstDeref(self: *Analyze, func: ?*Fn, deref: *text.Inst.Deref) InnerError!*Inst { | 635 | fn analyzeInstDeref(self: *Analyze, func: ?*Fn, deref: *text.Inst.Deref) InnerError!*Inst { |
| 573 | const ptr = try self.resolveInst(func, deref.positionals.ptr); | 636 | const ptr = try self.resolveInst(func, deref.positionals.ptr); |
| 574 | const elem_ty = switch (ptr.ty.zigTypeTag()) { | 637 | const elem_ty = switch (ptr.ty.zigTypeTag()) { |
| ... | @@ -654,7 +717,22 @@ const Analyze = struct { | ... | @@ -654,7 +717,22 @@ const Analyze = struct { |
| 654 | return self.constInst(inst.src, .{ .ty = dest_type, .val = val }); | 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 | fn bitcast(self: *Analyze, func: ?*Fn, dest_type: Type, inst: *Inst) !*Inst { | 738 | fn bitcast(self: *Analyze, func: ?*Fn, dest_type: Type, inst: *Inst) !*Inst { |