From 9585c5dc1fa3cef34ebdc5a5d39af88db60c6f15 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 7 Aug 2018 16:03:57 +0200 Subject: [PATCH] Introduce const_cstr!() macro and use it where applicable. --- src/librustc_codegen_llvm/attributes.rs | 14 +++---- src/librustc_codegen_llvm/base.rs | 4 +- src/librustc_codegen_llvm/builder.rs | 6 +-- src/librustc_codegen_llvm/consts.rs | 2 +- .../debuginfo/metadata.rs | 4 +- src/librustc_data_structures/const_cstr.rs | 42 +++++++++++++++++++ src/librustc_data_structures/lib.rs | 1 + 7 files changed, 56 insertions(+), 17 deletions(-) create mode 100644 src/librustc_data_structures/const_cstr.rs diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index 714e8914e48c..74f7e6f2ce75 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -9,7 +9,7 @@ // except according to those terms. //! Set and unset common attributes on LLVM values. -use std::ffi::{CStr, CString}; +use std::ffi::CString; use rustc::hir::CodegenFnAttrFlags; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; @@ -75,7 +75,7 @@ pub fn set_frame_pointer_elimination(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) if cx.sess().must_not_eliminate_frame_pointers() { llvm::AddFunctionAttrStringValue( llfn, llvm::AttributePlace::Function, - cstr("no-frame-pointer-elim\0"), cstr("true\0")); + const_cstr!("no-frame-pointer-elim"), const_cstr!("true")); } } @@ -108,7 +108,7 @@ pub fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { // This is defined in the `compiler-builtins` crate for each architecture. llvm::AddFunctionAttrStringValue( llfn, llvm::AttributePlace::Function, - cstr("probe-stack\0"), cstr("__rust_probestack\0")); + const_cstr!("probe-stack"), const_cstr!("__rust_probestack")); } pub fn llvm_target_features(sess: &Session) -> impl Iterator { @@ -202,7 +202,7 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value, id: DefId) { let val = CString::new(features).unwrap(); llvm::AddFunctionAttrStringValue( llfn, llvm::AttributePlace::Function, - cstr("target-features\0"), &val); + const_cstr!("target-features"), &val); } // Note that currently the `wasm-import-module` doesn't do anything, but @@ -213,17 +213,13 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value, id: DefId) { llvm::AddFunctionAttrStringValue( llfn, llvm::AttributePlace::Function, - cstr("wasm-import-module\0"), + const_cstr!("wasm-import-module"), &module, ); } } } -fn cstr(s: &'static str) -> &CStr { - CStr::from_bytes_with_nul(s.as_bytes()).expect("null-terminated string") -} - pub fn provide(providers: &mut Providers) { providers.target_features_whitelist = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index 54ff5d219b39..4415adc27d6d 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -1255,8 +1255,8 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Create the llvm.used variable // This variable has type [N x i8*] and is stored in the llvm.metadata section if !cx.used_statics.borrow().is_empty() { - let name = CString::new("llvm.used").unwrap(); - let section = CString::new("llvm.metadata").unwrap(); + let name = const_cstr!("llvm.used"); + let section = const_cstr!("llvm.metadata"); let array = C_array(Type::i8(&cx).ptr_to(), &*cx.used_statics.borrow()); unsafe { diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index b174cd8c7ac7..bc82886714ae 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -975,7 +975,7 @@ impl Builder<'a, 'll, 'tcx> { parent: Option<&'ll Value>, args: &[&'ll Value]) -> &'ll Value { self.count_insn("cleanuppad"); - let name = CString::new("cleanuppad").unwrap(); + let name = const_cstr!("cleanuppad"); let ret = unsafe { llvm::LLVMRustBuildCleanupPad(self.llbuilder, parent, @@ -1001,7 +1001,7 @@ impl Builder<'a, 'll, 'tcx> { parent: &'ll Value, args: &[&'ll Value]) -> &'ll Value { self.count_insn("catchpad"); - let name = CString::new("catchpad").unwrap(); + let name = const_cstr!("catchpad"); let ret = unsafe { llvm::LLVMRustBuildCatchPad(self.llbuilder, parent, args.len() as c_uint, args.as_ptr(), @@ -1025,7 +1025,7 @@ impl Builder<'a, 'll, 'tcx> { num_handlers: usize, ) -> &'ll Value { self.count_insn("catchswitch"); - let name = CString::new("catchswitch").unwrap(); + let name = const_cstr!("catchswitch"); let ret = unsafe { llvm::LLVMRustBuildCatchSwitch(self.llbuilder, parent, unwind, num_handlers as c_uint, diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index fafc0e723225..5501e915976a 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -328,7 +328,7 @@ pub fn codegen_static<'a, 'tcx>( } else { // If we created the global with the wrong type, // correct the type. - let empty_string = CString::new("").unwrap(); + let empty_string = const_cstr!(""); let name_str_ref = CStr::from_ptr(llvm::LLVMGetValueName(g)); let name_string = CString::new(name_str_ref.to_bytes()).unwrap(); llvm::LLVMSetValueName(g, empty_string.as_ptr()); diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 8ee2404e10cd..3bd1a1519b6b 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -883,7 +883,7 @@ pub fn compile_unit_metadata(tcx: TyCtxt, gcov_cu_info.as_ptr(), gcov_cu_info.len() as c_uint); - let llvm_gcov_ident = CString::new("llvm.gcov").unwrap(); + let llvm_gcov_ident = const_cstr!("llvm.gcov"); llvm::LLVMAddNamedMetadataOperand(debug_context.llmod, llvm_gcov_ident.as_ptr(), gcov_metadata); @@ -1780,7 +1780,7 @@ pub fn create_vtable_metadata( // later on in llvm/lib/IR/Value.cpp. let empty_array = create_DIArray(DIB(cx), &[]); - let name = CString::new("vtable").unwrap(); + let name = const_cstr!("vtable"); // Create a new one each time. We don't want metadata caching // here, because each vtable will refer to a unique containing diff --git a/src/librustc_data_structures/const_cstr.rs b/src/librustc_data_structures/const_cstr.rs new file mode 100644 index 000000000000..4589d973b6a4 --- /dev/null +++ b/src/librustc_data_structures/const_cstr.rs @@ -0,0 +1,42 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/// This macro creates a zero-overhead &CStr by adding a NUL terminator to +/// the string literal passed into it at compile-time. Use it like: +/// +/// ``` +/// let some_const_cstr = const_cstr!("abc"); +/// ``` +/// +/// The above is roughly equivalent to: +/// +/// ``` +/// let some_const_cstr = CStr::from_bytes_with_nul(b"abc\0").unwrap() +/// ``` +/// +/// Note that macro only checks the string literal for internal NULs if +/// debug-assertions are enabled in order to avoid runtime overhead in release +/// builds. +#[macro_export] +macro_rules! const_cstr { + ($s:expr) => ({ + use std::ffi::CStr; + + let str_plus_nul = concat!($s, "\0"); + + if cfg!(debug_assertions) { + CStr::from_bytes_with_nul(str_plus_nul.as_bytes()).unwrap() + } else { + unsafe { + CStr::from_bytes_with_nul_unchecked(str_plus_nul.as_bytes()) + } + } + }) +} diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 3aa15f472a27..bd11a2977ffb 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -60,6 +60,7 @@ pub mod array_vec; pub mod base_n; pub mod bitslice; pub mod bitvec; +pub mod const_cstr; pub mod flock; pub mod fx; pub mod graph;