Skip to content

OS X exception tables wrong with internal assembler (file/parallelism release mode crashes) #362

Closed
@dnadlinger

Description

@dnadlinger

This one has been a giant trip down the rabbit hole.

Rather reduced test case:

; ModuleID = 'file.ll'
target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-apple-darwin11.4.2"

%1 = type opaque
%14 = type { %1*, i8*, { i64, i8* }, { i64, i8* }, i64, %1*, %1* }
@aconstant = external constant %14, align 8

@0 = internal global [72 x i8] zeroinitializer
@1 = internal constant %14 zeroinitializer
@_ZTIi = external constant i8*

define i32 @main() noreturn uwtable {
  %a = alloca [2048 x i8], align 1
  %c = call noalias i8* @newclass()
  %d = getelementptr i8* %c, i64 16
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %d, i8* bitcast ({ i64, i8* }* getelementptr (%14* @aconstant, i64 0, i32 2) to i8*), i64 56, i32 1, i1 false)
  %e = call noalias i8* @newclass()
  %f = bitcast i8* %e to %14*
  %g = getelementptr i8* %e, i64 16
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %g, i8* bitcast ({ i64, i8* }* getelementptr (%14* @aconstant, i64 0, i32 2) to i8*), i64 56, i32 1, i1 false)
  %h = call i8* @__cxa_allocate_exception(i64 4) nounwind
  %i = bitcast i8* %h to i32*
  store i32 42, i32* %i
  call void @__cxa_throw(i8* %h, i8* bitcast (i8** @_ZTIi to i8*), i8* null) noreturn
  unreachable
}

define noalias i8* @newclass() {
  ret i8* getelementptr inbounds ([72 x i8]* @0, i32 0, i32 0)
}

declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind

declare i8* @__cxa_allocate_exception(i64)

declare void @__cxa_throw(i8*, i8*, i8*)
; ModuleID = 'constant.ll'
target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-apple-darwin11.4.2"

%0 = type { %1*, i8*, { i64, i8* }, { i64, i8* }, i64, %1*, %1* }
%1 = type opaque
@aconstant = constant %0 zeroinitializer, align 8

Compile constant.ll using llc -filetype=obj constant.ll. Then, try two versions of compiling file.ll:

llc -O1 file.ll && clang -c file.s && clang++ file.o constant.o -o file.good && ./file.good

vs.

llc -O1 -filetype=obj file.ll && clang++ file.o constant.o -o file.bad && ./file.bad

test.bad crashes in the same way as the std.file/std.parallelism tests do in release mode, while test.good works fine ("terminate called throwing an exception").

The only difference between the two files is in the unwinding info. A diff of the unwinddump output shows that the stack size in the "bad" version is horribly wrong.

- [  1] funcOffset=0x00000DB0, encoding[  1]=0x030DF800 (stack size=0x00000840, rbx,r12,r13,r14,r15,rbp) _main
+ [  1] funcOffset=0x00000DB0, encoding[  1]=0x0309F800 (stack size=0xEC81488B, rbx,r12,r13,r14,r15,rbp) _main

Will open an upstream bug report asap.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions