-
Notifications
You must be signed in to change notification settings - Fork 13.8k
asm! support for the Xtensa architecture #147302
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
base: master
Are you sure you want to change the base?
Conversation
Some changes occurred in compiler/rustc_codegen_gcc |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Co-authored-by: Taiki Endo <te316e89@gmail.com> Co-authored-by: Kerry Jones <kerry@iodrive.co.za>
The job Click to see the possible cause of the failure (guessed by this bot)
|
// Custom TIE extensions - https://en.wikipedia.org/wiki/Tensilica_Instruction_Extension | ||
// Espressif specific, and are checked validated on the cpu name | ||
gpio_out: reg = ["gpio_out"] % has_gpio_out, | ||
expstate: reg = ["expstate"] % has_expstate, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most of these seem to be control registers. For most targets you wouldn't directly ask the value to be present in the target register at the start of the inline asm block, but rather put it in a gpr and then use whichever special instruction is necessary to move it into this control register (wrmsr
or mov crN, ...on x86,
msron arm,
csrrw` on riscv, ...) inside the asm block and in fact I don't think you can tell LLVM to do this kind of write to control registers.
Aren't writes to control registers generally effectively side-effectful? Making that go through the regular register allocator seems like it could reorder the writes in way that may cause unintended behavior. Or are you special casing writes to those control registers to happen right at the start of the inline asm block?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a general rule, only 2 kinds of registers need to be made available as inline asm operands:
- Registers which can hold values as inputs and outputs
- Registers which are not preserved across calls, so that they can be specified as clobbers (needed for
clobber_abi
).
Everything else isn't needed here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is also missing an update to the unstable book entry for asm_experimental_arch
.
|
||
#error = ["a0"] => "a0 is used internally by LLVM and cannot be used as an operand for inline asm", | ||
#error = ["sp", "a1"] => "sp is used internally by LLVM and cannot be used as an operand for inline asm", | ||
#error = ["a7"] => "a7 is used internally by LLVM as a frame pointer and cannot be used as an operand for inline asm", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The frame pointer can be either a7 or a15 depending on the ABI.
// Custom TIE extensions - https://en.wikipedia.org/wiki/Tensilica_Instruction_Extension | ||
// Espressif specific, and are checked validated on the cpu name | ||
gpio_out: reg = ["gpio_out"] % has_gpio_out, | ||
expstate: reg = ["expstate"] % has_expstate, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a general rule, only 2 kinds of registers need to be made available as inline asm operands:
- Registers which can hold values as inputs and outputs
- Registers which are not preserved across calls, so that they can be specified as clobbers (needed for
clobber_abi
).
Everything else isn't needed here.
def_reg_class! { | ||
Xtensa XtensaInlineAsmRegClass { | ||
reg, | ||
freg, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LLVM doesn't seem to support this. XtensaTargetLowering::getRegForInlineAsmConstraint
only handles r
constraints.
This implements the asm! support for Xtensa. We've been using this code for a few years in our fork and it's been working well. I finally found some time to clean it up a bit and start the upstreaming process. This should be one of the final PRs for Xtensa support on the Rust side (minus bug fixes of course). After this, we're mostly just waiting on the LLVM upstreaming which is going well. This PR doesn't cover all possible asm options for Xtensa, but the base ISA plus a few extras that are used in Espressif chips.
r? Amanieu