Skip to content

Commit 0e8618a

Browse files
committed
[TableGen][CallingConv] Add CCAssignToRegTuple for synthetic registers.
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 e33cf4b commit 0e8618a

File tree

3 files changed

+113
-4
lines changed

3 files changed

+113
-4
lines changed

llvm/include/llvm/Target/TargetCallingConv.td

Lines changed: 7 additions & 0 deletions
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,
Lines changed: 78 additions & 0 deletions
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

Lines changed: 28 additions & 4 deletions
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 getQualifiedNameFromInit(const Init *I);
4654
};
4755
} // End anonymous namespace
4856

@@ -125,6 +133,21 @@ 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::getQualifiedNameFromInit(const Init *I) {
139+
if (const auto *DI = dyn_cast<DefInit>(I))
140+
return getQualifiedName(DI->getDef());
141+
142+
const auto *SI = dyn_cast<StringInit>(I);
143+
assert(SI && "unexpected Init kind");
144+
if (const CodeGenRegister *CGR = RegistersByDefName.lookup(SI->getValue()))
145+
return getQualifiedName(CGR->TheDef);
146+
147+
PrintFatalError("register not defined: " + SI->getAsString());
148+
return "";
149+
}
150+
128151
void CallingConvEmitter::emitAction(const Record *Action, indent Indent,
129152
raw_ostream &O) {
130153

@@ -133,7 +156,7 @@ void CallingConvEmitter::emitAction(const Record *Action, indent Indent,
133156
O << Indent << " ";
134157
ListSeparator LS;
135158
for (const Init *V : RL->getValues())
136-
O << LS << getQualifiedName(cast<DefInit>(V)->getDef());
159+
O << LS << getQualifiedNameFromInit(V);
137160
O << "\n" << Indent << "};\n";
138161
};
139162

@@ -142,7 +165,7 @@ void CallingConvEmitter::emitAction(const Record *Action, indent Indent,
142165
SmallVector<std::string> Parms;
143166
if (RegLists[0]->size() == 1) {
144167
for (const ListInit *LI : RegLists)
145-
Parms.push_back(getQualifiedName(LI->getElementAsRecord(0)));
168+
Parms.push_back(getQualifiedNameFromInit(LI->getElement(0)));
146169
} else {
147170
for (const std::string &S : RLNames)
148171
Parms.push_back(S + utostr(++Counter));
@@ -207,10 +230,11 @@ void CallingConvEmitter::emitAction(const Record *Action, indent Indent,
207230
<< Indent + 2 << "return false;\n";
208231
DelegateToMap[CurrentAction].insert(CC->getName().str());
209232
} else if (Action->isSubClassOf("CCAssignToReg") ||
233+
Action->isSubClassOf("CCAssignToRegTuple") ||
210234
Action->isSubClassOf("CCAssignToRegAndStack")) {
211235
const ListInit *RegList = Action->getValueAsListInit("RegList");
212236
for (unsigned I = 0, E = RegList->size(); I != E; ++I) {
213-
std::string Name = getQualifiedName(RegList->getElementAsRecord(I));
237+
std::string Name = getQualifiedNameFromInit(RegList->getElement(I));
214238
if (SwiftAction)
215239
AssignedSwiftRegsMap[CurrentAction].insert(std::move(Name));
216240
else

0 commit comments

Comments
 (0)