|
13 | 13 |
|
14 | 14 | #include "SparcISelLowering.h" |
15 | 15 | #include "MCTargetDesc/SparcMCExpr.h" |
| 16 | +#include "MCTargetDesc/SparcMCTargetDesc.h" |
16 | 17 | #include "SparcMachineFunctionInfo.h" |
17 | 18 | #include "SparcRegisterInfo.h" |
18 | 19 | #include "SparcTargetMachine.h" |
|
28 | 29 | #include "llvm/CodeGen/SelectionDAGNodes.h" |
29 | 30 | #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" |
30 | 31 | #include "llvm/IR/DerivedTypes.h" |
| 32 | +#include "llvm/IR/DiagnosticInfo.h" |
31 | 33 | #include "llvm/IR/Function.h" |
32 | 34 | #include "llvm/IR/Module.h" |
33 | 35 | #include "llvm/Support/ErrorHandling.h" |
@@ -729,6 +731,30 @@ SDValue SparcTargetLowering::LowerFormalArguments_64( |
729 | 731 | return Chain; |
730 | 732 | } |
731 | 733 |
|
| 734 | +// Check whether any of the argument registers are reserved |
| 735 | +static bool isAnyArgRegReserved(const SparcRegisterInfo *TRI, |
| 736 | + const MachineFunction &MF) { |
| 737 | + // The register window design means that outgoing parameters at O* |
| 738 | + // will appear in the callee as I*. |
| 739 | + // Be conservative and check both sides of the register names. |
| 740 | + bool Outgoing = |
| 741 | + llvm::any_of(SP::GPROutgoingArgRegClass, [TRI, &MF](MCPhysReg r) { |
| 742 | + return TRI->isReservedReg(MF, r); |
| 743 | + }); |
| 744 | + bool Incoming = |
| 745 | + llvm::any_of(SP::GPRIncomingArgRegClass, [TRI, &MF](MCPhysReg r) { |
| 746 | + return TRI->isReservedReg(MF, r); |
| 747 | + }); |
| 748 | + return Outgoing || Incoming; |
| 749 | +} |
| 750 | + |
| 751 | +static void emitReservedArgRegCallError(const MachineFunction &MF) { |
| 752 | + const Function &F = MF.getFunction(); |
| 753 | + F.getContext().diagnose(DiagnosticInfoUnsupported{ |
| 754 | + F, ("SPARC doesn't support" |
| 755 | + " function calls if any of the argument registers is reserved.")}); |
| 756 | +} |
| 757 | + |
732 | 758 | SDValue |
733 | 759 | SparcTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, |
734 | 760 | SmallVectorImpl<SDValue> &InVals) const { |
@@ -1057,8 +1083,8 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI, |
1057 | 1083 | ? TRI->getRTCallPreservedMask(CallConv) |
1058 | 1084 | : TRI->getCallPreservedMask(DAG.getMachineFunction(), CallConv)); |
1059 | 1085 |
|
1060 | | - if (TRI->isAnyArgRegReserved(MF)) |
1061 | | - TRI->emitReservedArgRegCallError(MF); |
| 1086 | + if (isAnyArgRegReserved(TRI, MF)) |
| 1087 | + emitReservedArgRegCallError(MF); |
1062 | 1088 |
|
1063 | 1089 | assert(Mask && "Missing call preserved mask for calling convention"); |
1064 | 1090 | Ops.push_back(DAG.getRegisterMask(Mask)); |
@@ -1130,6 +1156,9 @@ Register SparcTargetLowering::getRegisterByName(const char* RegName, LLT VT, |
1130 | 1156 | .Case("g4", SP::G4).Case("g5", SP::G5).Case("g6", SP::G6).Case("g7", SP::G7) |
1131 | 1157 | .Default(0); |
1132 | 1158 |
|
| 1159 | + // If we're directly referencing register names |
| 1160 | + // (e.g in GCC C extension `register int r asm("g1");`), |
| 1161 | + // make sure that said register is in the reserve list. |
1133 | 1162 | const SparcRegisterInfo *TRI = Subtarget->getRegisterInfo(); |
1134 | 1163 | if (!TRI->isReservedReg(MF, Reg)) |
1135 | 1164 | Reg = 0; |
@@ -1383,8 +1412,8 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI, |
1383 | 1412 | : TRI->getCallPreservedMask(DAG.getMachineFunction(), |
1384 | 1413 | CLI.CallConv)); |
1385 | 1414 |
|
1386 | | - if (TRI->isAnyArgRegReserved(MF)) |
1387 | | - TRI->emitReservedArgRegCallError(MF); |
| 1415 | + if (isAnyArgRegReserved(TRI, MF)) |
| 1416 | + emitReservedArgRegCallError(MF); |
1388 | 1417 |
|
1389 | 1418 | assert(Mask && "Missing call preserved mask for calling convention"); |
1390 | 1419 | Ops.push_back(DAG.getRegisterMask(Mask)); |
|
0 commit comments