Skip to content

Frame pointer clobbered when restoring callee-saved registers #45

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

Closed
dylanmckay opened this issue May 1, 2017 · 6 comments
Closed

Frame pointer clobbered when restoring callee-saved registers #45

dylanmckay opened this issue May 1, 2017 · 6 comments
Labels
A-llvm Affects the LLVM AVR backend has-llvm-commit This issue should be fixed in upstream LLVM has-reduced-testcase A small LLVM IR file exists that demonstrates the problem

Comments

@dylanmckay
Copy link
Member

dylanmckay commented May 1, 2017

Discovered while working on #38.

I've found a problem which causes Y to be clobbered before function epilogue .

The function emission code looks something like this

  • Emit function prologue
  • Restore callee saved registers
  • Emit function epilogue

It looks like Y is automatically restored before the epilogue is generated. The epilogue assumes that 'Y' still contains SP, but it in actual fact contains its original value at the time the function was called.

This should be an easy fix.

I've been using the same testcase as in #38, shown here

interrupt.ll

; ModuleID = 'interrupt.cgu-0.rs'
source_filename = "interrupt.cgu-0.rs"
target datalayout = "e-p:16:16:16-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-n8"
target triple = "avr-atmel-none"

@__rustc_debug_gdb_scripts_section__ = internal unnamed_addr constant [34 x i8] c"\01gdb_load_rust_pretty_printers.py\00", section ".debug_gdb_scripts", align 1

; Function Attrs: nounwind uwtable
define void @main() unnamed_addr #0 !dbg !5 {
start:
  %tmp_ret2 = alloca i8
  %tmp_ret1 = alloca i8
  %tmp_ret = alloca i8
  %0 = load volatile i8, i8* inttoptr (i16 36 to i8*), align 1, !dbg !10
  store i8 %0, i8* %tmp_ret, !dbg !10
  %1 = load i8, i8* %tmp_ret, !dbg !10
  br label %bb1, !dbg !10

bb1:                                              ; preds = %start
  %2 = or i8 %1, 32, !dbg !10
  store volatile i8 %2, i8* inttoptr (i16 36 to i8*), align 1, !dbg !10
  br label %bb2, !dbg !10

bb2:                                              ; preds = %bb1
  %3 = load volatile i8, i8* inttoptr (i16 129 to i8*), align 1, !dbg !11
  store i8 %3, i8* %tmp_ret1, !dbg !11
  %4 = load i8, i8* %tmp_ret1, !dbg !11
  br label %bb3, !dbg !11

bb3:                                              ; preds = %bb2
  %5 = or i8 %4, 13, !dbg !11
  store volatile i8 %5, i8* inttoptr (i16 129 to i8*), align 1, !dbg !11
  br label %bb4, !dbg !11

bb4:                                              ; preds = %bb3
  store volatile i16 -3036, i16* inttoptr (i16 136 to i16*), align 2, !dbg !12
  br label %bb5, !dbg !12

bb5:                                              ; preds = %bb4
  %6 = load volatile i8, i8* inttoptr (i16 111 to i8*), align 1, !dbg !13
  store i8 %6, i8* %tmp_ret2, !dbg !13
  %7 = load i8, i8* %tmp_ret2, !dbg !13
  br label %bb6, !dbg !13

bb6:                                              ; preds = %bb5
  %8 = or i8 %7, 2, !dbg !13
  store volatile i8 %8, i8* inttoptr (i16 111 to i8*), align 1, !dbg !13
  br label %bb7, !dbg !13

bb7:                                              ; preds = %bb6
  call void asm "SEI", ""(), !dbg !14, !srcloc !15
  br label %bb8, !dbg !16

bb8:                                              ; preds = %bb8, %bb7
  br label %bb8, !dbg !16
}

; Function Attrs: nounwind uwtable
define avr_signalcc  void @__vector_11() unnamed_addr #0 !dbg !17 {
start:
  %tmp_ret = alloca i8
  %0 = load volatile i8, i8* inttoptr (i16 37 to i8*), align 1, !dbg !18
  store i8 %0, i8* %tmp_ret, !dbg !18
  %1 = load i8, i8* %tmp_ret, !dbg !18
  br label %bb1, !dbg !18

bb1:                                              ; preds = %start
  %2 = xor i8 %1, 32, !dbg !18
  store volatile i8 %2, i8* inttoptr (i16 37 to i8*), align 1, !dbg !18
  br label %bb2, !dbg !18

bb2:                                              ; preds = %bb1
  ret void, !dbg !19
}

attributes #0 = { nounwind uwtable "no-frame-pointer-elim"="true" }

!llvm.module.flags = !{!0, !1}
!llvm.dbg.cu = !{!2}

!0 = !{i32 1, !"PIE Level", i32 2}
!1 = !{i32 2, !"Debug Info Version", i32 3}
!2 = distinct !DICompileUnit(language: DW_LANG_Rust, file: !3, producer: "clang LLVM (rustc version 1.18.0-dev (f8982f5c8 2017-04-27))", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4)
!3 = !DIFile(filename: "interrupt", directory: "/home/dylan/projects/builds/rust-lang/avr-rust")
!4 = !{}
!5 = distinct !DISubprogram(name: "main", linkageName: "_ZN9interrupt4mainE", scope: !7, file: !6, line: 87, type: !8, isLocal: false, isDefinition: true, scopeLine: 87, flags: DIFlagPrototyped, isOptimized: false, unit: !2, templateParams: !4, variables: !4)
!6 = !DIFile(filename: "/tmp/interrupt.rs", directory: "/home/dylan/projects/builds/rust-lang/avr-rust")
!7 = !DINamespace(name: "interrupt", scope: null, file: !6, line: 1)
!8 = !DISubroutineType(types: !9)
!9 = !{null}
!10 = !DILocation(line: 89, scope: !5)
!11 = !DILocation(line: 92, scope: !5)
!12 = !DILocation(line: 95, scope: !5)
!13 = !DILocation(line: 98, scope: !5)
!14 = !DILocation(line: 101, scope: !5)
!15 = !{i32 1}
!16 = !DILocation(line: 103, scope: !5)
!17 = distinct !DISubprogram(name: "__vector_11", linkageName: "_ZN9interrupt11__vector_11E", scope: !7, file: !6, line: 108, type: !8, isLocal: false, isDefinition: true, scopeLine: 108, flags: DIFlagPrototyped, isOptimized: false, unit: !2, templateParams: !4, variables: !4)
!18 = !DILocation(line: 109, scope: !17)
!19 = !DILocation(line: 110, scope: !17)
@dylanmckay dylanmckay added the A-llvm Affects the LLVM AVR backend label May 1, 2017
@dylanmckay
Copy link
Member Author

Got a fix for this locally but it breaks a bunch of tests (presumably because the call frame for all functions has now changed).

@dylanmckay
Copy link
Member Author

dylanmckay commented May 2, 2017

Fixed in r301887 (EDIT: and in r301893). We previously broke the buildbot (#38, so we could enable FP everywhere).

I will leave the bot red because the 'FP everywhere' thing is temporary and not worth updating dozens of tests for.

Once we revert the 'fp everywhere' patch and come up with a better fix, I will have to go back and fix the tests broken by r301887 (EDIT: and in r301893) itself.

Cherry-picking the patches into our fork.

@dylanmckay
Copy link
Member Author

By the way @gergoerdi, with the commits for this and #38, your interrupt test case (in #38) compiles fine and doesn't give any warnings from simavr.

dylanmckay pushed a commit that referenced this issue May 2, 2017
@dylanmckay
Copy link
Member Author

dylanmckay commented May 2, 2017

Cherry picked the fixes from llvm-mirror/llvm@b0cacfc in 577e28d.

@dylanmckay dylanmckay added has-llvm-commit This issue should be fixed in upstream LLVM has-reduced-testcase A small LLVM IR file exists that demonstrates the problem labels May 2, 2017
@dylanmckay
Copy link
Member Author

I reverted the 'FP everywhere' commit locally so that I could fix all of the tests that r301887 broke. I discovered that r301887 actually regressed normal functions.

I've pushing up another fix, and now the test suite (while still red) is only red because of #38.

@dylanmckay
Copy link
Member Author

dylanmckay commented May 2, 2017

The fix (llvm-mirror/llvm@8c15c7b) is now in avr-support

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-llvm Affects the LLVM AVR backend has-llvm-commit This issue should be fixed in upstream LLVM has-reduced-testcase A small LLVM IR file exists that demonstrates the problem
Projects
None yet
Development

No branches or pull requests

1 participant