compiler: Check session initialization emission
6bebd6db26274993190d06f0261c38e9a0d809f5eb40ca5ac30f0017d875ca9c
1 parent
694546bb
lib/std/lang/lower.rad
+16 -5
| 5782 | 5782 | try emitFillLoop(self, r.dataReg, fillVal, r.count, *info.itemType, elemSize); |
|
| 5783 | 5783 | } |
|
| 5784 | 5784 | } |
|
| 5785 | 5785 | ||
| 5786 | 5786 | /// Emit a typed fill loop: `for i in 0..count { dst[i * stride] = value; }`. |
|
| 5787 | - | unsafe fn emitFillLoop 'arena 'phase 'function ( |
|
| 5787 | + | fn emitFillLoop 'arena 'phase 'function ( |
|
| 5788 | 5788 | self: &mut FnLowerer 'arena 'phase 'function, |
|
| 5789 | 5789 | dst: il::Reg, |
|
| 5790 | 5790 | value: il::Val, |
|
| 5791 | 5791 | count: il::Val, |
|
| 5792 | 5792 | elemType: resolver::Type, |
| 7058 | 7058 | let result = try emitCallValue(self, il::Val::Reg(functionReg), runtime, args); |
|
| 7059 | 7059 | return SessionInitialization { allocation, result, value, count }; |
|
| 7060 | 7060 | } |
|
| 7061 | 7061 | ||
| 7062 | 7062 | /// Initialize successful reservation storage before its reference is published. |
|
| 7063 | - | unsafe fn initializeSessionAllocation 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, prepared: SessionInitialization) |
|
| 7063 | + | fn initializeSessionAllocation 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, prepared: SessionInitialization) |
|
| 7064 | 7064 | throws (LowerError) where 'arena: 'phase, 'phase: 'function |
|
| 7065 | 7065 | { |
|
| 7066 | 7066 | let allocation = prepared.allocation; |
|
| 7067 | 7067 | let base = emitValToReg(self, prepared.result); |
|
| 7068 | + | unsafe { |
|
| 7069 | + | let layout = resolver::getTypeLayout(*allocation.item); |
|
| 7070 | + | try emitSessionInitialization(self, prepared, base, layout.size); |
|
| 7071 | + | } |
|
| 7072 | + | } |
|
| 7073 | + | ||
| 7074 | + | /// Emit writes to reserved session storage using its resolved item size. |
|
| 7075 | + | fn emitSessionInitialization 'arena 'phase 'function ( |
|
| 7076 | + | self: &mut FnLowerer 'arena 'phase 'function, prepared: SessionInitialization, |
|
| 7077 | + | base: il::Reg, itemSize: u32 |
|
| 7078 | + | ) throws (LowerError) where 'arena: 'phase, 'phase: 'function { |
|
| 7079 | + | let allocation = prepared.allocation; |
|
| 7068 | 7080 | let value = prepared.value; |
|
| 7069 | 7081 | let count = prepared.count; |
|
| 7070 | - | let layout = resolver::getTypeLayout(*allocation.item); |
|
| 7071 | 7082 | let destination = nextReg(self); |
|
| 7072 | 7083 | emitLoadW64At(self, destination, base, RESULT_VAL_OFFSET); |
|
| 7073 | 7084 | match allocation.kind { |
|
| 7074 | 7085 | case resolver::SessionAllocationKind::New => |
|
| 7075 | 7086 | try emitStore(self, destination, 0, *allocation.item, value), |
|
| 7076 | 7087 | case resolver::SessionAllocationKind::Copy => { |
|
| 7077 | 7088 | let source = loadSlicePtr(self, emitValToReg(self, value)); |
|
| 7078 | - | let bytes = emitTypedBinOp(self, il::BinOp::Mul, il::Type::W32, count, il::Val::Imm(layout.size as i64)); |
|
| 7089 | + | let bytes = emitTypedBinOp(self, il::BinOp::Mul, il::Type::W32, count, il::Val::Imm(itemSize as i64)); |
|
| 7079 | 7090 | try emitByteCopyLoop(self, destination, source, bytes, "allocate.copy"); |
|
| 7080 | 7091 | } |
|
| 7081 | 7092 | case resolver::SessionAllocationKind::Fill => |
|
| 7082 | - | try emitFillLoop(self, destination, value, count, *allocation.item, layout.size), |
|
| 7093 | + | try emitFillLoop(self, destination, value, count, *allocation.item, itemSize), |
|
| 7083 | 7094 | } |
|
| 7084 | 7095 | } |
|
| 7085 | 7096 | ||
| 7086 | 7097 | /// Lower a call expression, which may be a function call or type constructor. |
|
| 7087 | 7098 | unsafe fn lowerCallOrCtor 'arena 'phase 'function (self: &mut FnLowerer 'arena 'phase 'function, node: *ast::Node, call: ast::Call) -> il::Val throws (LowerError) where 'arena: 'phase, 'phase: 'function { |