lower: Share constant slice data insertion

a7f15291cc1c15c8080affa5754f38030aa7aca0b1007046bdd5735ba45544ab
Use one data insertion path for constant slices and carry the data
builder's zero-initialization result into it. This avoids duplicate
construction and another scan of mutable constant values.

Keep immutable data reuse and distinct storage for mutable literals.

Assisted-by: Codex:gpt-6-astra
Alexis Sellier committed ago 1 parent 625eabb9
lib/std/lang/lower.rad +11 -17
1860 1860
1861 1861
/// Lower constant data to a slice value.
1862 1862
/// Creates or reuses a data section entry, then builds a slice header on the stack.
1863 1863
fn lowerConstDataAsSlice(
1864 1864
    self: *mut FnLowerer,
1865 -
    values: *[il::DataValue],
1865 +
    result: *ConstDataResult,
1866 1866
    alignment: u32,
1867 1867
    readOnly: bool,
1868 1868
    elemTy: *resolver::Type,
1869 1869
    mutable: bool,
1870 1870
    length: u32
1871 1871
) -> il::Val throws (LowerError) {
1872 +
    let values = result.values;
1872 1873
    let elemLayout = resolver::getTypeLayout(*elemTy);
1873 1874
    let size = elemLayout.size * length;
1874 1875
    let mut dataName: *[u8] = undefined;
1876 +
    let mut found: ?*[u8] = nil;
1875 1877
    if readOnly {
1876 -
        if let found = findConstData(self.low, values, alignment) {
1877 -
            set dataName = found;
1878 -
        } else {
1879 -
            set dataName = try nextDataName(self);
1880 -
            self.low.data.append(il::Data {
1881 -
                name: dataName,
1882 -
                size,
1883 -
                alignment,
1884 -
                readOnly,
1885 -
                isZeroInit: false,
1886 -
                values,
1887 -
            }, self.low.allocator);
1888 -
        }
1878 +
        set found = findConstData(self.low, values, alignment);
1879 +
    }
1880 +
    if let name = found {
1881 +
        set dataName = name;
1889 1882
    } else {
1890 1883
        set dataName = try nextDataName(self);
1891 1884
        self.low.data.append(il::Data {
1892 1885
            name: dataName,
1893 1886
            size,
1894 1887
            alignment,
1895 1888
            readOnly,
1896 -
            isZeroInit: dataValuesAreZeroInit(values),
1889 +
            isZeroInit: not readOnly and result.zeroInit,
1897 1890
            values,
1898 1891
        }, self.low.allocator);
1899 1892
    }
1900 1893
1901 1894
    // Get data address.
5107 5100
            else => throw LowerError::UnexpectedNodeValue(arrayNode),
5108 5101
        }
5109 5102
        let result = dataBuilderFinish(&b);
5110 5103
        let alignment = resolver::getTypeLayout(*item).alignment;
5111 5104
        return try lowerConstDataAsSlice(
5112 -
            self, result.values, alignment, not mutable,
5105 +
            self, &result, alignment, not mutable,
5113 5106
            item, mutable, length
5114 5107
        );
5115 5108
    }
5116 5109
    let data = try lowerExpr(self, arrayNode);
5117 5110
    let count = il::Val::Imm(length as i64);
6173 6166
    let ptr = try! alloc::alloc(
6174 6167
        self.low.arena, @sizeOf(il::DataValue), @alignOf(il::DataValue)
6175 6168
    ) as *mut il::DataValue;
6176 6169
6177 6170
    set *ptr = il::DataValue { item: il::DataItem::Str(s), count: 1 };
6171 +
    let result = ConstDataResult { values: @sliceOf(ptr, 1), zeroInit: false };
6178 6172
6179 6173
    return try lowerConstDataAsSlice(
6180 -
        self, @sliceOf(ptr, 1), 1, true, item, mutable, s.len
6174 +
        self, &result, 1, true, item, mutable, s.len
6181 6175
    );
6182 6176
}
6183 6177
6184 6178
/// Lower a builtin call expression.
6185 6179
fn lowerBuiltinCall(self: *mut FnLowerer, node: *ast::Node, kind: ast::Builtin, args: *mut [*ast::Node]) -> il::Val throws (LowerError) {