|
30 | 30 | #include "llvm/ADT/SmallVectorExtras.h" |
31 | 31 | #include "llvm/ADT/Statistic.h" |
32 | 32 | #include "llvm/ADT/StringRef.h" |
| 33 | +#include "llvm/ADT/StringSwitch.h" |
33 | 34 | #include "llvm/ADT/Twine.h" |
34 | 35 | #include "llvm/Analysis/LoopInfo.h" |
35 | 36 | #include "llvm/Analysis/MemoryLocation.h" |
@@ -13126,6 +13127,20 @@ AArch64TargetLowering::getRegForInlineAsmConstraint( |
13126 | 13127 | return std::make_pair(unsigned(AArch64::ZT0), &AArch64::ZTRRegClass); |
13127 | 13128 | } |
13128 | 13129 |
|
| 13130 | + // Clang will correctly decode the usage of register name aliases into their |
| 13131 | + // official names. However, other frontends like `rustc` do not. This allows |
| 13132 | + // users of these frontends to use the ABI names for registers in LLVM-style |
| 13133 | + // register constraints. |
| 13134 | + // |
| 13135 | + // x31->sp is not included here because it's not a general register and |
| 13136 | + // needs different handling |
| 13137 | + unsigned XRegFromAlias = StringSwitch<unsigned>(Constraint.lower()) |
| 13138 | + .Cases({"{x29}", "{fp}"}, AArch64::FP) |
| 13139 | + .Cases({"{x30}", "{lr}"}, AArch64::LR) |
| 13140 | + .Default(AArch64::NoRegister); |
| 13141 | + if (XRegFromAlias != AArch64::NoRegister) |
| 13142 | + return std::make_pair(XRegFromAlias, &AArch64::GPR64RegClass); |
| 13143 | + |
13129 | 13144 | // Use the default implementation in TargetLowering to convert the register |
13130 | 13145 | // constraint into a member of a register class. |
13131 | 13146 | std::pair<unsigned, const TargetRegisterClass *> Res; |
|
0 commit comments