Skip to content

Commit 8209d17

Browse files
committed
Nul terminate rust string literals
This allows taking advantage of the C string merging functionality of linkers, reducing code size.
1 parent dc0bae1 commit 8209d17

File tree

8 files changed

+48
-35
lines changed

8 files changed

+48
-35
lines changed

compiler/rustc_const_eval/src/interpret/intrinsics.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,12 @@ use crate::fluent_generated as fluent;
2525

2626
/// Directly returns an `Allocation` containing an absolute path representation of the given type.
2727
pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> (AllocId, u64) {
28-
let path = crate::util::type_name(tcx, ty);
29-
let bytes = path.into_bytes();
30-
let len = bytes.len().try_into().unwrap();
31-
(tcx.allocate_bytes_dedup(bytes, CTFE_ALLOC_SALT), len)
28+
let mut path = crate::util::type_name(tcx, ty);
29+
let path_len = path.len().try_into().unwrap();
30+
if !path.contains('\0') {
31+
path.push('\0');
32+
};
33+
(tcx.allocate_bytes_dedup(path.into_bytes(), CTFE_ALLOC_SALT), path_len)
3234
}
3335
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
3436
/// Generates a value of `TypeId` for `ty` in-place.

compiler/rustc_const_eval/src/interpret/place.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,11 +1024,16 @@ where
10241024
&mut self,
10251025
s: &str,
10261026
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> {
1027-
let bytes = s.as_bytes();
1028-
let ptr = self.allocate_bytes_dedup(bytes)?;
1027+
let ptr = if !s.contains('\0') {
1028+
let mut bytes = s.as_bytes().to_owned();
1029+
bytes.push(0);
1030+
self.allocate_bytes_dedup(&bytes)?
1031+
} else {
1032+
self.allocate_bytes_dedup(s.as_bytes())?
1033+
};
10291034

10301035
// Create length metadata for the string.
1031-
let meta = Scalar::from_target_usize(u64::try_from(bytes.len()).unwrap(), self);
1036+
let meta = Scalar::from_target_usize(u64::try_from(s.len()).unwrap(), self);
10321037

10331038
// Get layout for Rust's str type.
10341039
let layout = self.layout_of(self.tcx.types.str_).unwrap();

compiler/rustc_mir_build/src/builder/expr/as_constant.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,15 @@ fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx>
120120

121121
let value = match (lit, lit_ty.kind()) {
122122
(ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
123-
let s = s.as_str().as_bytes();
124-
let len = s.len();
125-
let allocation = tcx.allocate_bytes_dedup(s, CTFE_ALLOC_SALT);
126-
ConstValue::Slice { alloc_id: allocation, meta: len.try_into().unwrap() }
123+
let s = s.as_str();
124+
let allocation = if !s.contains('\0') {
125+
let mut s = s.to_owned();
126+
s.push('\0');
127+
tcx.allocate_bytes_dedup(s.as_bytes(), CTFE_ALLOC_SALT)
128+
} else {
129+
tcx.allocate_bytes_dedup(s.as_bytes(), CTFE_ALLOC_SALT)
130+
};
131+
ConstValue::Slice { alloc_id: allocation, meta: s.len().try_into().unwrap() }
127132
}
128133
(ast::LitKind::ByteStr(byte_sym, _), ty::Ref(_, inner_ty, _))
129134
if matches!(inner_ty.kind(), ty::Slice(_)) =>

tests/codegen-llvm/remap_path_prefix/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ mod aux_mod;
1212
include!("aux_mod.rs");
1313

1414
// Here we check that the expansion of the file!() macro is mapped.
15-
// CHECK: @alloc_5761061597a97f66e13ef2ff92712c4b = private unnamed_addr constant [34 x i8] c"/the/src/remap_path_prefix/main.rs"
15+
// CHECK: @alloc_4079a2e7607f89f86df6b8a72ba0dd06 = private unnamed_addr constant [35 x i8] c"/the/src/remap_path_prefix/main.rs\00"
1616
pub static FILE_PATH: &'static str = file!();
1717

1818
fn main() {

tests/mir-opt/const_allocation.main.GVN.after.32bit.mir

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,27 +33,27 @@ ALLOC2 (size: 16, align: 4) {
3333
╾ALLOC4<imm>╼ 03 00 00 00 ╾ALLOC5<imm>╼ 03 00 00 00 │ ╾──╼....╾──╼....
3434
}
3535

36-
ALLOC4 (size: 3, align: 1) {
37-
66 6f 6f │ foo
36+
ALLOC4 (size: 4, align: 1) {
37+
66 6f 6f 00 │ foo.
3838
}
3939

40-
ALLOC5 (size: 3, align: 1) {
41-
62 61 72 │ bar
40+
ALLOC5 (size: 4, align: 1) {
41+
62 61 72 00 │ bar.
4242
}
4343

4444
ALLOC3 (size: 24, align: 4) {
4545
0x00 │ ╾ALLOC6<imm>╼ 03 00 00 00 ╾ALLOC7<imm>╼ 03 00 00 00 │ ╾──╼....╾──╼....
4646
0x10 │ ╾ALLOC8<imm>╼ 04 00 00 00 │ ╾──╼....
4747
}
4848

49-
ALLOC6 (size: 3, align: 1) {
50-
6d 65 68 │ meh
49+
ALLOC6 (size: 4, align: 1) {
50+
6d 65 68 00 │ meh.
5151
}
5252

53-
ALLOC7 (size: 3, align: 1) {
54-
6d 6f 70 │ mop
53+
ALLOC7 (size: 4, align: 1) {
54+
6d 6f 70 00 │ mop.
5555
}
5656

57-
ALLOC8 (size: 4, align: 1) {
58-
6d c3 b6 70 │ m..p
57+
ALLOC8 (size: 5, align: 1) {
58+
6d c3 b6 70 00 │ m..p.
5959
}

tests/mir-opt/const_allocation.main.GVN.after.64bit.mir

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@ ALLOC2 (size: 32, align: 8) {
3636
0x10 │ ╾ALLOC5<imm>╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
3737
}
3838

39-
ALLOC4 (size: 3, align: 1) {
40-
66 6f 6f │ foo
39+
ALLOC4 (size: 4, align: 1) {
40+
66 6f 6f 00 │ foo.
4141
}
4242

43-
ALLOC5 (size: 3, align: 1) {
44-
62 61 72 │ bar
43+
ALLOC5 (size: 4, align: 1) {
44+
62 61 72 00 │ bar.
4545
}
4646

4747
ALLOC3 (size: 48, align: 8) {
@@ -50,14 +50,14 @@ ALLOC3 (size: 48, align: 8) {
5050
0x20 │ ╾ALLOC8<imm>╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
5151
}
5252

53-
ALLOC6 (size: 3, align: 1) {
54-
6d 65 68 │ meh
53+
ALLOC6 (size: 4, align: 1) {
54+
6d 65 68 00 │ meh.
5555
}
5656

57-
ALLOC7 (size: 3, align: 1) {
58-
6d 6f 70 │ mop
57+
ALLOC7 (size: 4, align: 1) {
58+
6d 6f 70 00 │ mop.
5959
}
6060

61-
ALLOC8 (size: 4, align: 1) {
62-
6d c3 b6 70 │ m..p
61+
ALLOC8 (size: 5, align: 1) {
62+
6d c3 b6 70 00 │ m..p.
6363
}

tests/ui-fulldeps/rustc_public/check_allocation.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,12 @@ fn check_bar(item: CrateItem) {
7777

7878
let alloc_id_0 = alloc.provenance.ptrs[0].1.0;
7979
let GlobalAlloc::Memory(allocation) = GlobalAlloc::from(alloc_id_0) else { unreachable!() };
80-
assert_eq!(allocation.bytes.len(), 3);
80+
assert_eq!(allocation.bytes.len(), 4);
8181
assert_eq!(allocation.bytes[0].unwrap(), Char::CapitalB.to_u8());
8282
assert_eq!(allocation.bytes[1].unwrap(), Char::SmallA.to_u8());
8383
assert_eq!(allocation.bytes[2].unwrap(), Char::SmallR.to_u8());
84-
assert_eq!(std::str::from_utf8(&allocation.raw_bytes().unwrap()), Ok("Bar"));
84+
assert_eq!(allocation.bytes[3].unwrap(), Char::Null.to_u8());
85+
assert_eq!(std::str::from_utf8(&allocation.raw_bytes().unwrap()), Ok("Bar\0"));
8586
}
8687

8788
/// Check the allocation data for static `C_STR`.

tests/ui-fulldeps/rustc_public/check_transform.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ fn test_transform() -> ControlFlow<()> {
3737
let target_fn = *get_item(&items, (ItemKind::Fn, "dummy")).unwrap();
3838
let instance = Instance::try_from(target_fn).unwrap();
3939
let body = instance.body().unwrap();
40-
check_msg(&body, "oops");
40+
check_msg(&body, "oops\0");
4141

4242
let new_msg = "new panic message";
4343
let new_body = change_panic_msg(body, new_msg);

0 commit comments

Comments
 (0)