clang: lib/CIR/CodeGen/CIRGenTypes.cpp Source File (original) (raw)

2

5

10

11#include

12

13using namespace clang;

15

17 : cgm(genModule), astContext(genModule.getASTContext()),

18 builder(cgm.getBuilder()), theCXXABI(cgm.getCXXABI()),

19 theABIInfo(cgm.getTargetCIRGenInfo().getABIInfo()) {}

20

22 for (auto i = functionInfos.begin(), e = functionInfos.end(); i != e;)

23 delete &*i++;

24}

25

27 return *builder.getContext();

28}

29

30

31

32

33

35

36

38

39

40 const TagType *tagType = type->getAs();

42 return true;

43

44

45 return tagType->isIncompleteType();

46}

47

48

49

50

51

52

55 return false;

56

57 if (const auto *fpt = dyn_cast(ft))

58 for (unsigned i = 0, e = fpt->getNumParams(); i != e; i++)

60 return false;

61

62 return true;

63}

64

65mlir::Type CIRGenTypes::convertFunctionTypeInternal(QualType qft) {

68

69

70

73 qft);

75 }

76

78 if (const auto *fpt = dyn_cast(ft)) {

81 } else {

85 }

86

88

89 return resultType;

90}

91

92

93

95 StringRef suffix) {

97 llvm::raw_svector_ostream outStream(typeName);

98

105

108 .print(outStream, policy);

111 else

112 outStream << builder.getUniqueAnonRecordName();

113

114 if (!suffix.empty())

115 outStream << suffix;

116

117 return builder.getUniqueRecordName(std::string(typeName));

118}

119

120

122 const auto it = recordDeclTypes.find(ty);

123 return it != recordDeclTypes.end() && it->second.isComplete();

124}

125

126

127

128static bool

130 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked);

131

132

133

134

135static bool

137 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked) {

138

139

140 if (!alreadyChecked.insert(rd).second)

141 return true;

142

144 "Expect RecordDecl to be CompleteDefinition");

146

147

149 return true;

150

151

153 return false;

154

155

156

157

158

159 if (const CXXRecordDecl *crd = dyn_cast(rd)) {

162 ->castAs()

163 ->getDecl()

164 ->getDefinitionOrSelf(),

165 cgt, alreadyChecked))

166 return false;

167 }

168

169

170

172 if (isSafeToConvert(field->getType(), cgt, alreadyChecked))

173 return false;

174

175

176 return true;

177}

178

179

180

181static bool

183 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked) {

184

186 qt = at->getValueType();

187

188

191

192

194 return isSafeToConvert(at->getElementType(), cgt, alreadyChecked);

195

196

197

198

199 return true;

200}

201

202

203

204

206

208 return true;

209

212}

213

214

216

217

218 const Type *key = astContext.getCanonicalTagType(rd).getTypePtr();

219 cir::RecordType entry = recordDeclTypes[key];

220

221

222

223

224 if (!entry) {

226 entry = builder.getIncompleteRecordTy(name, rd);

227 recordDeclTypes[key] = entry;

228 }

229

232 return entry;

233

234

236 deferredRecords.push_back(rd);

237 return entry;

238 }

239

240

241 bool insertResult = recordsBeingLaidOut.insert(key).second;

242 (void)insertResult;

243 assert(insertResult && "isSafeToCovert() should have caught this.");

244

245

246 if (const auto *cxxRecordDecl = dyn_cast(rd)) {

247 for (const auto &base : cxxRecordDecl->bases()) {

248 if (base.isVirtual())

249 continue;

251 }

252 }

253

254

255 std::unique_ptr layout = computeRecordLayout(rd, &entry);

256 recordDeclTypes[key] = entry;

257 cirGenRecordLayouts[key] = std::move(layout);

258

259

260 bool eraseResult = recordsBeingLaidOut.erase(key);

261 (void)eraseResult;

262 assert(eraseResult && "record not in RecordsBeingLaidOut set?");

263

264

265

267

268

269

270 if (recordsBeingLaidOut.empty())

271 while (!deferredRecords.empty())

273

274 return entry;

275}

276

278 type = astContext.getCanonicalType(type);

279 const Type *ty = type.getTypePtr();

280

281

282 if (const auto *recordType = dyn_cast(type))

284

285

286 TypeCacheTy::iterator tci = typeCache.find(ty);

288 return tci->second;

289

290

291

292

293 mlir::Type resultType = nullptr;

295 case Type::Record:

296 llvm_unreachable("Should have been handled above");

297

298 case Type::Builtin: {

300

301 case BuiltinType::Void:

302 resultType = cgm.voidTy;

303 break;

304

305

306 case BuiltinType::Bool:

308 break;

309

310

311 case BuiltinType::Char_S:

312 case BuiltinType::Int:

313 case BuiltinType::Int128:

314 case BuiltinType::Long:

315 case BuiltinType::LongLong:

316 case BuiltinType::SChar:

317 case BuiltinType::Short:

318 case BuiltinType::WChar_S:

319 resultType =

320 cir::IntType::get(&getMLIRContext(), astContext.getTypeSize(ty),

321 true);

322 break;

323

324 case BuiltinType::Char8:

325 case BuiltinType::Char16:

326 case BuiltinType::Char32:

327 case BuiltinType::Char_U:

328 case BuiltinType::UChar:

329 case BuiltinType::UInt:

330 case BuiltinType::UInt128:

331 case BuiltinType::ULong:

332 case BuiltinType::ULongLong:

333 case BuiltinType::UShort:

334 case BuiltinType::WChar_U:

335 resultType =

336 cir::IntType::get(&getMLIRContext(), astContext.getTypeSize(ty),

337 false);

338 break;

339

340

341 case BuiltinType::Float16:

342 resultType = cgm.fP16Ty;

343 break;

344 case BuiltinType::Half:

345 if (astContext.getLangOpts().NativeHalfType ||

346 !astContext.getTargetInfo().useFP16ConversionIntrinsics()) {

347 resultType = cgm.fP16Ty;

348 } else {

350 resultType = cgm.sInt32Ty;

351 }

352 break;

353 case BuiltinType::BFloat16:

354 resultType = cgm.bFloat16Ty;

355 break;

356 case BuiltinType::Float:

357 assert(&astContext.getFloatTypeSemantics(type) ==

358 &llvm::APFloat::IEEEsingle() &&

359 "ClangIR NYI: 'float' in a format other than IEEE 32-bit");

360 resultType = cgm.floatTy;

361 break;

362 case BuiltinType::Double:

363 assert(&astContext.getFloatTypeSemantics(type) ==

364 &llvm::APFloat::IEEEdouble() &&

365 "ClangIR NYI: 'double' in a format other than IEEE 64-bit");

366 resultType = cgm.doubleTy;

367 break;

368 case BuiltinType::LongDouble:

369 resultType =

370 builder.getLongDoubleTy(astContext.getFloatTypeSemantics(type));

371 break;

372 case BuiltinType::Float128:

373 resultType = cgm.fP128Ty;

374 break;

375 case BuiltinType::Ibm128:

377 resultType = cgm.sInt32Ty;

378 break;

379

380 case BuiltinType::NullPtr:

381

382

383

384

385 resultType = builder.getVoidPtrTy();

386 break;

387

388 default:

390 resultType = cgm.sInt32Ty;

391 break;

392 }

393 break;

394 }

395

396 case Type::Complex: {

398 mlir::Type elementTy = convertType(ct->getElementType());

399 resultType = cir::ComplexType::get(elementTy);

400 break;

401 }

402

403 case Type::LValueReference:

404 case Type::RValueReference: {

408 resultType = builder.getPointerTo(pointeeType, elemTy.getAddressSpace());

409 assert(resultType && "Cannot get pointer type?");

410 break;

411 }

412

413 case Type::Pointer: {

417

418 mlir::Type pointeeType = convertType(elemTy);

419

420 resultType = builder.getPointerTo(pointeeType, elemTy.getAddressSpace());

421 break;

422 }

423

424 case Type::VariableArray: {

428

429

431 break;

432 }

433

434 case Type::IncompleteArray: {

438

440

441

443 elemTy = cgm.sInt8Ty;

444 }

445

446 resultType = cir::ArrayType::get(elemTy, 0);

447 break;

448 }

449

450 case Type::ConstantArray: {

453

454

455

457 cgm.errorNYI(SourceLocation(), "arrays of undefined struct type", type);

458 resultType = cgm.uInt32Ty;

459 break;

460 }

461

462 resultType = cir::ArrayType::get(elemTy, arrTy->getSize().getZExtValue());

463 break;

464 }

465

466 case Type::ExtVector:

467 case Type::Vector: {

470 resultType = cir::VectorType::get(elemTy, vec->getNumElements());

471 break;

472 }

473

474 case Type::Enum: {

476 if (auto integerType = ed->getIntegerType(); !integerType.isNull())

478

479

480

481 resultType = cgm.uInt32Ty;

482 break;

483 }

484

485 case Type::MemberPointer: {

487

488 mlir::Type memberTy = convertType(mpt->getPointeeType());

489 auto clsTy = mlir::castcir::RecordType(

491 if (mpt->isMemberDataPointer()) {

492 resultType = cir::DataMemberType::get(memberTy, clsTy);

493 } else {

496 }

497 break;

498 }

499

500 case Type::FunctionNoProto:

501 case Type::FunctionProto:

502 resultType = convertFunctionTypeInternal(type);

503 break;

504

505 case Type::BitInt: {

507 if (bitIntTy->getNumBits() > cir::IntType::maxBitwidth()) {

509 resultType = cgm.sInt32Ty;

510 } else {

511 resultType = cir::IntType::get(&getMLIRContext(), bitIntTy->getNumBits(),

512 bitIntTy->isSigned());

513 }

514 break;

515 }

516

517 case Type::Atomic: {

520

521

522 uint64_t valueSize = astContext.getTypeSize(valueType);

523 uint64_t atomicSize = astContext.getTypeSize(ty);

524 if (valueSize != atomicSize) {

525 cgm.errorNYI("convertType: atomic type value size != atomic size");

526 }

527

528 break;

529 }

530

531 default:

533 type->getTypeClassName());

534 resultType = cgm.sInt32Ty;

535 break;

536 }

537

538 assert(resultType && "Type conversion not yet implemented");

539

541 return resultType;

542}

543

545 bool forBitField) {

546 assert(qualType->isConstantMatrixType() && "Matrix types NYI");

547

549

550 assert(!forBitField && "Bit fields NYI");

551

552

553

554 if (forBitField && qualType->isBitIntType())

555 assert(qualType->isBitIntType() && "Bit field with type _BitInt NYI");

556

557 return convertedType;

558}

559

560

563 const auto *key = astContext.getCanonicalTagType(rd).getTypePtr();

564

565

566 auto it = cirGenRecordLayouts.find(key);

567 if (it != cirGenRecordLayouts.end())

568 return *it->second;

569

570

572

573

574 it = cirGenRecordLayouts.find(key);

575

576 assert(it != cirGenRecordLayouts.end() &&

577 "Unable to find record layout information for type");

578 return *it->second;

579}

580

583 return astContext.getTargetNullPointerValue(t) == 0;

584

585 if (const auto *at = astContext.getAsArrayType(t)) {

587 return true;

588

589 if (const auto *cat = dyn_cast(at))

590 if (astContext.getConstantArrayElementCount(cat) == 0)

591 return true;

592 }

593

596

598 cgm.errorNYI(SourceLocation(), "isZeroInitializable for MemberPointerType",

599 t);

600 return false;

601 }

602

603 return true;

604}

605

609

614 assert(llvm::all_of(argTypes,

616

617 llvm::FoldingSetNodeID id;

619

620 void *insertPos = nullptr;

621 CIRGenFunctionInfo *fi = functionInfos.FindNodeOrInsertPos(id, insertPos);

622 if (fi) {

623

624

625 assert(

628 "Bad match based on CIRGenFunctionInfo folding set id");

629 return *fi;

630 }

631

633

634

636 functionInfos.InsertNode(fi, insertPos);

637

638 return *fi;

639}

640

642 assert(!dyn_cast(gd.getDecl()) &&

643 "This is reported as a FIXME in LLVM codegen");

645

649

651}

652

653

654

656

657

658

659 if (const auto *ed = dyn_cast(td)) {

660

661

662

663

664

665 assert(

667 ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()) ||

669 typeCache[ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()]));

670

671

673 return;

674 }

675

676

677

679 if (rd->isDependentType())

680 return;

681

682

683

684 if (recordDeclTypes.count(astContext.getCanonicalTagType(rd).getTypePtr()))

686

687

688

690}

Defines the clang::ASTContext interface.

static bool isSafeToConvert(QualType qt, CIRGenTypes &cgt, llvm::SmallPtrSetImpl< const RecordDecl * > &alreadyChecked)

Return true if it is safe to convert this field type, which requires the record elements contained by...

Definition CIRGenTypes.cpp:182

static Decl::Kind getKind(const Decl *D)

C Language Family Type Representation.

const ArrayType * getAsArrayType(QualType T) const

Type Query functions.

CanQualType getCanonicalTagType(const TagDecl *TD) const

QualType getElementType() const

unsigned getIndexTypeCVRQualifiers() const

CanQualType getReturnType() const

const_arg_iterator argTypesEnd() const

static void Profile(llvm::FoldingSetNodeID &id, RequiredArgs required, CanQualType resultType, llvm::ArrayRef< CanQualType > argTypes)

const_arg_iterator argTypesBegin() const

static CIRGenFunctionInfo * create(CanQualType resultType, llvm::ArrayRef< CanQualType > argTypes, RequiredArgs required)

This class organizes the cross-function state that is used while generating CIR code.

DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)

Helpers to emit "not yet implemented" error diagnostics.

This class handles record and union layout info while lowering AST types to CIR types.

bool isZeroInitializable() const

Check whether this struct can be C++ zero-initialized with a zeroinitializer.

This class organizes the cross-module state that is used while lowering AST types to CIR types.

const CIRGenFunctionInfo & arrangeGlobalDeclaration(GlobalDecl gd)

Definition CIRGenTypes.cpp:641

const CIRGenFunctionInfo & arrangeCXXStructorDeclaration(clang::GlobalDecl gd)

const CIRGenFunctionInfo & arrangeFreeFunctionType(CanQual< FunctionProtoType > fpt)

bool isZeroInitializable(clang::QualType ty)

Return whether a type can be zero-initialized (in the C++ sense) with an LLVM zeroinitializer.

Definition CIRGenTypes.cpp:581

bool isFuncTypeConvertible(const clang::FunctionType *ft)

Utility to check whether a function type can be converted to a CIR type (i.e.

Definition CIRGenTypes.cpp:53

CIRGenTypes(CIRGenModule &cgm)

Definition CIRGenTypes.cpp:16

bool isRecordBeingLaidOut(const clang::Type *ty) const

CIRGenBuilderTy & getBuilder() const

mlir::MLIRContext & getMLIRContext() const

Definition CIRGenTypes.cpp:26

const CIRGenFunctionInfo & arrangeCIRFunctionInfo(CanQualType returnType, llvm::ArrayRef< CanQualType > argTypes, RequiredArgs required)

Definition CIRGenTypes.cpp:611

cir::FuncType getFunctionType(const CIRGenFunctionInfo &info)

Get the CIR function type for.

bool isFuncParamTypeConvertible(clang::QualType type)

Return true if the specified type in a function parameter or result position can be converted to a CI...

Definition CIRGenTypes.cpp:34

void updateCompletedType(const clang::TagDecl *td)

UpdateCompletedType - when we find the full definition for a TagDecl, replace the 'opaque' type we pr...

Definition CIRGenTypes.cpp:655

~CIRGenTypes()

Definition CIRGenTypes.cpp:21

std::string getRecordTypeName(const clang::RecordDecl *, llvm::StringRef suffix)

Definition CIRGenTypes.cpp:94

bool noRecordsBeingLaidOut() const

const ABIInfo & getABIInfo() const

const CIRGenFunctionInfo & arrangeFunctionDeclaration(const clang::FunctionDecl *fd)

Free functions are functions that are compatible with an ordinary C function pointer type.

clang::ASTContext & getASTContext() const

bool isRecordLayoutComplete(const clang::Type *ty) const

Return true if the specified type is already completely laid out.

Definition CIRGenTypes.cpp:121

mlir::Type convertType(clang::QualType type)

Convert a Clang type into a mlir::Type.

Definition CIRGenTypes.cpp:277

const CIRGenRecordLayout & getCIRGenRecordLayout(const clang::RecordDecl *rd)

Return record layout info for the given record decl.

Definition CIRGenTypes.cpp:562

std::unique_ptr< CIRGenRecordLayout > computeRecordLayout(const clang::RecordDecl *rd, cir::RecordType *ty)

mlir::Type convertRecordDeclType(const clang::RecordDecl *recordDecl)

Lay out a tagged decl type like struct or union.

Definition CIRGenTypes.cpp:215

mlir::Type convertTypeForMem(clang::QualType, bool forBitField=false)

Convert type T into an mlir::Type.

Definition CIRGenTypes.cpp:544

A class for recording the number of arguments that a function signature requires.

Represents a base class of a C++ class.

Represents a C++ struct/union/class.

static CanQual< T > CreateUnsafe(QualType Other)

Builds a canonical type from a QualType.

bool isCanonicalAsParam() const

Determines if this canonical type is furthermore canonical as a parameter.

const T * getTypePtr() const

Retrieve the underlying type pointer, which refers to a canonical type.

Represents the canonical version of C arrays with a specified constant size.

llvm::APInt getSize() const

Return the constant array size as an APInt.

Represents a member of a struct/union/class.

FunctionType - C99 6.7.5.3 - Function Declarators.

QualType getReturnType() const

GlobalDecl - represents a global declaration.

const Decl * getDecl() const

Represents a C array with an unspecified size.

A pointer to member type per C++ 8.3.3 - Pointers to members.

PointerType - C99 6.7.5.1 - Pointer Declarators.

QualType getPointeeType() const

A (possibly-)qualified type.

const Type * getTypePtr() const

Retrieves a pointer to the underlying (unqualified) type.

LangAS getAddressSpace() const

Return the address space of this type.

void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const

Represents a struct/union/class.

field_range fields() const

RecordDecl * getDefinition() const

Returns the RecordDecl that actually defines this struct/union/class.

Base for LValueReferenceType and RValueReferenceType.

QualType getPointeeType() const

Encodes a location in the source.

Represents the declaration of a struct/union/class/enum.

bool isCompleteDefinition() const

Return true if this decl has its body fully specified.

The base class of the type hierarchy.

RecordDecl * getAsRecordDecl() const

Retrieves the RecordDecl this type refers to.

bool isConstantMatrixType() const

EnumDecl * castAsEnumDecl() const

TypeClass getTypeClass() const

const T * getAs() const

Member-template getAs'.

Represents a C array with a specified size that is not an integer-constant-expression.

Represents a GCC generic vector type.

unsigned getNumElements() const

QualType getElementType() const

Defines the clang::TargetInfo interface.

bool isSized(mlir::Type ty)

Returns true if the type is a CIR sized type.

@ Type

The l-value was considered opaque, so the alignment was determined from a type.

const internal::VariadicDynCastAllOfMatcher< Decl, TypedefNameDecl > typedefNameDecl

Matches typedef name declarations.

const AstTypeMatcher< TagType > tagType

const internal::VariadicAllOfMatcher< Type > type

Matches Types in the clang AST.

const AstTypeMatcher< RecordType > recordType

const internal::VariadicDynCastAllOfMatcher< Decl, CXXRecordDecl > cxxRecordDecl

Matches C++ class declarations.

const internal::VariadicDynCastAllOfMatcher< Decl, RecordDecl > recordDecl

Matches class, struct, and union declarations.

const internal::VariadicAllOfMatcher< QualType > qualType

Matches QualTypes in the clang AST.

The JSON file list parser is used to communicate input to InstallAPI.

CanQual< Type > CanQualType

Represents a canonical, potentially-qualified type.

bool isa(CodeGen::Address addr)

U cast(CodeGen::Address addr)

static bool skippedLayout()

static bool opCallCallConv()

static bool generateDebugInfo()

Describes how types, statements, expressions, and declarations should be printed.

unsigned SuppressTagKeyword

Whether type printing should skip printing the tag keyword.

unsigned AlwaysIncludeTypeForTemplateArgument

Whether to use type suffixes (eg: 1U) on integral non-type template parameters.

unsigned SuppressInlineNamespace

Suppress printing parts of scope specifiers that correspond to inline namespaces.

unsigned PrintAsCanonical

Whether to print entities as written or canonically.