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

Assertion "LowerFormalArguments didn't emit the correct number of values!" failed #57

Closed
gergoerdi opened this issue May 14, 2017 · 14 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

@gergoerdi
Copy link
Collaborator

gergoerdi commented May 14, 2017

target triple = "avr-atmel-none"

; Function Attrs: norecurse nounwind readonly uwtable
define i128 @"_ZN43_$LT$i32$u20$as$u20$core..fmt..num..Int$GT$7to_u12817haa6ed143bf6636caE"(i32* noalias nocapture readonly dereferenceable(4)) unnamed_addr #6 {
start:
  %1 = load i32, i32* %0, align 4
  %2 = sext i32 %1 to i128
  ret i128 %2
}

EDIT (@dylanmckay): Here is another reproduction caused with non-i128 types. This was originally raised on #89. We should double check whatever fix is made fixes both of these.

declare i8 @do_something(i8 %val)

define { i1, i8 } @main(i8) #2 {
entry:
  %1 = call zeroext i8 @do_something(i8 zeroext %0)
  %2 = insertvalue { i1, i8 } { i1 true, i8 undef }, i8 %1, 1
  ret { i1, i8 } %2
}
CodeGen/SelectionDAG/SelectionDAGBuilder.cpp:8143: void llvm::SelectionDAGISel::LowerArguments(const llvm::Function&): Assertion `InVals.size() == Ins.size() && "LowerFormalArguments didn't emit the correct number of values!"' failed.
#0 0x0000000001721085 llvm::sys::PrintStackTrace(llvm::raw_ostream&) (/home/cactus/prog/rust/rust-avr/build/build/x86_64-unknown-linux-gnu/llvm/bin/llc+0x1721085)
#1 0x000000000171f09e llvm::sys::RunSignalHandlers() (/home/cactus/prog/rust/rust-avr/build/build/x86_64-unknown-linux-gnu/llvm/bin/llc+0x171f09e)
#2 0x000000000171f202 SignalHandler(int) (/home/cactus/prog/rust/rust-avr/build/build/x86_64-unknown-linux-gnu/llvm/bin/llc+0x171f202)
#3 0x00007fa62aaf3330 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x10330)
#4 0x00007fa629cafc37 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x36c37)
#5 0x00007fa629cb3028 abort (/lib/x86_64-linux-gnu/libc.so.6+0x3a028)
#6 0x00007fa629ca8bf6 (/lib/x86_64-linux-gnu/libc.so.6+0x2fbf6)
#7 0x00007fa629ca8ca2 (/lib/x86_64-linux-gnu/libc.so.6+0x2fca2)
#8 0x00000000015c0f83 llvm::SelectionDAGISel::LowerArguments(llvm::Function const&) (/home/cactus/prog/rust/rust-avr/build/build/x86_64-unknown-linux-gnu/llvm/bin/llc+0x15c0f83)
#9 0x00000000016091cc llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&) (/home/cactus/prog/rust/rust-avr/build/build/x86_64-unknown-linux-gnu/llvm/bin/llc+0x16091cc)
#10 0x000000000160ac3c llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) [clone .part.948] (/home/cactus/prog/rust/rust-avr/build/build/x86_64-unknown-linux-gnu/llvm/bin/llc+0x160ac3c)
#11 0x00000000010e8523 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (/home/cactus/prog/rust/rust-avr/build/build/x86_64-unknown-linux-gnu/llvm/bin/llc+0x10e8523)
#12 0x000000000138ba03 llvm::FPPassManager::runOnFunction(llvm::Function&) (/home/cactus/prog/rust/rust-avr/build/build/x86_64-unknown-linux-gnu/llvm/bin/llc+0x138ba03)
#13 0x000000000138baac llvm::FPPassManager::runOnModule(llvm::Module&) (/home/cactus/prog/rust/rust-avr/build/build/x86_64-unknown-linux-gnu/llvm/bin/llc+0x138baac)
#14 0x000000000138c80f llvm::legacy::PassManagerImpl::run(llvm::Module&) (/home/cactus/prog/rust/rust-avr/build/build/x86_64-unknown-linux-gnu/llvm/bin/llc+0x138c80f)
#15 0x0000000000697f74 compileModule(char**, llvm::LLVMContext&) (/home/cactus/prog/rust/rust-avr/build/build/x86_64-unknown-linux-gnu/llvm/bin/llc+0x697f74)
#16 0x0000000000646a90 main (/home/cactus/prog/rust/rust-avr/build/build/x86_64-unknown-linux-gnu/llvm/bin/llc+0x646a90)
#17 0x00007fa629c9af45 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21f45)
#18 0x000000000068d2b5 _start (/home/cactus/prog/rust/rust-avr/build/build/x86_64-unknown-linux-gnu/llvm/bin/llc+0x68d2b5)
Stack dump:
0.	Program arguments: /home/cactus/prog/rust/rust-avr/build/build/x86_64-unknown-linux-gnu/llvm/bin/llc -mcpu=atmega328p a.ll 
1.	Running pass 'Function Pass Manager' on module 'a.ll'.
2.	Running pass 'AVR DAG->DAG Instruction Selection' on function '@"_ZN43_$LT$i32$u20$as$u20$core..fmt..num..Int$GT$7to_u12817haa6ed143bf6636caE"'
@dylanmckay
Copy link
Member

This is occurring because SelectionDAGISel::LowerArguments notices that FuncInfo->CanLowerReturn is false and so it attempts to convert the return value into an argument.

For some reason, our LowerFormalArguments is not doing what it should be in this case.

I can verify that this is causing it because if I add more registers to the calling convention

  def RetCC_AVR : CallingConv
  <[
    // i8 is returned in R24.
    CCIfType<[i8], CCAssignToReg<[R24]>>,

    // i16 are returned in R25:R24, R23:R22, R21:R20 and R19:R18.
    CCIfType<[i16], CCAssignToReg<[R25R24, R23R22, R21R20, R19R18, R17R16, R15R14, R13R12, R11R10]>>
  ]>;

It compiles successfully.

@dylanmckay
Copy link
Member

I think we're missing something like this (taken from MipsISelLowering.cpp)

  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
    // The mips ABIs for returning structs by value requires that we copy
    // the sret argument into $v0 for the return. Save the argument into
    // a virtual register so that we can access it from the return points.
    if (Ins[i].Flags.isSRet()) {
      unsigned Reg = MipsFI->getSRetReturnReg();
      if (!Reg) {
        Reg = MF.getRegInfo().createVirtualRegister(
            getRegClassFor(ABI.IsN64() ? MVT::i64 : MVT::i32));
        MipsFI->setSRetReturnReg(Reg);
      }
      SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), DL, Reg, InVals[i]);
      Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Copy, Chain);
      break;
    }
  }

@dylanmckay
Copy link
Member

I think this is not actually it, it's just something similar.

@dylanmckay
Copy link
Member

It's strange that there's an extra argument for the return value, but analyzeArguments is only populating ArgLocs with one element.

@dylanmckay
Copy link
Member

It looks like our parseFunctionArgs method is directly reading the arguments from a Function object, and not the arguments supplied by the SelectionDAGBuilder - this will be why we are only lowering one argument but not two.

@dylanmckay
Copy link
Member

dylanmckay commented Aug 23, 2017

Have pushed to a WIP patch avr-rust/llvm/branches/issue-57

Fixing the bug triggers another bug in add.ll and a bunch of other tests.

shepmaster added a commit to avr-rust/blink that referenced this issue Oct 7, 2017
It's better to have release mode in the long run, and this works around avr-rust/rust-legacy-fork#57.
@dylanmckay dylanmckay changed the title Assertion failure on i128 Assertion "LowerFormalArguments didn't emit the correct number of values!" failed Feb 8, 2018
@brainlag
Copy link

Here is patch which should fix this bug: https://gist.github.com/brainlag/51928996f539bfafcfe0531e5dfd6236

It is based on @dylanmckay WIP patch. He got it almost right. The reason why some other tests fail is because parameters which are i32 or bigger gets split into 2 or more parameters and you have to skip over these.

@dylanmckay
Copy link
Member

Your patch works fine, and doesn't regress the testsuite either!

Upstreamed in r325474.

@dylanmckay dylanmckay added the has-llvm-commit This issue should be fixed in upstream LLVM label Feb 19, 2018
@shepmaster
Copy link
Member

and doesn't regress the testsuite either!

Should there be a new test added for the original bug?

@brainlag
Copy link

jyknight pushed a commit to jyknight/llvm-monorepo that referenced this issue Mar 20, 2018
The test is taken from
avr-rust/rust-legacy-fork#57

The originally implementation of struct return lowering was made in
r325474.

Patch by Peter Nimmervoll

llvm-svn=327967
@dylanmckay
Copy link
Member

@brainlag's test added in r327967

earl pushed a commit to earl/llvm-mirror that referenced this issue Mar 20, 2018
The test is taken from
avr-rust/rust-legacy-fork#57

The originally implementation of struct return lowering was made in
r325474.

Patch by Peter Nimmervoll

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@327967 91177308-0d34-0410-b5e6-96231b3b80d8
shepmaster pushed a commit to avr-rust/libcore that referenced this issue Apr 25, 2018
@leo60228
Copy link

Wait, should this be closed?

@dylanmckay
Copy link
Member

I upstreamed this patch to LLVM, but then I thought it broke the testsuite.

I just doubled checked and it didn't, so I'll cherry-pick this now.

dylanmckay added a commit that referenced this issue Jul 19, 2018
This commit cherry-picks the fix for #57.

This corresponds to the upstream LLVM commit r325474.
@dylanmckay
Copy link
Member

Cherry-picked in 567801d.

dylanmckay added a commit to dylanmckay/llvm that referenced this issue Nov 5, 2018
…uired by the ABI

When returning structs, the fields need to be reversed. Without this,
the ABI of the generated executables is not compatible with avr-gcc,
nor will LLVM allow it to be compiled.

Here is the assertion message when complex structs are used:

    Impossible reg-to-reg copy
    UNREACHABLE executed at llvm/lib/Target/AVR/AVRInstrInfo.cpp!

This was first noticed in avr-rust/rust-legacy-fork#92.

Description by Peter

    The AVR couldn't handle returning structs like this at all (see avr-rust/rust-legacy-fork#57).
    It only expects to ever return an iXX and only when XX is >=32 it needs to reverse
    the registers because of the calling convention. Now for this bug where we have
    { i8, i32 } and registers {[0] = i8, [1] = i16, [2] = i16} it only should reverse
    registers 1 and 2 but not 0.

Patch by Peter Nimmervoll (@brainlag) and Tim Neumann (@TimNN)
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

5 participants