avr-rust / rust-legacy-fork

[deprecated; merged upstream] A fork of the Rust programming language with AVR support
Other
493 stars 14 forks source link

Expected either Y or Z register #128

Open hercek opened 5 years ago

hercek commented 5 years ago

The invalid assembly generated error seems to be back when compiling blink.

rustup run avr-toolchain xargo build --target avr-atmega328p --release Compiling core v0.0.0 (file:///home/peter/rust/rust/src/libcore) Expected either Y or Z register UNREACHABLE executed at /home/peter/rust/rust/src/llvm/lib/Target/AVR/MCTargetDesc/AVRMCCodeEmitter.cpp:146! error: Could not compile core.

asheidan commented 5 years ago

I got the same error message while compiling the blink project (though the error seems to be from libcore) but the cause was another file:

rustup run avr-toolchain xargo build --target avr-atmega328p --release
   Compiling core v0.0.0 (/Users/emieri/Documents/Source/avr-rust/rust/src/libcore)
Expected either Y or Z register
UNREACHABLE executed at ~/avr-rust/rust/src/llvm/lib/Target/AVR/MCTargetDesc/AVRMCCodeEmitter.cpp:146!
error: Could not compile `core`.

Please let me know if I can help out by providing more information.

Vinc0682 commented 5 years ago

I have the same issue in combination with a message that wont go away after running xargo update or cargo update.



warning: Patch rustc-std-workspace-core v1.0.0 (/home/myusername/Downloads/rduino/rust/src/tools/rustc-std-workspace-core) was not used in the crate graph.
Check that the patched package version and available features are compatible
with the dependency requirements. If the patch has a different version from
what is locked in the Cargo.lock file, run cargo update to use the new
version. This may also occur with an optional dependency that is not enabled.
   Compiling core v0.0.0 (/home/myusername/Downloads/rduino/rust/src/libcore)
Expected either Y or Z register
UNREACHABLE executed at /home/myusername/Downloads/rduino/rust/src/llvm/lib/Target/AVR/MCTargetDesc/AVRMCCodeEmitter.cpp:146!
error: Could not compile core.

Caused by:
  process didn't exit successfully: rustc --crate-name core /home/myusername/Downloads/rduino/rust/src/libcore/lib.rs --color always --crate-type lib --emit=dep-info,link -C opt-level=3 -C metadata=d55c7e2141792a61 -C extra-filename=-d55c7e2141792a61 --out-dir /tmp/xargo.5TwVNc9HZZly/target/avr-atmega328p/release/deps --target avr-atmega328p -L dependency=/tmp/xargo.5TwVNc9HZZly/target/avr-atmega328p/release/deps -L dependency=/tmp/xargo.5TwVNc9HZZly/target/release/deps --sysroot /home/myusername/.xargo -Z force-unstable-if-unmarked (signal: 6, SIGABRT: process abort signal)
error: "cargo" "build" "--release" "--manifest-path" "/tmp/xargo.5TwVNc9HZZly/Cargo.toml" "--target" "avr-atmega328p" "-p" "core"` failed with exit code: Some(101)```

Stacktrace: 
`stack backtrace:
   0: error_chain::make_backtrace::hcdf05aaec9e819e0 (0x5617e25cc817)
   1: <error_chain::State as core::default::Default>::default::h69c20e25da695e17 (0x5617e25cc8a5)
   2: <std::process::Command as xargo::extensions::CommandExt>::run::h0942c6558146e76d (0x5617e2586daf)
   3: xargo::sysroot::build::h6514e4e6ffd86301 (0x5617e258fba8)
   4: xargo::sysroot::update::h137743eccc702b26 (0x5617e2593314)
   5: xargo::main::h402bd633f396879f (0x5617e25a0209)
   6: std::rt::lang_start::{{closure}}::h2e435953cbd00c95 (0x5617e257f6c2)
   7: std::rt::lang_start_internal::{{closure}}::h95abf94266177bce (0x5617e25eba42)
             at src/libstd/rt.rs:49
      std::panicking::try::do_call::h197f8ee7e1151bb3
             at src/libstd/panicking.rs:297
   8: __rust_maybe_catch_panic (0x5617e25f4309)
             at src/libpanic_unwind/lib.rs:92
   9: std::panicking::try::he1e9af636df1f58f (0x5617e25ec595)
             at src/libstd/panicking.rs:276
      std::panic::catch_unwind::hd1ca050dcb3c7db9
             at src/libstd/panic.rs:388
      std::rt::lang_start_internal::he9a94834a09ccf7f
             at src/libstd/rt.rs:48
  10: main (0x5617e25a0c91)
  11: __libc_start_main (0x7f1106a35b96)
  12: _start (0x5617e25744b9)
  13: <unknown> (0x0)
`

How to reproduce:

1. Clone this repository

2. Follow the installation instructions, I have changed the prefix in the configure step and not set avr-rust to my default toolchain

3. Clone the blink example

4. Follow the usage instructions with the adjusted path to the avr-rust src
carlos4242 commented 5 years ago

I was about to raise a dupe...

Found the same issue myself.

carlos4242 commented 5 years ago

This LLVM IR is failing to compile and crashing LLC.

; ModuleID = 'main_clean.ll'
source_filename = "main.ll"
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.9"

@start2 = external local_unnamed_addr global i8*, align 8
@finish3 = external local_unnamed_addr global i8*, align 8
@__swift_reflection_version = linkonce_odr hidden constant i16 1
@llvm.used = appending global [1 x i8*] [i8* bitcast (i16* @__swift_reflection_version to i8*)], section "llvm.metadata"

define i32 @main(i32, i8** nocapture readnone) local_unnamed_addr #0 {
entry:
  tail call void @_TF3AVR11SetupSerialFT8baudRateVs6UInt16_T_(i16 -7936)
  %2 = load i64, i64* bitcast (i8** @start2 to i64*), align 8
  %3 = tail call i1 @_TIF3AVR5printFT7messageGSqGSPVs4Int8__10addNewlineSb_T_A0_()
  tail call void @_TF3AVR5printFT7messageGSqGSPVs4Int8__10addNewlineSb_T_(i64 %2, i1 %3)
  %4 = tail call i8* @_TF4mainau2i1Vs5Int16()
  %._value = bitcast i8* %4 to i16*
  %5 = load i16, i16* %._value, align 2
  %6 = tail call i8* @_TF4mainau2i2Vs5Int16()
  %._value1 = bitcast i8* %6 to i16*
  %7 = load i16, i16* %._value1, align 2
  %8 = add i16 %7, %5
  tail call void @_TF4main6expectFTVs5Int16S0__T_(i16 %8, i16 149)
  %9 = tail call i8* @_TF4mainau2i3Vs5Int16()
  %._value2 = bitcast i8* %9 to i16*
  %10 = load i16, i16* %._value2, align 2
  %11 = tail call i8* @_TF4mainau2i4Vs5Int16()
  %._value3 = bitcast i8* %11 to i16*
  %12 = load i16, i16* %._value3, align 2
  %13 = add i16 %12, %10
  tail call void @_TF4main6expectFTVs5Int16S0__T_(i16 %13, i16 108)
  %14 = tail call i8* @_TF4mainau2i5Vs5Int16()
  %._value4 = bitcast i8* %14 to i16*
  %15 = load i16, i16* %._value4, align 2
  %16 = tail call i8* @_TF4mainau2i6Vs5Int16()
  %._value5 = bitcast i8* %16 to i16*
  %17 = load i16, i16* %._value5, align 2
  %18 = add i16 %17, %15
  tail call void @_TF4main6expectFTVs5Int16S0__T_(i16 %18, i16 53)
  %19 = load i16, i16* %._value4, align 2
  %20 = load i16, i16* %._value5, align 2
  %21 = sub i16 %19, %20
  tail call void @_TF4main6expectFTVs5Int16S0__T_(i16 %21, i16 -39)
  %22 = load i16, i16* %._value5, align 2
  %23 = load i16, i16* %._value4, align 2
  %24 = sub i16 %22, %23
  tail call void @_TF4main6expectFTVs5Int16S0__T_(i16 %24, i16 39)
  %25 = load i16, i16* %._value, align 2
  %26 = load i16, i16* %._value1, align 2
  %27 = mul i16 %26, %25
  tail call void @_TF4main6expectFTVs5Int16S0__T_(i16 %27, i16 5130)
  %28 = load i16, i16* %._value, align 2
  %29 = load i16, i16* %._value1, align 2
  %30 = icmp eq i16 %29, 0
  br i1 %30, label %109, label %31

Compiled with llc main_clean_opt.ll -O3 -march=avr -mcpu=atmega328p -filetype=obj it crashes:

Expected either Y or Z register
UNREACHABLE executed at ../../lib/Target/AVR/MCTargetDesc/AVRMCCodeEmitter.cpp:146!
Stack dump:
0.  Program arguments: bin/llc main_clean_opt.ll -O3 -march=avr -mcpu=atmega328p -filetype=obj 
1.  Running pass 'Function Pass Manager' on module 'main_clean_opt.ll'.
2.  Running pass 'AVR Assembly Printer' on function '@main'
0  llc                      0x00000001114e519c llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 60
1  llc                      0x00000001114e5769 PrintStackTraceSignalHandler(void*) + 25
2  llc                      0x00000001114e1e3e llvm::sys::RunSignalHandlers() + 990
3  llc                      0x00000001114e6409 SignalHandler(int) + 505
4  libsystem_platform.dylib 0x00007fff60069b3d _sigtramp + 29
5  libsystem_platform.dylib 0x0000000116b38bc6 _sigtramp + 3064787110
6  libsystem_c.dylib        0x00007fff5ff271c9 abort + 127
7  llc                      0x0000000111388110 llvm::install_out_of_memory_new_handler() + 0
8  llc                      0x000000010f8cf2b7 llvm::AVRMCCodeEmitter::encodeMemri(llvm::MCInst const&, unsigned int, llvm::SmallVectorImpl<llvm::MCFixup>&, llvm::MCSubtargetInfo const&) const + 263
9  llc                      0x000000010f8d0365 llvm::AVRMCCodeEmitter::getBinaryCodeForInstr(llvm::MCInst const&, llvm::SmallVectorImpl<llvm::MCFixup>&, llvm::MCSubtargetInfo const&) const + 1957
10 llc                      0x000000010f8cfb7b llvm::AVRMCCodeEmitter::encodeInstruction(llvm::MCInst const&, llvm::raw_ostream&, llvm::SmallVectorImpl<llvm::MCFixup>&, llvm::MCSubtargetInfo const&) const + 187
11 llc                      0x00000001109caeb3 llvm::MCELFStreamer::EmitInstToData(llvm::MCInst const&, llvm::MCSubtargetInfo const&) + 211
12 llc                      0x0000000110a0716a llvm::MCObjectStreamer::EmitInstructionImpl(llvm::MCInst const&, llvm::MCSubtargetInfo const&) + 250
13 llc                      0x0000000110a07040 llvm::MCObjectStreamer::EmitInstruction(llvm::MCInst const&, llvm::MCSubtargetInfo const&, bool) + 80
14 llc                      0x000000010fd2567e llvm::AsmPrinter::EmitToStreamer(llvm::MCStreamer&, llvm::MCInst const&) + 78
15 llc                      0x000000010f8802a4 llvm::AVRAsmPrinter::EmitInstruction(llvm::MachineInstr const*) + 164
16 llc                      0x000000010fd2db63 llvm::AsmPrinter::EmitFunctionBody() + 4419
17 llc                      0x000000010f880458 llvm::AsmPrinter::runOnMachineFunction(llvm::MachineFunction&) + 56
18 llc                      0x0000000110126471 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) + 545
19 llc                      0x00000001107e6f67 llvm::FPPassManager::runOnFunction(llvm::Function&) + 503
20 llc                      0x00000001107e7635 llvm::FPPassManager::runOnModule(llvm::Module&) + 117
21 llc                      0x00000001107e819a (anonymous namespace)::MPPassManager::runOnModule(llvm::Module&) + 1546
22 llc                      0x00000001107e790e llvm::legacy::PassManagerImpl::run(llvm::Module&) + 366
23 llc                      0x00000001107e8cb1 llvm::legacy::PassManager::run(llvm::Module&) + 33
24 llc                      0x000000010eff383f compileModule(char**, llvm::LLVMContext&) + 24159
25 llc                      0x000000010efecd9f main + 5487
26 libdyld.dylib            0x00007fff5fe7eed9 start + 1
Abort trap: 6

Compiling to .s and using avr-gcc shows that the error is we aren't allowed to use LDD with the X register.

Compiled to assembly it produces this non compilable code:

        mov     r16, r24
        movw    r18, r10
        movw    r20, r12
        movw    r22, r14
        movw    r24, r8
        call    _TF3AVR5printFT7messageGSqGSPVs4Int8__10addNewlineSb_T_
        call    _TF4mainau2i1Vs5Int16
        movw    r26, r24
        ld      r16, X
        ldd     r17, X+1
        movw    r12, r26

ldd r17, X+1 is not valid AVR assembly I think? https://www.microchip.com/webdoc/avrassembler/avrassembler.wb_instruction_list.html

My suspicion is that commit 87c4dc90ec85cd7d107adfe66e3707346b3ad796 has caused a regression. I'll try to investigate after sleep.

carlos4242 commented 5 years ago

This minimum llvm IR causes the crash:

define i32 @main(i32, i8** nocapture readnone) local_unnamed_addr {
entry:
  %2 = tail call i8* @globalVal()
  %._value = bitcast i8* %2 to i16*
  %3 = load i16, i16* %._value, align 2
  tail call void @expect(i16 %3, i16 149)
  ret i32 0
}

declare hidden void @expect(i16, i16) local_unnamed_addr
declare hidden i8* @globalVal() local_unnamed_addr

It produces this assembly:

    .text
    .file   "main_clean_opt.ll"
    .globl  main                    ; -- Begin function main
    .p2align    1
    .type   main,@function
main:                                   ; @main
; %bb.0:                                ; %entry
    call    globalVal
    movw    r26, r24
    ld  r24, X
    ldd r25, X+1
    ldi r22, 149
    ldi r23, 0
    call    expect
    ldi r22, 0
    ldi r23, 0
    movw    r24, r22
    ret
.Lfunc_end0:
    .size   main, .Lfunc_end0-main
                                        ; -- End function
    .hidden expect
    .hidden globalVal

This is invalid and cannot be compiled by either gcc or llvm, it should be using Y or Z for indirect access, not X; outputting an object file instead of assembly causes the crash. I'll bugpoint and try to bisect which commit(s) introduced the issue later. Note: 87c4dc90ec85cd7d107adfe66e3707346b3ad796 has turned this into a crash but there were existing issues that needed resolution, so reverting that commit does not resolve the problem.

hercek commented 5 years ago

I do not know what is the syntax used by llvm but the proper assembly should have been:

ld    r24, X+    ; load byte pointed by X to r24 and postincrement X
ld    r25, X     ; load byte pointed by X to r25

These are valid instructions (ld instruction uses X register) and the message that register Y or Z should have been used is wrong.

Edit: Or maybe it really should have used Y or Z register because llvm authors decided that X will not be used in this context. The point is that all (X,Y,Z) are possible as for as at least ATmega23u4 and ATXmega128A4U are concerned.

Edit2: I see. They limited themselves to Y and Z registers so that they can use ldd r,Y+q and ldd r,Z+q variants. Even when it is not needed in this case.

carlos4242 commented 5 years ago

That exactly what the compiler used to do before.

This commit changed the behaviour: https://github.com/avr-rust/llvm/commit/87c4dc90ec85cd7d107adfe66e3707346b3ad796

The bug being fixed is that ld r24, X+ ld r25, X Is valid but changes X (I.e. r26/r27) which was causing issues to some people.

This fix seems to have changed the emitted code to ld r24, X ldd r25, X+1

To avoid side effects.

Which is invalid for X (but works for Y or Z)

I’m not clear how the patch works but I think there are two broad approaches that seem sense:

1) leave the new code but change the register selection so that it will only ever select Y or Z.

2) revert to the old code, but find a way to tell the compiler the X register is “clobbered” after this operation and cannot be reused. It should act accordingly.

I’m not really sure how to do either so I’m only helping with advice and unit tests until more experienced people can help pick it up!

On 10 Mar 2019, at 19:38, hercek notifications@github.com wrote:

I do not know what is the syntax used by llvm but the proper assembly should have been:

ld r24, X+ ; load byte pointed by X to r24 and postincrement X ld r25, X ; load byte pointed by X to r25 These are valid instructions (ld instruction uses X register) and the message that register Y or Z should have been used is wrong.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.

carlos4242 commented 5 years ago

Ran bugpoint to get a minimum test case:

define i32 @main(i32, i8** nocapture readnone) local_unnamed_addr {
entry:
  %2 = load i16, i16* undef, align 2
  tail call void @expect(i16 %2, i16 149)
  ret i32 0
}

declare hidden void @expect(i16, i16) local_unnamed_addr
declare hidden i8* @globalVal() local_unnamed_addr
carlos4242 commented 5 years ago

OK have a hack patch you guys can use to get going for emergency purposes: https://github.com/avr-rust/llvm/pull/11

The patch is meant to limit the selection of the LDWRdPtr pseudo instruction to the Y and Z registers, hopefully eliminating the crash for you guys (and me and my customers).

But it should be considered only if you need to get going now. The better solution will be to wait until more experienced developers (@dylanmckay @shepmaster @brainlag) have had a chance to look at the issue and come up with the correct solution (whatever that is).

Here is the assembly produced when the above minimum test case is compiled:

main:                                   ; @main
; %bb.0:                                ; %entry
    ld  r24, Z
    ldd r25, Z+1
    ldi r22, 149
    ldi r23, 0
    call    expect
    ldi r22, 0
    ldi r23, 0
    movw    r24, r22
    ret

...and it compiles with -filetype=obj so it should fix you guys' issue.

But...

This patch breaks two unit tests, and really needs more experienced developers to check it.

    LLVM :: CodeGen/AVR/high-pressure-on-ptrregs.ll
    LLVM :: CodeGen/AVR/load.ll

The second one is incompatible with the patch because it expects the X register to be used, that might just mean if my fix is valid then that unit test needs altering accordingly. The first one looks more serious because it suggests that the patch increases register pressure in some circumstances so it could cause some other more complex compilations to crash.

Hope this helps anyway.

Carl

hercek commented 5 years ago

High register pressure should not lead to a crash. Variables can be always spilled to memory if there is enough registers to perform one binary operation in them (i.e. for two operands and a memory pointer). AVR has plenty enough registers for that even when some registers are dedicated to e.g. stack frame. The generated code would be slow but I prefer a slow code which works to a quick code which cannot be generated at all.

Anyway that was just a rant. I wanted to ask two things: 1) Where one can read documents identified as PR39553 or PR13375 etc. 2) Where does this code (from AVRInstrInfo.td) define that the value of $ptrreg is incremented/modified/destroyed?

let canFoldAsLoad = 1,
isReMaterializable = 1 in
{
  // LDW Rd+1:Rd, P
  // Expands to:
  // ld Rd,   P+
  // ld Rd+1, P
  let Constraints = "@earlyclobber $reg" in
  def LDWRdPtr : Pseudo<(outs DREGS:$reg),
                        (ins PTRREGS:$ptrreg),
                        "ldw\t$reg, $ptrreg",
                        [(set i16:$reg, (load i16:$ptrreg))]>,
                 Requires<[HasSRAM]>;
}
carlos4242 commented 5 years ago

I’m sure you’re right generally. My guess is that because these are special registers, there are certain times where they have to be used and stack spilling isn’t an option, for example the frame pointer. I don’t have a unit test that will cause the run out of registers crash so I can’t debug what is going on but my guess would be that there is specific code to throw an error when these specific register shortages occur.

You’re right that the block below does not indicate that the value of $ptrreg is incremented/modified/destroyed, because it no longer is.

Since Keshav's patch was included in avr-rust, in the avr-rust-2019-01-18 branch, the ptr register is no longer clobbered because the pseudo code expansion now uses LDD. But his patch forgot to take account of the fact that the X register is not valid for this code, that is what my small patch corrected. But my patch has now sometimes caused running out of registers. Does that make sense?

What i’m looking at with Dylan and the LLVM developers is whether it’s possible to revert Keshav’s patch, go back to the old code but change the pseudo function definition to define that the ptrreg is clobbered. I don’t currently know how to do that as I’m a novice developer when it comes to LLVM*.

What do you think?

(*I have over 25 years of professional development on other platforms/languages.)

On 13 Mar 2019, at 09:14, hercek notifications@github.com wrote:

High register pressure should not lead to a crash. Variables can be always spilled to memory if there is enough registers to perform one binary operation in them (i.e. for two operands and a memory pointer). AVR has plenty enough registers for that even when some registers are dedicated to e.g. stack frame. The generated code would be slow but I prefer a slow code which works to a quick code which cannot be generated at all.

Anyway that was just a rant. I wanted to ask two things:

Where one can read documents identified as PR39553 or PR13375 etc. Where does this code (from AVRInstrInfo.td) define that the value of $ptrreg is incremented/modified/destroyed? let canFoldAsLoad = 1, isReMaterializable = 1 in { // LDW Rd+1:Rd, P // Expands to: // ld Rd, P+ // ld Rd+1, P let Constraints = "@earlyclobber $reg" in def LDWRdPtr : Pseudo<(outs DREGS:$reg), (ins PTRREGS:$ptrreg), "ldw\t$reg, $ptrreg", [(set i16:$reg, (load i16:$ptrreg))]>, Requires<[HasSRAM]>; } — You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/avr-rust/rust/issues/128#issuecomment-472339948, or mute the thread https://github.com/notifications/unsubscribe-auth/ADP6WsiTDs7R6YEw3K0VtaYJvArcdLzuks5vWMFwgaJpZM4aZAlA.

hercek commented 5 years ago

Well, I think that the best option is to divide the LDWRdPtr into two versions. One will use displacements only and work with Y and Z only. The second one will use memory indexed mode and work with X, Y, and Z.

The problem is that I never worked with llvm as well and I do not know how to indicate PRE_DEC and POST_INC MemIndexedMode. These modes are used in ARM. The inspiration can be taken from pre_store, post_store fragments of ARM pseudo-instructions for pattern matching indexed stores.

But I'm OK with a working solution. It does not need to be the best one.

hercek commented 5 years ago

I tried to compile blinky with carlos4242's patch. For a change, libcore cannot be compiled because llvm runs out of registers.

carlos4242 commented 5 years ago

Well, I think that the best option is to divide the LDWRdPtr into two versions. One will use displacements only and work with Y and Z only. The second one will use memory indexed mode and work with X, Y, and Z.

The problem is that I never worked with llvm as well and I do not know how to indicate PRE_DEC and POST_INC MemIndexedMode. These modes are used in ARM. The inspiration can be taken from pre_store, post_store fragments of ARM pseudo-instructions for pattern matching indexed stores.

But I'm OK with a working solution. It does not need to be the best one.

Good approach. There are already multiple similar pseudo instructions like this. I'm really new to llvm, I think they each have a pattern to match and which one is selected depends on matching the pattern on the selectionDAG. So I guess the ideal would be a version of the instruction definitions that said "if you have Y or Z available, you can use this version, if not, use this version but the X will be clobbered". I have no idea how to write this. :)

I think the best fix is to find out how to make the second version, which may be to do with Tied registers, I put a question to llvm-dev but haven't go an answer.

carlos4242 commented 5 years ago

p.s. On the subject of register pressure, I think there's also a sort of "underlying bug" that there should be no circumstances where you're forced to use one of the pointer registers but it was working before the patch so I guess that bug is lower priority.

hercek commented 5 years ago

Well, even if register allocator thinks that it needs to use some particular register which is taken by a variable then I do not understand why it does not spill the variable into memory. The inability to spill looks like a bug.

Anyway my modified version of the code generator with carlos4242's patch can compile high-pressure-on-ptrregs.ll and load.ll tests but it cannot compile this:

source_filename = "core.cgu.0"
target datalayout = "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8"
target triple = "avr-unknown-unknown"

%"bbb" = type { [0 x i8], { [0 x i8]*, i16 }*, [0 x i8], i16*, [0 x i8], i16*, [0 x i8] }

; Function Attrs: noreturn nounwind uwtable
define internal fastcc void @"aaa"(%"bbb"* noalias nocapture readonly dereferenceable(6) %arg0) unnamed_addr addrspace(1) #11 {
start:
  %0 = bitcast %"bbb"* %arg0 to { [0 x i8]*, i16 }**
  %1 = load { [0 x i8]*, i16 }*, { [0 x i8]*, i16 }** %0, align 1, !nonnull !0
  %2 = getelementptr inbounds { [0 x i8]*, i16 }, { [0 x i8]*, i16 }* %1, i16 0, i32 1
  %3 = load i16, i16* %2, align 1
  %4 = load i16, i16* undef, align 1
  tail call addrspace(1) void @_ZNE([0 x i8]* noalias nonnull readonly undef, i16 %3, i16 undef, i16 %4)
  unreachable
}

; Function Attrs: cold noinline noreturn nounwind uwtable
declare void @_ZNE([0 x i8]* noalias nonnull readonly, i16, i16, i16) unnamed_addr addrspace(1) #10

attributes #0 = { norecurse nounwind readnone uwtable "target-cpu"="atmega328p" }

!0 = !{}

libcore does not compile as a consequence of that.

dylanmckay commented 5 years ago

The dreaded "ran out of registers" error again.

I did some searching and came across PR18825 from the ARM backend

  • Short Story *

This test case exposes several fundamental limitations that may not be easy to fix. There is a workaround though, disabling the register coalescer in that case: -join-liveintervals=false

  • Long Story *

The register coalescer over constrained the register allocation problem and our live-range splitting mechanism is not able to recover from that situation.

I tried compiling @hercek's IR file with llc -join-liveintervals=false and it compiled without error.

It generated this assembly:

aaa:                                    ; @aaa
; %bb.0:                                ; %start
        ld      r18, Z
        ldd     r19, Z+1
        movw    r30, r24
        ld      r24, Z
        ldd     r25, Z+1
        movw    r30, r24
        ldd     r22, Z+2
        ldd     r23, Z+3
        call    _ZNE
.Lfunc_end0:
        .size   aaa, .Lfunc_end0-aaa
                                        ; -- End function

        ; Declaring this symbol tells the CRT that it should
        ;copy all variables from program memory to RAM on startup
        .globl  __do_copy_data
        ; Declaring this symbol tells the CRT that it should
        ;clear the zeroed data section on startup
        .globl  __do_clear_bss

In that bug, Chris B created a patch. He describes it here:

This patch is a workaround for the reported issue. It adds a subtarget hook to allow the target to back off from register coalescing when it is not profitable (as can be the case when you are using lots of large vector registers).

The patch can be found here https://github.com/llvm-mirror/llvm/commit/01d8611240d26dbf124d216983d2396234f62b95

If relaxing the register coalescer for AVR stops the register allocator choking on "ran out of registers", we should be able to add a hook to our target, just like ARM does in that same patch, to avoid coalescing for some sets of AVR programs.

hercek commented 5 years ago

It looks to me that the only reasonable option is to disable register coalescing on PTRDISPREGS class completely. The heuristic used form ARM looks kind of adhoc anyway.

Maybe it can be done more easily than by adding an AVRSubtarget::shouldCoalesce hook?

The point is that PTRDISPREGS class has only two members: Y and Z. And Y is almost always dedicated to stack frame pointer. Therefore we have only one pointer register Z and the instructions using it are early-clobber. Looks to me like it would be very rare when it would make sense to coalesce PTRDISPREGS class.

Btw, the register allocator state when the error happens is here:

(gdb) p this->VRM->dump()
********** REGISTER MAP **********
[%1 -> $r19r18] DREGS
[%3 -> $r31r30] PTRDISPREGS
[%6 -> $r23r22] DREGS_WITHOUT_Z_WORKAROUND
[%7 -> $r31r30] PTRDISPREGS
[%10 -> $r25r24] DREGS

$20 = void
(gdb) p this->LIS->dump()
********** INTERVALS **********
R18 [144r,160r:0)  0@144r
R19 [144r,160r:0)  0@144r
R22 [128r,160r:0)  0@128r
R23 [128r,160r:0)  0@128r
R24 [0B,16r:0)  0@0B-phi
R25 [0B,16r:0)  0@0B-phi
R30 EMPTY
R31 EMPTY
%1 [32e,144r:0)  0@32e weight:3.937622e-03
%3 EMPTY weight:INF
%5 [16r,64r:0)  0@16r weight:4.464286e-03
%6 [96e,128r:0)  0@96e weight:4.665127e-03
%7 [64e,96r:0)  0@64e weight:INF
%10 [16r,56r:0)  0@16r weight:4.590909e-03
%11 [56r,64r:0)  0@56r weight:INF
RegMasks: 160r
********** MACHINEINSTRS **********
# Machine code for function aaa: NoPHIs, TracksLiveness
Function Live Ins: $r25r24 in %0

0B  bb.0.start:
      liveins: $r25r24
16B   %10:dregs = COPY $r25r24
32B   early-clobber %1:dregs = LDWRdPtr undef %3:ptrdispregs :: (load 2 from `i16* undef`, align 1)
56B   %11:ptrdispregs = COPY %10:dregs
64B   early-clobber %7:ptrdispregs = LDWRdPtr %11:ptrdispregs :: (dereferenceable load 2 from %ir.0, align 1)
96B   early-clobber %6:dregs_without_z_workaround = LDDWRdPtrQ %7:ptrdispregs, 2 :: (load 2 from %ir.2, align 1)
112B      ADJCALLSTACKDOWN 0, 0, implicit-def dead $sp, implicit-def dead $sreg, implicit $sp
128B      $r23r22 = COPY %6:dregs_without_z_workaround
144B      $r19r18 = COPY %1:dregs
160B      CALLk @_ZNE, <regmask $r2 $r3 $r4 $r5 $r6 $r7 $r8 $r9 $r10 $r11 $r12 $r13 $r14 $r15 $r16 $r17 $r28 $r29 $r3r2 $r5r4 $r7r6 $r9r8 $r11r10 $r13r12 $r15r14 $r17r16 $r29r28>, implicit $sp, implicit undef $r25r24, implicit $r23r22, implicit undef $r21r20, implicit $r19r18, implicit-def $sp
176B      ADJCALLSTACKUP 0, 0, implicit-def dead $sp, implicit-def dead $sreg, implicit $sp

# End machine code for function aaa.

$21 = void
(gdb)

The problem is the instruction at index 96B. Z register is already taken by %7 so it cannot be used for %11 and Y register is (presumably?) taken by a stack frame (even when it is not indicated in the register map).

hercek commented 5 years ago

Since nobody answered I assume that my proposal for fix is good enough.

Here is a patch witch fixes the LDWRdPtr instruction (as proposed by carlos4242) and the coalescing of PTRDISPREGS class (as roughly porposed by dylanmckay).

It makes it possible to compile core library as it is present in this rust branch for AVR. I still cannot compile blinky but the error seems to be completely different now. Something with compiler_builtins dependency.

From a31cb28eead215557746c515a59fc09af563c8d6 Mon Sep 17 00:00:00 2001
From: Peter Hercek <phercek@gmail.com>
Date: Sat, 13 Apr 2019 19:39:57 +0200
Subject: [PATCH] [AVR] Fix LDWRdPtr register class to PTRDISPREGS and disable
 coalescing on it

LDWRdPtr instruction uses an immediate displacement and therefore supports
only PTRDISPREGS class and not the bigger PTRREGS class. Fixing the class
prevents the 'Expected either Y or Z class' compiler crash.

But the class fix leads to another compiler crash:  register allocator runs
out of registers.

Memory access with a pointer in a register and a displacement is possible
only for registers in PTRDISPREGS class. This class has only two members: Y,Z.
If a stack frame is used then Y register is dedicated to it. This leaves only
register Z for holding pointers to memory.

If we would allow register coalescing on PTRDISPREGS class then register
allocator can lock Z register to some virtual register. Lager instructions
requiring a memory acces then fail during the register allocation phase since
there is no available register to hold a pointer if Y register was already
taken for a stack frame. This patch prevents it by keeping Z register
spillable. It does it by not allowing coalescer to lock it.
---
 lib/Target/AVR/AVRInstrInfo.td     |  6 +++---
 lib/Target/AVR/AVRRegisterInfo.cpp | 10 ++++++++++
 lib/Target/AVR/AVRRegisterInfo.h   |  9 +++++++++
 3 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/lib/Target/AVR/AVRInstrInfo.td b/lib/Target/AVR/AVRInstrInfo.td
index 5720af7d8df..3ef7fb8da4e 100644
--- a/lib/Target/AVR/AVRInstrInfo.td
+++ b/lib/Target/AVR/AVRInstrInfo.td
@@ -1151,11 +1151,11 @@ isReMaterializable = 1 in
   // LDW Rd+1:Rd, P
   //
   // Expands to:
-  // ld Rd,   P+
-  // ld Rd+1, P
+  // ld Rd,   P
+  // ld Rd+1, P+1
   let Constraints = "@earlyclobber $reg" in
   def LDWRdPtr : Pseudo<(outs DREGS:$reg),
-                        (ins PTRREGS:$ptrreg),
+                        (ins PTRDISPREGS:$ptrreg),
                         "ldw\t$reg, $ptrreg",
                         [(set i16:$reg, (load i16:$ptrreg))]>,
                  Requires<[HasSRAM]>;
diff --git a/lib/Target/AVR/AVRRegisterInfo.cpp b/lib/Target/AVR/AVRRegisterInfo.cpp
index 808a85e459c..f31bd9970e9 100644
--- a/lib/Target/AVR/AVRRegisterInfo.cpp
+++ b/lib/Target/AVR/AVRRegisterInfo.cpp
@@ -273,4 +273,14 @@ void AVRRegisterInfo::splitReg(unsigned Reg,
     HiReg = getSubReg(Reg, AVR::sub_hi);
 }

+bool AVRRegisterInfo::shouldCoalesce(MachineInstr * /*MI*/,
+                      const TargetRegisterClass * /*SrcRC*/,
+                      unsigned /*SubReg*/,
+                      const TargetRegisterClass * /*DstRC*/,
+                      unsigned /*DstSubReg*/,
+                      const TargetRegisterClass *NewRC,
+                      LiveIntervals & /*LIS*/) const {
+    return NewRC != &AVR::PTRDISPREGSRegClass;
+}
+
 } // end of namespace llvm
diff --git a/lib/Target/AVR/AVRRegisterInfo.h b/lib/Target/AVR/AVRRegisterInfo.h
index 104b336b9c4..ae252c79d45 100644
--- a/lib/Target/AVR/AVRRegisterInfo.h
+++ b/lib/Target/AVR/AVRRegisterInfo.h
@@ -56,6 +56,15 @@ public:
     return true;
   }

+  /// SrcRC and DstRC will be morphed into NewRC if this returns true
+  bool shouldCoalesce(MachineInstr *MI,
+                      const TargetRegisterClass *SrcRC,
+                      unsigned SubReg,
+                      const TargetRegisterClass *DstRC,
+                      unsigned DstSubReg,
+                      const TargetRegisterClass *NewRC,
+                      LiveIntervals &LIS) const override;
+
 };

 } // end namespace llvm
-- 
2.21.0

It is not an ideal solution from the performance point of view but significantly better than a crashing compiler.

hercek commented 5 years ago

BTW: libcore can be now compiled without DREGS_WITHOUT_Z_WORKAROUND after my patch.

I wanted to try it since I do not understand why it should be needed when Z can be spilled now.

Also if I understand the meaning of earclyclobber well then there is a disagreement between LDWRdPtr being marked as earlycloober and the corresponding expansion template specialization which checks and works around the src and dst registers being the same. Either earlyclobber is not needed or the src and dst check for being the same is not needed. Comments?

shepmaster commented 5 years ago

Here's a reduced testcase from the updated codebase:

; ModuleID = 'bugpoint-reduced-simplified.bc'
source_filename = "core.37hoedwx-cgu.0"
target datalayout = "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8"
target triple = "avr-unknown-unknown"

%num__flt2dec__Part = type { [0 x i8], i8, [4 x i8] }
%num__flt2dec__decoder__FullDecoded = type { [26 x i8], i8, [0 x i8] }
%num__flt2dec__Formatted = type { [0 x i8], { [0 x i8]*, i16 }, [0 x i8], { [0 x %num__flt2dec__Part]*, i16 }, [0 x i8] }
%num__flt2dec__Part__Copy = type { [1 x i8], { [0 x i8]*, i16 }, [0 x i8] }

@anon.4c2386cf7531a237a70031c52b819347.56 = external dso_local unnamed_addr constant <{ [1 x i8] }>, align 1
@anon.4c2386cf7531a237a70031c52b819347.57 = external dso_local unnamed_addr constant <{ [3 x i8] }>, align 1
@anon.4c2386cf7531a237a70031c52b819347.63 = external dso_local unnamed_addr constant <{ [3 x i8] }>, align 1
@anon.4c2386cf7531a237a70031c52b819347.64 = external dso_local unnamed_addr constant <{ [3 x i8] }>, align 1

declare dso_local fastcc { [0 x %num__flt2dec__Part]*, i16 } @core__slice__Index([0 x %num__flt2dec__Part]*, i16, i16) unnamed_addr addrspace(1) #0

declare i32 @rust_eh_personality(...) unnamed_addr addrspace(1) #0

declare void @_ZN4core3num7flt2dec7decoder6decode17h56dc0fcd87a4559cE({ [0 x i8], i8, [0 x i8], %num__flt2dec__decoder__FullDecoded, [0 x i8] }*, double) unnamed_addr addrspace(1) #0

declare { [0 x i8]*, i16 } @_ZN4core3num7flt2dec14determine_sign17h04b9993823707283E(i8, %num__flt2dec__decoder__FullDecoded*, i1) unnamed_addr addrspace(1) #0

define void @_ZN4core3num7flt2dec19to_shortest_exp_str17h47df2ff6a62ba60cE(%num__flt2dec__Formatted*, double, i8, i16, i16, i1, [0 x i8]*, i16, [0 x %num__flt2dec__Part]*, i16) unnamed_addr addrspace(1) #0 personality i32 (...) addrspace(1)* @rust_eh_personality {
start:
  %10 = icmp ult i16 %9, 6
  br i1 %10, label %bb4, label %bb5

bb4:                                              ; preds = %start
  unreachable

bb5:                                              ; preds = %start
  call addrspace(1) void @_ZN4core3num7flt2dec7decoder6decode17h56dc0fcd87a4559cE({ [0 x i8], i8, [0 x i8], %num__flt2dec__decoder__FullDecoded, [0 x i8] }* noalias nocapture nonnull sret dereferenceable(28) null, double %1)
  %11 = call addrspace(1) { [0 x i8]*, i16 } @_ZN4core3num7flt2dec14determine_sign17h04b9993823707283E(i8 %2, %num__flt2dec__decoder__FullDecoded* noalias nonnull readonly align 1 dereferenceable(27) undef, i1 zeroext undef)
  switch i2 undef, label %bb13 [
    i2 0, label %bb15
    i2 1, label %bb18
    i2 -2, label %bb30
    i2 -1, label %bb32
  ]

bb13:                                             ; preds = %bb5
  unreachable

bb15:                                             ; preds = %bb5
  %12 = tail call fastcc addrspace(1) { [0 x %num__flt2dec__Part]*, i16 } @core__slice__Index([0 x %num__flt2dec__Part]* noalias nonnull readonly align 1 %8, i16 %9, i16 1)
  %13 = getelementptr inbounds %num__flt2dec__Formatted, %num__flt2dec__Formatted* %0, i16 0, i32 3, i32 1
  store i16 0, i16* %13, align 1
  ret void

bb18:                                             ; preds = %bb5
  %14 = bitcast [0 x %num__flt2dec__Part]* %8 to %num__flt2dec__Part__Copy*
  %15 = getelementptr inbounds %num__flt2dec__Part__Copy, %num__flt2dec__Part__Copy* %14, i16 0, i32 1, i32 0
  store [0 x i8]* bitcast (<{ [3 x i8] }>* @anon.4c2386cf7531a237a70031c52b819347.57 to [0 x i8]*), [0 x i8]** %15, align 1
  unreachable

bb30:                                             ; preds = %bb5
  %16 = icmp slt i16 %3, 1
  %17 = icmp sgt i16 %4, 0
  %_61.0 = and i1 %16, %17
  %. = select i1 %5, [0 x i8]* bitcast (<{ [3 x i8] }>* @anon.4c2386cf7531a237a70031c52b819347.63 to [0 x i8]*), [0 x i8]* bitcast (<{ [3 x i8] }>* @anon.4c2386cf7531a237a70031c52b819347.64 to [0 x i8]*)
  %_60.sroa.5.0 = select i1 %_61.0, [0 x i8]* bitcast (<{ [1 x i8] }>* @anon.4c2386cf7531a237a70031c52b819347.56 to [0 x i8]*), [0 x i8]* %.
  %_60.sroa.7.0 = select i1 %_61.0, i16 1, i16 3
  store [0 x i8]* %_60.sroa.5.0, [0 x i8]** undef, align 1
  %_60.sroa.7.0..sroa_idx = getelementptr inbounds [0 x %num__flt2dec__Part], [0 x %num__flt2dec__Part]* %8, i16 0, i16 0, i32 0, i16 3
  %_60.sroa.7.0..sroa_cast52 = bitcast i8* %_60.sroa.7.0..sroa_idx to i16*
  store i16 %_60.sroa.7.0, i16* %_60.sroa.7.0..sroa_cast52, align 1
  unreachable

bb32:                                             ; preds = %bb5
  unreachable
}

attributes #0 = { "target-cpu"="atmega328p" }

!llvm.module.flags = !{!0}

!0 = !{i32 2, !"Debug Info Version", i32 3}

It fails to compile, even with @hercek's patch, but does compile with -join-liveintervals=false:


$ llc -march=avr -mcpu=atmega328p -filetype=obj ran-out-of-regs.ll
LLVM ERROR: ran out of registers during register allocation

$ llc -march=avr -mcpu=atmega328p -filetype=obj -join-liveintervals=false ran-out-of-regs.ll
brainlag commented 5 years ago

Also if I understand the meaning of earclyclobber well then there is a disagreement between LDWRdPtr being marked as earlycloober and the corresponding expansion template specialization which checks and works around the src and dst registers being the same. Either earlyclobber is not needed or the src and dst check for being the same is not needed. Comments?

The AVR backend was written a long time ago (almost 10 years ago?) and a lot has changed in llvm but the AVR backend was never updated to these changes. This could be a bug in AVR, or a workaround for a specific bug in LLVM which doesn't exist anymore, or a workaround for a bug which still exists. Nobody really knows. If you think it is wrong you have to figure it out if this really the case. I don't think there is anyone around who can answer you why this is like it is.

hercek commented 5 years ago

shepmaster: Can you try also with this patch (it drops DREGS_WITHOUT_Z_WORKAROUND)? I can compile your reduced test case just fine in my llvm version which does not have Z workaround. My point is that it should not be needed any more and I believe it leads to a less optimal code as well. Therefore (if possible) we should try without it. Here is the patch which removes Z_WORKAROUND:

diff --git a/lib/Target/AVR/AVRInstrInfo.td b/lib/Target/AVR/AVRInstrInfo.td
index 3ef7fb8da4e..6d391abc0fd 100644
--- a/lib/Target/AVR/AVRInstrInfo.td
+++ b/lib/Target/AVR/AVRInstrInfo.td
@@ -1222,7 +1222,7 @@ isReMaterializable = 1 in
   // ldd Rd,   P+q
   // ldd Rd+1, P+q+1
   let Constraints = "@earlyclobber $dst" in
-  def LDDWRdPtrQ : Pseudo<(outs DREGS_WITHOUT_Z_WORKAROUND:$dst),
+  def LDDWRdPtrQ : Pseudo<(outs DREGS:$dst),
                           (ins memri:$memri),
                           "lddw\t$dst, $memri",
                           [(set i16:$dst, (load addr:$memri))]>,
diff --git a/lib/Target/AVR/AVRRegisterInfo.td b/lib/Target/AVR/AVRRegisterInfo.td
index d55252bcac4..8162f12052b 100644
--- a/lib/Target/AVR/AVRRegisterInfo.td
+++ b/lib/Target/AVR/AVRRegisterInfo.td
@@ -157,26 +157,6 @@ def DREGS : RegisterClass<"AVR", [i16], 8,
     R9R8, R7R6, R5R4, R3R2, R1R0
   )>;

-// The 16-bit DREGS register class, excluding the Z pointer register.
-//
-// This is used by instructions which cause high pointer register
-// contention which leads to an assertion in the register allocator.
-//
-// There is no technical reason why instructions that use this class
-// cannot use Z; it's simply a workaround a regalloc bug.
-//
-// More information can be found in PR39553.
-def DREGS_WITHOUT_Z_WORKAROUND : RegisterClass<"AVR", [i16], 8,
-  (
-    // Return value and arguments.
-    add R25R24, R19R18, R21R20, R23R22,
-    // Scratch registers.
-    R27R26,
-    // Callee saved registers.
-    R29R28, R17R16, R15R14, R13R12, R11R10,
-    R9R8, R7R6, R5R4, R3R2, R1R0
-  )>;
-
 // 16-bit register class for immediate instructions.
 def DLDREGS : RegisterClass<"AVR", [i16], 8,
   (

Just a guess (which may not be valid if the register allocator and coalsecer are clever enough): I can imagine the "run out of registers" problem persisting with my very simple patch which disables coalescing for PTRDISPREGS. These are registers R28 - R31. Those registers are listed also in some other classes. AVRRegisterInfo::shouldCoalesce() implementation should be extended so that we never coalesce Z register (R30R31) regardless of which class the register is mentioned in. Currently, R30 and $31 are in PTRDISPREGS, PTRREGS, and few more classes which do not seem that relevant. I would try to disable Z register (R30R31) coalescing specifically (if it can be done). We cannot afford to allow coalescer to lock down Z register since it is the only register we have for pointers in many cases (ie. the cases when both immediate displacement and stack frame are needed or when we need to read/write data from/to program memory).

shepmaster commented 5 years ago

Can you try also with this patch

Yes, applying that does seem to improve the situation. I'll try again with libcore.

hercek commented 5 years ago

I looked at it a bit more. Trying to disable the coalescence for register Z specifically would need to change the interface of AVRRegisterInfo::shouldCoalesce at least(*). That will have influence on all targets using it (at least AMDGPU, SystemZ, ARM, Hexagon). I do not have an idea how hard it would be to push the interface change upstream.

(*) It may be much more complicated depending on how coalesced virtual register is handled when it is assigned a physical register.

hercek commented 5 years ago

I looked at it even more and it is good to apply this on top of my patch:

diff --git a/lib/Target/AVR/AVRRegisterInfo.cpp b/lib/Target/AVR/AVRRegisterInfo.cpp
index f31bd9970e9..ff15356030e 100644
--- a/lib/Target/AVR/AVRRegisterInfo.cpp
+++ b/lib/Target/AVR/AVRRegisterInfo.cpp
@@ -276,11 +276,11 @@ void AVRRegisterInfo::splitReg(unsigned Reg,
 bool AVRRegisterInfo::shouldCoalesce(MachineInstr * /*MI*/,
                       const TargetRegisterClass * /*SrcRC*/,
                       unsigned /*SubReg*/,
-                      const TargetRegisterClass * /*DstRC*/,
+                      const TargetRegisterClass * DstRC,
                       unsigned /*DstSubReg*/,
-                      const TargetRegisterClass *NewRC,
+                      const TargetRegisterClass * /*NewRC*/,
                       LiveIntervals & /*LIS*/) const {
-    return NewRC != &AVR::PTRDISPREGSRegClass;
+    return DstRC != &AVR::PTRDISPREGSRegClass;
 }

 } // end of namespace llvm

Some coalescing on PTRDISPREGS could have still happened since NewRC can be nullptr when DstReg is physical. I did not notice that before. Any coalescing on PTRDISPREGS is disabled after this fix to my patch .... that is if the comments in the source code are correct.

techdragon commented 5 years ago

Now that https://github.com/dylanmckay/llvm/commit/9083457e21edbec1df36b6d417b89310f6affd04 has been merged, is that an upstream fix to the issue here? or does more work need to be done?

hercek commented 5 years ago

Fixing register class from PTRREGS to PTRDISPREGS is a step in a good direction but it is not enough. It only replaces this error with error "ran out of registers". You need to disable coalescing on Z register completely. You may achieve that to a significant degree by applying all the patches I posted here.

Unfortunately I do not know whether it is enough because I did not achieve any more progress. The primary reason for no progress on my side is because I'm blocked by unresolved dependency on compiler_builtins. So I cannot compile blink because of compiler_builtins. And I cannot compile compiler_builtins because it was missing dependency on std ... if I recall correctly. When I saw it I have given up because I expect std to depend on core which would make a nice dependency cycle :)

If somebody can point me to some information how to bootstrap compile compiler_builtins for AVR then let me know and I may look at this again.

Rahix commented 5 years ago

@hercek, if this is the same issue I encountered, just adding a Xargo.toml with

[dependencies.core]
stage = 0

[dependencies.compiler_builtins]
stage = 1
version = "= 0.1.3"

should be enough to get blink compiling again.

dylanmckay commented 5 years ago

Upstream fix accepted.

dylanmckay commented 5 years ago

I've also landed a commit upstream that disables register coalescing to the Y and Z registers.

llvm/llvm-project@45eb4c7e55341c0b83a21dedecc092e273795eda

heshananupama commented 5 years ago

Hi! Is there any changes that have been made and committed? Could we get the blink program to work now?

carlos4242 commented 5 years ago

Tbh I never really properly understood all this but it sounds good. Lol! Sent from my BlackBerry® wireless device

-----Original Message----- From: Dylan McKay notifications@github.com Date: Sat, 01 Jun 2019 05:37:31 To: avr-rust/rustrust@noreply.github.com Reply-To: avr-rust/rust reply@reply.github.com Cc: Carl Petocarl@petosoft.com; Commentcomment@noreply.github.com Subject: Re: [avr-rust/rust] Expected either Y or Z register (#128)

I've also landed a commit upstream that disables register coalescing to the Y and Z registers.

https://github.com/llvm/llvm-project/commit/45eb4c7e55341c0b83a21dedecc092e273795eda

-- You are receiving this because you commented. Reply to this email directly or view it on GitHub: https://github.com/avr-rust/rust/issues/128#issuecomment-497941847

carlos4242 commented 5 years ago

Nice :) Sent from my BlackBerry® wireless device

-----Original Message----- From: Dylan McKay notifications@github.com Date: Sat, 01 Jun 2019 01:34:59 To: avr-rust/rustrust@noreply.github.com Reply-To: avr-rust/rust reply@reply.github.com Cc: Carl Petocarl@petosoft.com; Commentcomment@noreply.github.com Subject: Re: [avr-rust/rust] Expected either Y or Z register (#128)

Upstream fix accepted.

-- You are receiving this because you commented. Reply to this email directly or view it on GitHub: https://github.com/avr-rust/rust/issues/128#issuecomment-497925518