Uh oh!
There was an error while loading. Please reload this page.
Add asm! support for MIPS - #76839
Conversation
rust-highfive
commented
Sep 17, 2020
r? @estebank (rust_highfive has picked a reviewer for you, use r? to override) |
Uh oh!
There was an error while loading. Please reload this page.
Amanieu
commented
Sep 17, 2020
I think the crash is because LLVM expects register names to be prefixed with |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
For MIPS64 you should add I64. Also most targets support the use of f32 and f64 in general purpose registers for soft-float.
There was a problem hiding this comment.
I'm trying for mips32 BE first. Don't know much about MIPS64, but I'd try in other PR.
Still crashed locally for me after changing register names. GDB Backtrace in https://gist.github.com/lzutao/4f8ae72f9e89e1dfc21ff2dcdd890584 . Looks like some kinds of null deref. |
This comment has been minimized.
This comment has been minimized.
Uh oh!
There was an error while loading. Please reload this page.
Amanieu
commented
Sep 18, 2020
It's just that CI doesn't run these tests since they are marked |
ead21a2 to
6df5567CompareCodegen fail at this line: Not sure how to resolve this: |
So here I have more complete backtrack using gdbwarning: used $at (currently $1) without ".set noat"
--> /home/lzutao/fork/rust/worktree/mips/src/test/assembly/asm/mips-types.rs:52:15
|
52 | asm!("move {}, {}", out($class) y, in($class) x);
| ^
|
note: instantiated into assembly here
--> <inline asm>:1:11
|
1 | move $2, $1
| ^
rustc: /home/lzutao/fork/rust/worktree/mips/src/llvm-project/llvm/include/llvm/CodeGen/TargetLowering.h:831: virtual const llvm::TargetRegisterClass* llvm::TargetLoweringBase::getRegClassFor(llvm::MVT, bool) const: Assertion `RC && "This value type is not natively supported!"' failed.Process 5450 stopped* thread #5, name = 'rustc', stop reason = hit program assert frame #4: 0x00007ffff04c26a3 librustc_driver-ff4867624e9288b7.so`llvm::TargetLoweringBase::getRegClassFor(isDivergent=<unavailable>, VT=<unavailable>, this=<unavailable>) const at TargetLowering.h:831:5 828 virtual const TargetRegisterClass *getRegClassFor(MVT VT, bool isDivergent = false) const { 829 (void)isDivergent; 830 const TargetRegisterClass *RC = RegClassForVT[VT.SimpleTy];-> 831 assert(RC && "This value type is not natively supported!"); 832 return RC; 833 } 834lldb bt(lldb) bt
* thread #5, name = 'rustc', stop reason = hit program assert
frame #0: 0x00007fffee87dfff libc.so.6`__GI_raise(sig=6) at raise.c:51 frame #1: 0x00007fffee87f42a libc.so.6`__GI_abort at abort.c:89 frame #2: 0x00007fffee876e67 libc.so.6`__assert_fail_base(fmt="", assertion=<unavailable>, file=<unavailable>, line=<unavailable>, function=<unavailable>) at assert.c:92 frame #3: 0x00007fffee876f12 libc.so.6`__GI___assert_fail(assertion=<unavailable>, file=<unavailable>, line=<unavailable>, function=<unavailable>) at assert.c:101
* frame #4: 0x00007ffff04c26a3 librustc_driver-ff4867624e9288b7.so`llvm::TargetLoweringBase::getRegClassFor(isDivergent=<unavailable>, VT=<unavailable>, this=<unavailable>) const at TargetLowering.h:831:5 frame #5: 0x00007ffff04ce8b2 librustc_driver-ff4867624e9288b7.so`llvm::MipsTargetLowering::parseRegForInlineAsmConstraint(llvm::StringRef, llvm::MVT) const at MipsISelLowering.cpp:4099:3 frame #6: 0x00007ffff04ce8ad librustc_driver-ff4867624e9288b7.so`llvm::MipsTargetLowering::parseRegForInlineAsmConstraint(this=<unavailable>, C=<unavailable>, VT=<unavailable>) const at MipsISelLowering.cpp:4084 frame #7: 0x00007ffff04e3da0 librustc_driver-ff4867624e9288b7.so`llvm::MipsTargetLowering::getRegForInlineAsmConstraint(this=0x00007fffd80229b0, TRI=0x00007fffd80217c0, Constraint=(Data = "{$8}", Length = 4), VT=(SimpleTy = i8)) const at MipsISelLowering.cpp:4165:54 frame #8: 0x00007ffff12b0242 librustc_driver-ff4867624e9288b7.so`::GetRegistersForValue(DAG=0x00007fffd8001cb0, DL=0x00007fffecb17260, OpInfo=0x00007fffecb173c0, RefOpInfo=0x00007fffecb173c0)::SDISelAsmOperandInfo &, (anonymous namespace)::SDISelAsmOperandInfo &) at SelectionDAGBuilder.cpp:7954:61 frame #9: 0x00007ffff12eafe2 librustc_driver-ff4867624e9288b7.so`llvm::SelectionDAGBuilder::visitInlineAsm(this=0x00007fffd8002780, Call=0x00007fffe81c7060) at SelectionDAGBuilder.cpp:8260:25 frame #10: 0x00007ffff12fc223 librustc_driver-ff4867624e9288b7.so`llvm::SelectionDAGBuilder::visit(this=0x00007fffd8002780, I=0x00007fffe81c7060) at SelectionDAGBuilder.cpp:1141:8 frame #11: 0x00007ffff135e619 librustc_driver-ff4867624e9288b7.so`llvm::SelectionDAGISel::SelectBasicBlock(this=0x00007fffd80016c0, Begin=<unavailable>, End=llvm::BasicBlock::const_iterator @ rbx, HadTailCall=0x00007fffecb18db0) at SelectionDAGISel.cpp:699:17 frame #12: 0x00007ffff1362c62 librustc_driver-ff4867624e9288b7.so`llvm::SelectionDAGISel::SelectAllBasicBlocks(this=0x00007fffd80016c0, Fn=0x00007fffe81baa28) at SelectionDAGISel.cpp:1520:27 frame #13: 0x00007ffff13640d0 librustc_driver-ff4867624e9288b7.so`llvm::SelectionDAGISel::runOnMachineFunction(this=0x00007fffd80016c0, mf=0x00007fffd805c030) at SelectionDAGISel.cpp:504:23 frame #14: 0x00007ffff04c20fb librustc_driver-ff4867624e9288b7.so`llvm::MipsDAGToDAGISel::runOnMachineFunction(this=0x00007fffd80016c0, MF=0x00007fffd805c030) at MipsISelDAGToDAG.cpp:58:52 frame #15: 0x00007ffff16735a5 librustc_driver-ff4867624e9288b7.so`llvm::MachineFunctionPass::runOnFunction(this=0x00007fffd80016c0, F=0x00007fffe81baa28) at MachineFunctionPass.cpp:73:33 frame #16: 0x00007ffff23f1b33 librustc_driver-ff4867624e9288b7.so`llvm::FPPassManager::runOnFunction(this=0x00007fffd8007fb0, F=0x00007fffe81baa28) at LegacyPassManager.cpp:1587:40 frame #17: 0x00007ffff23f2181 librustc_driver-ff4867624e9288b7.so`llvm::FPPassManager::runOnModule(this=0x00007fffd8007fb0, M=0x00007fffe8101080) at LegacyPassManager.cpp:1629:29 frame #18: 0x00007ffff23f0ace librustc_driver-ff4867624e9288b7.so`llvm::legacy::PassManagerImpl::run(llvm::Module&) at LegacyPassManager.cpp:1698:38 frame #19: 0x00007ffff23f0861 librustc_driver-ff4867624e9288b7.so`llvm::legacy::PassManagerImpl::run(this=0x00007fffd8000960, M=0x00007fffe8101080) at LegacyPassManager.cpp:614 frame #20: 0x00007fffefd9cf55 librustc_driver-ff4867624e9288b7.so`LLVMRustWriteOutputFile + 581 frame #21: 0x00007fffefd69548 librustc_driver-ff4867624e9288b7.so`rustc_codegen_llvm::back::write::write_output_file::h8f8e8512ef3d7b66 + 88 frame #22: 0x00007fffefc16907 librustc_driver-ff4867624e9288b7.so`rustc_codegen_llvm::back::write::codegen::with_codegen::h2785a5280d050ea5 + 119 frame #23: 0x00007fffefd6cc73 librustc_driver-ff4867624e9288b7.so`rustc_codegen_llvm::back::write::codegen::h1dcdb5946b72520a + 2899 frame #24: 0x00007fffefd0beeb librustc_driver-ff4867624e9288b7.so`rustc_codegen_ssa::back::write::finish_intra_module_work::h63ef7bb6d09628bd + 219 frame #25: 0x00007fffefd06fa9 librustc_driver-ff4867624e9288b7.so`rustc_codegen_ssa::back::write::execute_work_item::hfe14f77f2358639e + 2745 frame #26: 0x00007fffefc17ca2 librustc_driver-ff4867624e9288b7.so`std::sys_common::backtrace::__rust_begin_short_backtrace::h7e5ec54f2af1c982 + 194 frame #27: 0x00007fffefd87c5a librustc_driver-ff4867624e9288b7.so`std::panicking::try::h9dc227032d219e6e + 42 frame #28: 0x00007fffefc0435d librustc_driver-ff4867624e9288b7.so`core::ops::function::FnOnce::call_once$u7b$$u7b$vtable.shim$u7d$$u7d$::h0fb2f699d71f4606 + 93 frame #29: 0x00007fffeec56278 libstd-43e93f8b75aa198d.so`_$LT$alloc..boxed..Box$LT$F$GT$$u20$as$u20$core..ops..function..FnOnce$LT$A$GT$$GT$::call_once::h2e60e5e0bf1169eb + 24 frame #30: 0x00007fffeec6bd1a libstd-43e93f8b75aa198d.so`std::sys::unix::thread::Thread::new::thread_start::h46685771fe1620e2 + 26 frame #31: 0x00007fffee00f4a4 libpthread.so.0`start_thread(arg=0x00007fffecb1b700) at pthread_create.c:456 frame #32: 0x00007fffee933d0f libc.so.6`__clone at clone.S:97 |
I can reproduce the issue. It seems that the generated LLVM-IR missing %0 = calli8asmsideeffectalignstack"move $$t0, $$t0", "={$8},{$8},~{memory}"(i8%x), !srcloc!2it should be %0 = calli8asmsideeffectalignstack"move $$t0, $$t0", "=r{$8},r{$8},~{memory}"(i8%x), !srcloc!2With LLVM IR and minimal Rust code example that with current state of this PR crashed the codegen: https://rust.godbolt.org/z/c64qG7 |
Amanieu
commented
Sep 21, 2020
Adding the |
Oops, you're right.
Are there any bugs in bugs.llvm.org/ or this is an intentional design ? (Also I currently cannot reply on zulip. The network at night is slow or having issues, I cannot connect to zulip at all). |
Amanieu
commented
Sep 21, 2020
We already have a lot of workarounds for LLVM not accepting certain types, we can just add one more. You'll need to add:
You'll also want to add support for Finally you should update the asm documentation in |
I prefer to do this later, in another PR because I only have a little knowledge for MIPS32 I learned in school. |
There was a problem hiding this comment.
Should we do zero-extend for u8 or u16 ?
There was a problem hiding this comment.
No. The asm! documentation specifies that the upper bits of a register are undefined when you pass a smaller value in. So we can do either.
I just ran a few tests on godbolt and it turns out that zero-extension can always be done in 1 instruction while sign-extension sometimes needs 2 (unlike what my previous comment said). You should change this to always zero-extend.
There was a problem hiding this comment.
Hmm this is probably confusing since I change my mind halfway through the comment. But basically it doesn't really matter if you sext or zext from the spec point of view.
tesuji
commented
Sep 22, 2020
Which ones you want me to write there? Should I write about LLVM restrictions on i8/i16 |
Amanieu
commented
Sep 22, 2020
Just update the various tables with MIPS details. I don't think any other changes are needed. The existing spec is clear enough for the case of values smaller than a register. We don't want to guarantee zero extension since this may change in the future if LLVM gets proper support for i8/i16. |
Uh oh!
There was an error while loading. Please reload this page.
Amanieu
commented
Sep 26, 2020
I think you should just use |
I want to limit what registers the assembler is able to generate based on general calling convention. |
Amanieu
commented
Sep 26, 2020
Well, what we're really testing here is that the LLVM backend doesn't choke on types it can't support. The actual register number is not important, only that some register is chosen. |
Amanieu
commented
Sep 26, 2020
LGTM |
This patch also: * Add soft-float supports: only f32 * zero-extend i8/i16 to i32 because MIPS only supports register-length arithmetic. * Update table in asm! chapter in unstable book.
tesuji
commented
Sep 27, 2020
Squashed. |
Amanieu
commented
Sep 27, 2020
@bors r+ |
bors
commented
Sep 27, 2020
📌 Commit 9000710 has been approved by |
bors
commented
Sep 27, 2020
⌛ Testing commit 9000710 with merge 46d58327c4a259163e2a0f7f4e69b3d74e24bfe6... |
bors
commented
Sep 27, 2020
💔 Test failed - checks-actions |
tesuji
commented
Sep 27, 2020
from build log: https://github.com/rust-lang-ci/rust/runs/1172123270 |
kennytm
commented
Sep 27, 2020
@bors retry |
…as-schievink Rollup of 7 pull requests Successful merges: - rust-lang#76839 (Add asm! support for MIPS) - rust-lang#77203 (Check for missing const-stability attributes in `rustc_passes`) - rust-lang#77249 (Separate `private_intra_doc_links` and `broken_intra_doc_links` into separate lints) - rust-lang#77252 (reduce overlong line) - rust-lang#77256 (Fix typo in ExpnData documentation) - rust-lang#77262 (Remove duplicate comment) - rust-lang#77263 (Clean up trivial if let) Failed merges: r? `@ghost`
Add asm! support for mips64 - [x] Updated `src/doc/unstable-book/src/library-features/asm.md`. - [ ] No vector type support. I don't know much about those types. cc rust-lang#76839
For now, I only add support for mips32.
mips64 may come in future PRs if I could learn more about the target.