compiler: Build string data through checked storage
508ce34e05a6b7feaf9f06e7e9767134a787398f71cc6966f1e9fb0804e629fa
1 parent
54994768
lib/std/lang/lower.rad
+7 -15
| 1895 | 1895 | dataPrefix: *[u8] |
|
| 1896 | 1896 | ) -> *[u8] throws (LowerError) where 'arena: 'phase { |
|
| 1897 | 1897 | if let existing = findStringData(self, s) { |
|
| 1898 | 1898 | return existing; |
|
| 1899 | 1899 | } |
|
| 1900 | - | let values = try! alloc::allocSlice( |
|
| 1901 | - | self.arena, @sizeOf(il::DataValue), @alignOf(il::DataValue), 1 |
|
| 1902 | - | ) as *mut [il::DataValue]; |
|
| 1903 | - | ||
| 1904 | - | set values[0] = il::DataValue { |
|
| 1905 | - | item: il::DataItem::Str(s), |
|
| 1906 | - | count: 1 |
|
| 1907 | - | }; |
|
| 1908 | - | return try pushDeclData(self, s.len, 1, true, &values[..1], dataPrefix); |
|
| 1900 | + | let mut builder = dataBuilder(alloc::arenaAllocator(self.arena)); |
|
| 1901 | + | dataBuilderPush(&mut builder, il::DataValue { item: il::DataItem::Str(s), count: 1 }); |
|
| 1902 | + | let result = dataBuilderFinish(builder); |
|
| 1903 | + | return try pushDeclData(self, s.len, 1, true, result.values, dataPrefix); |
|
| 1909 | 1904 | } |
|
| 1910 | 1905 | ||
| 1911 | 1906 | /// Compare two data items for structural equality. |
|
| 1912 | 1907 | /// Unlike raw byte comparison, this correctly ignores padding bytes in unions. |
|
| 1913 | 1908 | fn dataItemEq(a: il::DataItem, b: il::DataItem) -> bool { |
| 6403 | 6398 | // Get the slice type from the node. |
|
| 6404 | 6399 | let sliceTy = try typeOf(self, node); |
|
| 6405 | 6400 | let case resolver::Type::Slice { item, mutable, .. } = sliceTy |
|
| 6406 | 6401 | else throw LowerError::ExpectedSliceOrArray; |
|
| 6407 | 6402 | // Build the string data value. |
|
| 6408 | - | let ptr = try! alloc::alloc( |
|
| 6409 | - | self.low.arena, @sizeOf(il::DataValue), @alignOf(il::DataValue) |
|
| 6410 | - | ) as *mut il::DataValue; |
|
| 6411 | - | ||
| 6412 | - | set *ptr = il::DataValue { item: il::DataItem::Str(s), count: 1 }; |
|
| 6413 | - | let result = ConstDataResult { values: @sliceOf(ptr, 1), zeroInit: false }; |
|
| 6403 | + | let mut builder = dataBuilder(alloc::arenaAllocator(self.low.arena)); |
|
| 6404 | + | dataBuilderPush(&mut builder, il::DataValue { item: il::DataItem::Str(s), count: 1 }); |
|
| 6405 | + | let result = dataBuilderFinish(builder); |
|
| 6414 | 6406 | ||
| 6415 | 6407 | return try lowerConstDataAsSlice( |
|
| 6416 | 6408 | self, &result, 1, true, item, mutable, s.len |
|
| 6417 | 6409 | ); |
|
| 6418 | 6410 | } |
test/tests/const.backing.names.rad
+16 -0
| 4 | 4 | constant WORDS: [*[u8]; 12] = ["a", "bb", "ccc", "dddd", "eeeee", "ffffff", "ggggggg", "hhhhhhhh", "iiiiiiiii", "jjjjjjjjjj", "kkkkkkkkkkk", "llllllllllll"]; |
|
| 5 | 5 | ||
| 6 | 6 | /// A separate declaration with some identical string contents. |
|
| 7 | 7 | constant OTHER: [*[u8]; 3] = ["ccc", "a", "bb"]; |
|
| 8 | 8 | ||
| 9 | + | /// Backing strings include zero-length and embedded-zero payloads. |
|
| 10 | + | constant SPECIAL: [*[u8]; 3] = ["", "a\0b", "\0"]; |
|
| 11 | + | ||
| 9 | 12 | /// Check that generated names retain the correct backing bytes. |
|
| 10 | 13 | @default fn main() -> u32 { |
|
| 11 | 14 | for index in 0..WORDS.len { |
|
| 12 | 15 | let word = WORDS[index]; |
|
| 13 | 16 | assert word.len == index + 1; |
| 16 | 19 | } |
|
| 17 | 20 | } |
|
| 18 | 21 | assert OTHER[0] == WORDS[2]; |
|
| 19 | 22 | assert OTHER[1] == WORDS[0]; |
|
| 20 | 23 | assert OTHER[2] == WORDS[1]; |
|
| 24 | + | let empty = ""; |
|
| 25 | + | let embedded = "a\0b"; |
|
| 26 | + | let zero = "\0"; |
|
| 27 | + | assert empty.len == 0; |
|
| 28 | + | assert SPECIAL[0].len == 0; |
|
| 29 | + | assert embedded.len == 3; |
|
| 30 | + | assert embedded[0] == 'a'; |
|
| 31 | + | assert embedded[1] == 0; |
|
| 32 | + | assert embedded[2] == 'b'; |
|
| 33 | + | assert zero.len == 1; |
|
| 34 | + | assert zero[0] == 0; |
|
| 35 | + | assert SPECIAL[1] == embedded; |
|
| 36 | + | assert SPECIAL[2] == zero; |
|
| 21 | 37 | return 0; |
|
| 22 | 38 | } |