Skip to content

Commit 7c1cd9b

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 1688182 commit 7c1cd9b

File tree

6 files changed

+49
-31
lines changed

6 files changed

+49
-31
lines changed

compiler/rustc_const_eval/src/interpret/intrinsics.rs

+12-5
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,17 @@ use super::{
2424
use crate::fluent_generated as fluent;
2525

2626
/// Directly returns an `Allocation` containing an absolute path representation of the given type.
27-
pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAllocation<'tcx> {
28-
let path = crate::util::type_name(tcx, ty);
27+
pub(crate) fn alloc_type_name<'tcx>(
28+
tcx: TyCtxt<'tcx>,
29+
ty: Ty<'tcx>,
30+
) -> (ConstAllocation<'tcx>, u64) {
31+
let mut path = crate::util::type_name(tcx, ty);
32+
let path_len = path.len().try_into().unwrap();
33+
if !path.contains('\0') {
34+
path.push('\0');
35+
};
2936
let alloc = Allocation::from_bytes_byte_aligned_immutable(path.into_bytes());
30-
tcx.mk_const_alloc(alloc)
37+
(tcx.mk_const_alloc(alloc), path_len)
3138
}
3239

3340
/// The logic for all nullary intrinsics is implemented here. These intrinsics don't get evaluated
@@ -43,8 +50,8 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
4350
interp_ok(match name {
4451
sym::type_name => {
4552
ensure_monomorphic_enough(tcx, tp_ty)?;
46-
let alloc = alloc_type_name(tcx, tp_ty);
47-
ConstValue::Slice { data: alloc, meta: alloc.inner().size().bytes() }
53+
let (alloc, path_len) = alloc_type_name(tcx, tp_ty);
54+
ConstValue::Slice { data: alloc, meta: path_len }
4855
}
4956
sym::needs_drop => {
5057
ensure_monomorphic_enough(tcx, tp_ty)?;

compiler/rustc_const_eval/src/interpret/place.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -1019,11 +1019,16 @@ where
10191019
&mut self,
10201020
s: &str,
10211021
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> {
1022-
let bytes = s.as_bytes();
1023-
let ptr = self.allocate_bytes_dedup(bytes)?;
1022+
let ptr = if !s.contains('\0') {
1023+
let mut bytes = s.as_bytes().to_owned();
1024+
bytes.push(0);
1025+
self.allocate_bytes_dedup(&bytes)?
1026+
} else {
1027+
self.allocate_bytes_dedup(s.as_bytes())?
1028+
};
10241029

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

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

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

+8-2
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,15 @@ fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx>
125125
let value = match (lit, lit_ty.kind()) {
126126
(ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
127127
let s = s.as_str();
128-
let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes());
128+
let allocation = if !s.contains('\0') {
129+
let mut s = s.to_owned();
130+
s.push('\0');
131+
Allocation::from_bytes_byte_aligned_immutable(s.as_bytes())
132+
} else {
133+
Allocation::from_bytes_byte_aligned_immutable(s.as_bytes())
134+
};
129135
let allocation = tcx.mk_const_alloc(allocation);
130-
ConstValue::Slice { data: allocation, meta: allocation.inner().size().bytes() }
136+
ConstValue::Slice { data: allocation, meta: s.len().try_into().unwrap() }
131137
}
132138
(ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _))
133139
if matches!(inner_ty.kind(), ty::Slice(_)) =>

tests/codegen/remap_path_prefix/main.rs

+1-1
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

+10-10
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

+10-10
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
}

0 commit comments

Comments
 (0)