compiler: Own function descriptors until IL publication
812133279aaf8913ee8fb4918d992ffd53fdf497df668137a7813125dc1d5456
1 parent
e76df48f
lib/std/lang/lower.rad
+5 -5
| 1105 | 1105 | // as the first argument; the callee writes the return value into it. |
|
| 1106 | 1106 | if requiresReturnParam(fnType) and not isExtern { |
|
| 1107 | 1107 | set fnLow.returnReg = nextReg(&mut fnLow); |
|
| 1108 | 1108 | } |
|
| 1109 | 1109 | let lowParams = try lowerParams(&mut fnLow, *fnType, decl.sig.params, nil); |
|
| 1110 | - | let func = try! alloc::allocRaw(fnLow.arena, @sizeOf(il::Fn), @alignOf(il::Fn)) as *unsafe mut il::Fn; |
|
| 1110 | + | let func = try! alloc::alloc(&mut *fnLow.arena, @sizeOf(il::Fn), @alignOf(il::Fn)) as *mut il::Fn; |
|
| 1111 | 1111 | ||
| 1112 | 1112 | // Throwing functions return a result aggregate (word-sized pointer). |
|
| 1113 | 1113 | // TODO: The resolver should set an appropriate type that takes into account |
|
| 1114 | 1114 | // the throws list. It shouldn't set the return type to the "success" |
|
| 1115 | 1115 | // value only. |
| 1124 | 1124 | blocks: &[], |
|
| 1125 | 1125 | }; |
|
| 1126 | 1126 | let body = decl.body else { |
|
| 1127 | 1127 | // Extern functions have no body. |
|
| 1128 | 1128 | assert isExtern; |
|
| 1129 | - | return func; |
|
| 1129 | + | return (&*func) as *unsafe il::Fn; |
|
| 1130 | 1130 | }; |
|
| 1131 | 1131 | set func.blocks = try lowerFnBody(&mut fnLow, body); |
|
| 1132 | 1132 | set func.isLeaf = fnLow.isLeaf; |
|
| 1133 | 1133 | ||
| 1134 | - | return func; |
|
| 1134 | + | return (&*func) as *unsafe il::Fn; |
|
| 1135 | 1135 | } |
|
| 1136 | 1136 | } |
|
| 1137 | 1137 | ||
| 1138 | 1138 | /// Build a qualified name of the form "Type::method". |
|
| 1139 | 1139 | unsafe fn instanceMethodName 'arena 'phase (self: &mut Lowerer 'arena 'phase, modId: ?u16, typeName: *[u8], methodName: *[u8]) -> *[u8] where 'arena: 'phase { |
| 1272 | 1272 | let mut fnLow = fnLowerer(parent, node.span.offset, fnType, qualName, arena, variables); |
|
| 1273 | 1273 | if requiresReturnParam(fnType) { |
|
| 1274 | 1274 | set fnLow.returnReg = nextReg(&mut fnLow); |
|
| 1275 | 1275 | } |
|
| 1276 | 1276 | let lowParams = try lowerParams(&mut fnLow, *fnType, sig.params, receiverName); |
|
| 1277 | - | let func = try! alloc::allocRaw(fnLow.arena, @sizeOf(il::Fn), @alignOf(il::Fn)) as *unsafe mut il::Fn; |
|
| 1277 | + | let func = try! alloc::alloc(&mut *fnLow.arena, @sizeOf(il::Fn), @alignOf(il::Fn)) as *mut il::Fn; |
|
| 1278 | 1278 | ||
| 1279 | 1279 | let returnType = il::Type::W64 if fnType.throwList.len > 0 |
|
| 1280 | 1280 | else ilType(fnLow.low, *fnType.returnType); |
|
| 1281 | 1281 | set *func = il::Fn { |
|
| 1282 | 1282 | name: qualName, |
| 1287 | 1287 | blocks: &[], |
|
| 1288 | 1288 | }; |
|
| 1289 | 1289 | set func.blocks = try lowerFnBody(&mut fnLow, body); |
|
| 1290 | 1290 | set func.isLeaf = fnLow.isLeaf; |
|
| 1291 | 1291 | ||
| 1292 | - | return func; |
|
| 1292 | + | return (&*func) as *unsafe il::Fn; |
|
| 1293 | 1293 | } |
|
| 1294 | 1294 | } |
|
| 1295 | 1295 | ||
| 1296 | 1296 | /// Lower a standalone method declaration. |
|
| 1297 | 1297 | /// Produces a function with qualified name `Type::method`. |
test/tests/ssa.instruction.storage.rad
+12 -0
| 4 | 4 | record Input: Copy { |
|
| 5 | 5 | /// Full-width input retained by the receiver. |
|
| 6 | 6 | value: u64, |
|
| 7 | 7 | } |
|
| 8 | 8 | ||
| 9 | + | /// Construct an aggregate through a regular function return. |
|
| 10 | + | fn makeInput(value: u64) -> Input { |
|
| 11 | + | return Input { value }; |
|
| 12 | + | } |
|
| 13 | + | ||
| 14 | + | /// Return an aggregate after nested function calls from a method. |
|
| 15 | + | fn (input: &Input) advanced() -> Input { |
|
| 16 | + | return makeInput(advance(input.value)); |
|
| 17 | + | } |
|
| 18 | + | ||
| 9 | 19 | /// Lower a method with a receiver, explicit parameter, and nested calls. |
|
| 10 | 20 | fn (input: &Input) combine(selected: bool) -> u64 { |
|
| 11 | 21 | return combine(input.value, selected); |
|
| 12 | 22 | } |
|
| 13 | 23 |
| 36 | 46 | let value = (index as u64) + 0x100000000; |
|
| 37 | 47 | let base = (value + 7) * 3 + (value + 14) * 5; |
|
| 38 | 48 | assert combine(value, true) == base + (value + 21) * 11; |
|
| 39 | 49 | assert combine(value, false) == base + (value + 21) * 13; |
|
| 40 | 50 | let input = Input { value }; |
|
| 51 | + | let advanced = input.advanced(); |
|
| 52 | + | assert advanced.value == value + 7; |
|
| 41 | 53 | assert input.combine(true) == base + (value + 21) * 11; |
|
| 42 | 54 | assert input.combine(false) == base + (value + 21) * 13; |
|
| 43 | 55 | } |
|
| 44 | 56 | return 0; |
|
| 45 | 57 | } |