compiler: Construct initialized element pointer results

7988f48b4d3bd79e2c25b3aedab82fb3f9a6f42c16c22d83aed9e159ccad50a0
Alexis Sellier committed ago 1 parent f04dd59a
lib/std/lang/lower.rad +9 -10
5321 5321
    let subjectTy = resolver::autoDeref(containerTy);
5322 5322
    let baseVal = try lowerExpr(self, container);
5323 5323
    let indexVal = try lowerExpr(self, index);
5324 5324
    let baseReg = emitValToReg(self, baseVal);
5325 5325
5326 -
    let mut dataReg = baseReg;
5327 -
    let mut elemType: resolver::Type = undefined;
5328 -
5329 5326
    match subjectTy {
5330 5327
        case resolver::Type::Slice { item, .. } => {
5331 -
            set elemType = *item;
5328 +
            let elemType = *item;
5332 5329
            let sliceLen = loadSliceLen(self, baseReg);
5333 5330
            // Runtime safety check: index must be strictly less than slice length.
5334 5331
            try emitTrapUnlessCmp(self, il::CmpOp::Ult, il::Type::W32, indexVal, sliceLen);
5335 5332
5336 -
            set dataReg = loadSlicePtr(self, baseReg);
5333 +
            let dataReg = loadSlicePtr(self, baseReg);
5334 +
            let elemLayout = resolver::getTypeLayout(elemType);
5335 +
            let elemReg = emitElem(self, elemLayout.size, dataReg, indexVal);
5336 +
            return ElemPtrResult { elemReg, elemType };
5337 5337
        }
5338 5338
        case resolver::Type::Array(arrInfo) => {
5339 -
            set elemType = *arrInfo.item;
5339 +
            let elemType = *arrInfo.item;
5340 5340
            // Runtime safety check: index must be strictly less than array length.
5341 5341
            // Skip when the index is a compile-time constant, since we check
5342 5342
            // that in the resolver.
5343 5343
            if not resolver::isConstExpr(self.low.resolver, index) {
5344 5344
                let arrLen = il::Val::Imm(arrInfo.length as i64);
5345 5345
                try emitTrapUnlessCmp(self, il::CmpOp::Ult, il::Type::W32, indexVal, arrLen);
5346 5346
            }
5347 +
            let elemLayout = resolver::getTypeLayout(elemType);
5348 +
            let elemReg = emitElem(self, elemLayout.size, baseReg, indexVal);
5349 +
            return ElemPtrResult { elemReg, elemType };
5347 5350
        }
5348 5351
        else => throw LowerError::ExpectedSliceOrArray,
5349 5352
    }
5350 -
    let elemLayout = resolver::getTypeLayout(elemType);
5351 -
    let elemReg = emitElem(self, elemLayout.size, dataReg, indexVal);
5352 -
5353 -
    return ElemPtrResult { elemReg, elemType };
5354 5353
}
5355 5354
5356 5355
/// Lower a dereference expression.
5357 5356
/// Handles both pointer deref (`*ptr`) and record deref (`*r` on single-field
5358 5357
/// unlabeled record). Both read at offset 0 using the resolver-assigned type.
test/tests/element.pointer.widths.rad added +60 -0
1 +
//! returns: 0
2 +
3 +
/// Store and load one byte through a slice.
4 +
fn byteItem(items: &mut [u8], index: u32, value: u8) -> u8 {
5 +
    set items[index] = value;
6 +
    return items[index];
7 +
}
8 +
9 +
/// Store and load one full-width word through a slice.
10 +
fn wordItem(items: &mut [u64], index: u32, value: u64) -> u64 {
11 +
    set items[index] = value;
12 +
    return items[index];
13 +
}
14 +
15 +
/// An aggregate with two independently checked fields.
16 +
record Pair: Copy {
17 +
    /// First word.
18 +
    first: u32,
19 +
    /// Second word.
20 +
    second: u64,
21 +
}
22 +
23 +
/// Store and load an aggregate through a slice.
24 +
fn pairItem(items: &mut [Pair], index: u32, value: Pair) -> Pair {
25 +
    set items[index] = value;
26 +
    return items[index];
27 +
}
28 +
29 +
/// Check dynamic array and slice addressing at each element boundary.
30 +
@default fn main() -> u32 {
31 +
    let mut bytes: [u8; 5] = [0; 5];
32 +
    let mut words: [u64; 5] = [0; 5];
33 +
    let mut pairs: [Pair; 5] = [Pair { first: 0, second: 0 }; 5];
34 +
    for index in 0..5 {
35 +
        set bytes[index] = index as u8;
36 +
        set words[index] = 0x100000000 + index as u64;
37 +
        set pairs[index] = Pair { first: index, second: words[index] };
38 +
    }
39 +
    for index in 0..5 {
40 +
        assert bytes[index] == index as u8;
41 +
        assert words[index] == 0x100000000 + index as u64;
42 +
        assert pairs[index].first == index;
43 +
        assert pairs[index].second == words[index];
44 +
        assert byteItem(&mut bytes[..], index, 255 - index as u8) == 255 - index as u8;
45 +
        assert wordItem(&mut words[..], index, 0x200000000 + index as u64) == 0x200000000 + index as u64;
46 +
        let value = Pair { first: index + 10, second: words[index] };
47 +
        let result = pairItem(&mut pairs[..], index, value);
48 +
        assert result.first == value.first;
49 +
        assert result.second == value.second;
50 +
    }
51 +
    for index in 0..5 {
52 +
        assert bytes[index] == 255 - index as u8;
53 +
        assert words[index] == 0x200000000 + index as u64;
54 +
        assert pairs[index].first == index + 10;
55 +
        assert pairs[index].second == words[index];
56 +
    }
57 +
    assert bytes[0] == 255;
58 +
    assert bytes[4] == 251;
59 +
    return 0;
60 +
}