Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bad codegen with const used on the left of @ pattern #22850

Closed
kmcallister opened this issue Feb 26, 2015 · 2 comments
Closed

Bad codegen with const used on the left of @ pattern #22850

kmcallister opened this issue Feb 26, 2015 · 2 comments
Labels
A-codegen Area: Code generation I-crash Issue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics.

Comments

@kmcallister
Copy link
Contributor

Possibly the treatment as a match vs. a binding is inconsistent between typeck and trans. The unused variable lint is also peculiar.

macro_rules! foo {
    ($n:expr) => {
        match $n {
            zzzz @ _ => zzzz + 1,       
            _ => 0,
        }
    }
} 

fn main() {
    const zzzz: i32 = 3; 
    assert_eq!(foo!(3), 4);
}
$ rustc --version
rustc 1.0.0-dev (4db0b3246 2015-02-25) (built 2015-02-26)

$ rustc -C debuginfo=2 foo.rs   # only happens w/o opt
foo.rs:4:13: 4:21 warning: unused variable: `zzzz`, #[warn(unused_variables)] on by default
foo.rs:4             zzzz @ _ => zzzz + 1,
                     ^~~~~~~~
foo.rs:1:1: 8:2 note: in expansion of foo!
foo.rs:12:16: 12:24 note: expansion site
<std macros>:1:1: 9:39 note: in expansion of assert_eq!
foo.rs:12:5: 12:28 note: expansion site
foo.rs:11:5: 11:25 warning: constant `zzzz` should have an upper case name such as `ZZZZ`, #[warn(non_upper_case_globals)] on by default
foo.rs:11     const zzzz: i32 = 3;
              ^~~~~~~~~~~~~~~~~~~~
foo.rs:4:13: 4:21 warning: constant in pattern `zzzz` should have an upper case name such as `ZZZZ`, #[warn(non_upper_case_globals)] on by default
foo.rs:4             zzzz @ _ => zzzz + 1,
                     ^~~~~~~~
foo.rs:1:1: 8:2 note: in expansion of foo!
foo.rs:12:16: 12:24 note: expansion site
<std macros>:1:1: 9:39 note: in expansion of assert_eq!
foo.rs:12:5: 12:28 note: expansion site

$ gdb ./foo
(gdb) run
Starting program: /tmp/foo 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Program received signal SIGSEGV, Segmentation fault.
0x0000555555559146 in foo::main () at foo.rs:10
10      fn main() {

IR:

; ModuleID = 'foo.0.rs'
target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

%str_slice = type { i8*, i64 }
%"2.core::fmt::Formatter" = type { i32, i32, i8, %"2.core::option::Option<usize>", %"2.core::option::Option<usize>", { i8*, void (i8*)** }, %"2.core::slice::Iter<core::fmt::ArgumentV1>", { %"2.core::fmt::ArgumentV1"*, i64 } }
%"2.core::option::Option<usize>" = type { i64, [0 x i64], [1 x i64] }
%"2.core::slice::Iter<core::fmt::ArgumentV1>" = type { %"2.core::fmt::ArgumentV1"*, %"2.core::fmt::ArgumentV1"*, %"2.core::marker::PhantomData<&'static core::fmt::ArgumentV1>" }
%"2.core::fmt::ArgumentV1" = type { %"2.core::fmt::Void"*, i8 (%"2.core::fmt::Void"*, %"2.core::fmt::Formatter"*)* }
%"2.core::fmt::Void" = type {}
%"2.core::marker::PhantomData<&'static core::fmt::ArgumentV1>" = type {}
%"2.core::fmt::Arguments" = type { { %str_slice*, i64 }, %"2.core::option::Option<&'static [core::fmt::rt::v1::Argument]>", { %"2.core::fmt::ArgumentV1"*, i64 } }
%"2.core::option::Option<&'static [core::fmt::rt::v1::Argument]>" = type { { %"2.core::fmt::rt::v1::Argument"*, i64 } }
%"2.core::fmt::rt::v1::Argument" = type { %"2.core::fmt::rt::v1::Position", %"2.core::fmt::rt::v1::FormatSpec" }
%"2.core::fmt::rt::v1::Position" = type { i64, [0 x i64], [1 x i64] }
%"2.core::fmt::rt::v1::FormatSpec" = type { i32, i8, i32, %"2.core::fmt::rt::v1::Count", %"2.core::fmt::rt::v1::Count" }
%"2.core::fmt::rt::v1::Count" = type { i64, [0 x i64], [1 x i64] }

@const19 = internal unnamed_addr constant i32 3
@const22 = internal unnamed_addr constant i32 4
@const26 = internal unnamed_addr constant i32 0
@const27 = internal unnamed_addr constant i32* @const22
@const133 = internal unnamed_addr constant { { i8*, i8* } } zeroinitializer
@str1146 = internal constant [63 x i8] c"assertion failed: `(left == right) && (right == left)` (left: `"
@str1147 = internal constant [11 x i8] c"`, right: `"
@str1148 = internal constant [2 x i8] c"`)"
@ref68 = internal unnamed_addr constant [3 x %str_slice] [%str_slice { i8* getelementptr inbounds ([63 x i8]* @str1146, i32 0, i32 0), i64 63 }, %str_slice { i8* getelementptr inbounds ([11 x i8]* @str1147, i32 0, i32 0), i64 11 }, %str_slice { i8* getelementptr inbounds ([2 x i8]* @str1148, i32 0, i32 0), i64 2 }]
@_ZN4main15__STATIC_FMTSTR20h0eec925d33596e3a9aaE = internal constant { %str_slice*, i64 } { %str_slice* getelementptr inbounds ([3 x %str_slice]* @ref68, i32 0, i32 0), i64 3 }
@const90 = internal unnamed_addr constant i8 (i32*, %"2.core::fmt::Formatter"*)* @_ZN3fmt3num14i32.fmt..Debug3fmt20h82571085d6d53e2c8uBE
@str1159 = internal constant [6 x i8] c"foo.rs"
@_ZN4main10_FILE_LINE20ha7672bc1aa8c4e82KbaE = internal constant { %str_slice, i64 } { %str_slice { i8* getelementptr inbounds ([6 x i8]* @str1159, i32 0, i32 0), i64 6 }, i64 12 }

; Function Attrs: uwtable
define internal void @_ZN4main20hd61647c88ae5d91beaaE() unnamed_addr #0 {
entry-block:
  %0 = alloca { i32*, i32* }
  %1 = alloca i32
  %match = alloca i32
  %__llmatch = alloca i32*
  %zzzz = alloca i32
  %addr_of = alloca i32
  %__llmatch3 = alloca i32**
  %left_val = alloca i32*
  %__llmatch4 = alloca i32**
  %right_val = alloca i32*
  %2 = alloca %"2.core::fmt::Arguments"
  %3 = alloca { %str_slice*, i64 }
  %4 = alloca [2 x %"2.core::fmt::ArgumentV1"]
  %5 = alloca { i32*, i32* }
  %__llmatch7 = alloca i32**
  %__arg0 = alloca i32*
  %__llmatch8 = alloca i32**
  %__arg1 = alloca i32*
  %auto_deref = alloca [2 x %"2.core::fmt::ArgumentV1"]*
  %__fat_ptr = alloca { %"2.core::fmt::ArgumentV1"*, i64 }
  %__fat_ptr10 = alloca { %"2.core::fmt::ArgumentV1"*, i64 }
  %6 = alloca { %str_slice, i64 }*
  %7 = getelementptr inbounds { i32*, i32* }* %0, i32 0, i32 0
  store i32 3, i32* %match
  %8 = load i32* %match
  switch i32 %8, label %match_else [
    i32 3, label %match_case
  ]

case_body:                                        ; preds = %match_case
  %9 = load i32** %__llmatch
  %10 = load i32* %9
  store i32 %10, i32* %zzzz
  store i32 4, i32* %1
  br label %join

case_body1:                                       ; preds = %match_else
  store i32 0, i32* %1
  br label %join

match_else:                                       ; preds = %entry-block
  br label %case_body1

match_case:                                       ; preds = %entry-block
  br label %case_body

join:                                             ; preds = %case_body1, %case_body
  %11 = load i32* %1
  store i32 %11, i32* %addr_of
  store i32* %addr_of, i32** %7
  %12 = getelementptr inbounds { i32*, i32* }* %0, i32 0, i32 1
  store i32* @const22, i32** %12
  %13 = getelementptr inbounds { i32*, i32* }* %0, i32 0, i32 0
  %14 = getelementptr inbounds { i32*, i32* }* %0, i32 0, i32 1
  store i32** %13, i32*** %__llmatch3
  store i32** %14, i32*** %__llmatch4
  br label %case_body2

case_body2:                                       ; preds = %join
  %15 = load i32*** %__llmatch3
  %16 = load i32** %15, !nonnull !0
  store i32* %16, i32** %left_val
  %17 = load i32*** %__llmatch4
  %18 = load i32** %17, !nonnull !0
  store i32* %18, i32** %right_val
  %19 = load i32** %left_val, !nonnull !0
  %20 = load i32** %right_val, !nonnull !0
  %21 = load i32* %19
  %22 = load i32* %20
  %23 = icmp eq i32 %21, %22
  br i1 %23, label %before_rhs, label %join5

join5:                                            ; preds = %before_rhs, %case_body2
  %24 = phi i1 [ %23, %case_body2 ], [ %30, %before_rhs ]
  %25 = xor i1 %24, true
  br i1 %25, label %then-block-51-, label %next-block

before_rhs:                                       ; preds = %case_body2
  %26 = load i32** %right_val, !nonnull !0
  %27 = load i32** %left_val, !nonnull !0
  %28 = load i32* %26
  %29 = load i32* %27
  %30 = icmp eq i32 %28, %29
  br label %join5

then-block-51-:                                   ; preds = %join5
  %31 = bitcast { %str_slice*, i64 }* %3 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %31, i8* bitcast ({ %str_slice*, i64 }* @_ZN4main15__STATIC_FMTSTR20h0eec925d33596e3a9aaE to i8*), i64 16, i32 8, i1 false)
  %32 = getelementptr inbounds { i32*, i32* }* %5, i32 0, i32 0
  %33 = load i32** %left_val, !nonnull !0
  store i32* %33, i32** %32
  %34 = getelementptr inbounds { i32*, i32* }* %5, i32 0, i32 1
  %35 = load i32** %right_val, !nonnull !0
  store i32* %35, i32** %34
  %36 = getelementptr inbounds { i32*, i32* }* %5, i32 0, i32 0
  %37 = getelementptr inbounds { i32*, i32* }* %5, i32 0, i32 1
  store i32** %36, i32*** %__llmatch7
  store i32** %37, i32*** %__llmatch8
  br label %case_body6

case_body6:                                       ; preds = %then-block-51-
  %38 = load i32*** %__llmatch8
  %39 = load i32** %38, !nonnull !0
  store i32* %39, i32** %__arg1
  %40 = load i32*** %__llmatch7
  %41 = load i32** %40, !nonnull !0
  store i32* %41, i32** %__arg0
  %42 = getelementptr inbounds [2 x %"2.core::fmt::ArgumentV1"]* %4, i32 0, i32 0
  %43 = getelementptr inbounds %"2.core::fmt::ArgumentV1"* %42, i32 0
  %44 = load i32** %__arg0, !nonnull !0
  call void @"_ZN3fmt24ArgumentV1$LT$$u27$a$GT$3new21h11701018729727839244E"(%"2.core::fmt::ArgumentV1"* noalias nocapture sret dereferenceable(16) %43, i32* noalias readonly dereferenceable(4) %44, i8 (i32*, %"2.core::fmt::Formatter"*)* @_ZN3fmt3num14i32.fmt..Debug3fmt20h82571085d6d53e2c8uBE)
  %45 = getelementptr inbounds %"2.core::fmt::ArgumentV1"* %42, i32 1
  %46 = load i32** %__arg1, !nonnull !0
  call void @"_ZN3fmt24ArgumentV1$LT$$u27$a$GT$3new21h11701018729727839244E"(%"2.core::fmt::ArgumentV1"* noalias nocapture sret dereferenceable(16) %45, i32* noalias readonly dereferenceable(4) %46, i8 (i32*, %"2.core::fmt::Formatter"*)* @_ZN3fmt3num14i32.fmt..Debug3fmt20h82571085d6d53e2c8uBE)
  br label %join9

join9:                                            ; preds = %case_body6
  store [2 x %"2.core::fmt::ArgumentV1"]* %4, [2 x %"2.core::fmt::ArgumentV1"]** %auto_deref
  %47 = load [2 x %"2.core::fmt::ArgumentV1"]** %auto_deref, !nonnull !0
  %48 = bitcast [2 x %"2.core::fmt::ArgumentV1"]* %47 to %"2.core::fmt::ArgumentV1"*
  %49 = getelementptr inbounds { %"2.core::fmt::ArgumentV1"*, i64 }* %__fat_ptr, i32 0, i32 0
  store %"2.core::fmt::ArgumentV1"* %48, %"2.core::fmt::ArgumentV1"** %49
  %50 = getelementptr inbounds { %"2.core::fmt::ArgumentV1"*, i64 }* %__fat_ptr, i32 0, i32 1
  store i64 2, i64* %50
  %51 = bitcast { %"2.core::fmt::ArgumentV1"*, i64 }* %__fat_ptr to i8*
  %52 = bitcast { %"2.core::fmt::ArgumentV1"*, i64 }* %__fat_ptr10 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %52, i8* %51, i64 16, i32 8, i1 false)
  call void @"_ZN3fmt23Arguments$LT$$u27$a$GT$6new_v120hddb70f9412632ed662BE"(%"2.core::fmt::Arguments"* noalias nocapture sret dereferenceable(48) %2, { %str_slice*, i64 }* noalias nocapture dereferenceable(16) %3, { %"2.core::fmt::ArgumentV1"*, i64 }* noalias nocapture dereferenceable(16) %__fat_ptr10)
  store { %str_slice, i64 }* @_ZN4main10_FILE_LINE20ha7672bc1aa8c4e82KbaE, { %str_slice, i64 }** %6
  %53 = load { %str_slice, i64 }** %6, !nonnull !0
  call void @_ZN2rt6unwind16begin_unwind_fmt20hbda8d92395aa47d1LOIE(%"2.core::fmt::Arguments"* noalias nocapture dereferenceable(48) %2, { %str_slice, i64 }* noalias readonly dereferenceable(24) %53)
  unreachable

next-block:                                       ; preds = %join5
  br label %join11

join11:                                           ; preds = %next-block
  ret void
}

define i64 @main(i64, i8**) unnamed_addr #1 {
top:
  %2 = call i64 @_ZN2rt10lang_start20h7a2fc813423057b2l4IE(i8* bitcast (void ()* @_ZN4main20hd61647c88ae5d91beaaE to i8*), i64 %0, i8** %1)
  ret i64 %2
}

declare i64 @_ZN2rt10lang_start20h7a2fc813423057b2l4IE(i8*, i64, i8**) unnamed_addr #1

; Function Attrs: cold noinline noreturn
declare void @_ZN2rt6unwind16begin_unwind_fmt20hbda8d92395aa47d1LOIE(%"2.core::fmt::Arguments"* noalias nocapture dereferenceable(48), { %str_slice, i64 }* noalias readonly dereferenceable(24)) unnamed_addr #2

; Function Attrs: inlinehint uwtable
define internal void @"_ZN3fmt23Arguments$LT$$u27$a$GT$6new_v120hddb70f9412632ed662BE"(%"2.core::fmt::Arguments"* noalias nocapture sret dereferenceable(48), { %str_slice*, i64 }* noalias nocapture dereferenceable(16), { %"2.core::fmt::ArgumentV1"*, i64 }* noalias nocapture dereferenceable(16)) unnamed_addr #3 {
entry-block:
  %3 = getelementptr inbounds %"2.core::fmt::Arguments"* %0, i32 0, i32 0
  %4 = bitcast { %str_slice*, i64 }* %1 to i8*
  %5 = bitcast { %str_slice*, i64 }* %3 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %5, i8* %4, i64 16, i32 8, i1 false)
  %6 = getelementptr inbounds %"2.core::fmt::Arguments"* %0, i32 0, i32 1
  %7 = bitcast %"2.core::option::Option<&'static [core::fmt::rt::v1::Argument]>"* %6 to { { i8*, i8* } }*
  %8 = bitcast { { i8*, i8* } }* %7 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %8, i8* bitcast ({ { i8*, i8* } }* @const133 to i8*), i64 16, i32 8, i1 false)
  %9 = getelementptr inbounds %"2.core::fmt::Arguments"* %0, i32 0, i32 2
  %10 = bitcast { %"2.core::fmt::ArgumentV1"*, i64 }* %2 to i8*
  %11 = bitcast { %"2.core::fmt::ArgumentV1"*, i64 }* %9 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %11, i8* %10, i64 16, i32 8, i1 false)
  ret void
}

; Function Attrs: nounwind
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1) unnamed_addr #4

; Function Attrs: uwtable
define internal void @"_ZN3fmt24ArgumentV1$LT$$u27$a$GT$3new21h11701018729727839244E"(%"2.core::fmt::ArgumentV1"* noalias nocapture sret dereferenceable(16), i32* noalias readonly dereferenceable(4), i8 (i32*, %"2.core::fmt::Formatter"*)*) unnamed_addr #0 {
entry-block:
  %x = alloca i32*
  %f = alloca i8 (i32*, %"2.core::fmt::Formatter"*)*
  store i32* %1, i32** %x
  store i8 (i32*, %"2.core::fmt::Formatter"*)* %2, i8 (i32*, %"2.core::fmt::Formatter"*)** %f
  %3 = getelementptr inbounds %"2.core::fmt::ArgumentV1"* %0, i32 0, i32 1
  %4 = load i8 (i32*, %"2.core::fmt::Formatter"*)** %f
  %5 = bitcast i8 (i32*, %"2.core::fmt::Formatter"*)* %4 to i8 (%"2.core::fmt::Void"*, %"2.core::fmt::Formatter"*)*
  store i8 (%"2.core::fmt::Void"*, %"2.core::fmt::Formatter"*)* %5, i8 (%"2.core::fmt::Void"*, %"2.core::fmt::Formatter"*)** %3
  %6 = getelementptr inbounds %"2.core::fmt::ArgumentV1"* %0, i32 0, i32 0
  %7 = load i32** %x, !nonnull !0
  %8 = bitcast i32* %7 to %"2.core::fmt::Void"*
  store %"2.core::fmt::Void"* %8, %"2.core::fmt::Void"** %6
  ret void
}

declare i8 @_ZN3fmt3num14i32.fmt..Debug3fmt20h82571085d6d53e2c8uBE(i32* noalias readonly dereferenceable(4), %"2.core::fmt::Formatter"* noalias dereferenceable(96)) unnamed_addr #1

attributes #0 = { uwtable "split-stack" }
attributes #1 = { "split-stack" }
attributes #2 = { cold noinline noreturn "split-stack" }
attributes #3 = { inlinehint uwtable "split-stack" }
attributes #4 = { nounwind "split-stack" }

!0 = !{}
@kmcallister kmcallister added I-crash Issue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics. A-codegen Area: Code generation I-nominated labels Feb 26, 2015
@Aatch
Copy link
Contributor

Aatch commented Feb 27, 2015

Hmm, I can't seem to reproduce with a compiler that is very close to the current master. Could you try with the latest master?

@kmcallister
Copy link
Contributor Author

Yeah, I can't reproduce it anymore on rustc 1.0.0-dev (bd0d8e4 2015-02-27) (built 2015-02-27).

There are lots of things that could cause this. My computer isn't 100% stable (heavy overclock) so that's one possibility.

Still pretty worrying, but I don't know how to proceed with investigating.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-codegen Area: Code generation I-crash Issue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics.
Projects
None yet
Development

No branches or pull requests

2 participants