Skip to content

Commit 7d05f67

Browse files
authored
[TableGen][CallingConv] Add CCAssignToRegTuple for synthetic registers. (#137826)
Currently CCAssignToReg takes a list<Register>. There are tuple-heavy back-ends where we would like to reference any register-- whether those are singletons or those defined by RegisterTuples. However, the latter are synthesized during tuple expansion and are not visible outside of the register info emitter. The problem is that the parser will see tuple registers as undefined variables before the calling convention emitter is ever reached. To defer evaluation of the symbol, we introduce CCAssignToRegTuple which takes list<string> instead. This allows us to defer the actual register name lookup until the emitter runs-- where we also validate that the register actually exists. This is currently used in a downstream back-end which will be upstreamed very soon. In the meantime, a unit test is provided to exercise the feature.
1 parent 5dc3cd0 commit 7d05f67

File tree

3 files changed

+112
-4
lines changed

3 files changed

+112
-4
lines changed

llvm/include/llvm/Target/TargetCallingConv.td

+7
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,13 @@ class CCAssignToReg<list<Register> regList> : CCAction {
113113
list<Register> RegList = regList;
114114
}
115115

116+
/// CCAssignToRegTuple - Same as CCAssignToReg, but with a list of registers as
117+
/// strings. This is needed because records synthesized during tuple expansion
118+
/// are not visible outside of the register info emitter.
119+
class CCAssignToRegTuple<list<string> regList> : CCAction {
120+
list<string> RegList = regList;
121+
}
122+
116123
/// CCAssignToRegWithShadow - Same as CCAssignToReg, but with list of registers
117124
/// which became shadowed, when some register is used.
118125
class CCAssignToRegWithShadow<list<Register> regList,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// RUN: llvm-tblgen --gen-callingconv -I %p/../../include -I %p/Common %s 2>&1 | FileCheck %s
2+
// RUN: not llvm-tblgen -DERROR1 --gen-callingconv -I %p/../../include -I %p/Common %s 2>&1 | FileCheck --check-prefix=CHECK-ERROR1 %s
3+
// RUN: not llvm-tblgen -DERROR2 --gen-callingconv -I %p/../../include -I %p/Common %s 2>&1 | FileCheck --check-prefix=CHECK-ERROR2 %s
4+
5+
include "reg-with-subregs-common.td"
6+
7+
def CC_ABI1 : CallingConv<[
8+
// Use singleton definitions directly.
9+
CCIfType<[i32, f32],
10+
CCAssignToReg<[R8, R9, R10, R11, R12, R13, R14, R15]>>,
11+
12+
// Use tuple definitions indirectly as strings.
13+
CCIfType<[i64, f64],
14+
CCAssignToRegTuple<["R8_R9", "R10_R11", "R12_R13", "R14_R15"]>>,
15+
16+
CCIfType<[i128],
17+
CCAssignToRegTuple<["R8_R9_R10_R11", "R12_R13_R14_R15"]>>,
18+
19+
CCIfType<[v8i32],
20+
CCAssignToRegTuple<["R8_R9_R10_R11_R12_R13_R14_R15"]>>,
21+
]>;
22+
23+
// CHECK: if (LocVT == MVT::i32 ||
24+
// CHECK: LocVT == MVT::f32) {
25+
// CHECK: static const MCPhysReg RegList1[] = {
26+
// CHECK: R8, R9, R10, R11, R12, R13, R14, R15
27+
// CHECK: };
28+
// CHECK: if (MCRegister Reg = State.AllocateReg(RegList1)) {
29+
// CHECK: State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
30+
// CHECK: return false;
31+
// CHECK: }
32+
// CHECK: }
33+
34+
// CHECK: if (LocVT == MVT::i64 ||
35+
// CHECK: LocVT == MVT::f64) {
36+
// CHECK: static const MCPhysReg RegList2[] = {
37+
// CHECK: R8_R9, R10_R11, R12_R13, R14_R15
38+
// CHECK: };
39+
// CHECK: if (MCRegister Reg = State.AllocateReg(RegList2)) {
40+
// CHECK: State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
41+
// CHECK: return false;
42+
// CHECK: }
43+
// CHECK: }
44+
45+
// CHECK: if (LocVT == MVT::i128) {
46+
// CHECK: static const MCPhysReg RegList3[] = {
47+
// CHECK: R8_R9_R10_R11, R12_R13_R14_R15
48+
// CHECK: };
49+
// CHECK: if (MCRegister Reg = State.AllocateReg(RegList3)) {
50+
// CHECK: State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
51+
// CHECK: return false;
52+
// CHECK: }
53+
// CHECK: }
54+
55+
// CHECK: if (LocVT == MVT::v8i32) {
56+
// CHECK: if (MCRegister Reg = State.AllocateReg(R8_R9_R10_R11_R12_R13_R14_R15)) {
57+
// CHECK: State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
58+
// CHECK: return false;
59+
// CHECK: }
60+
// CHECK: }
61+
62+
#ifdef ERROR1
63+
def CC_ABI2 : CallingConv<[
64+
// Test that referencing an undefined tuple is diagnosed as an error.
65+
// CHECK-ERROR1: error: register not defined: "R89_R33"
66+
CCIfType<[i64, f64],
67+
CCAssignToRegTuple<["R89_R33", "R12_R13", "R14_R15"]>>,
68+
]>;
69+
#endif
70+
71+
#ifdef ERROR2
72+
def CC_ABI3 : CallingConv<[
73+
// Currently an error: Use tuple definitions directly.
74+
// CHECK-ERROR2: error: Variable not defined: 'R8_R9_R10_R11'
75+
CCIfType<[i128],
76+
CCAssignToRegTuple<[R8_R9_R10_R11, R12_R13_R14_R15]>>,
77+
]>;
78+
#endif

llvm/utils/TableGen/CallingConvEmitter.cpp

+27-4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//
1212
//===----------------------------------------------------------------------===//
1313

14+
#include "Common/CodeGenRegisters.h"
1415
#include "Common/CodeGenTarget.h"
1516
#include "llvm/Support/FormatVariadic.h"
1617
#include "llvm/Support/InterleavedRange.h"
@@ -26,6 +27,7 @@ using namespace llvm;
2627
namespace {
2728
class CallingConvEmitter {
2829
const RecordKeeper &Records;
30+
const CodeGenTarget Target;
2931
unsigned Counter = 0u;
3032
std::string CurrentAction;
3133
bool SwiftAction = false;
@@ -35,14 +37,20 @@ class CallingConvEmitter {
3537
std::map<std::string, std::set<std::string>> DelegateToMap;
3638

3739
public:
38-
explicit CallingConvEmitter(const RecordKeeper &R) : Records(R) {}
40+
explicit CallingConvEmitter(const RecordKeeper &R) : Records(R), Target(R) {
41+
for (const CodeGenRegister &Reg : Target.getRegBank().getRegisters())
42+
RegistersByDefName.try_emplace(Reg.getName(), &Reg);
43+
}
3944

4045
void run(raw_ostream &O);
4146

4247
private:
4348
void emitCallingConv(const Record *CC, raw_ostream &O);
4449
void emitAction(const Record *Action, indent Indent, raw_ostream &O);
4550
void emitArgRegisterLists(raw_ostream &O);
51+
52+
StringMap<const CodeGenRegister *> RegistersByDefName;
53+
std::string getQualifiedRegisterName(const Init *I);
4654
};
4755
} // End anonymous namespace
4856

@@ -125,6 +133,20 @@ void CallingConvEmitter::emitCallingConv(const Record *CC, raw_ostream &O) {
125133
O << "}\n";
126134
}
127135

136+
// Return the name of the specified Init (DefInit or StringInit), with a
137+
// namespace qualifier if the corresponding record contains one.
138+
std::string CallingConvEmitter::getQualifiedRegisterName(const Init *I) {
139+
if (const auto *DI = dyn_cast<DefInit>(I))
140+
return getQualifiedName(DI->getDef());
141+
142+
const auto *SI = cast<StringInit>(I);
143+
if (const CodeGenRegister *CGR = RegistersByDefName.lookup(SI->getValue()))
144+
return getQualifiedName(CGR->TheDef);
145+
146+
PrintFatalError("register not defined: " + SI->getAsString());
147+
return "";
148+
}
149+
128150
void CallingConvEmitter::emitAction(const Record *Action, indent Indent,
129151
raw_ostream &O) {
130152

@@ -133,7 +155,7 @@ void CallingConvEmitter::emitAction(const Record *Action, indent Indent,
133155
O << Indent << " ";
134156
ListSeparator LS;
135157
for (const Init *V : RL->getValues())
136-
O << LS << getQualifiedName(cast<DefInit>(V)->getDef());
158+
O << LS << getQualifiedRegisterName(V);
137159
O << "\n" << Indent << "};\n";
138160
};
139161

@@ -142,7 +164,7 @@ void CallingConvEmitter::emitAction(const Record *Action, indent Indent,
142164
SmallVector<std::string> Parms;
143165
if (RegLists[0]->size() == 1) {
144166
for (const ListInit *LI : RegLists)
145-
Parms.push_back(getQualifiedName(LI->getElementAsRecord(0)));
167+
Parms.push_back(getQualifiedRegisterName(LI->getElement(0)));
146168
} else {
147169
for (const std::string &S : RLNames)
148170
Parms.push_back(S + utostr(++Counter));
@@ -207,10 +229,11 @@ void CallingConvEmitter::emitAction(const Record *Action, indent Indent,
207229
<< Indent + 2 << "return false;\n";
208230
DelegateToMap[CurrentAction].insert(CC->getName().str());
209231
} else if (Action->isSubClassOf("CCAssignToReg") ||
232+
Action->isSubClassOf("CCAssignToRegTuple") ||
210233
Action->isSubClassOf("CCAssignToRegAndStack")) {
211234
const ListInit *RegList = Action->getValueAsListInit("RegList");
212235
for (unsigned I = 0, E = RegList->size(); I != E; ++I) {
213-
std::string Name = getQualifiedName(RegList->getElementAsRecord(I));
236+
std::string Name = getQualifiedRegisterName(RegList->getElement(I));
214237
if (SwiftAction)
215238
AssignedSwiftRegsMap[CurrentAction].insert(std::move(Name));
216239
else

0 commit comments

Comments
 (0)