compiler: Check aggregate return classification
63b266a538584fff5c4de9a86a0e10daee3e5e0087bb34a26438429e59fb0dcd
1 parent
7a69753c
lib/std/lang/lower.rad
+16 -7
| 4388 | 4388 | } |
|
| 4389 | 4389 | } |
|
| 4390 | 4390 | ||
| 4391 | 4391 | /// Check if a resolver type is a small aggregate that can be |
|
| 4392 | 4392 | /// passed or returned by value in a register. |
|
| 4393 | - | unsafe fn isSmallAggregate(typ: resolver::Type) -> bool { |
|
| 4393 | + | fn isSmallAggregate(typ: resolver::Type) -> bool { |
|
| 4394 | 4394 | match typ { |
|
| 4395 | - | case resolver::Type::Nominal(_) => { |
|
| 4396 | - | if resolver::isVoidUnion(typ) { |
|
| 4397 | - | return false; |
|
| 4395 | + | case resolver::Type::Nominal(info) => { |
|
| 4396 | + | unsafe { |
|
| 4397 | + | return nominalFitsRegister(*info); |
|
| 4398 | 4398 | } |
|
| 4399 | - | let layout = resolver::getTypeLayout(typ); |
|
| 4400 | - | return layout.size <= resolver::PTR_SIZE; |
|
| 4401 | 4399 | } |
|
| 4402 | 4400 | else => return false, |
|
| 4403 | 4401 | } |
|
| 4404 | 4402 | } |
|
| 4405 | 4403 | ||
| 4404 | + | /// Check whether a nominal aggregate uses one register for its value. |
|
| 4405 | + | fn nominalFitsRegister(info: resolver::NominalType) -> bool { |
|
| 4406 | + | if let case resolver::NominalType::Union(unionInfo) = info { |
|
| 4407 | + | if unionInfo.isAllVoid { |
|
| 4408 | + | return false; |
|
| 4409 | + | } |
|
| 4410 | + | } |
|
| 4411 | + | let layout = resolver::getNominalLayout(info); |
|
| 4412 | + | return layout.size <= resolver::PTR_SIZE; |
|
| 4413 | + | } |
|
| 4414 | + | ||
| 4406 | 4415 | /// Whether a function needs a hidden return parameter. |
|
| 4407 | 4416 | /// |
|
| 4408 | 4417 | /// This is the case for throwing functions, which return a result aggregate, |
|
| 4409 | 4418 | /// and for functions returning large aggregates that cannot be passed in |
|
| 4410 | 4419 | /// registers. |
|
| 4411 | - | unsafe fn requiresReturnParam(fnType: *resolver::FnType) -> bool { |
|
| 4420 | + | fn requiresReturnParam(fnType: *resolver::FnType) -> bool { |
|
| 4412 | 4421 | return fnType.throwList.len > 0 |
|
| 4413 | 4422 | or (isAggregateType(*fnType.returnType) |
|
| 4414 | 4423 | and not isSmallAggregate(*fnType.returnType)); |
|
| 4415 | 4424 | } |
|
| 4416 | 4425 |