clang 23.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/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
16#include "mlir/IR/Attributes.h"
17#include "mlir/IR/Builders.h"
18#include "mlir/IR/BuiltinAttributes.h"
19#include "mlir/Support/LLVM.h"
22
25#include "llvm/ADT/APFloat.h"
26#include "llvm/ADT/STLExtras.h"
27#include "llvm/IR/FPEnv.h"
28
29namespace clang::CIRGen {
30
32 const CIRGenTypeCache &typeCache;
33 bool isFPConstrained = false;
34 llvm::fp::ExceptionBehavior defaultConstrainedExcept = llvm::fp::ebStrict;
35 llvm::RoundingMode defaultConstrainedRounding = llvm::RoundingMode::Dynamic;
36
37 llvm::StringMap<unsigned> recordNames;
38 llvm::StringMap<unsigned> globalsVersioning;
39
40public:
41 CIRGenBuilderTy(mlir::MLIRContext &mlirContext, const CIRGenTypeCache &tc)
42 : CIRBaseBuilderTy(mlirContext), typeCache(tc) {}
43
44 /// Get a cir::ConstArrayAttr for a string literal.
45 /// Note: This is different from what is returned by
46 /// mlir::Builder::getStringAttr() which is an mlir::StringAttr.
47 mlir::Attribute getString(llvm::StringRef str, mlir::Type eltTy,
48 std::optional<size_t> size,
49 bool ensureNullTerm = true) {
50 size_t finalSize = size.value_or(str.size());
51
52 size_t lastNonZeroPos = str.find_last_not_of('\0');
53 // If the string is full of null bytes, emit a #cir.zero rather than
54 // a #cir.const_array.
55 if (lastNonZeroPos == llvm::StringRef::npos) {
56 auto arrayTy = cir::ArrayType::get(eltTy, finalSize);
57 return cir::ZeroAttr::get(arrayTy);
58 }
59
60 // We emit trailing zeros for all trailing zeros, so the null-terminator in
61 // a constant is always in trailing zeros, and the null-terminator is
62 // skipped in the CIR representation.
63 size_t trailingZerosNum = finalSize - lastNonZeroPos - 1;
64 auto truncatedArrayTy =
65 cir::ArrayType::get(eltTy, finalSize - trailingZerosNum);
66 auto strAttr = mlir::StringAttr::get(str.drop_back(trailingZerosNum),
67 truncatedArrayTy);
68
69 // Most C strings are null terminated, so if we are ensuring there is one,
70 // grow the array size by 1 to add a trailing zero if necessary. The 'auto'
71 // calculation of trailing zeros (the difference between the provided string
72 // and the type) will ensure we get the count correct.
73 finalSize += (ensureNullTerm && trailingZerosNum == 0);
74
75 auto fullArrayTy = cir::ArrayType::get(eltTy, finalSize);
76 return cir::ConstArrayAttr::get(fullArrayTy, strAttr);
77 }
78
79 cir::ConstArrayAttr getConstArray(mlir::Attribute attrs,
80 cir::ArrayType arrayTy) const {
81 return cir::ConstArrayAttr::get(arrayTy, attrs);
82 }
83
84 mlir::Attribute getConstRecordOrZeroAttr(mlir::ArrayAttr arrayAttr,
85 bool packed = false,
86 bool padded = false,
87 mlir::Type type = {});
88
89 cir::ConstRecordAttr getAnonConstRecord(mlir::ArrayAttr arrayAttr,
90 bool packed = false,
91 bool padded = false,
92 mlir::Type ty = {}) {
94 for (auto &f : arrayAttr) {
95 auto ta = mlir::cast<mlir::TypedAttr>(f);
96 members.push_back(ta.getType());
97 }
98
99 if (!ty)
100 ty = getAnonRecordTy(members, packed, padded);
101
102 auto sTy = mlir::cast<cir::RecordType>(ty);
103 return cir::ConstRecordAttr::get(sTy, arrayAttr);
104 }
105
106 cir::TypeInfoAttr getTypeInfo(mlir::ArrayAttr fieldsAttr) {
107 cir::ConstRecordAttr anonRecord = getAnonConstRecord(fieldsAttr);
108 return cir::TypeInfoAttr::get(anonRecord.getType(), fieldsAttr);
109 }
110
111 std::string getUniqueAnonRecordName() { return getUniqueRecordName("anon"); }
112
113 std::string getUniqueRecordName(const std::string &baseName) {
114 auto it = recordNames.find(baseName);
115 if (it == recordNames.end()) {
116 recordNames[baseName] = 0;
117 return baseName;
118 }
119
120 return baseName + "." + std::to_string(recordNames[baseName]++);
121 }
122
123 //
124 // Floating point specific helpers
125 // -------------------------------
126 //
127
128 /// Enable/Disable use of constrained floating point math. When enabled the
129 /// CreateF<op>() calls instead create constrained floating point intrinsic
130 /// calls. Fast math flags are unaffected by this setting.
131 void setIsFPConstrained(bool isCon) { isFPConstrained = isCon; }
132
133 /// Query for the use of constrained floating point math
134 bool getIsFPConstrained() const { return isFPConstrained; }
135
136 /// Set the exception handling to be used with constrained floating point
137 void setDefaultConstrainedExcept(llvm::fp::ExceptionBehavior newExcept) {
138 assert(llvm::convertExceptionBehaviorToStr(newExcept) &&
139 "Garbage strict exception behavior!");
140 defaultConstrainedExcept = newExcept;
141 }
142
143 /// Get the exception handling used with constrained floating point
144 llvm::fp::ExceptionBehavior getDefaultConstrainedExcept() const {
145 return defaultConstrainedExcept;
146 }
147
148 /// Set the rounding mode handling to be used with constrained floating point
149 void setDefaultConstrainedRounding(llvm::RoundingMode newRounding) {
150 assert(llvm::convertRoundingModeToStr(newRounding) &&
151 "Garbage strict rounding mode!");
152 defaultConstrainedRounding = newRounding;
153 }
154
155 /// Get the rounding mode handling used with constrained floating point
156 llvm::RoundingMode getDefaultConstrainedRounding() const {
157 return defaultConstrainedRounding;
158 }
159
160 cir::LongDoubleType getLongDoubleTy(const llvm::fltSemantics &format) const {
161 if (&format == &llvm::APFloat::IEEEdouble())
162 return cir::LongDoubleType::get(getContext(), typeCache.doubleTy);
163 if (&format == &llvm::APFloat::x87DoubleExtended())
164 return cir::LongDoubleType::get(getContext(), typeCache.fP80Ty);
165 if (&format == &llvm::APFloat::IEEEquad())
166 return cir::LongDoubleType::get(getContext(), typeCache.fP128Ty);
167 if (&format == &llvm::APFloat::PPCDoubleDouble())
168 llvm_unreachable("NYI: PPC double-double format for long double");
169 llvm_unreachable("Unsupported format for long double");
170 }
171
172 mlir::Type getPtrToVPtrType() {
173 return getPointerTo(cir::VPtrType::get(getContext()));
174 }
175
176 cir::FuncType getFuncType(llvm::ArrayRef<mlir::Type> params, mlir::Type retTy,
177 bool isVarArg = false) {
178 return cir::FuncType::get(params, retTy, isVarArg);
179 }
180
181 /// Get a CIR record kind from a AST declaration tag.
182 /// Returns true if the tag kind represents a C++ class (as opposed to a
183 /// plain struct).
186 }
187
188 /// Returns true if the tag kind is a union.
191 }
192
193 /// Get a CIR named record type.
194 ///
195 /// If a record already exists and is complete, but the client tries to fetch
196 /// it with a different set of attributes, this method will crash.
198 bool packed, bool padded,
199 llvm::StringRef name) {
200 const auto nameAttr = getStringAttr(name);
202
203 // Create or get the struct type (named anonymous struct helper — always
204 // struct, never class or union at this call site).
205 auto type = cir::StructType::get(getContext(), members, nameAttr, packed,
206 padded, /*is_class=*/false);
207
208 // If we found an existing type, verify that either it is incomplete or
209 // it matches the requested attributes.
210 assert(!type.isIncomplete() ||
211 (type.getMembers() == members && type.getPacked() == packed &&
212 type.getPadded() == padded));
213
214 // Complete an incomplete record or ensure the existing complete record
215 // matches the requested attributes.
216 type.complete(members, packed, padded);
217
218 return type;
219 }
220
221 cir::RecordType getCompleteRecordType(mlir::ArrayAttr fields,
222 bool packed = false,
223 bool padded = false,
224 llvm::StringRef name = "");
225
226 /// Get an incomplete CIR record type. If we have a complete record
227 /// declaration, we may create an incomplete type and then add the
228 /// members, so \p rd here may be complete.
230 const clang::RecordDecl *rd) {
231 const mlir::StringAttr nameAttr = getStringAttr(name);
232 if (rd && tagKindIsUnion(rd->getTagKind()))
233 return cir::UnionType::get(getContext(), nameAttr);
234 bool is_class = rd && tagKindIsClass(rd->getTagKind());
235 return cir::StructType::get(getContext(), nameAttr, is_class);
236 }
237
238 //
239 // Operation creation helpers
240 // --------------------------
241 //
243 cir::CopyOp createCopy(Address dst, Address src, bool isVolatile = false,
244 bool skipTailPadding = false) {
245 cir::CopyOp op = createCopy(dst.getPointer(), src.getPointer(), isVolatile,
246 skipTailPadding);
247 op.setDstAlignment(dst.getAlignment().getQuantity());
248 op.setSrcAlignment(src.getAlignment().getQuantity());
249 return op;
250 }
251
252 cir::MemCpyOp createMemCpy(mlir::Location loc, mlir::Value dst,
253 mlir::Value src, mlir::Value len) {
254 return cir::MemCpyOp::create(*this, loc, dst, src, len);
255 }
256
257 cir::MemMoveOp createMemMove(mlir::Location loc, mlir::Value dst,
258 mlir::Value src, mlir::Value len) {
259 return cir::MemMoveOp::create(*this, loc, dst, src, len);
260 }
261
262 cir::MemSetOp createMemSet(mlir::Location loc, mlir::Value dst,
263 mlir::Value val, mlir::Value len) {
264 assert(val.getType() == getUInt8Ty());
265 return cir::MemSetOp::create(*this, loc, dst, {}, val, len);
266 }
267
268 cir::MemSetOp createMemSet(mlir::Location loc, Address dst, mlir::Value val,
269 mlir::Value len) {
270 mlir::IntegerAttr align = getAlignmentAttr(dst.getAlignment());
271 assert(val.getType() == getUInt8Ty());
272 return cir::MemSetOp::create(*this, loc, dst.getPointer(), align, val, len);
273 }
274 // ---------------------------
275
276 cir::DataMemberAttr getDataMemberAttr(cir::DataMemberType ty,
278 return cir::DataMemberAttr::get(ty, path);
279 }
280
281 cir::DataMemberAttr getNullDataMemberAttr(cir::DataMemberType ty) {
282 return cir::DataMemberAttr::get(ty);
283 }
284
285 // Return true if the value is a null constant such as null pointer, (+0.0)
286 // for floating-point or zero initializer
287 bool isNullValue(mlir::Attribute attr) const {
288 if (mlir::isa<cir::ZeroAttr>(attr))
289 return true;
290
291 if (const auto ptrVal = mlir::dyn_cast<cir::ConstPtrAttr>(attr))
292 return ptrVal.isNullValue();
293
294 if (const auto intVal = mlir::dyn_cast<cir::IntAttr>(attr))
295 return intVal.isNullValue();
296
297 if (const auto boolVal = mlir::dyn_cast<cir::BoolAttr>(attr))
298 return !boolVal.getValue();
299
300 if (auto fpAttr = mlir::dyn_cast<cir::FPAttr>(attr)) {
301 auto fpVal = fpAttr.getValue();
302 bool ignored;
303 llvm::APFloat fv(+0.0);
304 fv.convert(fpVal.getSemantics(), llvm::APFloat::rmNearestTiesToEven,
305 &ignored);
306 return fv.bitwiseIsEqual(fpVal);
307 }
308 if (const auto recordVal = mlir::dyn_cast<cir::ConstRecordAttr>(attr)) {
309 for (const auto elt : recordVal.getMembers()) {
310 // FIXME(cir): the record's ID should not be considered a member.
311 if (mlir::isa<mlir::StringAttr>(elt))
312 continue;
313 if (!isNullValue(elt))
314 return false;
315 }
316 return true;
317 }
318
319 if (const auto arrayVal = mlir::dyn_cast<cir::ConstArrayAttr>(attr)) {
320 if (mlir::isa<mlir::StringAttr>(arrayVal.getElts()))
321 return false;
322
323 return llvm::all_of(
324 mlir::cast<mlir::ArrayAttr>(arrayVal.getElts()),
325 [&](const mlir::Attribute &elt) { return isNullValue(elt); });
326 }
327 return false;
328 }
329
330 //
331 // Type helpers
332 // ------------
333 //
334 cir::IntType getUIntNTy(int n) {
335 switch (n) {
336 case 8:
337 return getUInt8Ty();
338 case 16:
339 return getUInt16Ty();
340 case 32:
341 return getUInt32Ty();
342 case 64:
343 return getUInt64Ty();
344 default:
345 return cir::IntType::get(getContext(), n, false);
346 }
347 }
348
349 cir::IntType getSIntNTy(int n) {
350 switch (n) {
351 case 8:
352 return getSInt8Ty();
353 case 16:
354 return getSInt16Ty();
355 case 32:
356 return getSInt32Ty();
357 case 64:
358 return getSInt64Ty();
359 default:
360 return cir::IntType::get(getContext(), n, true);
361 }
362 }
363
364 cir::VoidType getVoidTy() { return typeCache.voidTy; }
365
366 cir::IntType getSInt8Ty() { return typeCache.sInt8Ty; }
367 cir::IntType getSInt16Ty() { return typeCache.sInt16Ty; }
368 cir::IntType getSInt32Ty() { return typeCache.sInt32Ty; }
369 cir::IntType getSInt64Ty() { return typeCache.sInt64Ty; }
370
371 cir::IntType getUInt8Ty() { return typeCache.uInt8Ty; }
372 cir::IntType getUInt16Ty() { return typeCache.uInt16Ty; }
373 cir::IntType getUInt32Ty() { return typeCache.uInt32Ty; }
374 cir::IntType getUInt64Ty() { return typeCache.uInt64Ty; }
375
376 cir::FP16Type getFp16Ty() { return typeCache.fP16Ty; }
377 cir::BF16Type getBfloat6Ty() { return typeCache.bFloat16Ty; }
378 cir::SingleType getSingleTy() { return typeCache.floatTy; }
379 cir::DoubleType getDoubleTy() { return typeCache.doubleTy; }
380
381 cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal);
382
383 cir::ConstantOp getConstInt(mlir::Location loc, llvm::APInt intVal,
384 bool isUnsigned = true);
385
386 cir::ConstantOp getConstInt(mlir::Location loc, mlir::Type t, uint64_t c);
387
388 cir::ConstantOp getConstFP(mlir::Location loc, mlir::Type t,
389 llvm::APFloat fpVal);
390
391 bool isInt8Ty(mlir::Type i) {
392 return i == typeCache.uInt8Ty || i == typeCache.sInt8Ty;
393 }
394 bool isInt16Ty(mlir::Type i) {
395 return i == typeCache.uInt16Ty || i == typeCache.sInt16Ty;
396 }
397 bool isInt32Ty(mlir::Type i) {
398 return i == typeCache.uInt32Ty || i == typeCache.sInt32Ty;
399 }
400 bool isInt64Ty(mlir::Type i) {
401 return i == typeCache.uInt64Ty || i == typeCache.sInt64Ty;
402 }
403 bool isInt(mlir::Type i) { return mlir::isa<cir::IntType>(i); }
404
405 cir::IntType getExtendedIntTy(cir::IntType ty, bool isSigned) {
406 switch (ty.getWidth()) {
407 case 8:
408 return isSigned ? typeCache.sInt16Ty : typeCache.uInt16Ty;
409 case 16:
410 return isSigned ? typeCache.sInt32Ty : typeCache.uInt32Ty;
411 case 32:
412 return isSigned ? typeCache.sInt64Ty : typeCache.uInt64Ty;
413 default:
414 llvm_unreachable("NYI");
415 }
416 }
417
418 cir::IntType getTruncatedIntTy(cir::IntType ty, bool isSigned) {
419 switch (ty.getWidth()) {
420 case 16:
421 return isSigned ? typeCache.sInt8Ty : typeCache.uInt8Ty;
422 case 32:
423 return isSigned ? typeCache.sInt16Ty : typeCache.uInt16Ty;
424 case 64:
425 return isSigned ? typeCache.sInt32Ty : typeCache.uInt32Ty;
426 default:
427 llvm_unreachable("NYI");
428 }
429 }
430
431 cir::VectorType
432 getExtendedOrTruncatedElementVectorType(cir::VectorType vt, bool isExtended,
433 bool isSigned = false) {
434 auto elementTy = mlir::dyn_cast_or_null<cir::IntType>(vt.getElementType());
435 assert(elementTy && "expected int vector");
436 return cir::VectorType::get(isExtended
437 ? getExtendedIntTy(elementTy, isSigned)
438 : getTruncatedIntTy(elementTy, isSigned),
439 vt.getSize());
440 }
441
442 // Fetch the type representing a pointer to unsigned int8 values.
443 cir::PointerType getUInt8PtrTy() { return typeCache.uInt8PtrTy; }
444
445 /// Get a CIR anonymous struct type.
447 bool packed = false, bool padded = false) {
449 return cir::StructType::get(getContext(), members, packed, padded,
450 /*is_class=*/false);
451 }
452
453 //===--------------------------------------------------------------------===//
454 // Constant creation helpers
455 //===--------------------------------------------------------------------===//
456 cir::ConstantOp getSInt32(int32_t c, mlir::Location loc) {
457 return getConstantInt(loc, getSInt32Ty(), c);
458 }
459 cir::ConstantOp getUInt32(uint32_t c, mlir::Location loc) {
460 return getConstantInt(loc, getUInt32Ty(), c);
461 }
462 cir::ConstantOp getSInt64(uint64_t c, mlir::Location loc) {
463 return getConstantInt(loc, getSInt64Ty(), c);
464 }
465 cir::ConstantOp getUInt64(uint64_t c, mlir::Location loc) {
466 return getConstantInt(loc, getUInt64Ty(), c);
467 }
468
469 cir::ConstantOp getZero(mlir::Location loc, mlir::Type ty) {
470 // TODO: dispatch creation for primitive types.
471 assert((mlir::isa<cir::RecordType>(ty) || mlir::isa<cir::ArrayType>(ty) ||
472 mlir::isa<cir::VectorType>(ty)) &&
473 "NYI for other types");
474 return cir::ConstantOp::create(*this, loc, cir::ZeroAttr::get(ty));
475 }
476
477 //===--------------------------------------------------------------------===//
478 // UnaryOp creation helpers
479 //===--------------------------------------------------------------------===//
480 mlir::Value createNeg(mlir::Location loc, mlir::Value value,
481 bool nsw = false) {
482
483 if (auto intTy = mlir::dyn_cast<cir::IntType>(value.getType())) {
484 // Source is a unsigned integer: first cast it to signed.
485 if (intTy.isUnsigned())
486 value = createIntCast(value, getSIntNTy(intTy.getWidth()));
487 return createMinus(loc, value, nsw);
488 }
489
490 llvm_unreachable("negation for the given type is NYI");
491 }
492
493 //===--------------------------------------------------------------------===//
494 // CastOp creation helpers
495 //===--------------------------------------------------------------------===//
496
497 // TODO: split this to createFPExt/createFPTrunc when we have dedicated cast
498 // operations.
499 mlir::Value createFloatingCast(mlir::Value v, mlir::Type destType) {
501
502 return cir::CastOp::create(*this, v.getLoc(), destType,
503 cir::CastKind::floating, v);
504 }
505
506 mlir::Value createDynCast(mlir::Location loc, mlir::Value src,
507 cir::PointerType destType, bool isRefCast,
508 cir::DynamicCastInfoAttr info) {
509 auto castKind =
510 isRefCast ? cir::DynamicCastKind::Ref : cir::DynamicCastKind::Ptr;
511 return cir::DynamicCastOp::create(*this, loc, destType, castKind, src, info,
512 /*relative_layout=*/false);
513 }
514
515 mlir::Value createDynCastToVoid(mlir::Location loc, mlir::Value src,
516 bool vtableUseRelativeLayout) {
517 // TODO(cir): consider address space here.
519 cir::PointerType destTy = getVoidPtrTy();
520 return cir::DynamicCastOp::create(
521 *this, loc, destTy, cir::DynamicCastKind::Ptr, src,
522 cir::DynamicCastInfoAttr{}, vtableUseRelativeLayout);
523 }
524
525 //===--------------------------------------------------------------------===//
526 // Address creation helpers
527 //===--------------------------------------------------------------------===//
528 Address createBaseClassAddr(mlir::Location loc, Address addr,
529 mlir::Type destType, unsigned offset,
530 bool assumeNotNull) {
531 if (destType == addr.getElementType())
532 return addr;
533
534 auto ptrTy = getPointerTo(destType);
535 auto baseAddr =
536 cir::BaseClassAddrOp::create(*this, loc, ptrTy, addr.getPointer(),
537 mlir::APInt(64, offset), assumeNotNull);
538 return Address(baseAddr, destType, addr.getAlignment());
539 }
540
541 Address createDerivedClassAddr(mlir::Location loc, Address addr,
542 mlir::Type destType, unsigned offset,
543 bool assumeNotNull) {
544 if (destType == addr.getElementType())
545 return addr;
546
547 cir::PointerType ptrTy = getPointerTo(destType);
548 auto derivedAddr =
549 cir::DerivedClassAddrOp::create(*this, loc, ptrTy, addr.getPointer(),
550 mlir::APInt(64, offset), assumeNotNull);
551 return Address(derivedAddr, destType, addr.getAlignment());
552 }
553
554 //===--------------------------------------------------------------------===//
555 // Virtual Address creation helpers
556 //===--------------------------------------------------------------------===//
557 mlir::Value createVTTAddrPoint(mlir::Location loc, mlir::Type retTy,
558 mlir::Value addr, uint64_t offset) {
559 return cir::VTTAddrPointOp::create(*this, loc, retTy,
560 mlir::FlatSymbolRefAttr{}, addr, offset);
561 }
562
563 mlir::Value createVTTAddrPoint(mlir::Location loc, mlir::Type retTy,
564 mlir::FlatSymbolRefAttr sym, uint64_t offset) {
565 return cir::VTTAddrPointOp::create(*this, loc, retTy, sym, mlir::Value{},
566 offset);
567 }
568
569 //===--------------------------------------------------------------------===//
570 // Other creation helpers
571 //===--------------------------------------------------------------------===//
572 cir::IsFPClassOp createIsFPClass(mlir::Location loc, mlir::Value src,
573 cir::FPClassTest flags) {
574 // FPClassTest occupies bits 0-9 (fcAllFlags). Sema rejects an
575 // out-of-range __builtin_isfpclass mask, so any extra bit here is an
576 // internal error; assert and mask it off so lowering stays well-formed.
577 uint32_t raw = static_cast<uint32_t>(flags);
578 uint32_t all = static_cast<uint32_t>(cir::FPClassTest::All);
579 assert((raw & ~all) == 0 && "FPClassTest mask has bits outside 0-9");
580 flags = static_cast<cir::FPClassTest>(raw & all);
581 return cir::IsFPClassOp::create(*this, loc, src, flags);
582 }
583
584 /// Cast the element type of the given address to a different type,
585 /// preserving information like the alignment.
586 Address createElementBitCast(mlir::Location loc, Address addr,
587 mlir::Type destType) {
588 if (destType == addr.getElementType())
589 return addr;
590
591 auto ptrTy = getPointerTo(destType);
592 return Address(createBitcast(loc, addr.getPointer(), ptrTy), destType,
593 addr.getAlignment());
594 }
595
596 cir::LoadOp createLoad(mlir::Location loc, Address addr,
597 bool isVolatile = false, bool isNontemporal = false) {
598 mlir::IntegerAttr align = getAlignmentAttr(addr.getAlignment());
599 return cir::LoadOp::create(*this, loc, addr.getPointer(), /*isDeref=*/false,
600 isVolatile, isNontemporal,
601 /*alignment=*/align,
602 /*sync_scope=*/cir::SyncScopeKindAttr{},
603 /*mem_order=*/cir::MemOrderAttr{},
604 /*invariant=*/false);
605 }
606
607 cir::LoadOp createAlignedLoad(mlir::Location loc, mlir::Type ty,
608 mlir::Value ptr, llvm::MaybeAlign align) {
609 if (ty != mlir::cast<cir::PointerType>(ptr.getType()).getPointee())
610 ptr = createPtrBitcast(ptr, ty);
611 uint64_t alignment = align ? align->value() : 0;
612 mlir::IntegerAttr alignAttr = getAlignmentAttr(alignment);
613 return cir::LoadOp::create(*this, loc, ptr, /*isDeref=*/false,
614 /*isVolatile=*/false, /*isNontemporal=*/false,
615 alignAttr,
616 /*sync_scope=*/cir::SyncScopeKindAttr{},
617 /*mem_order=*/cir::MemOrderAttr{},
618 /*invariant=*/false);
619 }
620
621 cir::LoadOp
622 createAlignedLoad(mlir::Location loc, mlir::Type ty, mlir::Value ptr,
624 return createAlignedLoad(loc, ty, ptr, align.getAsAlign());
625 }
626
627 cir::StoreOp createStore(mlir::Location loc, mlir::Value val, Address dst,
628 bool isVolatile = false, bool isNontemporal = false,
629 mlir::IntegerAttr align = {},
630 cir::SyncScopeKindAttr scope = {},
631 cir::MemOrderAttr order = {}) {
632 if (!align)
633 align = getAlignmentAttr(dst.getAlignment());
634 return CIRBaseBuilderTy::createStore(loc, val, dst.getPointer(), isVolatile,
635 isNontemporal, align, scope, order);
636 }
637
638 /// Create a cir.complex.real_ptr operation that derives a pointer to the real
639 /// part of the complex value pointed to by the specified pointer value.
640 mlir::Value createComplexRealPtr(mlir::Location loc, mlir::Value value) {
641 auto srcPtrTy = mlir::cast<cir::PointerType>(value.getType());
642 auto srcComplexTy = mlir::cast<cir::ComplexType>(srcPtrTy.getPointee());
643 return cir::ComplexRealPtrOp::create(
644 *this, loc, getPointerTo(srcComplexTy.getElementType()), value);
645 }
646
647 Address createComplexRealPtr(mlir::Location loc, Address addr) {
648 return Address{createComplexRealPtr(loc, addr.getPointer()),
649 addr.getAlignment()};
650 }
651
652 /// Create a cir.complex.imag_ptr operation that derives a pointer to the
653 /// imaginary part of the complex value pointed to by the specified pointer
654 /// value.
655 mlir::Value createComplexImagPtr(mlir::Location loc, mlir::Value value) {
656 auto srcPtrTy = mlir::cast<cir::PointerType>(value.getType());
657 auto srcComplexTy = mlir::cast<cir::ComplexType>(srcPtrTy.getPointee());
658 return cir::ComplexImagPtrOp::create(
659 *this, loc, getPointerTo(srcComplexTy.getElementType()), value);
660 }
661
662 Address createComplexImagPtr(mlir::Location loc, Address addr) {
663 return Address{createComplexImagPtr(loc, addr.getPointer()),
664 addr.getAlignment()};
665 }
666
668 Address createGetMember(mlir::Location loc, Address base,
669 llvm::StringRef name, unsigned index) {
670 auto recordTy = mlir::cast<cir::RecordType>(base.getElementType());
671
672 assert(index < recordTy.getMembers().size() &&
673 "member index out of bounds");
674 mlir::Type memberTy = recordTy.getMembers()[index];
675 mlir::Type memberPtrTy = getPointerTo(memberTy);
676
677 auto moduleOp =
678 getInsertionBlock()->getParentOp()->getParentOfType<mlir::ModuleOp>();
679 mlir::DataLayout layout(moduleOp);
680 auto memberOffset =
681 CharUnits::fromQuantity(recordTy.getElementOffset(layout, index));
682
683 mlir::Value memberPtr =
684 createGetMember(loc, memberPtrTy, base.getBasePointer(), name, index);
685 return Address(memberPtr, memberTy,
686 base.getAlignment().alignmentAtOffset(memberOffset),
687 base.isKnownNonNull());
688 }
689
690 cir::GetRuntimeMemberOp createGetIndirectMember(mlir::Location loc,
691 mlir::Value objectPtr,
692 mlir::Value memberPtr) {
693 auto memberPtrTy = mlir::cast<cir::DataMemberType>(memberPtr.getType());
694
695 // TODO(cir): consider address space.
697 cir::PointerType resultTy = getPointerTo(memberPtrTy.getMemberTy());
698
699 return cir::GetRuntimeMemberOp::create(*this, loc, resultTy, objectPtr,
700 memberPtr);
701 }
702
703 /// Create a cir.ptr_stride operation to get access to an array element.
704 /// \p idx is the index of the element to access, \p shouldDecay is true if
705 /// the result should decay to a pointer to the element type.
706 mlir::Value getArrayElement(mlir::Location arrayLocBegin,
707 mlir::Location arrayLocEnd, mlir::Value arrayPtr,
708 mlir::Type eltTy, mlir::Value idx,
709 bool shouldDecay);
710
711 /// Returns a decayed pointer to the first element of the array
712 /// pointed to by \p arrayPtr.
713 mlir::Value maybeBuildArrayDecay(mlir::Location loc, mlir::Value arrayPtr,
714 mlir::Type eltTy);
715
716 // Convert byte offset to sequence of high-level indices suitable for
717 // GlobalViewAttr. Ideally we shouldn't deal with low-level offsets at all
718 // but currently some parts of Clang AST, which we don't want to touch just
719 // yet, return them.
721 int64_t offset, mlir::Type ty, cir::CIRDataLayout layout,
723
724 // Convert high-level indices (e.g. from GlobalViewAttr) to byte offset.
726 mlir::Type ty,
728
729 /// Creates a versioned global variable. If the symbol is already taken, an ID
730 /// will be appended to the symbol. The returned global must always be queried
731 /// for its name so it can be referenced correctly.
732 [[nodiscard]] cir::GlobalOp
733 createVersionedGlobal(mlir::ModuleOp module, mlir::Location loc,
734 mlir::StringRef name, mlir::Type type, bool isConstant,
735 cir::GlobalLinkageKind linkage,
736 mlir::ptr::MemorySpaceAttrInterface addrSpace = {}) {
737 // Create a unique name if the given name is already taken.
738 std::string uniqueName;
739 if (unsigned version = globalsVersioning[name.str()]++)
740 uniqueName = name.str() + "." + std::to_string(version);
741 else
742 uniqueName = name.str();
743
744 return createGlobal(module, loc, uniqueName, type, isConstant, linkage,
745 addrSpace);
746 }
747
748 cir::StackSaveOp createStackSave(mlir::Location loc, mlir::Type ty) {
749 return cir::StackSaveOp::create(*this, loc, ty);
750 }
751
752 cir::StackRestoreOp createStackRestore(mlir::Location loc, mlir::Value v) {
753 return cir::StackRestoreOp::create(*this, loc, v);
754 }
755
757 mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
758 const llvm::APSInt &ltRes, const llvm::APSInt &eqRes,
759 const llvm::APSInt &gtRes, cir::CmpOrdering ordering) {
760 assert(ltRes.getBitWidth() == eqRes.getBitWidth() &&
761 ltRes.getBitWidth() == gtRes.getBitWidth() &&
762 "the three comparison results must have the same bit width");
763 assert((ordering == cir::CmpOrdering::Strong ||
764 ordering == cir::CmpOrdering::Weak) &&
765 "total ordering must be strong or weak");
766 cir::IntType cmpResultTy = getSIntNTy(ltRes.getBitWidth());
767 auto infoAttr = cir::CmpThreeWayInfoAttr::get(
768 getContext(), ordering, ltRes.getSExtValue(), eqRes.getSExtValue(),
769 gtRes.getSExtValue());
770 return cir::CmpThreeWayOp::create(*this, loc, cmpResultTy, lhs, rhs,
771 infoAttr);
772 }
773
775 mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
776 const llvm::APSInt &ltRes, const llvm::APSInt &eqRes,
777 const llvm::APSInt &gtRes, const llvm::APSInt &unorderedRes) {
778 assert(ltRes.getBitWidth() == eqRes.getBitWidth() &&
779 ltRes.getBitWidth() == gtRes.getBitWidth() &&
780 ltRes.getBitWidth() == unorderedRes.getBitWidth() &&
781 "the four comparison results must have the same bit width");
782 cir::IntType cmpResultTy = getSIntNTy(ltRes.getBitWidth());
783 auto infoAttr = cir::CmpThreeWayInfoAttr::get(
784 getContext(), ltRes.getSExtValue(), eqRes.getSExtValue(),
785 gtRes.getSExtValue(), unorderedRes.getSExtValue());
786 return cir::CmpThreeWayOp::create(*this, loc, cmpResultTy, lhs, rhs,
787 infoAttr);
788 }
789
790 mlir::Value createSetBitfield(mlir::Location loc, mlir::Type resultType,
791 Address dstAddr, mlir::Type storageType,
792 mlir::Value src, const CIRGenBitFieldInfo &info,
793 bool isLvalueVolatile, bool useVolatile) {
794 unsigned offset = useVolatile ? info.volatileOffset : info.offset;
795
796 // If using AAPCS and the field is volatile, load with the size of the
797 // declared field
798 storageType =
799 useVolatile ? cir::IntType::get(storageType.getContext(),
800 info.volatileStorageSize, info.isSigned)
801 : storageType;
802 return cir::SetBitfieldOp::create(
803 *this, loc, resultType, dstAddr.getPointer(), storageType, src,
804 info.name, info.size, offset, info.isSigned, isLvalueVolatile,
805 dstAddr.getAlignment().getAsAlign().value());
806 }
807
808 mlir::Value createGetBitfield(mlir::Location loc, mlir::Type resultType,
809 Address addr, mlir::Type storageType,
810 const CIRGenBitFieldInfo &info,
811 bool isLvalueVolatile, bool useVolatile) {
812 unsigned offset = useVolatile ? info.volatileOffset : info.offset;
813
814 // If using AAPCS and the field is volatile, load with the size of the
815 // declared field
816 storageType =
817 useVolatile ? cir::IntType::get(storageType.getContext(),
818 info.volatileStorageSize, info.isSigned)
819 : storageType;
820 return cir::GetBitfieldOp::create(*this, loc, resultType, addr.getPointer(),
821 storageType, info.name, info.size, offset,
822 info.isSigned, isLvalueVolatile,
823 addr.getAlignment().getAsAlign().value());
824 }
825
826 mlir::Value createMaskedLoad(mlir::Location loc, mlir::Type ty,
827 mlir::Value ptr, llvm::Align alignment,
828 mlir::Value mask, mlir::Value passThru) {
829 assert(mlir::isa<cir::VectorType>(ty) && "Type should be vector");
830 assert(mask && "Mask should not be all-ones (null)");
831
832 if (!passThru)
833 passThru = this->getConstant(loc, cir::PoisonAttr::get(ty));
834
835 auto alignAttr =
836 this->getI64IntegerAttr(static_cast<int64_t>(alignment.value()));
837
838 return cir::VecMaskedLoadOp::create(*this, loc, ty, ptr, mask, passThru,
839 alignAttr);
840 }
841
842 cir::VecShuffleOp
843 createVecShuffle(mlir::Location loc, mlir::Value vec1, mlir::Value vec2,
845 auto vecType = mlir::cast<cir::VectorType>(vec1.getType());
846 auto resultTy =
847 cir::VectorType::get(vecType.getElementType(), maskAttrs.size());
848 return cir::VecShuffleOp::create(*this, loc, resultTy, vec1, vec2,
849 getArrayAttr(maskAttrs));
850 }
851
852 cir::VecShuffleOp createVecShuffle(mlir::Location loc, mlir::Value vec1,
853 mlir::Value vec2,
855 auto maskAttrs = llvm::to_vector_of<mlir::Attribute>(
856 llvm::map_range(mask, [&](int32_t idx) {
857 return cir::IntAttr::get(getSInt32Ty(), idx);
858 }));
859 return createVecShuffle(loc, vec1, vec2, maskAttrs);
860 }
861
862 cir::VecShuffleOp createVecShuffle(mlir::Location loc, mlir::Value vec1,
864 /// Create a unary shuffle. The second vector operand of the IR instruction
865 /// is poison.
866 cir::ConstantOp poison =
867 getConstant(loc, cir::PoisonAttr::get(vec1.getType()));
868 return createVecShuffle(loc, vec1, poison, mask);
869 }
870
871 template <typename... Operands>
872 mlir::Value emitIntrinsicCallOp(mlir::Location loc, const llvm::StringRef str,
873 const mlir::Type &resTy, Operands &&...op) {
874 return cir::LLVMIntrinsicCallOp::create(*this, loc,
875 this->getStringAttr(str), resTy,
876 std::forward<Operands>(op)...)
877 .getResult();
878 }
879};
880
881} // namespace clang::CIRGen
882
883#endif
static bool isUnsigned(SValBuilder &SVB, NonLoc Value)
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
cir::CopyOp createCopy(mlir::Value dst, mlir::Value src, bool isVolatile=false, bool skipTailPadding=false)
Create a copy with inferred length.
cir::GetMemberOp createGetMember(mlir::Location loc, mlir::Type resultTy, mlir::Value base, llvm::StringRef name, unsigned index)
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, mlir::Value dst, bool isVolatile=false, bool isNontemporal=false, mlir::IntegerAttr align={}, cir::SyncScopeKindAttr scope={}, cir::MemOrderAttr order={})
cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr)
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)
mlir::IntegerAttr getAlignmentAttr(clang::CharUnits alignment)
mlir::Value createMinus(mlir::Location loc, mlir::Value input, bool nsw=false)
cir::ConstantOp getConstantInt(mlir::Location loc, mlir::Type ty, int64_t value)
cir::PointerType getVoidPtrTy(clang::LangAS langAS=clang::LangAS::Default)
cir::GlobalOp createGlobal(mlir::ModuleOp mlirModule, mlir::Location loc, mlir::StringRef name, mlir::Type type, bool isConstant, cir::GlobalLinkageKind linkage, mlir::ptr::MemorySpaceAttrInterface addrSpace)
C++ view class that accepts both !cir.struct and !cir.union types.
Definition CIRTypes.h:93
bool isKnownNonNull() const
Whether the pointer is known not to be null.
Definition Address.h:168
mlir::Value getPointer() const
Definition Address.h:98
mlir::Type getElementType() const
Definition Address.h:125
clang::CharUnits getAlignment() const
Definition Address.h:138
mlir::Value getBasePointer() const
Definition Address.h:103
cir::MemMoveOp createMemMove(mlir::Location loc, mlir::Value dst, mlir::Value src, mlir::Value len)
cir::RecordType getCompleteNamedRecordType(llvm::ArrayRef< mlir::Type > members, bool packed, bool padded, llvm::StringRef name)
Get a CIR named record type.
cir::StackSaveOp createStackSave(mlir::Location loc, mlir::Type ty)
cir::TypeInfoAttr getTypeInfo(mlir::ArrayAttr fieldsAttr)
cir::CmpThreeWayOp createThreeWayCmpTotalOrdering(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, const llvm::APSInt &ltRes, const llvm::APSInt &eqRes, const llvm::APSInt &gtRes, cir::CmpOrdering ordering)
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::VecShuffleOp createVecShuffle(mlir::Location loc, mlir::Value vec1, mlir::Value vec2, llvm::ArrayRef< int64_t > mask)
cir::ConstantOp getUInt64(uint64_t c, mlir::Location loc)
mlir::Value emitIntrinsicCallOp(mlir::Location loc, const llvm::StringRef str, const mlir::Type &resTy, Operands &&...op)
cir::IntType getSIntNTy(int n)
cir::ConstRecordAttr getAnonConstRecord(mlir::ArrayAttr arrayAttr, bool packed=false, bool padded=false, mlir::Type ty={})
cir::DataMemberAttr getDataMemberAttr(cir::DataMemberType ty, llvm::ArrayRef< int32_t > path)
cir::ConstantOp getSInt64(uint64_t c, mlir::Location loc)
cir::IntType getTruncatedIntTy(cir::IntType ty, bool isSigned)
cir::RecordType getIncompleteRecordTy(llvm::StringRef name, const clang::RecordDecl *rd)
Get an incomplete CIR record type.
cir::ConstantOp getUInt32(uint32_t c, mlir::Location loc)
Address createGetMember(mlir::Location loc, Address base, llvm::StringRef name, unsigned index)
void setDefaultConstrainedRounding(llvm::RoundingMode newRounding)
Set the rounding mode handling to be used with constrained floating point.
cir::MemCpyOp createMemCpy(mlir::Location loc, mlir::Value dst, mlir::Value src, mlir::Value len)
cir::VecShuffleOp createVecShuffle(mlir::Location loc, mlir::Value vec1, mlir::Value vec2, llvm::ArrayRef< mlir::Attribute > maskAttrs)
mlir::Value createNeg(mlir::Location loc, mlir::Value value, bool nsw=false)
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::LoadOp createLoad(mlir::Location loc, Address addr, bool isVolatile=false, bool isNontemporal=false)
cir::CmpThreeWayOp createThreeWayCmpPartialOrdering(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, const llvm::APSInt &ltRes, const llvm::APSInt &eqRes, const llvm::APSInt &gtRes, const llvm::APSInt &unorderedRes)
mlir::Value createVTTAddrPoint(mlir::Location loc, mlir::Type retTy, mlir::FlatSymbolRefAttr sym, uint64_t offset)
mlir::Value createMaskedLoad(mlir::Location loc, mlir::Type ty, mlir::Value ptr, llvm::Align alignment, mlir::Value mask, mlir::Value passThru)
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.
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, Address dst, bool isVolatile=false, bool isNontemporal=false, mlir::IntegerAttr align={}, cir::SyncScopeKindAttr scope={}, cir::MemOrderAttr order={})
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)
cir::FuncType getFuncType(llvm::ArrayRef< mlir::Type > params, mlir::Type retTy, bool isVarArg=false)
cir::MemSetOp createMemSet(mlir::Location loc, Address dst, mlir::Value val, mlir::Value len)
cir::IntType getExtendedIntTy(cir::IntType ty, bool isSigned)
Address createDerivedClassAddr(mlir::Location loc, Address addr, mlir::Type destType, unsigned offset, bool assumeNotNull)
static bool tagKindIsUnion(const clang::TagTypeKind kind)
Returns true if the tag kind is a union.
uint64_t computeOffsetFromGlobalViewIndices(const cir::CIRDataLayout &layout, mlir::Type ty, llvm::ArrayRef< int64_t > indices)
cir::GetRuntimeMemberOp createGetIndirectMember(mlir::Location loc, mlir::Value objectPtr, mlir::Value memberPtr)
llvm::RoundingMode getDefaultConstrainedRounding() const
Get the rounding mode handling used with constrained floating point.
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...
void setDefaultConstrainedExcept(llvm::fp::ExceptionBehavior newExcept)
Set the exception handling to be used with constrained floating point.
static bool tagKindIsClass(const clang::TagTypeKind kind)
Get a CIR record kind from a AST declaration tag.
mlir::Value createDynCastToVoid(mlir::Location loc, mlir::Value src, bool vtableUseRelativeLayout)
cir::ConstantOp getZero(mlir::Location loc, mlir::Type ty)
cir::VecShuffleOp createVecShuffle(mlir::Location loc, mlir::Value vec1, llvm::ArrayRef< int64_t > mask)
mlir::Value createDynCast(mlir::Location loc, mlir::Value src, cir::PointerType destType, bool isRefCast, cir::DynamicCastInfoAttr info)
llvm::fp::ExceptionBehavior getDefaultConstrainedExcept() const
Get the exception handling used with constrained floating point.
mlir::Value createGetBitfield(mlir::Location loc, mlir::Type resultType, Address addr, mlir::Type storageType, const CIRGenBitFieldInfo &info, bool isLvalueVolatile, bool useVolatile)
cir::StructType getAnonRecordTy(llvm::ArrayRef< mlir::Type > members, bool packed=false, bool padded=false)
Get a CIR anonymous struct type.
bool isNullValue(mlir::Attribute attr) const
cir::StackRestoreOp createStackRestore(mlir::Location loc, mlir::Value v)
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)
cir::GlobalOp createVersionedGlobal(mlir::ModuleOp module, mlir::Location loc, mlir::StringRef name, mlir::Type type, bool isConstant, cir::GlobalLinkageKind linkage, mlir::ptr::MemorySpaceAttrInterface addrSpace={})
Creates a versioned global variable.
bool getIsFPConstrained() const
Query for the use of constrained floating point math.
CIRGenBuilderTy(mlir::MLIRContext &mlirContext, const CIRGenTypeCache &tc)
cir::IsFPClassOp createIsFPClass(mlir::Location loc, mlir::Value src, cir::FPClassTest flags)
cir::RecordType getCompleteRecordType(mlir::ArrayAttr fields, bool packed=false, bool padded=false, llvm::StringRef name="")
mlir::Attribute getString(llvm::StringRef str, mlir::Type eltTy, std::optional< size_t > size, bool ensureNullTerm=true)
Get a cir::ConstArrayAttr for a string literal.
cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal)
void setIsFPConstrained(bool isCon)
Enable/Disable use of constrained floating point math.
void computeGlobalViewIndicesFromFlatOffset(int64_t offset, mlir::Type ty, cir::CIRDataLayout layout, llvm::SmallVectorImpl< int64_t > &indices)
Address createComplexImagPtr(mlir::Location loc, Address addr)
cir::VectorType getExtendedOrTruncatedElementVectorType(cir::VectorType vt, bool isExtended, bool isSigned=false)
cir::DataMemberAttr getNullDataMemberAttr(cir::DataMemberType ty)
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::MemSetOp createMemSet(mlir::Location loc, mlir::Value dst, mlir::Value val, mlir::Value len)
cir::LongDoubleType getLongDoubleTy(const llvm::fltSemantics &format) const
cir::CopyOp createCopy(Address dst, Address src, bool isVolatile=false, bool skipTailPadding=false)
cir::ConstArrayAttr getConstArray(mlir::Attribute attrs, cir::ArrayType arrayTy) const
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::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
CharUnits alignmentAtOffset(CharUnits offset) const
Given that this is a non-zero alignment value, what is the alignment at the given offset?
Definition CharUnits.h:207
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
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition CharUnits.h:185
static CharUnits One()
One - Construct a CharUnits quantity of one.
Definition CharUnits.h:58
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition CharUnits.h:63
Represents a struct/union/class.
Definition Decl.h:4360
TagKind getTagKind() const
Definition Decl.h:3952
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
TagTypeKind
The kind of a tag type.
Definition TypeBase.h:5995
@ Class
The "class" keyword.
Definition TypeBase.h:6006
@ Union
The "union" keyword.
Definition TypeBase.h:6003
int __ovld __cnfn all(char)
Returns 1 if the most significant bit in all components of x is set; otherwise returns 0.
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 int32_t
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t
static bool addressSpace()
static bool fpConstraints()
static bool astRecordDeclAttr()
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.