diff options
| author | Michael Woerister <michaelwoerister@posteo> | 2018-08-07 16:04:34 +0200 |
|---|---|---|
| committer | Michael Woerister <michaelwoerister@posteo> | 2018-08-10 11:13:00 +0200 |
| commit | 88d84b38f19eff3c25ec88931f04bf2640edf2b5 (patch) | |
| tree | 1b161e6842a4e32c29ba92332eb5b28f81d0e3ec | |
| parent | 9585c5dc1fa3cef34ebdc5a5d39af88db60c6f15 (diff) | |
| download | rust-88d84b38f19eff3c25ec88931f04bf2640edf2b5.tar.gz rust-88d84b38f19eff3c25ec88931f04bf2640edf2b5.zip | |
Introduce SmallCStr and use it where applicable.
| -rw-r--r-- | src/librustc_codegen_llvm/attributes.rs | 2 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/back/write.rs | 10 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/base.rs | 5 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/builder.rs | 8 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/context.rs | 10 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/debuginfo/metadata.rs | 74 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/debuginfo/mod.rs | 7 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/debuginfo/namespace.rs | 4 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/declare.rs | 14 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/llvm/mod.rs | 5 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/type_.rs | 4 | ||||
| -rw-r--r-- | src/librustc_data_structures/lib.rs | 1 | ||||
| -rw-r--r-- | src/librustc_data_structures/small_c_str.rs | 131 |
13 files changed, 200 insertions, 75 deletions
diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index 74f7e6f2ce7..816242129f3 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -128,7 +128,7 @@ pub fn apply_target_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { llvm::AddFunctionAttrStringValue( llfn, llvm::AttributePlace::Function, - cstr("target-cpu\0"), + const_cstr!("target-cpu"), target_cpu.as_c_str()); } diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index cdfa874b177..ebe8b797414 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -31,6 +31,7 @@ use rustc::hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc::ty::TyCtxt; use rustc::util::common::{time_ext, time_depth, set_time_depth, print_time_passes_entry}; use rustc_fs_util::{path2cstr, link_or_copy}; +use rustc_data_structures::small_c_str::SmallCStr; use errors::{self, Handler, Level, DiagnosticBuilder, FatalError, DiagnosticId}; use errors::emitter::{Emitter}; use syntax::attr; @@ -170,11 +171,8 @@ pub fn target_machine_factory(sess: &Session, find_features: bool) let singlethread = sess.target.target.options.singlethread; - let triple = &sess.target.target.llvm_target; - - let triple = CString::new(triple.as_bytes()).unwrap(); - let cpu = sess.target_cpu(); - let cpu = CString::new(cpu.as_bytes()).unwrap(); + let triple = SmallCStr::new(&sess.target.target.llvm_target); + let cpu = SmallCStr::new(sess.target_cpu()); let features = attributes::llvm_target_features(sess) .collect::<Vec<_>>() .join(","); @@ -522,7 +520,7 @@ unsafe fn optimize(cgcx: &CodegenContext, // If we're verifying or linting, add them to the function pass // manager. let addpass = |pass_name: &str| { - let pass_name = CString::new(pass_name).unwrap(); + let pass_name = SmallCStr::new(pass_name); let pass = match llvm::LLVMRustFindAndCreatePass(pass_name.as_ptr()) { Some(pass) => pass, None => return false, diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index 4415adc27d6..7ca6a89dd9b 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -73,6 +73,7 @@ use type_::Type; use type_of::LayoutLlvmExt; use rustc::util::nodemap::{FxHashMap, FxHashSet, DefIdSet}; use CrateInfo; +use rustc_data_structures::small_c_str::SmallCStr; use rustc_data_structures::sync::Lrc; use std::any::Any; @@ -533,7 +534,7 @@ pub fn set_link_section(llval: &Value, attrs: &CodegenFnAttrs) { None => return, }; unsafe { - let buf = CString::new(sect.as_str().as_bytes()).unwrap(); + let buf = SmallCStr::new(§.as_str()); llvm::LLVMSetSection(llval, buf.as_ptr()); } } @@ -681,7 +682,7 @@ fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, unsafe { llvm::LLVMSetInitializer(llglobal, llconst); let section_name = metadata::metadata_section_name(&tcx.sess.target.target); - let name = CString::new(section_name).unwrap(); + let name = SmallCStr::new(section_name); llvm::LLVMSetSection(llglobal, name.as_ptr()); // Also generate a .section directive to force no diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index bc82886714a..b0f88bd4189 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -18,9 +18,9 @@ use libc::{c_uint, c_char}; use rustc::ty::TyCtxt; use rustc::ty::layout::{Align, Size}; use rustc::session::{config, Session}; +use rustc_data_structures::small_c_str::SmallCStr; use std::borrow::Cow; -use std::ffi::CString; use std::ops::Range; use std::ptr; @@ -58,7 +58,7 @@ impl Builder<'a, 'll, 'tcx> { pub fn new_block<'b>(cx: &'a CodegenCx<'ll, 'tcx>, llfn: &'ll Value, name: &'b str) -> Self { let bx = Builder::with_cx(cx); let llbb = unsafe { - let name = CString::new(name).unwrap(); + let name = SmallCStr::new(name); llvm::LLVMAppendBasicBlockInContext( cx.llcx, llfn, @@ -118,7 +118,7 @@ impl Builder<'a, 'll, 'tcx> { } pub fn set_value_name(&self, value: &'ll Value, name: &str) { - let cname = CString::new(name.as_bytes()).unwrap(); + let cname = SmallCStr::new(name); unsafe { llvm::LLVMSetValueName(value, cname.as_ptr()); } @@ -436,7 +436,7 @@ impl Builder<'a, 'll, 'tcx> { let alloca = if name.is_empty() { llvm::LLVMBuildAlloca(self.llbuilder, ty, noname()) } else { - let name = CString::new(name).unwrap(); + let name = SmallCStr::new(name); llvm::LLVMBuildAlloca(self.llbuilder, ty, name.as_ptr()) }; diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 7a308bb6e88..781f8ebbb78 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -26,6 +26,7 @@ use type_::Type; use type_of::PointeeInfo; use rustc_data_structures::base_n; +use rustc_data_structures::small_c_str::SmallCStr; use rustc::mir::mono::Stats; use rustc::session::config::{self, DebugInfo}; use rustc::session::Session; @@ -34,7 +35,7 @@ use rustc::ty::{self, Ty, TyCtxt}; use rustc::util::nodemap::FxHashMap; use rustc_target::spec::{HasTargetSpec, Target}; -use std::ffi::{CStr, CString}; +use std::ffi::CStr; use std::cell::{Cell, RefCell}; use std::iter; use std::str; @@ -161,7 +162,7 @@ pub unsafe fn create_module( llcx: &'ll llvm::Context, mod_name: &str, ) -> &'ll llvm::Module { - let mod_name = CString::new(mod_name).unwrap(); + let mod_name = SmallCStr::new(mod_name); let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx); // Ensure the data-layout values hardcoded remain the defaults. @@ -201,11 +202,10 @@ pub unsafe fn create_module( } } - let data_layout = CString::new(&sess.target.target.data_layout[..]).unwrap(); + let data_layout = SmallCStr::new(&sess.target.target.data_layout); llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr()); - let llvm_target = sess.target.target.llvm_target.as_bytes(); - let llvm_target = CString::new(llvm_target).unwrap(); + let llvm_target = SmallCStr::new(&sess.target.target.llvm_target); llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr()); if is_pie_binary(sess) { diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 3bd1a1519b6..223fa75723c 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -37,6 +37,7 @@ use rustc::ty::layout::{self, Align, LayoutOf, PrimitiveExt, Size, TyLayout}; use rustc::session::config; use rustc::util::nodemap::FxHashMap; use rustc_fs_util::path2cstr; +use rustc_data_structures::small_c_str::SmallCStr; use libc::{c_uint, c_longlong}; use std::ffi::CString; @@ -274,7 +275,7 @@ impl RecursiveTypeDescription<'ll, 'tcx> { // ... and attach them to the stub to complete it. set_members_of_composite_type(cx, metadata_stub, - &member_descriptions[..]); + member_descriptions); return MetadataCreationResult::new(metadata_stub, true); } } @@ -349,7 +350,7 @@ fn vec_slice_metadata( let (pointer_size, pointer_align) = cx.size_and_align_of(data_ptr_type); let (usize_size, usize_align) = cx.size_and_align_of(cx.tcx.types.usize); - let member_descriptions = [ + let member_descriptions = vec![ MemberDescription { name: "data_ptr".to_string(), type_metadata: data_ptr_metadata, @@ -374,7 +375,7 @@ fn vec_slice_metadata( slice_ptr_type, &slice_type_name[..], unique_type_id, - &member_descriptions, + member_descriptions, NO_SCOPE_METADATA, file_metadata, span); @@ -460,7 +461,7 @@ fn trait_pointer_metadata( let data_ptr_field = layout.field(cx, 0); let vtable_field = layout.field(cx, 1); - let member_descriptions = [ + let member_descriptions = vec![ MemberDescription { name: "pointer".to_string(), type_metadata: type_metadata(cx, @@ -485,7 +486,7 @@ fn trait_pointer_metadata( trait_object_type, &trait_type_name[..], unique_type_id, - &member_descriptions, + member_descriptions, containing_scope, file_metadata, syntax_pos::DUMMY_SP) @@ -746,8 +747,8 @@ fn file_metadata_raw(cx: &CodegenCx<'ll, '_>, debug!("file_metadata: file_name: {}, directory: {}", file_name, directory); - let file_name = CString::new(file_name).unwrap(); - let directory = CString::new(directory).unwrap(); + let file_name = SmallCStr::new(file_name); + let directory = SmallCStr::new(directory); let file_metadata = unsafe { llvm::LLVMRustDIBuilderCreateFile(DIB(cx), @@ -782,7 +783,7 @@ fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { }; let (size, align) = cx.size_and_align_of(t); - let name = CString::new(name).unwrap(); + let name = SmallCStr::new(name); let ty_metadata = unsafe { llvm::LLVMRustDIBuilderCreateBasicType( DIB(cx), @@ -813,7 +814,7 @@ fn pointer_type_metadata( ) -> &'ll DIType { let (pointer_size, pointer_align) = cx.size_and_align_of(pointer_type); let name = compute_debuginfo_type_name(cx, pointer_type, false); - let name = CString::new(name).unwrap(); + let name = SmallCStr::new(&name); unsafe { llvm::LLVMRustDIBuilderCreatePointerType( DIB(cx), @@ -847,9 +848,9 @@ pub fn compile_unit_metadata(tcx: TyCtxt, let producer = format!("clang LLVM (rustc version {})", (option_env!("CFG_VERSION")).expect("CFG_VERSION")); - let name_in_debuginfo = name_in_debuginfo.to_string_lossy().into_owned(); - let name_in_debuginfo = CString::new(name_in_debuginfo).unwrap(); - let work_dir = CString::new(&tcx.sess.working_dir.0.to_string_lossy()[..]).unwrap(); + let name_in_debuginfo = name_in_debuginfo.to_string_lossy(); + let name_in_debuginfo = SmallCStr::new(&name_in_debuginfo); + let work_dir = SmallCStr::new(&tcx.sess.working_dir.0.to_string_lossy()); let producer = CString::new(producer).unwrap(); let flags = "\0"; let split_name = "\0"; @@ -1187,7 +1188,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { set_members_of_composite_type(cx, variant_type_metadata, - &member_descriptions[..]); + member_descriptions); vec![ MemberDescription { name: "".to_string(), @@ -1217,7 +1218,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { set_members_of_composite_type(cx, variant_type_metadata, - &member_descriptions); + member_descriptions); MemberDescription { name: "".to_string(), type_metadata: variant_type_metadata, @@ -1244,7 +1245,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { set_members_of_composite_type(cx, variant_type_metadata, - &variant_member_descriptions[..]); + variant_member_descriptions); // Encode the information about the null variant in the union // member's name. @@ -1416,8 +1417,7 @@ fn prepare_enum_metadata( let enumerators_metadata: Vec<_> = def.discriminants(cx.tcx) .zip(&def.variants) .map(|(discr, v)| { - let token = v.name.as_str(); - let name = CString::new(token.as_bytes()).unwrap(); + let name = SmallCStr::new(&v.name.as_str()); unsafe { Some(llvm::LLVMRustDIBuilderCreateEnumerator( DIB(cx), @@ -1442,7 +1442,7 @@ fn prepare_enum_metadata( type_metadata(cx, discr.to_ty(cx.tcx), syntax_pos::DUMMY_SP); let discriminant_name = get_enum_discriminant_name(cx, enum_def_id).as_str(); - let name = CString::new(discriminant_name.as_bytes()).unwrap(); + let name = SmallCStr::new(&discriminant_name); let discriminant_type_metadata = unsafe { llvm::LLVMRustDIBuilderCreateEnumerationType( DIB(cx), @@ -1482,10 +1482,10 @@ fn prepare_enum_metadata( let (enum_type_size, enum_type_align) = layout.size_and_align(); - let enum_name = CString::new(enum_name).unwrap(); - let unique_type_id_str = CString::new( - debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id).as_bytes() - ).unwrap(); + let enum_name = SmallCStr::new(&enum_name); + let unique_type_id_str = SmallCStr::new( + debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id) + ); let enum_metadata = unsafe { llvm::LLVMRustDIBuilderCreateUnionType( DIB(cx), @@ -1531,7 +1531,7 @@ fn composite_type_metadata( composite_type: Ty<'tcx>, composite_type_name: &str, composite_type_unique_id: UniqueTypeId, - member_descriptions: &[MemberDescription<'ll>], + member_descriptions: Vec<MemberDescription<'ll>>, containing_scope: Option<&'ll DIScope>, // Ignore source location information as long as it @@ -1555,7 +1555,7 @@ fn composite_type_metadata( fn set_members_of_composite_type(cx: &CodegenCx<'ll, '_>, composite_type_metadata: &'ll DICompositeType, - member_descriptions: &[MemberDescription<'ll>]) { + member_descriptions: Vec<MemberDescription<'ll>>) { // In some rare cases LLVM metadata uniquing would lead to an existing type // description being used instead of a new one created in // create_struct_stub. This would cause a hard to trace assertion in @@ -1574,10 +1574,9 @@ fn set_members_of_composite_type(cx: &CodegenCx<'ll, '_>, } let member_metadata: Vec<_> = member_descriptions - .iter() + .into_iter() .map(|member_description| { - let member_name = member_description.name.as_bytes(); - let member_name = CString::new(member_name).unwrap(); + let member_name = CString::new(member_description.name).unwrap(); unsafe { Some(llvm::LLVMRustDIBuilderCreateMemberType( DIB(cx), @@ -1613,10 +1612,10 @@ fn create_struct_stub( ) -> &'ll DICompositeType { let (struct_size, struct_align) = cx.size_and_align_of(struct_type); - let name = CString::new(struct_type_name).unwrap(); - let unique_type_id = CString::new( - debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id).as_bytes() - ).unwrap(); + let name = SmallCStr::new(struct_type_name); + let unique_type_id = SmallCStr::new( + debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id) + ); let metadata_stub = unsafe { // LLVMRustDIBuilderCreateStructType() wants an empty array. A null // pointer will lead to hard to trace and debug LLVM assertions @@ -1651,10 +1650,10 @@ fn create_union_stub( ) -> &'ll DICompositeType { let (union_size, union_align) = cx.size_and_align_of(union_type); - let name = CString::new(union_type_name).unwrap(); - let unique_type_id = CString::new( - debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id).as_bytes() - ).unwrap(); + let name = SmallCStr::new(union_type_name); + let unique_type_id = SmallCStr::new( + debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id) + ); let metadata_stub = unsafe { // LLVMRustDIBuilderCreateUnionType() wants an empty array. A null // pointer will lead to hard to trace and debug LLVM assertions @@ -1713,13 +1712,12 @@ pub fn create_global_var_metadata( let is_local_to_unit = is_node_local_to_unit(cx, def_id); let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx); let type_metadata = type_metadata(cx, variable_type, span); - let var_name = tcx.item_name(def_id).to_string(); - let var_name = CString::new(var_name).unwrap(); + let var_name = SmallCStr::new(&tcx.item_name(def_id).as_str()); let linkage_name = if no_mangle { None } else { let linkage_name = mangled_name_of_instance(cx, Instance::mono(tcx, def_id)); - Some(CString::new(linkage_name.to_string()).unwrap()) + Some(SmallCStr::new(&linkage_name.as_str())) }; let global_align = cx.align_of(variable_type); diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index d4fb2549a75..fcb8bc3fe2b 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -34,6 +34,7 @@ use rustc::ty::{self, ParamEnv, Ty, InstanceDef}; use rustc::mir; use rustc::session::config::{self, DebugInfo}; use rustc::util::nodemap::{DefIdMap, FxHashMap, FxHashSet}; +use rustc_data_structures::small_c_str::SmallCStr; use value::Value; use libc::c_uint; @@ -265,7 +266,7 @@ pub fn create_function_debug_context( let is_local_to_unit = is_node_local_to_unit(cx, def_id); let function_name = CString::new(name).unwrap(); - let linkage_name = CString::new(linkage_name.to_string()).unwrap(); + let linkage_name = SmallCStr::new(&linkage_name.as_str()); let mut flags = DIFlags::FlagPrototyped; @@ -407,7 +408,7 @@ pub fn create_function_debug_context( let actual_type = cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty); let actual_type_metadata = type_metadata(cx, actual_type, syntax_pos::DUMMY_SP); - let name = CString::new(name.as_str().as_bytes()).unwrap(); + let name = SmallCStr::new(&name.as_str()); Some(unsafe { Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( DIB(cx), @@ -510,7 +511,7 @@ pub fn declare_local( }; let align = cx.align_of(variable_type); - let name = CString::new(variable_name.as_str().as_bytes()).unwrap(); + let name = SmallCStr::new(&variable_name.as_str()); match (variable_access, &[][..]) { (DirectVariable { alloca }, address_operations) | (IndirectVariable {alloca, address_operations}, _) => { diff --git a/src/librustc_codegen_llvm/debuginfo/namespace.rs b/src/librustc_codegen_llvm/debuginfo/namespace.rs index 9f1141a7e7d..06f8a4b131b 100644 --- a/src/librustc_codegen_llvm/debuginfo/namespace.rs +++ b/src/librustc_codegen_llvm/debuginfo/namespace.rs @@ -21,7 +21,7 @@ use rustc::hir::def_id::DefId; use rustc::hir::map::DefPathData; use common::CodegenCx; -use std::ffi::CString; +use rustc_data_structures::small_c_str::SmallCStr; pub fn mangled_name_of_instance<'a, 'tcx>( cx: &CodegenCx<'a, 'tcx>, @@ -49,7 +49,7 @@ pub fn item_namespace(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope { data => data.as_interned_str().as_str() }; - let namespace_name = CString::new(namespace_name.as_bytes()).unwrap(); + let namespace_name = SmallCStr::new(&namespace_name); let scope = unsafe { llvm::LLVMRustDIBuilderCreateNameSpace( diff --git a/src/librustc_codegen_llvm/declare.rs b/src/librustc_codegen_llvm/declare.rs index a0310eecd59..5e743ac51bc 100644 --- a/src/librustc_codegen_llvm/declare.rs +++ b/src/librustc_codegen_llvm/declare.rs @@ -25,6 +25,7 @@ use llvm::AttributePlace::Function; use rustc::ty::{self, Ty}; use rustc::ty::layout::{self, LayoutOf}; use rustc::session::config::Sanitizer; +use rustc_data_structures::small_c_str::SmallCStr; use rustc_target::spec::PanicStrategy; use abi::{Abi, FnType, FnTypeExt}; use attributes; @@ -33,7 +34,6 @@ use common; use type_::Type; use value::Value; -use std::ffi::CString; /// Declare a global value. /// @@ -41,9 +41,7 @@ use std::ffi::CString; /// return its Value instead. pub fn declare_global(cx: &CodegenCx<'ll, '_>, name: &str, ty: &'ll Type) -> &'ll Value { debug!("declare_global(name={:?})", name); - let namebuf = CString::new(name).unwrap_or_else(|_|{ - bug!("name {:?} contains an interior null byte", name) - }); + let namebuf = SmallCStr::new(name); unsafe { llvm::LLVMRustGetOrInsertGlobal(cx.llmod, namebuf.as_ptr(), ty) } @@ -61,9 +59,7 @@ fn declare_raw_fn( ty: &'ll Type, ) -> &'ll Value { debug!("declare_raw_fn(name={:?}, ty={:?})", name, ty); - let namebuf = CString::new(name).unwrap_or_else(|_|{ - bug!("name {:?} contains an interior null byte", name) - }); + let namebuf = SmallCStr::new(name); let llfn = unsafe { llvm::LLVMRustGetOrInsertFunction(cx.llmod, namebuf.as_ptr(), ty) }; @@ -214,9 +210,7 @@ pub fn define_internal_fn( /// Get declared value by name. pub fn get_declared_value(cx: &CodegenCx<'ll, '_>, name: &str) -> Option<&'ll Value> { debug!("get_declared_value(name={:?})", name); - let namebuf = CString::new(name).unwrap_or_else(|_|{ - bug!("name {:?} contains an interior null byte", name) - }); + let namebuf = SmallCStr::new(name); unsafe { llvm::LLVMRustGetNamedValue(cx.llmod, namebuf.as_ptr()) } } diff --git a/src/librustc_codegen_llvm/llvm/mod.rs b/src/librustc_codegen_llvm/llvm/mod.rs index 558d2a2bc87..4343c8c184e 100644 --- a/src/librustc_codegen_llvm/llvm/mod.rs +++ b/src/librustc_codegen_llvm/llvm/mod.rs @@ -24,9 +24,10 @@ pub use self::Linkage::*; use std::str::FromStr; use std::string::FromUtf8Error; use std::slice; -use std::ffi::{CString, CStr}; +use std::ffi::CStr; use std::cell::RefCell; use libc::{self, c_uint, c_char, size_t}; +use rustc_data_structures::small_c_str::SmallCStr; pub mod archive_ro; pub mod diagnostic; @@ -264,7 +265,7 @@ pub struct OperandBundleDef<'a> { impl OperandBundleDef<'a> { pub fn new(name: &str, vals: &[&'a Value]) -> Self { - let name = CString::new(name).unwrap(); + let name = SmallCStr::new(name); let def = unsafe { LLVMRustBuildOperandBundleDef(name.as_ptr(), vals.as_ptr(), vals.len() as c_uint) }; diff --git a/src/librustc_codegen_llvm/type_.rs b/src/librustc_codegen_llvm/type_.rs index 9fa7cc46aee..51a233d7916 100644 --- a/src/librustc_codegen_llvm/type_.rs +++ b/src/librustc_codegen_llvm/type_.rs @@ -19,8 +19,8 @@ use context::CodegenCx; use syntax::ast; use rustc::ty::layout::{self, Align, Size}; +use rustc_data_structures::small_c_str::SmallCStr; -use std::ffi::CString; use std::fmt; use libc::c_uint; @@ -201,7 +201,7 @@ impl Type { } pub fn named_struct(cx: &CodegenCx<'ll, '_>, name: &str) -> &'ll Type { - let name = CString::new(name).unwrap(); + let name = SmallCStr::new(name); unsafe { llvm::LLVMStructCreateNamed(cx.llcx, name.as_ptr()) } diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index bd11a2977ff..8a586d8c233 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -70,6 +70,7 @@ pub mod obligation_forest; pub mod owning_ref; pub mod ptr_key; pub mod sip128; +pub mod small_c_str; pub mod small_vec; pub mod snapshot_map; pub use ena::snapshot_vec; diff --git a/src/librustc_data_structures/small_c_str.rs b/src/librustc_data_structures/small_c_str.rs new file mode 100644 index 00000000000..b0ad83e4979 --- /dev/null +++ b/src/librustc_data_structures/small_c_str.rs @@ -0,0 +1,131 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::ffi; +use std::ops::Deref; + +const SIZE: usize = 38; + +/// Like SmallVec but for C strings. +#[derive(Clone)] +pub enum SmallCStr { + OnStack { + data: [u8; SIZE], + len_with_nul: u8, + }, + OnHeap { + data: ffi::CString, + } +} + +impl SmallCStr { + #[inline] + pub fn new(s: &str) -> SmallCStr { + if s.len() < SIZE { + let mut data = [0; SIZE]; + data[.. s.len()].copy_from_slice(s.as_bytes()); + let len_with_nul = s.len() + 1; + + // Make sure once that this is a valid CStr + if let Err(e) = ffi::CStr::from_bytes_with_nul(&data[.. len_with_nul]) { + panic!("The string \"{}\" cannot be converted into a CStr: {}", s, e); + } + + SmallCStr::OnStack { + data, + len_with_nul: len_with_nul as u8, + } + } else { + SmallCStr::OnHeap { + data: ffi::CString::new(s).unwrap() + } + } + } + + #[inline] + pub fn as_c_str(&self) -> &ffi::CStr { + match *self { + SmallCStr::OnStack { ref data, len_with_nul } => { + unsafe { + let slice = &data[.. len_with_nul as usize]; + ffi::CStr::from_bytes_with_nul_unchecked(slice) + } + } + SmallCStr::OnHeap { ref data } => { + data.as_c_str() + } + } + } + + #[inline] + pub fn len_with_nul(&self) -> usize { + match *self { + SmallCStr::OnStack { len_with_nul, .. } => { + len_with_nul as usize + } + SmallCStr::OnHeap { ref data } => { + data.as_bytes_with_nul().len() + } + } + } +} + +impl Deref for SmallCStr { + type Target = ffi::CStr; + + fn deref(&self) -> &ffi::CStr { + self.as_c_str() + } +} + + +#[test] +fn short() { + const TEXT: &str = "abcd"; + let reference = ffi::CString::new(TEXT.to_string()).unwrap(); + + let scs = SmallCStr::new(TEXT); + + assert_eq!(scs.len_with_nul(), TEXT.len() + 1); + assert_eq!(scs.as_c_str(), reference.as_c_str()); + assert!(if let SmallCStr::OnStack { .. } = scs { true } else { false }); +} + +#[test] +fn empty() { + const TEXT: &str = ""; + let reference = ffi::CString::new(TEXT.to_string()).unwrap(); + + let scs = SmallCStr::new(TEXT); + + assert_eq!(scs.len_with_nul(), TEXT.len() + 1); + assert_eq!(scs.as_c_str(), reference.as_c_str()); + assert!(if let SmallCStr::OnStack { .. } = scs { true } else { false }); +} + +#[test] +fn long() { + const TEXT: &str = "01234567890123456789012345678901234567890123456789\ + 01234567890123456789012345678901234567890123456789\ + 01234567890123456789012345678901234567890123456789"; + let reference = ffi::CString::new(TEXT.to_string()).unwrap(); + + let scs = SmallCStr::new(TEXT); + + assert_eq!(scs.len_with_nul(), TEXT.len() + 1); + assert_eq!(scs.as_c_str(), reference.as_c_str()); + assert!(if let SmallCStr::OnHeap { .. } = scs { true } else { false }); +} + +#[test] +#[should_panic] +fn internal_nul() { + let _ = SmallCStr::new("abcd\0def"); +} |
