From 80c052bed76d7b7406e956747012bc8a929fe909 Mon Sep 17 00:00:00 2001 From: Dan Robertson Date: Tue, 5 Feb 2019 15:52:54 +0000 Subject: [PATCH] Do not ICE in codegen given a extern_type static The layout of a extern_type static is unsized, but may pass the Well-Formed check in typeck. As a result, we cannot assume that a static is sized when generating the `Place` for an r-value. --- src/librustc_codegen_ssa/mir/place.rs | 19 ++++++++++++++++++- .../static-extern-type/Makefile | 5 +++++ .../static-extern-type/define-foo.c | 11 +++++++++++ .../static-extern-type/use-foo.rs | 14 ++++++++++++++ 4 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 src/test/run-make-fulldeps/static-extern-type/Makefile create mode 100644 src/test/run-make-fulldeps/static-extern-type/define-foo.c create mode 100644 src/test/run-make-fulldeps/static-extern-type/use-foo.rs diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index b10611e5ac797..596f97a038892 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -41,6 +41,21 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> { } } + fn new_thin_place>( + bx: &mut Bx, + llval: V, + layout: TyLayout<'tcx>, + align: Align, + ) -> PlaceRef<'tcx, V> { + assert!(!bx.cx().type_has_metadata(layout.ty)); + PlaceRef { + llval, + llextra: None, + layout, + align + } + } + pub fn alloca>( bx: &mut Bx, layout: TyLayout<'tcx>, @@ -421,8 +436,10 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } mir::Place::Static(box mir::Static { def_id, ty }) => { + // NB: The layout of a static may be unsized as is the case when working + // with a static that is an extern_type. let layout = cx.layout_of(self.monomorphize(&ty)); - PlaceRef::new_sized(bx.get_static(def_id), layout, layout.align.abi) + PlaceRef::new_thin_place(bx, bx.get_static(def_id), layout, layout.align.abi) }, mir::Place::Projection(box mir::Projection { ref base, diff --git a/src/test/run-make-fulldeps/static-extern-type/Makefile b/src/test/run-make-fulldeps/static-extern-type/Makefile new file mode 100644 index 0000000000000..5879fc0ce7781 --- /dev/null +++ b/src/test/run-make-fulldeps/static-extern-type/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: $(call NATIVE_STATICLIB,define-foo) + $(RUSTC) -ldefine-foo use-foo.rs + $(call RUN,use-foo) || exit 1 diff --git a/src/test/run-make-fulldeps/static-extern-type/define-foo.c b/src/test/run-make-fulldeps/static-extern-type/define-foo.c new file mode 100644 index 0000000000000..39be5acfa1118 --- /dev/null +++ b/src/test/run-make-fulldeps/static-extern-type/define-foo.c @@ -0,0 +1,11 @@ +#include + +struct Foo { + uint8_t x; +}; + +struct Foo FOO = { 42 }; + +uint8_t bar(const struct Foo* foo) { + return foo->x; +} diff --git a/src/test/run-make-fulldeps/static-extern-type/use-foo.rs b/src/test/run-make-fulldeps/static-extern-type/use-foo.rs new file mode 100644 index 0000000000000..932b5b5944bc7 --- /dev/null +++ b/src/test/run-make-fulldeps/static-extern-type/use-foo.rs @@ -0,0 +1,14 @@ +#![feature(extern_types)] + +extern "C" { + type Foo; + static FOO: Foo; + fn bar(foo: *const Foo) -> u8; +} + +fn main() { + unsafe { + let foo = &FOO; + assert_eq!(bar(foo), 42); + } +}