Skip to content

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

Closed
@kmcallister

Description

@kmcallister

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 = !{}

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-codegenArea: Code generationI-crashIssue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions