Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions llvm/include/llvm/Target/TargetCallingConv.td
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,13 @@ class CCAssignToReg<list<Register> regList> : CCAction {
list<Register> RegList = regList;
}

/// CCAssignToRegTuple - Same as CCAssignToReg, but with a list of registers as
/// strings. This is needed because records synthesized during tuple expansion
/// are not visible outside of the register info emitter.
class CCAssignToRegTuple<list<string> regList> : CCAction {
list<string> RegList = regList;
}

/// CCAssignToRegWithShadow - Same as CCAssignToReg, but with list of registers
/// which became shadowed, when some register is used.
class CCAssignToRegWithShadow<list<Register> regList,
Expand Down
78 changes: 78 additions & 0 deletions llvm/test/TableGen/cc-assign-to-reg-tuple.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// RUN: llvm-tblgen --gen-callingconv -I %p/../../include -I %p/Common %s 2>&1 | FileCheck %s
// RUN: not llvm-tblgen -DERROR1 --gen-callingconv -I %p/../../include -I %p/Common %s 2>&1 | FileCheck --check-prefix=CHECK-ERROR1 %s
// RUN: not llvm-tblgen -DERROR2 --gen-callingconv -I %p/../../include -I %p/Common %s 2>&1 | FileCheck --check-prefix=CHECK-ERROR2 %s

include "reg-with-subregs-common.td"

def CC_ABI1 : CallingConv<[
// Use singleton definitions directly.
CCIfType<[i32, f32],
CCAssignToReg<[R8, R9, R10, R11, R12, R13, R14, R15]>>,

// Use tuple definitions indirectly as strings.
CCIfType<[i64, f64],
CCAssignToRegTuple<["R8_R9", "R10_R11", "R12_R13", "R14_R15"]>>,

CCIfType<[i128],
CCAssignToRegTuple<["R8_R9_R10_R11", "R12_R13_R14_R15"]>>,

CCIfType<[v8i32],
CCAssignToRegTuple<["R8_R9_R10_R11_R12_R13_R14_R15"]>>,
]>;

// CHECK: if (LocVT == MVT::i32 ||
// CHECK: LocVT == MVT::f32) {
// CHECK: static const MCPhysReg RegList1[] = {
// CHECK: R8, R9, R10, R11, R12, R13, R14, R15
// CHECK: };
// CHECK: if (MCRegister Reg = State.AllocateReg(RegList1)) {
// CHECK: State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
// CHECK: return false;
// CHECK: }
// CHECK: }

// CHECK: if (LocVT == MVT::i64 ||
// CHECK: LocVT == MVT::f64) {
// CHECK: static const MCPhysReg RegList2[] = {
// CHECK: R8_R9, R10_R11, R12_R13, R14_R15
// CHECK: };
// CHECK: if (MCRegister Reg = State.AllocateReg(RegList2)) {
// CHECK: State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
// CHECK: return false;
// CHECK: }
// CHECK: }

// CHECK: if (LocVT == MVT::i128) {
// CHECK: static const MCPhysReg RegList3[] = {
// CHECK: R8_R9_R10_R11, R12_R13_R14_R15
// CHECK: };
// CHECK: if (MCRegister Reg = State.AllocateReg(RegList3)) {
// CHECK: State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
// CHECK: return false;
// CHECK: }
// CHECK: }

// CHECK: if (LocVT == MVT::v8i32) {
// CHECK: if (MCRegister Reg = State.AllocateReg(R8_R9_R10_R11_R12_R13_R14_R15)) {
// CHECK: State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
// CHECK: return false;
// CHECK: }
// CHECK: }

#ifdef ERROR1
def CC_ABI2 : CallingConv<[
// Test that referencing an undefined tuple is diagnosed as an error.
// CHECK-ERROR1: error: register not defined: "R89_R33"
CCIfType<[i64, f64],
CCAssignToRegTuple<["R89_R33", "R12_R13", "R14_R15"]>>,
]>;
#endif

#ifdef ERROR2
def CC_ABI3 : CallingConv<[
// Currently an error: Use tuple definitions directly.
// CHECK-ERROR2: error: Variable not defined: 'R8_R9_R10_R11'
CCIfType<[i128],
CCAssignToRegTuple<[R8_R9_R10_R11, R12_R13_R14_R15]>>,
]>;
#endif
32 changes: 28 additions & 4 deletions llvm/utils/TableGen/CallingConvEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//

#include "Common/CodeGenRegisters.h"
#include "Common/CodeGenTarget.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/InterleavedRange.h"
Expand All @@ -26,6 +27,7 @@ using namespace llvm;
namespace {
class CallingConvEmitter {
const RecordKeeper &Records;
const CodeGenTarget Target;
unsigned Counter = 0u;
std::string CurrentAction;
bool SwiftAction = false;
Expand All @@ -35,14 +37,20 @@ class CallingConvEmitter {
std::map<std::string, std::set<std::string>> DelegateToMap;

public:
explicit CallingConvEmitter(const RecordKeeper &R) : Records(R) {}
explicit CallingConvEmitter(const RecordKeeper &R) : Records(R), Target(R) {
for (const CodeGenRegister &Reg : Target.getRegBank().getRegisters())
RegistersByDefName.try_emplace(Reg.getName(), &Reg);
}

void run(raw_ostream &O);

private:
void emitCallingConv(const Record *CC, raw_ostream &O);
void emitAction(const Record *Action, indent Indent, raw_ostream &O);
void emitArgRegisterLists(raw_ostream &O);

StringMap<const CodeGenRegister *> RegistersByDefName;
std::string getQualifiedNameFromInit(const Init *I);
};
} // End anonymous namespace

Expand Down Expand Up @@ -125,6 +133,21 @@ void CallingConvEmitter::emitCallingConv(const Record *CC, raw_ostream &O) {
O << "}\n";
}

// Return the name of the specified Init (DefInit or StringInit), with a
// namespace qualifier if the corresponding record contains one.
std::string CallingConvEmitter::getQualifiedNameFromInit(const Init *I) {
if (const auto *DI = dyn_cast<DefInit>(I))
return getQualifiedName(DI->getDef());

const auto *SI = dyn_cast<StringInit>(I);
assert(SI && "unexpected Init kind");
if (const CodeGenRegister *CGR = RegistersByDefName.lookup(SI->getValue()))
return getQualifiedName(CGR->TheDef);

PrintFatalError("register not defined: " + SI->getAsString());
return "";
}

void CallingConvEmitter::emitAction(const Record *Action, indent Indent,
raw_ostream &O) {

Expand All @@ -133,7 +156,7 @@ void CallingConvEmitter::emitAction(const Record *Action, indent Indent,
O << Indent << " ";
ListSeparator LS;
for (const Init *V : RL->getValues())
O << LS << getQualifiedName(cast<DefInit>(V)->getDef());
O << LS << getQualifiedNameFromInit(V);
O << "\n" << Indent << "};\n";
};

Expand All @@ -142,7 +165,7 @@ void CallingConvEmitter::emitAction(const Record *Action, indent Indent,
SmallVector<std::string> Parms;
if (RegLists[0]->size() == 1) {
for (const ListInit *LI : RegLists)
Parms.push_back(getQualifiedName(LI->getElementAsRecord(0)));
Parms.push_back(getQualifiedNameFromInit(LI->getElement(0)));
} else {
for (const std::string &S : RLNames)
Parms.push_back(S + utostr(++Counter));
Expand Down Expand Up @@ -207,10 +230,11 @@ void CallingConvEmitter::emitAction(const Record *Action, indent Indent,
<< Indent + 2 << "return false;\n";
DelegateToMap[CurrentAction].insert(CC->getName().str());
} else if (Action->isSubClassOf("CCAssignToReg") ||
Action->isSubClassOf("CCAssignToRegTuple") ||
Action->isSubClassOf("CCAssignToRegAndStack")) {
const ListInit *RegList = Action->getValueAsListInit("RegList");
for (unsigned I = 0, E = RegList->size(); I != E; ++I) {
std::string Name = getQualifiedName(RegList->getElementAsRecord(I));
std::string Name = getQualifiedNameFromInit(RegList->getElement(I));
if (SwiftAction)
AssignedSwiftRegsMap[CurrentAction].insert(std::move(Name));
else
Expand Down