Skip to content

Commit 79dff8d

Browse files
committed
gccrs: Introduce CStr language item
gcc/rust/ChangeLog: * util/rust-lang-item.h(LangItem::Kind): New CSTR kind. * util/rust-lang-item.cc(LangItem::lang_items): Ditto. * backend/rust-compile-type.cc(visit(TyTy::ReferenceType)): Add specific record type for CStr. * typecheck/rust-hir-type-check-base.cc(resolve_literal): Update C_STRING case to resolve to the CStr language item instead. gcc/testsuite/ChangeLog: * rust/compile/c_string.rs: Add CStr language item definition. * rust/compile/c_string_null_byte_check.rs: Ditto. Signed-Off-By: Yap Zhi Heng <yapzhhg@gmail.com>
1 parent 22b34af commit 79dff8d

6 files changed

Lines changed: 85 additions & 18 deletions

File tree

gcc/rust/backend/rust-compile-type.cc

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,41 @@ TyTyResolveCompile::visit (const TyTy::ReferenceType &type)
685685
return;
686686
}
687687

688+
// Check for CStr, create a specific record for it
689+
do
690+
{
691+
if (type.get_base ()->get_kind () != TyTy::TypeKind::ADT)
692+
break;
693+
694+
const TyTy::ADTType *adt
695+
= static_cast<const TyTy::ADTType *> (type.get_base ());
696+
auto &mappings = Analysis::Mappings::get ();
697+
auto cstr_item = mappings.lookup_lang_item (LangItem::Kind::CSTR);
698+
if (!cstr_item.has_value ())
699+
break;
700+
701+
HirId cstr_hirid = mappings.lookup_defid (cstr_item.value ())
702+
.value ()
703+
->get_mappings ()
704+
.get_hirid ();
705+
706+
if (cstr_hirid != adt->get_ref ())
707+
break;
708+
709+
// &CStr is a fat pointer: { *const u8, usize }
710+
// Reuse the c_char (u8) slice fat-pointer layout
711+
TyTy::BaseType *u8 = nullptr;
712+
ctx->get_tyctx ()->lookup_builtin ("u8", &u8);
713+
// Create a synthetic SliceType over u8 and use that record layout
714+
TyTy::SliceType synthetic_slice (adt->get_ref (), adt->get_ident ().locus,
715+
TyTy::TyVar (u8->get_ref ()));
716+
tree type_record = create_slice_type_record (synthetic_slice);
717+
translated
718+
= Backend::named_type ("&CStr", type_record, adt->get_ident ().locus);
719+
return;
720+
}
721+
while (false);
722+
688723
tree base_compiled_type
689724
= TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode);
690725
if (type.is_mutable ())

gcc/rust/typecheck/rust-hir-type-check-base.cc

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -397,24 +397,28 @@ TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings,
397397
break;
398398
}
399399

400-
/* This is a pointer to a null-terminated byte slice (&[u8]). */
401-
TyTy::BaseType *u8;
402-
auto ok = context->lookup_builtin ("u8", &u8);
403-
rust_assert (ok);
400+
auto lang_item_defined
401+
= mappings.lookup_lang_item (LangItem::Kind::CSTR);
404402

405-
auto crate_num = mappings.get_current_crate ();
406-
Analysis::NodeMapping slice_mapping (crate_num, UNKNOWN_NODEID,
407-
mappings.get_next_hir_id (
408-
crate_num),
409-
UNKNOWN_LOCAL_DEFID);
403+
if (!lang_item_defined)
404+
{
405+
rust_error_at (locus, "unable to find lang item: %<c_str%>");
406+
infered = new TyTy::ErrorType (expr_mappings.get_hirid (), locus);
407+
break;
408+
}
410409

411-
TyTy::SliceType *slice
412-
= new TyTy::SliceType (slice_mapping.get_hirid (), locus,
413-
TyTy::TyVar (u8->get_ref ()));
414-
context->insert_type (slice_mapping, slice);
410+
DefId cstr_defid = lang_item_defined.value ();
411+
HIR::Item *item = mappings.lookup_defid (cstr_defid).value ();
412+
413+
TyTy::BaseType *item_type = nullptr;
414+
bool ok = context->lookup_type (item->get_mappings ().get_hirid (),
415+
&item_type);
416+
417+
rust_assert (ok);
418+
rust_assert (item_type->get_kind () == TyTy::TypeKind::ADT);
415419

416420
infered = new TyTy::ReferenceType (expr_mappings.get_hirid (),
417-
TyTy::TyVar (slice->get_ref ()),
421+
TyTy::TyVar (item_type->get_ref ()),
418422
Mutability::Imm,
419423
TyTy::Region::make_static ());
420424
}

gcc/rust/util/rust-lang-item.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ const BiMap<std::string, LangItem::Kind> Rust::LangItem::lang_items = {{
9292
{"slice_u8", Kind::SLICE_U8},
9393
{"slice", Kind::SLICE},
9494
{"str", Kind::STR},
95+
{"CStr", Kind::CSTR},
9596
{"f32_runtime", Kind::F32_RUNTIME},
9697
{"f64_runtime", Kind::F64_RUNTIME},
9798

gcc/rust/util/rust-lang-item.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ class LangItem
125125
SLICE_U8,
126126
SLICE,
127127
STR,
128+
CSTR,
128129
F32_RUNTIME,
129130
F64_RUNTIME,
130131

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,28 @@
11
// { dg-additional-options "-frust-c-style-string-literals" }
22
// { dg-output "gccrs\n" }
3-
#![feature(no_core)]
3+
#![feature(no_core, lang_items)]
44
#![no_core]
55

66
extern "C" {
7-
fn printf(s: *const i8, ...);
7+
fn printf(s: *const u8, ...);
8+
}
9+
10+
type c_char = u8;
11+
12+
#[lang = "CStr"]
13+
pub struct CStr {
14+
inner: [c_char]
15+
}
16+
17+
impl CStr {
18+
pub const fn to_ptr(&self) -> *const c_char {
19+
&self.inner as *const [c_char] as *const c_char
20+
}
821
}
922

1023
pub fn main() {
1124
let a = c"gccrs";
1225
unsafe {
13-
printf(a as *const [u8] as *const i8); // TODO change `as *const [u8]` to `.as_ptr()` when C strings are compiled to their own CStr type
26+
printf(a.to_ptr());
1427
}
1528
}

gcc/testsuite/rust/compile/c_string_null_byte_check.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,20 @@
11
// { dg-additional-options "-frust-c-style-string-literals" }
2-
#![feature(no_core)]
2+
#![feature(no_core, lang_items)]
33
#![no_core]
44

5+
type c_char = u8;
6+
7+
#[lang = "CStr"]
8+
pub struct CStr {
9+
inner: [c_char]
10+
}
11+
12+
impl CStr {
13+
pub const fn to_ptr(&self) -> *const c_char {
14+
&self.inner as *const [c_char] as *const c_char
15+
}
16+
}
17+
518
pub fn main() {
619
let _fail = c"gc\0crs";
720
// { dg-error "null characters in C string literals are not supported" "" { target *-*-* } .-1 }

0 commit comments

Comments
 (0)