clang 22.0.0git
CIRGenBuilder.h
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENBUILDER_H
10#define LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENBUILDER_H
11
12#include "Address.h"
13#include "CIRGenRecordLayout.h"
14#include "CIRGenTypeCache.h"
15#include "mlir/IR/Attributes.h"
16#include "mlir/IR/BuiltinAttributes.h"
17#include "mlir/Support/LLVM.h"
20
23#include "llvm/ADT/APFloat.h"
24#include "llvm/ADT/STLExtras.h"
25
26namespace clang::CIRGen {
27
29 const CIRGenTypeCache &typeCache;
30 llvm::StringMap<unsigned> recordNames;
31 llvm::StringMap<unsigned> globalsVersioning;
32
33public:
34 CIRGenBuilderTy(mlir::MLIRContext &mlirContext, const CIRGenTypeCache &tc)
35 : CIRBaseBuilderTy(mlirContext), typeCache(tc) {}
36
37 /// Get a cir::ConstArrayAttr for a string literal.
38 /// Note: This is different from what is returned by
39 /// mlir::Builder::getStringAttr() which is an mlir::StringAttr.
40 mlir::Attribute getString(llvm::StringRef str, mlir::Type eltTy,
41 std::optional<size_t> size) {
42 size_t finalSize = size.value_or(str.size());
43
44 size_t lastNonZeroPos = str.find_last_not_of('\0');
45 // If the string is full of null bytes, emit a #cir.zero rather than
46 // a #cir.const_array.
47 if (lastNonZeroPos == llvm::StringRef::npos) {
48 auto arrayTy = cir::ArrayType::get(eltTy, finalSize);
49 return cir::ZeroAttr::get(arrayTy);
50 }
51 // We emit trailing zeros only if there are multiple trailing zeros.
52 size_t trailingZerosNum = 0;
53 if (finalSize > lastNonZeroPos + 2)
54 trailingZerosNum = finalSize - lastNonZeroPos - 1;
55 auto truncatedArrayTy =
56 cir::ArrayType::get(eltTy, finalSize - trailingZerosNum);
57 auto fullArrayTy = cir::ArrayType::get(eltTy, finalSize);
58 return cir::ConstArrayAttr::get(
59 fullArrayTy,
60 mlir::StringAttr::get(str.drop_back(trailingZerosNum),
61 truncatedArrayTy),
62 trailingZerosNum);
63 }
64
65 cir::ConstArrayAttr getConstArray(mlir::Attribute attrs,
66 cir::ArrayType arrayTy) const {
67 return cir::ConstArrayAttr::get(arrayTy, attrs);
68 }
69
70 mlir::Attribute getConstRecordOrZeroAttr(mlir::ArrayAttr arrayAttr,
71 bool packed = false,
72 bool padded = false,
73 mlir::Type type = {});
74
75 cir::ConstRecordAttr getAnonConstRecord(mlir::ArrayAttr arrayAttr,
76 bool packed = false,
77 bool padded = false,
78 mlir::Type ty = {}) {
80 for (auto &f : arrayAttr) {
81 auto ta = mlir::cast<mlir::TypedAttr>(f);
82 members.push_back(ta.getType());
83 }
84
85 if (!ty)
86 ty = getAnonRecordTy(members, packed, padded);
87
88 auto sTy = mlir::cast<cir::RecordType>(ty);
89 return cir::ConstRecordAttr::get(sTy, arrayAttr);
90 }
91
92 std::string getUniqueAnonRecordName() { return getUniqueRecordName("anon"); }
93
94 std::string getUniqueRecordName(const std::string &baseName) {
95 auto it = recordNames.find(baseName);
96 if (it == recordNames.end()) {
97 recordNames[baseName] = 0;
98 return baseName;
99 }
100
101 return baseName + "." + std::to_string(recordNames[baseName]++);
102 }
103
104 cir::LongDoubleType getLongDoubleTy(const llvm::fltSemantics &format) const {
105 if (&format == &llvm::APFloat::IEEEdouble())
106 return cir::LongDoubleType::get(getContext(), typeCache.DoubleTy);
107 if (&format == &llvm::APFloat::x87DoubleExtended())
108 return cir::LongDoubleType::get(getContext(), typeCache.FP80Ty);
109 if (&format == &llvm::APFloat::IEEEquad())
110 return cir::LongDoubleType::get(getContext(), typeCache.FP128Ty);
111 if (&format == &llvm::APFloat::PPCDoubleDouble())
112 llvm_unreachable("NYI: PPC double-double format for long double");
113 llvm_unreachable("Unsupported format for long double");
114 }
115
116 mlir::Type getPtrToVPtrType() {
117 return getPointerTo(cir::VPtrType::get(getContext()));
118 }
119
120 /// Get a CIR record kind from a AST declaration tag.
121 cir::RecordType::RecordKind getRecordKind(const clang::TagTypeKind kind) {
122 switch (kind) {
124 return cir::RecordType::Class;
126 return cir::RecordType::Struct;
128 return cir::RecordType::Union;
130 llvm_unreachable("interface records are NYI");
132 llvm_unreachable("enums are not records");
133 }
134 llvm_unreachable("Unsupported record kind");
135 }
136
137 /// Get a CIR named record type.
138 ///
139 /// If a record already exists and is complete, but the client tries to fetch
140 /// it with a different set of attributes, this method will crash.
142 bool packed, bool padded,
143 llvm::StringRef name) {
144 const auto nameAttr = getStringAttr(name);
145 auto kind = cir::RecordType::RecordKind::Struct;
147
148 // Create or get the record.
149 auto type =
150 getType<cir::RecordType>(members, nameAttr, packed, padded, kind);
151
152 // If we found an existing type, verify that either it is incomplete or
153 // it matches the requested attributes.
154 assert(!type.isIncomplete() ||
155 (type.getMembers() == members && type.getPacked() == packed &&
156 type.getPadded() == padded));
157
158 // Complete an incomplete record or ensure the existing complete record
159 // matches the requested attributes.
160 type.complete(members, packed, padded);
161
162 return type;
163 }
164
165 cir::RecordType getCompleteRecordType(mlir::ArrayAttr fields,
166 bool packed = false,
167 bool padded = false,
168 llvm::StringRef name = "");
169
170 /// Get an incomplete CIR struct type. If we have a complete record
171 /// declaration, we may create an incomplete type and then add the
172 /// members, so \p rd here may be complete.
173 cir::RecordType getIncompleteRecordTy(llvm::StringRef name,
174 const clang::RecordDecl *rd) {
175 const mlir::StringAttr nameAttr = getStringAttr(name);
176 cir::RecordType::RecordKind kind = cir::RecordType::RecordKind::Struct;
177 if (rd)
178 kind = getRecordKind(rd->getTagKind());
179 return getType<cir::RecordType>(nameAttr, kind);
180 }
181
182 // Return true if the value is a null constant such as null pointer, (+0.0)
183 // for floating-point or zero initializer
184 bool isNullValue(mlir::Attribute attr) const {
185 if (mlir::isa<cir::ZeroAttr>(attr))
186 return true;
187
188 if (const auto ptrVal = mlir::dyn_cast<cir::ConstPtrAttr>(attr))
189 return ptrVal.isNullValue();
190
191 if (const auto intVal = mlir::dyn_cast<cir::IntAttr>(attr))
192 return intVal.isNullValue();
193
194 if (const auto boolVal = mlir::dyn_cast<cir::BoolAttr>(attr))
195 return !boolVal.getValue();
196
197 if (auto fpAttr = mlir::dyn_cast<cir::FPAttr>(attr)) {
198 auto fpVal = fpAttr.getValue();
199 bool ignored;
200 llvm::APFloat fv(+0.0);
201 fv.convert(fpVal.getSemantics(), llvm::APFloat::rmNearestTiesToEven,
202 &ignored);
203 return fv.bitwiseIsEqual(fpVal);
204 }
205
206 if (const auto arrayVal = mlir::dyn_cast<cir::ConstArrayAttr>(attr)) {
207 if (mlir::isa<mlir::StringAttr>(arrayVal.getElts()))
208 return false;
209
210 return llvm::all_of(
211 mlir::cast<mlir::ArrayAttr>(arrayVal.getElts()),
212 [&](const mlir::Attribute &elt) { return isNullValue(elt); });
213 }
214 return false;
215 }
216
217 //
218 // Type helpers
219 // ------------
220 //
221 cir::IntType getUIntNTy(int n) {
222 switch (n) {
223 case 8:
224 return getUInt8Ty();
225 case 16:
226 return getUInt16Ty();
227 case 32:
228 return getUInt32Ty();
229 case 64:
230 return getUInt64Ty();
231 default:
232 return cir::IntType::get(getContext(), n, false);
233 }
234 }
235
236 cir::IntType getSIntNTy(int n) {
237 switch (n) {
238 case 8:
239 return getSInt8Ty();
240 case 16:
241 return getSInt16Ty();
242 case 32:
243 return getSInt32Ty();
244 case 64:
245 return getSInt64Ty();
246 default:
247 return cir::IntType::get(getContext(), n, true);
248 }
249 }
250
251 cir::VoidType getVoidTy() { return typeCache.VoidTy; }
252
253 cir::IntType getSInt8Ty() { return typeCache.SInt8Ty; }
254 cir::IntType getSInt16Ty() { return typeCache.SInt16Ty; }
255 cir::IntType getSInt32Ty() { return typeCache.SInt32Ty; }
256 cir::IntType getSInt64Ty() { return typeCache.SInt64Ty; }
257
258 cir::IntType getUInt8Ty() { return typeCache.UInt8Ty; }
259 cir::IntType getUInt16Ty() { return typeCache.UInt16Ty; }
260 cir::IntType getUInt32Ty() { return typeCache.UInt32Ty; }
261 cir::IntType getUInt64Ty() { return typeCache.UInt64Ty; }
262
263 cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal);
264
265 cir::ConstantOp getConstInt(mlir::Location loc, llvm::APInt intVal);
266
267 cir::ConstantOp getConstInt(mlir::Location loc, mlir::Type t, uint64_t c);
268
269 cir::ConstantOp getConstFP(mlir::Location loc, mlir::Type t,
270 llvm::APFloat fpVal);
271
272 bool isInt8Ty(mlir::Type i) {
273 return i == typeCache.UInt8Ty || i == typeCache.SInt8Ty;
274 }
275 bool isInt16Ty(mlir::Type i) {
276 return i == typeCache.UInt16Ty || i == typeCache.SInt16Ty;
277 }
278 bool isInt32Ty(mlir::Type i) {
279 return i == typeCache.UInt32Ty || i == typeCache.SInt32Ty;
280 }
281 bool isInt64Ty(mlir::Type i) {
282 return i == typeCache.UInt64Ty || i == typeCache.SInt64Ty;
283 }
284 bool isInt(mlir::Type i) { return mlir::isa<cir::IntType>(i); }
285
286 // Fetch the type representing a pointer to unsigned int8 values.
287 cir::PointerType getUInt8PtrTy() { return typeCache.UInt8PtrTy; }
288
289 /// Get a CIR anonymous record type.
291 bool packed = false, bool padded = false) {
293 auto kind = cir::RecordType::RecordKind::Struct;
294 return getType<cir::RecordType>(members, packed, padded, kind);
295 }
296
297 //
298 // Constant creation helpers
299 // -------------------------
300 //
301 cir::ConstantOp getSInt32(int32_t c, mlir::Location loc) {
302 return getConstantInt(loc, getSInt32Ty(), c);
303 }
304 cir::ConstantOp getUInt32(uint32_t c, mlir::Location loc) {
305 return getConstantInt(loc, getUInt32Ty(), c);
306 }
307 cir::ConstantOp getSInt64(uint64_t c, mlir::Location loc) {
308 cir::IntType sInt64Ty = getSInt64Ty();
309 return cir::ConstantOp::create(*this, loc, cir::IntAttr::get(sInt64Ty, c));
310 }
311
312 // Creates constant nullptr for pointer type ty.
313 cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc) {
315 return cir::ConstantOp::create(*this, loc, getConstPtrAttr(ty, 0));
316 }
317
318 mlir::Value createNeg(mlir::Value value) {
319
320 if (auto intTy = mlir::dyn_cast<cir::IntType>(value.getType())) {
321 // Source is a unsigned integer: first cast it to signed.
322 if (intTy.isUnsigned())
323 value = createIntCast(value, getSIntNTy(intTy.getWidth()));
324 return cir::UnaryOp::create(*this, value.getLoc(), value.getType(),
325 cir::UnaryOpKind::Minus, value);
326 }
327
328 llvm_unreachable("negation for the given type is NYI");
329 }
330
331 // TODO: split this to createFPExt/createFPTrunc when we have dedicated cast
332 // operations.
333 mlir::Value createFloatingCast(mlir::Value v, mlir::Type destType) {
335
336 return cir::CastOp::create(*this, v.getLoc(), destType,
337 cir::CastKind::floating, v);
338 }
339
340 mlir::Value createFSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
344
345 return cir::BinOp::create(*this, loc, cir::BinOpKind::Sub, lhs, rhs);
346 }
347
348 mlir::Value createFAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
352
353 return cir::BinOp::create(*this, loc, cir::BinOpKind::Add, lhs, rhs);
354 }
355 mlir::Value createFMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
359
360 return cir::BinOp::create(*this, loc, cir::BinOpKind::Mul, lhs, rhs);
361 }
362 mlir::Value createFDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
366
367 return cir::BinOp::create(*this, loc, cir::BinOpKind::Div, lhs, rhs);
368 }
369
370 Address createBaseClassAddr(mlir::Location loc, Address addr,
371 mlir::Type destType, unsigned offset,
372 bool assumeNotNull) {
373 if (destType == addr.getElementType())
374 return addr;
375
376 auto ptrTy = getPointerTo(destType);
377 auto baseAddr =
378 cir::BaseClassAddrOp::create(*this, loc, ptrTy, addr.getPointer(),
379 mlir::APInt(64, offset), assumeNotNull);
380 return Address(baseAddr, destType, addr.getAlignment());
381 }
382
383 mlir::Value createVTTAddrPoint(mlir::Location loc, mlir::Type retTy,
384 mlir::Value addr, uint64_t offset) {
385 return cir::VTTAddrPointOp::create(*this, loc, retTy,
386 mlir::FlatSymbolRefAttr{}, addr, offset);
387 }
388
389 mlir::Value createVTTAddrPoint(mlir::Location loc, mlir::Type retTy,
390 mlir::FlatSymbolRefAttr sym, uint64_t offset) {
391 return cir::VTTAddrPointOp::create(*this, loc, retTy, sym, mlir::Value{},
392 offset);
393 }
394
395 /// Cast the element type of the given address to a different type,
396 /// preserving information like the alignment.
397 Address createElementBitCast(mlir::Location loc, Address addr,
398 mlir::Type destType) {
399 if (destType == addr.getElementType())
400 return addr;
401
402 auto ptrTy = getPointerTo(destType);
403 return Address(createBitcast(loc, addr.getPointer(), ptrTy), destType,
404 addr.getAlignment());
405 }
406
407 cir::LoadOp createLoad(mlir::Location loc, Address addr,
408 bool isVolatile = false) {
409 mlir::IntegerAttr align = getAlignmentAttr(addr.getAlignment());
410 return cir::LoadOp::create(*this, loc, addr.getPointer(), /*isDeref=*/false,
411 isVolatile, /*alignment=*/align,
412 /*mem_order=*/cir::MemOrderAttr{});
413 }
414
415 cir::LoadOp createAlignedLoad(mlir::Location loc, mlir::Type ty,
416 mlir::Value ptr, llvm::MaybeAlign align) {
417 if (ty != mlir::cast<cir::PointerType>(ptr.getType()).getPointee())
418 ptr = createPtrBitcast(ptr, ty);
419 uint64_t alignment = align ? align->value() : 0;
420 mlir::IntegerAttr alignAttr = getAlignmentAttr(alignment);
421 return cir::LoadOp::create(*this, loc, ptr, /*isDeref=*/false,
422 /*isVolatile=*/false, alignAttr,
423 /*mem_order=*/cir::MemOrderAttr{});
424 }
425
426 cir::LoadOp
427 createAlignedLoad(mlir::Location loc, mlir::Type ty, mlir::Value ptr,
429 return createAlignedLoad(loc, ty, ptr, align.getAsAlign());
430 }
431
432 cir::StoreOp createStore(mlir::Location loc, mlir::Value val, Address dst,
433 bool isVolatile = false,
434 mlir::IntegerAttr align = {},
435 cir::MemOrderAttr order = {}) {
436 if (!align)
437 align = getAlignmentAttr(dst.getAlignment());
438 return CIRBaseBuilderTy::createStore(loc, val, dst.getPointer(), isVolatile,
439 align, order);
440 }
441
442 /// Create a cir.complex.real_ptr operation that derives a pointer to the real
443 /// part of the complex value pointed to by the specified pointer value.
444 mlir::Value createComplexRealPtr(mlir::Location loc, mlir::Value value) {
445 auto srcPtrTy = mlir::cast<cir::PointerType>(value.getType());
446 auto srcComplexTy = mlir::cast<cir::ComplexType>(srcPtrTy.getPointee());
447 return cir::ComplexRealPtrOp::create(
448 *this, loc, getPointerTo(srcComplexTy.getElementType()), value);
449 }
450
451 Address createComplexRealPtr(mlir::Location loc, Address addr) {
452 return Address{createComplexRealPtr(loc, addr.getPointer()),
453 addr.getAlignment()};
454 }
455
456 /// Create a cir.complex.imag_ptr operation that derives a pointer to the
457 /// imaginary part of the complex value pointed to by the specified pointer
458 /// value.
459 mlir::Value createComplexImagPtr(mlir::Location loc, mlir::Value value) {
460 auto srcPtrTy = mlir::cast<cir::PointerType>(value.getType());
461 auto srcComplexTy = mlir::cast<cir::ComplexType>(srcPtrTy.getPointee());
462 return cir::ComplexImagPtrOp::create(
463 *this, loc, getPointerTo(srcComplexTy.getElementType()), value);
464 }
465
466 Address createComplexImagPtr(mlir::Location loc, Address addr) {
467 return Address{createComplexImagPtr(loc, addr.getPointer()),
468 addr.getAlignment()};
469 }
470
471 /// Create a cir.ptr_stride operation to get access to an array element.
472 /// \p idx is the index of the element to access, \p shouldDecay is true if
473 /// the result should decay to a pointer to the element type.
474 mlir::Value getArrayElement(mlir::Location arrayLocBegin,
475 mlir::Location arrayLocEnd, mlir::Value arrayPtr,
476 mlir::Type eltTy, mlir::Value idx,
477 bool shouldDecay);
478
479 /// Returns a decayed pointer to the first element of the array
480 /// pointed to by \p arrayPtr.
481 mlir::Value maybeBuildArrayDecay(mlir::Location loc, mlir::Value arrayPtr,
482 mlir::Type eltTy);
483
484 // Convert byte offset to sequence of high-level indices suitable for
485 // GlobalViewAttr. Ideally we shouldn't deal with low-level offsets at all
486 // but currently some parts of Clang AST, which we don't want to touch just
487 // yet, return them.
489 int64_t offset, mlir::Type ty, cir::CIRDataLayout layout,
491
492 /// Creates a versioned global variable. If the symbol is already taken, an ID
493 /// will be appended to the symbol. The returned global must always be queried
494 /// for its name so it can be referenced correctly.
495 [[nodiscard]] cir::GlobalOp
496 createVersionedGlobal(mlir::ModuleOp module, mlir::Location loc,
497 mlir::StringRef name, mlir::Type type, bool isConstant,
498 cir::GlobalLinkageKind linkage) {
499 // Create a unique name if the given name is already taken.
500 std::string uniqueName;
501 if (unsigned version = globalsVersioning[name.str()]++)
502 uniqueName = name.str() + "." + std::to_string(version);
503 else
504 uniqueName = name.str();
505
506 return createGlobal(module, loc, uniqueName, type, isConstant, linkage);
507 }
508
509 mlir::Value createSetBitfield(mlir::Location loc, mlir::Type resultType,
510 Address dstAddr, mlir::Type storageType,
511 mlir::Value src, const CIRGenBitFieldInfo &info,
512 bool isLvalueVolatile, bool useVolatile) {
513 unsigned offset = useVolatile ? info.volatileOffset : info.offset;
514
515 // If using AAPCS and the field is volatile, load with the size of the
516 // declared field
517 storageType =
518 useVolatile ? cir::IntType::get(storageType.getContext(),
519 info.volatileStorageSize, info.isSigned)
520 : storageType;
521 return cir::SetBitfieldOp::create(
522 *this, loc, resultType, dstAddr.getPointer(), storageType, src,
523 info.name, info.size, offset, info.isSigned, isLvalueVolatile,
524 dstAddr.getAlignment().getAsAlign().value());
525 }
526
527 mlir::Value createGetBitfield(mlir::Location loc, mlir::Type resultType,
528 Address addr, mlir::Type storageType,
529 const CIRGenBitFieldInfo &info,
530 bool isLvalueVolatile, bool useVolatile) {
531 unsigned offset = useVolatile ? info.volatileOffset : info.offset;
532
533 // If using AAPCS and the field is volatile, load with the size of the
534 // declared field
535 storageType =
536 useVolatile ? cir::IntType::get(storageType.getContext(),
537 info.volatileStorageSize, info.isSigned)
538 : storageType;
539 return cir::GetBitfieldOp::create(*this, loc, resultType, addr.getPointer(),
540 storageType, info.name, info.size, offset,
541 info.isSigned, isLvalueVolatile,
542 addr.getAlignment().getAsAlign().value());
543 }
544};
545
546} // namespace clang::CIRGen
547
548#endif
TokenType getType() const
Returns the token's type, e.g.
__device__ __2f16 float c
cir::PointerType getPointerTo(mlir::Type ty)
mlir::Value createPtrBitcast(mlir::Value src, mlir::Type newPointeeTy)
mlir::Value createIntCast(mlir::Value src, mlir::Type newTy)
mlir::Value createBitcast(mlir::Value src, mlir::Type newTy)
CIRBaseBuilderTy(mlir::MLIRContext &mlirContext)
cir::GlobalOp createGlobal(mlir::ModuleOp mlirModule, mlir::Location loc, mlir::StringRef name, mlir::Type type, bool isConstant, cir::GlobalLinkageKind linkage)
mlir::IntegerAttr getAlignmentAttr(clang::CharUnits alignment)
cir::ConstantOp getConstantInt(mlir::Location loc, mlir::Type ty, int64_t value)
mlir::TypedAttr getConstPtrAttr(mlir::Type type, int64_t value)
mlir::Value getPointer() const
Definition Address.h:81
mlir::Type getElementType() const
Definition Address.h:101
clang::CharUnits getAlignment() const
Definition Address.h:109
cir::RecordType getCompleteNamedRecordType(llvm::ArrayRef< mlir::Type > members, bool packed, bool padded, llvm::StringRef name)
Get a CIR named record type.
mlir::Value createComplexRealPtr(mlir::Location loc, mlir::Value value)
Create a cir.complex.real_ptr operation that derives a pointer to the real part of the complex value ...
cir::RecordType::RecordKind getRecordKind(const clang::TagTypeKind kind)
Get a CIR record kind from a AST declaration tag.
cir::IntType getSIntNTy(int n)
cir::ConstRecordAttr getAnonConstRecord(mlir::ArrayAttr arrayAttr, bool packed=false, bool padded=false, mlir::Type ty={})
cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc)
cir::ConstantOp getSInt64(uint64_t c, mlir::Location loc)
cir::RecordType getIncompleteRecordTy(llvm::StringRef name, const clang::RecordDecl *rd)
Get an incomplete CIR struct type.
cir::ConstantOp getUInt32(uint32_t c, mlir::Location loc)
cir::GlobalOp createVersionedGlobal(mlir::ModuleOp module, mlir::Location loc, mlir::StringRef name, mlir::Type type, bool isConstant, cir::GlobalLinkageKind linkage)
Creates a versioned global variable.
cir::PointerType getUInt8PtrTy()
std::string getUniqueRecordName(const std::string &baseName)
mlir::Attribute getConstRecordOrZeroAttr(mlir::ArrayAttr arrayAttr, bool packed=false, bool padded=false, mlir::Type type={})
cir::RecordType getAnonRecordTy(llvm::ArrayRef< mlir::Type > members, bool packed=false, bool padded=false)
Get a CIR anonymous record type.
mlir::Value createVTTAddrPoint(mlir::Location loc, mlir::Type retTy, mlir::FlatSymbolRefAttr sym, uint64_t offset)
Address createBaseClassAddr(mlir::Location loc, Address addr, mlir::Type destType, unsigned offset, bool assumeNotNull)
mlir::Value createComplexImagPtr(mlir::Location loc, mlir::Value value)
Create a cir.complex.imag_ptr operation that derives a pointer to the imaginary part of the complex v...
mlir::Value maybeBuildArrayDecay(mlir::Location loc, mlir::Value arrayPtr, mlir::Type eltTy)
Returns a decayed pointer to the first element of the array pointed to by arrayPtr.
mlir::Attribute getString(llvm::StringRef str, mlir::Type eltTy, std::optional< size_t > size)
Get a cir::ConstArrayAttr for a string literal.
cir::LoadOp createAlignedLoad(mlir::Location loc, mlir::Type ty, mlir::Value ptr, llvm::MaybeAlign align)
cir::ConstantOp getConstFP(mlir::Location loc, mlir::Type t, llvm::APFloat fpVal)
mlir::Value createFloatingCast(mlir::Value v, mlir::Type destType)
mlir::Value createFDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
Address createElementBitCast(mlir::Location loc, Address addr, mlir::Type destType)
Cast the element type of the given address to a different type, preserving information like the align...
mlir::Value createGetBitfield(mlir::Location loc, mlir::Type resultType, Address addr, mlir::Type storageType, const CIRGenBitFieldInfo &info, bool isLvalueVolatile, bool useVolatile)
bool isNullValue(mlir::Attribute attr) const
mlir::Value createSetBitfield(mlir::Location loc, mlir::Type resultType, Address dstAddr, mlir::Type storageType, mlir::Value src, const CIRGenBitFieldInfo &info, bool isLvalueVolatile, bool useVolatile)
Address createComplexRealPtr(mlir::Location loc, Address addr)
mlir::Value createFAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
CIRGenBuilderTy(mlir::MLIRContext &mlirContext, const CIRGenTypeCache &tc)
cir::RecordType getCompleteRecordType(mlir::ArrayAttr fields, bool packed=false, bool padded=false, llvm::StringRef name="")
cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal)
void computeGlobalViewIndicesFromFlatOffset(int64_t offset, mlir::Type ty, cir::CIRDataLayout layout, llvm::SmallVectorImpl< int64_t > &indices)
Address createComplexImagPtr(mlir::Location loc, Address addr)
mlir::Value createFMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::ConstantOp getSInt32(int32_t c, mlir::Location loc)
mlir::Value createVTTAddrPoint(mlir::Location loc, mlir::Type retTy, mlir::Value addr, uint64_t offset)
cir::LoadOp createLoad(mlir::Location loc, Address addr, bool isVolatile=false)
cir::LongDoubleType getLongDoubleTy(const llvm::fltSemantics &format) const
cir::ConstArrayAttr getConstArray(mlir::Attribute attrs, cir::ArrayType arrayTy) const
mlir::Value createFSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::IntType getUIntNTy(int n)
mlir::Value getArrayElement(mlir::Location arrayLocBegin, mlir::Location arrayLocEnd, mlir::Value arrayPtr, mlir::Type eltTy, mlir::Value idx, bool shouldDecay)
Create a cir.ptr_stride operation to get access to an array element.
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, Address dst, bool isVolatile=false, mlir::IntegerAttr align={}, cir::MemOrderAttr order={})
mlir::Value createNeg(mlir::Value value)
cir::LoadOp createAlignedLoad(mlir::Location loc, mlir::Type ty, mlir::Value ptr, clang::CharUnits align=clang::CharUnits::One())
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
Definition CharUnits.h:189
static CharUnits One()
One - Construct a CharUnits quantity of one.
Definition CharUnits.h:58
Represents a struct/union/class.
Definition Decl.h:4309
TagKind getTagKind() const
Definition Decl.h:3908
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
TagTypeKind
The kind of a tag type.
Definition TypeBase.h:5888
@ Interface
The "__interface" keyword.
Definition TypeBase.h:5893
@ Struct
The "struct" keyword.
Definition TypeBase.h:5890
@ Class
The "class" keyword.
Definition TypeBase.h:5899
@ Union
The "union" keyword.
Definition TypeBase.h:5896
@ Enum
The "enum" keyword.
Definition TypeBase.h:5902
static bool metaDataNode()
static bool targetCodeGenInfoGetNullPointer()
static bool fpConstraints()
static bool astRecordDeclAttr()
static bool fastMathFlags()
Record with information about how a bitfield should be accessed.
unsigned offset
The offset within a contiguous run of bitfields that are represented as a single "field" within the c...
unsigned volatileStorageSize
The storage size in bits which should be used when accessing this bitfield.
unsigned size
The total size of the bit-field, in bits.
unsigned isSigned
Whether the bit-field is signed.
unsigned volatileOffset
The offset within a contiguous run of bitfields that are represented as a single "field" within the c...
llvm::StringRef name
The name of a bitfield.
This structure provides a set of types that are commonly used during IR emission.