lower: Avoid redundant constant array layouts
45c563a2cb063ca486c722a93cff929889613682a455b8ad917e34f8f78947c1
Constant array element slots need no padding beyond their payloads. Use payload lowering directly and calculate layouts only where they are needed. Preserve padding within records and union payloads. Assisted-by: Codex:gpt-6-astra
1 parent
ecdf6a84
lib/std/lang/lower.rad
+9 -7
| 1406 | 1406 | } |
|
| 1407 | 1407 | dataSliceHeader(b, dataName, arrInfo.length); |
|
| 1408 | 1408 | } |
|
| 1409 | 1409 | ||
| 1410 | 1410 | /// Lower a constant expression payload into a builder without slot padding. |
|
| 1411 | + | /// Compute the type layout only when undefined data needs a byte count. |
|
| 1411 | 1412 | fn lowerConstDataPayloadInto( |
|
| 1412 | 1413 | self: *mut Lowerer, |
|
| 1413 | 1414 | node: *ast::Node, |
|
| 1414 | 1415 | ty: resolver::Type, |
|
| 1415 | 1416 | dataPrefix: *[u8], |
| 1434 | 1435 | try lowerConstUnionVariantInto(self, node, sym, ty, &mut [], dataPrefix, b); |
|
| 1435 | 1436 | return; |
|
| 1436 | 1437 | } |
|
| 1437 | 1438 | } |
|
| 1438 | 1439 | } |
|
| 1439 | - | let layout = resolver::getTypeLayout(ty); |
|
| 1440 | - | ||
| 1441 | 1440 | match node.value { |
|
| 1442 | 1441 | case ast::NodeValue::Undef => { |
|
| 1442 | + | let layout = resolver::getTypeLayout(ty); |
|
| 1443 | 1443 | dataBuilderPush(b, il::DataValue { |
|
| 1444 | 1444 | item: il::DataItem::Undef, |
|
| 1445 | 1445 | count: layout.size |
|
| 1446 | 1446 | }); |
|
| 1447 | 1447 | } |
| 1508 | 1508 | dataBuilderPush(b, il::DataValue { item: il::DataItem::Undef, count: padding }); |
|
| 1509 | 1509 | } |
|
| 1510 | 1510 | } |
|
| 1511 | 1511 | ||
| 1512 | 1512 | /// Flatten a constant array literal `[a, b, c]` into a builder. |
|
| 1513 | + | /// Each element payload fills its type size; no extra slot padding is needed. |
|
| 1513 | 1514 | fn lowerConstArrayLitInto( |
|
| 1514 | 1515 | self: *mut Lowerer, |
|
| 1515 | 1516 | elems: *mut [*ast::Node], |
|
| 1516 | 1517 | ty: resolver::Type, |
|
| 1517 | 1518 | dataPrefix: *[u8], |
|
| 1518 | 1519 | b: *mut DataValueBuilder |
|
| 1519 | 1520 | ) throws (LowerError) { |
|
| 1520 | 1521 | let case resolver::Type::Array(arrInfo) = ty |
|
| 1521 | 1522 | else throw LowerError::ExpectedArray; |
|
| 1522 | 1523 | let elemTy = *arrInfo.item; |
|
| 1523 | - | let elemLayout = resolver::getTypeLayout(elemTy); |
|
| 1524 | 1524 | ||
| 1525 | 1525 | for elem in elems { |
|
| 1526 | - | try lowerConstDataInto(self, elem, elemTy, elemLayout.size, dataPrefix, b); |
|
| 1526 | + | try lowerConstDataPayloadInto(self, elem, elemTy, dataPrefix, b); |
|
| 1527 | 1527 | } |
|
| 1528 | 1528 | } |
|
| 1529 | 1529 | ||
| 1530 | 1530 | /// Build data values for a constant array repeat literal `[item; count]`. |
|
| 1531 | + | /// Repeat element payloads without extra slot padding. Undefined data uses |
|
| 1532 | + | /// the element layout to compute the total byte count. |
|
| 1531 | 1533 | fn lowerConstArrayRepeatInto( |
|
| 1532 | 1534 | self: *mut Lowerer, |
|
| 1533 | 1535 | repeat: ast::ArrayRepeatLit, |
|
| 1534 | 1536 | ty: resolver::Type, |
|
| 1535 | 1537 | dataPrefix: *[u8], |
| 1537 | 1539 | ) throws (LowerError) { |
|
| 1538 | 1540 | let case resolver::Type::Array(arrInfo) = ty |
|
| 1539 | 1541 | else throw LowerError::ExpectedArray; |
|
| 1540 | 1542 | let length = arrInfo.length; |
|
| 1541 | 1543 | let elemTy = *arrInfo.item; |
|
| 1542 | - | let elemLayout = resolver::getTypeLayout(elemTy); |
|
| 1543 | 1544 | ||
| 1544 | 1545 | if let case ast::NodeValue::Undef = repeat.item.value { |
|
| 1546 | + | let elemLayout = resolver::getTypeLayout(elemTy); |
|
| 1545 | 1547 | dataBuilderPush(b, il::DataValue { |
|
| 1546 | 1548 | item: il::DataItem::Undef, |
|
| 1547 | 1549 | count: elemLayout.size * length |
|
| 1548 | 1550 | }); |
|
| 1549 | 1551 | } else if let val = resolver::constValueEntry(self.resolver, repeat.item) { |
|
| 1550 | 1552 | if let case resolver::ConstValue::String(_) = val { |
|
| 1551 | 1553 | // A string used as a slice is represented by a three-word slice |
|
| 1552 | 1554 | // header, not by the bytes of the string itself. |
|
| 1553 | 1555 | for _ in 0..length { |
|
| 1554 | - | try lowerConstDataInto(self, repeat.item, elemTy, elemLayout.size, dataPrefix, b); |
|
| 1556 | + | try lowerConstDataPayloadInto(self, repeat.item, elemTy, dataPrefix, b); |
|
| 1555 | 1557 | } |
|
| 1556 | 1558 | } else { |
|
| 1557 | 1559 | dataBuilderPush(b, il::DataValue { |
|
| 1558 | 1560 | item: constValueToDataItem(self, val, elemTy), |
|
| 1559 | 1561 | count: length |
|
| 1560 | 1562 | }); |
|
| 1561 | 1563 | } |
|
| 1562 | 1564 | } else { |
|
| 1563 | 1565 | for _ in 0..length { |
|
| 1564 | - | try lowerConstDataInto(self, repeat.item, elemTy, elemLayout.size, dataPrefix, b); |
|
| 1566 | + | try lowerConstDataPayloadInto(self, repeat.item, elemTy, dataPrefix, b); |
|
| 1565 | 1567 | } |
|
| 1566 | 1568 | } |
|
| 1567 | 1569 | } |
|
| 1568 | 1570 | ||
| 1569 | 1571 | /// Build data values for a constant record literal. |