Skip to content

Commit 93f55f6

Browse files
lanzasmeenai
authored andcommitted
[CIR] Support converting fns in CIRGenTypes::ConvertType
This patch adds a few functions to support converting AST types to MLIR types for functions
1 parent 148c85e commit 93f55f6

File tree

2 files changed

+93
-1
lines changed

2 files changed

+93
-1
lines changed

clang/lib/CIR/CIRGenTypes.cpp

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,78 @@ mlir::MLIRContext &CIRGenTypes::getMLIRContext() const {
106106
return *Builder.getContext();
107107
}
108108

109+
mlir::Type CIRGenTypes::ConvertFunctionTypeInternal(QualType QFT) {
110+
assert(QFT.isCanonical());
111+
const Type *Ty = QFT.getTypePtr();
112+
const FunctionType *FT = cast<FunctionType>(QFT.getTypePtr());
113+
// First, check whether we can build the full fucntion type. If the function
114+
// type depends on an incomplete type (e.g. a struct or enum), we cannot lower
115+
// the function type.
116+
assert(isFuncTypeConvertible(FT) && "NYI");
117+
118+
// While we're converting the parameter types for a function, we don't want to
119+
// recursively convert any pointed-to structs. Converting directly-used
120+
// structs is ok though.
121+
assert(RecordsBeingLaidOut.insert(Ty).second && "NYI");
122+
123+
// The function type can be built; call the appropriate routines to build it
124+
const CIRGenFunctionInfo *FI;
125+
const auto *FPT = dyn_cast<FunctionProtoType>(FT);
126+
assert(FPT && "FunctionNonPrototype NIY");
127+
FI = &arrangeFreeFunctionType(
128+
CanQual<FunctionProtoType>::CreateUnsafe(QualType(FPT, 0)));
129+
130+
mlir::Type ResultType = nullptr;
131+
// If there is something higher level prodding our CIRGenFunctionInfo, then
132+
// don't recurse into it again.
133+
assert(!FunctionsBeingProcessed.count(FI) && "NYI");
134+
135+
// Otherwise, we're good to go, go ahead and convert it.
136+
ResultType = GetFunctionType(*FI);
137+
138+
RecordsBeingLaidOut.erase(Ty);
139+
140+
assert(!SkippedLayout && "Shouldn't have skipped anything yet");
141+
142+
assert(RecordsBeingLaidOut.empty() && "Deferral NYI");
143+
assert(DeferredRecords.empty() && "Deferral NYI");
144+
145+
return ResultType;
146+
}
147+
148+
/// isFuncParamTypeConvertible - Return true if the specified type in a function
149+
/// parameter or result position can be converted to a CIR type at this point.
150+
/// This boils down to being whether it is complete, as well as whether we've
151+
/// temporarily deferred expanding the type because we're in a recursive
152+
/// context.
153+
bool CIRGenTypes::isFuncParamTypeConvertible(clang::QualType Ty) {
154+
// Some ABIs cannot have their member pointers represented in LLVM IR unless
155+
// certain circumstances have been reached.
156+
assert(!Ty->getAs<MemberPointerType>() && "NYI");
157+
158+
// If this isn't a tagged type, we can convert it!
159+
auto *TT = Ty->getAs<TagType>();
160+
assert(!TT && "Only non-TagTypes implemented atm.");
161+
return true;
162+
}
163+
164+
/// Code to verify a given function type is complete, i.e. the return type and
165+
/// all of the parameter types are complete. Also check to see if we are in a
166+
/// RS_StructPointer context, and if so whether any struct types have been
167+
/// pended. If so, we don't want to ask the ABI lowering code to handle a type
168+
/// that cannot be converted to a CIR type.
169+
bool CIRGenTypes::isFuncTypeConvertible(const FunctionType *FT) {
170+
if (!isFuncParamTypeConvertible(FT->getReturnType()))
171+
return false;
172+
173+
if (const auto *FPT = dyn_cast<FunctionProtoType>(FT))
174+
for (unsigned i = 0, e = FPT->getNumParams(); i != e; i++)
175+
if (!isFuncParamTypeConvertible(FPT->getParamType(i)))
176+
return false;
177+
178+
return true;
179+
}
180+
109181
/// ConvertType - Convert the specified type to its MLIR form.
110182
mlir::Type CIRGenTypes::ConvertType(QualType T) {
111183
T = Context.getCanonicalType(T);
@@ -376,7 +448,7 @@ mlir::Type CIRGenTypes::ConvertType(QualType T) {
376448
}
377449
case Type::FunctionNoProto:
378450
case Type::FunctionProto:
379-
assert(0 && "not implemented");
451+
ResultType = ConvertFunctionTypeInternal(T);
380452
break;
381453
case Type::ObjCObject:
382454
assert(0 && "not implemented");

clang/lib/CIR/CIRGenTypes.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,32 @@ class CIRGenTypes {
8989
/// Hold memoized CIRGenFunctionInfo results
9090
llvm::FoldingSet<CIRGenFunctionInfo> FunctionInfos;
9191

92+
/// This set keeps track of records that we're currently converting to a CIR
93+
/// type. For example, when converting:
94+
/// struct A { struct B { int x; } } when processing 'x', the 'A' and 'B'
95+
/// types will be in this set.
96+
llvm::SmallPtrSet<const clang::Type *, 4> RecordsBeingLaidOut;
97+
9298
llvm::SmallPtrSet<const CIRGenFunctionInfo *, 4> FunctionsBeingProcessed;
9399

100+
/// True if we didn't layout a function due to being inside a recursive struct
101+
/// conversion, set this to true.
102+
bool SkippedLayout;
103+
104+
llvm::SmallVector<const clang::RecordDecl *, 8> DeferredRecords;
105+
106+
/// Heper for ConvertType.
107+
mlir::Type ConvertFunctionTypeInternal(clang::QualType FT);
108+
94109
public:
95110
CIRGenTypes(CIRGenModule &cgm);
96111
~CIRGenTypes();
97112

113+
/// isFuncTypeConvertible - Utility to check whether a function type can be
114+
/// converted to a CIR type (i.e. doesn't depend on an incomplete tag type).
115+
bool isFuncTypeConvertible(const clang::FunctionType *FT);
116+
bool isFuncParamTypeConvertible(clang::QualType Ty);
117+
98118
/// Convert clang calling convention to LLVM calling convention.
99119
unsigned ClangCallConvToCIRCallConv(clang::CallingConv CC);
100120

0 commit comments

Comments
 (0)