|
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