clang 24.0.0git
CIRBaseBuilder.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_CIR_DIALECT_BUILDER_CIRBASEBUILDER_H
10#define LLVM_CLANG_CIR_DIALECT_BUILDER_CIRBASEBUILDER_H
11
12#include "clang/AST/CharUnits.h"
19#include "llvm/ADT/STLForwardCompat.h"
20#include "llvm/IR/FPEnv.h"
21#include "llvm/Support/ErrorHandling.h"
22
23#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
24#include "mlir/IR/Builders.h"
25#include "mlir/IR/BuiltinAttributes.h"
26#include "mlir/IR/Location.h"
27#include "mlir/IR/OperationSupport.h"
28#include "mlir/IR/Types.h"
29
30namespace cir {
31
32enum class OverflowBehavior {
33 None = 0,
34 NoSignedWrap = 1 << 0,
36 Saturated = 1 << 2,
37};
38
40 return static_cast<OverflowBehavior>(llvm::to_underlying(a) |
41 llvm::to_underlying(b));
42}
43
45 return static_cast<OverflowBehavior>(llvm::to_underlying(a) &
46 llvm::to_underlying(b));
47}
48
51 a = a | b;
52 return a;
53}
54
57 a = a & b;
58 return a;
59}
60
61constexpr bool testFlag(OverflowBehavior ob, OverflowBehavior flag) {
62 return (ob & flag) != OverflowBehavior::None;
63}
64
65class CIRBaseBuilderTy : public mlir::OpBuilder {
66
67public:
68 CIRBaseBuilderTy(mlir::MLIRContext &mlirContext)
69 : mlir::OpBuilder(&mlirContext) {}
70 CIRBaseBuilderTy(mlir::OpBuilder &builder) : mlir::OpBuilder(builder) {}
71
72 bool isFPConstrained = false;
75 llvm::RoundingMode defaultConstrainedRounding =
76 llvm::RoundingMode::NearestTiesToEven;
77
78 mlir::Value getConstAPInt(mlir::Location loc, mlir::Type typ,
79 const llvm::APInt &val) {
80 return cir::ConstantOp::create(*this, loc, cir::IntAttr::get(typ, val));
81 }
82
83 cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr) {
84 return cir::ConstantOp::create(*this, loc, attr);
85 }
86
87 cir::ConstantOp getConstantInt(mlir::Location loc, mlir::Type ty,
88 int64_t value) {
89 return getConstant(loc, cir::IntAttr::get(ty, value));
90 }
91
92 mlir::Value getSignedInt(mlir::Location loc, int64_t val, unsigned numBits) {
93 auto type = cir::IntType::get(getContext(), numBits, /*isSigned=*/true);
94 return getConstAPInt(loc, type,
95 llvm::APInt(numBits, val, /*isSigned=*/true));
96 }
97
98 mlir::Value getUnsignedInt(mlir::Location loc, uint64_t val,
99 unsigned numBits) {
100 auto type = cir::IntType::get(getContext(), numBits, /*isSigned=*/false);
101 return getConstAPInt(loc, type, llvm::APInt(numBits, val));
102 }
103
104 // Creates constant null value for integral type ty.
105 cir::ConstantOp getNullValue(mlir::Type ty, mlir::Location loc) {
106 return getConstant(loc, getZeroInitAttr(ty));
107 }
108
109 mlir::TypedAttr getConstNullPtrAttr(mlir::Type t) {
110 assert(mlir::isa<cir::PointerType>(t) && "expected cir.ptr");
111 return getConstPtrAttr(t, 0);
112 }
113
114 mlir::TypedAttr getNullDataMemberAttr(cir::DataMemberType ty) {
115 return cir::DataMemberAttr::get(ty);
116 }
117
118 mlir::TypedAttr getZeroInitAttr(mlir::Type ty) {
119 if (auto bitFieldTy = mlir::dyn_cast<cir::BitFieldType>(ty)) {
120 assert(bitFieldTy.ownsBytes() &&
121 "a zero-width bit-field takes no initializer");
122 return getZeroInitAttr(bitFieldTy.getStorageType());
123 }
124 if (mlir::isa<cir::IntType>(ty))
125 return cir::IntAttr::get(ty, 0);
126 if (cir::isAnyFloatingPointType(ty))
127 return cir::FPAttr::getZero(ty);
128 if (auto complexType = mlir::dyn_cast<cir::ComplexType>(ty))
129 return cir::ZeroAttr::get(complexType);
130 if (auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty))
131 return cir::ZeroAttr::get(arrTy);
132 if (auto vecTy = mlir::dyn_cast<cir::VectorType>(ty))
133 return cir::ZeroAttr::get(vecTy);
134 if (auto matrixTy = mlir::dyn_cast<cir::MatrixType>(ty))
135 return cir::ZeroAttr::get(matrixTy);
136 if (auto ptrTy = mlir::dyn_cast<cir::PointerType>(ty))
137 return getConstNullPtrAttr(ptrTy);
138 if (auto recordTy = mlir::dyn_cast<cir::RecordType>(ty))
139 return cir::ZeroAttr::get(recordTy);
140 if (auto dataMemberTy = mlir::dyn_cast<cir::DataMemberType>(ty))
141 return getNullDataMemberAttr(dataMemberTy);
142 if (auto methodTy = mlir::dyn_cast<cir::MethodType>(ty))
143 return getNullMethodAttr(methodTy);
144 if (auto vptrTy = mlir::dyn_cast<cir::VPtrType>(ty))
145 return cir::ZeroAttr::get(vptrTy);
146 if (mlir::isa<cir::BoolType>(ty)) {
147 return getFalseAttr();
148 }
149
150 llvm_unreachable("Zero initializer for given type is NYI");
151 }
152
153 cir::ConstantOp getBool(bool state, mlir::Location loc) {
154 return cir::ConstantOp::create(*this, loc, getCIRBoolAttr(state));
155 }
156 cir::ConstantOp getFalse(mlir::Location loc) { return getBool(false, loc); }
157 cir::ConstantOp getTrue(mlir::Location loc) { return getBool(true, loc); }
158
159 cir::BoolType getBoolTy() { return cir::BoolType::get(getContext()); }
160 cir::VoidType getVoidTy() { return cir::VoidType::get(getContext()); }
161
162 cir::IntType getUIntNTy(int n) {
163 return cir::IntType::get(getContext(), n, false);
164 }
165
166 static unsigned getCIRIntOrFloatBitWidth(mlir::Type eltTy) {
167 if (auto intType = mlir::dyn_cast<cir::IntTypeInterface>(eltTy))
168 return intType.getWidth();
169 if (auto floatType = mlir::dyn_cast<cir::FPTypeInterface>(eltTy))
170 return floatType.getWidth();
171
172 llvm_unreachable("Unsupported type in getCIRIntOrFloatBitWidth");
173 }
174 cir::IntType getSIntNTy(int n) {
175 return cir::IntType::get(getContext(), n, true);
176 }
177
178 cir::PointerType getPointerTo(mlir::Type ty) {
179 return cir::PointerType::get(ty);
180 }
181
182 cir::PointerType getPointerTo(mlir::Type ty,
183 mlir::ptr::MemorySpaceAttrInterface as) {
184 return cir::PointerType::get(ty, as);
185 }
186
187 cir::PointerType getPointerTo(mlir::Type ty, clang::LangAS langAS) {
188 if (langAS == clang::LangAS::Default)
189 return getPointerTo(ty);
190
191 mlir::ptr::MemorySpaceAttrInterface addrSpaceAttr =
192 cir::toCIRAddressSpaceAttr(*getContext(), langAS);
193 return getPointerTo(ty, addrSpaceAttr);
194 }
195
197 return getPointerTo(cir::VoidType::get(getContext()), langAS);
198 }
199
200 cir::PointerType getVoidPtrTy(mlir::ptr::MemorySpaceAttrInterface as) {
201 return getPointerTo(cir::VoidType::get(getContext()), as);
202 }
203
204 cir::MethodAttr getMethodAttr(cir::MethodType ty, cir::FuncOp methodFuncOp) {
205 auto methodFuncSymbolRef = mlir::FlatSymbolRefAttr::get(methodFuncOp);
206 return cir::MethodAttr::get(ty, methodFuncSymbolRef);
207 }
208
209 cir::MethodAttr getNullMethodAttr(cir::MethodType ty) {
210 return cir::MethodAttr::get(ty);
211 }
212
213 cir::BoolAttr getCIRBoolAttr(bool state) {
214 return cir::BoolAttr::get(getContext(), state);
215 }
216
217 cir::BoolAttr getTrueAttr() { return getCIRBoolAttr(true); }
218 cir::BoolAttr getFalseAttr() { return getCIRBoolAttr(false); }
219
220 //
221 // Floating point specific helpers
222 // -------------------------------
223 //
224
225 /// Enable/Disable use of constrained floating point math. When enabled the
226 /// CreateF<op>() calls instead create constrained floating point intrinsic
227 /// calls. Fast math flags are unaffected by this setting.
228 void setIsFPConstrained(bool isCon) { isFPConstrained = isCon; }
229
230 /// Query for the use of constrained floating point math
231 bool getIsFPConstrained() const { return isFPConstrained; }
232
233 /// Set the exception handling to be used with constrained floating point
238
239 /// Get the exception handling used with constrained floating point
243
244 /// Set the rounding mode handling to be used with constrained floating point
245 void setDefaultConstrainedRounding(llvm::RoundingMode newRounding) {
246 defaultConstrainedRounding = newRounding;
247 }
248
249 /// Get the rounding mode handling used with constrained floating point
250 llvm::RoundingMode getDefaultConstrainedRounding() const {
252 }
253
254 /// Build the `#cir.fenv` attribute describing the constrained floating-point
255 /// environment currently in effect. This is attached to floating-point
256 /// operations that support it to capture the rounding and exception
257 /// behavior. Returns a null attribute when constrained floating-point is not
258 /// enabled, in which case no attribute should be attached.
259 cir::FenvAttr getConstrainedFPAttr() {
260 if (!isFPConstrained)
261 return {};
262
263 cir::FPDynamicRoundingMode roundingMode;
265 case llvm::RoundingMode::NearestTiesToEven:
266 roundingMode = cir::FPDynamicRoundingMode::ToNearest;
267 break;
268 case llvm::RoundingMode::TowardNegative:
269 roundingMode = cir::FPDynamicRoundingMode::Downward;
270 break;
271 case llvm::RoundingMode::TowardPositive:
272 roundingMode = cir::FPDynamicRoundingMode::Upward;
273 break;
274 case llvm::RoundingMode::TowardZero:
275 roundingMode = cir::FPDynamicRoundingMode::UpwardZero;
276 break;
277 case llvm::RoundingMode::NearestTiesToAway:
278 roundingMode = cir::FPDynamicRoundingMode::ToNearestAway;
279 break;
280 case llvm::RoundingMode::Dynamic:
281 roundingMode = cir::FPDynamicRoundingMode::Unknown;
282 break;
283 default:
284 llvm_unreachable("unexpected constrained rounding mode");
285 }
286
287 cir::FPExceptionMode exceptMode;
288 bool strictExcept;
289 switch (defaultConstrainedExcept) {
291 exceptMode = cir::FPExceptionMode::Masked;
292 strictExcept = false;
293 break;
295 exceptMode = cir::FPExceptionMode::Unknown;
296 strictExcept = false;
297 break;
299 exceptMode = cir::FPExceptionMode::Unknown;
300 strictExcept = true;
301 break;
302 default:
303 llvm_unreachable("unexpected constrained exception mode");
304 }
305
306 return cir::FenvAttr::get(getContext(), roundingMode, exceptMode,
307 mlir::BoolAttr::get(getContext(), strictExcept));
308 }
309
310 mlir::Value createComplexCreate(mlir::Location loc, mlir::Value real,
311 mlir::Value imag) {
312 auto resultComplexTy = cir::ComplexType::get(real.getType());
313 return cir::ComplexCreateOp::create(*this, loc, resultComplexTy, real,
314 imag);
315 }
316
317 mlir::Value createComplexReal(mlir::Location loc, mlir::Value operand) {
318 auto resultType = operand.getType();
319 if (auto complexResultType = mlir::dyn_cast<cir::ComplexType>(resultType))
320 resultType = complexResultType.getElementType();
321 return cir::ComplexRealOp::create(*this, loc, resultType, operand);
322 }
323
324 mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand) {
325 auto resultType = operand.getType();
326 if (auto complexResultType = mlir::dyn_cast<cir::ComplexType>(resultType))
327 resultType = complexResultType.getElementType();
328 return cir::ComplexImagOp::create(*this, loc, resultType, operand);
329 }
330
331 mlir::Value createComplexAdd(mlir::Location loc, mlir::Value lhs,
332 mlir::Value rhs) {
333 auto complexTy = mlir::cast<cir::ComplexType>(lhs.getType());
334 if (cir::isAnyFloatingPointType(complexTy.getElementType())) {
335 cir::FenvAttr fenv = getConstrainedFPAttr();
336 return cir::ComplexFAddOp::create(*this, loc, lhs, rhs, fenv);
337 }
338 return cir::ComplexAddOp::create(*this, loc, lhs, rhs);
339 }
340
341 mlir::Value createComplexSub(mlir::Location loc, mlir::Value lhs,
342 mlir::Value rhs) {
343 auto complexTy = mlir::cast<cir::ComplexType>(lhs.getType());
344 if (cir::isAnyFloatingPointType(complexTy.getElementType())) {
345 cir::FenvAttr fenv = getConstrainedFPAttr();
346 return cir::ComplexFSubOp::create(*this, loc, lhs, rhs, fenv);
347 }
348 return cir::ComplexSubOp::create(*this, loc, lhs, rhs);
349 }
350
351 mlir::Value createComplexMul(mlir::Location loc, mlir::Value lhs,
352 mlir::Value rhs,
353 cir::ComplexRangeKind rangeKind) {
354 auto complexTy = mlir::cast<cir::ComplexType>(lhs.getType());
355 if (cir::isAnyFloatingPointType(complexTy.getElementType()))
356 return cir::ComplexFMulOp::create(*this, loc, lhs, rhs, rangeKind);
357 return cir::ComplexMulOp::create(*this, loc, lhs, rhs);
358 }
359
360 mlir::Value createComplexDiv(mlir::Location loc, mlir::Value lhs,
361 mlir::Value rhs,
362 cir::ComplexRangeKind rangeKind) {
363 auto complexTy = mlir::cast<cir::ComplexType>(lhs.getType());
364 if (cir::isAnyFloatingPointType(complexTy.getElementType()))
365 return cir::ComplexFDivOp::create(*this, loc, lhs, rhs, rangeKind);
366 return cir::ComplexDivOp::create(*this, loc, lhs, rhs);
367 }
368
369 mlir::Value createComplexConj(mlir::Location loc, mlir::Value operand) {
370 return cir::ComplexConjOp::create(*this, loc, operand.getType(), operand);
371 }
372
373 cir::LoadOp createLoad(mlir::Location loc, mlir::Value ptr,
374 bool isVolatile = false, uint64_t alignment = 0,
375 bool isNontemporal = false) {
376 mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
377 return cir::LoadOp::create(*this, loc, ptr, /*isDeref=*/false, isVolatile,
378 isNontemporal, alignmentAttr,
379 cir::SyncScopeKindAttr{}, cir::MemOrderAttr{},
380 /*invariant=*/false);
381 }
382
383 mlir::Value createAlignedLoad(mlir::Location loc, mlir::Value ptr,
384 uint64_t alignment) {
385 return createLoad(loc, ptr, /*isVolatile=*/false, alignment);
386 }
387
388 mlir::Value createNot(mlir::Location loc, mlir::Value value) {
389 return cir::NotOp::create(*this, loc, value);
390 }
391
392 mlir::Value createNot(mlir::Value value) {
393 return createNot(value.getLoc(), value);
394 }
395
396 /// Create a do-while operation.
397 cir::DoWhileOp createDoWhile(
398 mlir::Location loc,
399 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> condBuilder,
400 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> bodyBuilder) {
401 return cir::DoWhileOp::create(*this, loc, condBuilder, bodyBuilder);
402 }
403
404 /// Create a while operation.
405 cir::WhileOp createWhile(
406 mlir::Location loc,
407 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> condBuilder,
408 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> bodyBuilder) {
409 return cir::WhileOp::create(*this, loc, condBuilder, bodyBuilder);
410 }
411
412 /// Create a while operation with a per-iteration cleanup region.
413 cir::WhileOp createWhile(
414 mlir::Location loc,
415 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> condBuilder,
416 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> bodyBuilder,
417 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)>
418 cleanupBuilder,
419 cir::CleanupKind cleanupKind) {
420 return cir::WhileOp::create(*this, loc, condBuilder, bodyBuilder,
421 cleanupBuilder, cleanupKind);
422 }
423
424 /// Create a for operation.
425 cir::ForOp createFor(
426 mlir::Location loc,
427 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> condBuilder,
428 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> bodyBuilder,
429 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> stepBuilder) {
430 return cir::ForOp::create(*this, loc, condBuilder, bodyBuilder,
431 stepBuilder);
432 }
433
434 /// Create a for operation with a per-iteration cleanup region.
435 cir::ForOp createFor(
436 mlir::Location loc,
437 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> condBuilder,
438 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> bodyBuilder,
439 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> stepBuilder,
440 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)>
441 cleanupBuilder,
442 cir::CleanupKind cleanupKind) {
443 return cir::ForOp::create(*this, loc, condBuilder, bodyBuilder, stepBuilder,
444 cleanupBuilder, cleanupKind);
445 }
446
447 /// Create a break operation.
448 cir::BreakOp createBreak(mlir::Location loc) {
449 return cir::BreakOp::create(*this, loc);
450 }
451
452 /// Create a continue operation.
453 cir::ContinueOp createContinue(mlir::Location loc) {
454 return cir::ContinueOp::create(*this, loc);
455 }
456
457 mlir::Value createInc(mlir::Location loc, mlir::Value input,
458 bool nsw = false) {
459 return cir::IncOp::create(*this, loc, input, nsw);
460 }
461
462 mlir::Value createDec(mlir::Location loc, mlir::Value input,
463 bool nsw = false) {
464 return cir::DecOp::create(*this, loc, input, nsw);
465 }
466
467 mlir::Value createMinus(mlir::Location loc, mlir::Value input,
468 bool nsw = false) {
469 return cir::MinusOp::create(*this, loc, input, nsw);
470 }
471
472 mlir::TypedAttr getConstPtrAttr(mlir::Type type, int64_t value) {
473 return cir::ConstPtrAttr::get(type, getI64IntegerAttr(value));
474 }
475
476 mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
477 llvm::StringRef name, mlir::IntegerAttr alignment,
478 mlir::Value dynAllocSize) {
479 return cir::AllocaOp::create(*this, loc, addrType, name, alignment,
480 dynAllocSize);
481 }
482
483 mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
484 mlir::Type type, llvm::StringRef name,
485 clang::CharUnits alignment,
486 mlir::Value dynAllocSize) {
487 mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
488 return createAlloca(loc, addrType, name, alignmentAttr, dynAllocSize);
489 }
490
491 mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
492 llvm::StringRef name, mlir::IntegerAttr alignment) {
493 return cir::AllocaOp::create(*this, loc, addrType, name, alignment);
494 }
495
496 mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
497 llvm::StringRef name, clang::CharUnits alignment) {
498 mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
499 return createAlloca(loc, addrType, name, alignmentAttr);
500 }
501
502 /// Get constant address of a global variable as an MLIR attribute.
503 /// This wrapper infers the attribute type through the global op.
504 cir::GlobalViewAttr getGlobalViewAttr(cir::GlobalOp globalOp,
505 mlir::ArrayAttr indices = {}) {
506 cir::PointerType type = getPointerTo(globalOp.getSymType());
507 return getGlobalViewAttr(type, globalOp, indices);
508 }
509
510 /// Get constant address of a global variable as an MLIR attribute.
511 cir::GlobalViewAttr getGlobalViewAttr(cir::PointerType type,
512 cir::GlobalOp globalOp,
513 mlir::ArrayAttr indices = {},
514 bool addressPoint = false) {
515 auto symbol = mlir::FlatSymbolRefAttr::get(globalOp.getSymNameAttr());
516 return cir::GlobalViewAttr::get(type, symbol, indices, addressPoint);
517 }
518
519 /// Get constant address of a global variable as an MLIR attribute.
520 /// This overload converts raw int64_t indices to an ArrayAttr.
521 cir::GlobalViewAttr getGlobalViewAttr(cir::PointerType type,
522 cir::GlobalOp globalOp,
524 bool addressPoint = false) {
526 for (int64_t ind : indices)
527 attrs.push_back(getI64IntegerAttr(ind));
528 mlir::ArrayAttr arAttr = mlir::ArrayAttr::get(getContext(), attrs);
529 return getGlobalViewAttr(type, globalOp, arAttr, addressPoint);
530 }
531
532 cir::GetGlobalOp createGetGlobal(mlir::Location loc, cir::GlobalOp global,
533 bool threadLocal = false) {
534 return cir::GetGlobalOp::create(
535 *this, loc,
536 getPointerTo(global.getSymType(), global.getAddrSpaceAttr()),
537 global.getSymNameAttr(), threadLocal);
538 }
539
540 cir::GetGlobalOp createGetGlobal(cir::GlobalOp global,
541 bool threadLocal = false) {
542 return createGetGlobal(global.getLoc(), global, threadLocal);
543 }
544
545 /// Create a copy with inferred length.
546 cir::CopyOp createCopy(mlir::Value dst, mlir::Value src,
547 bool isVolatile = false,
548 bool skipTailPadding = false) {
549 return cir::CopyOp::create(*this, dst.getLoc(), dst, src,
550 /*dst_alignment=*/{}, /*src_alignment=*/{},
551 isVolatile, skipTailPadding);
552 }
553
554 cir::StoreOp createStore(mlir::Location loc, mlir::Value val, mlir::Value dst,
555 bool isVolatile = false, bool isNontemporal = false,
556 mlir::IntegerAttr align = {},
557 cir::SyncScopeKindAttr scope = {},
558 cir::MemOrderAttr order = {}) {
559 if (mlir::cast<cir::PointerType>(dst.getType()).getPointee() !=
560 val.getType())
561 dst = createPtrBitcast(dst, val.getType());
562 return cir::StoreOp::create(*this, loc, val, dst, isVolatile, isNontemporal,
563 align, scope, order);
564 }
565
566 /// Emit a load from an boolean flag variable.
567 cir::LoadOp createFlagLoad(mlir::Location loc, mlir::Value addr) {
568 mlir::Type boolTy = getBoolTy();
569 if (boolTy != mlir::cast<cir::PointerType>(addr.getType()).getPointee())
570 addr = createPtrBitcast(addr, boolTy);
571 return createLoad(loc, addr, /*isVolatile=*/false, /*alignment=*/1);
572 }
573
574 cir::StoreOp createFlagStore(mlir::Location loc, bool val, mlir::Value dst) {
575 mlir::Value flag = getBool(val, loc);
576 return CIRBaseBuilderTy::createStore(loc, flag, dst);
577 }
578
579 [[nodiscard]] cir::GlobalOp
580 createGlobal(mlir::ModuleOp mlirModule, mlir::Location loc,
581 mlir::StringRef name, mlir::Type type, bool isConstant,
582 cir::GlobalLinkageKind linkage,
583 mlir::ptr::MemorySpaceAttrInterface addrSpace) {
584 mlir::OpBuilder::InsertionGuard guard(*this);
585 setInsertionPointToStart(mlirModule.getBody());
586 return cir::GlobalOp::create(*this, loc, name, type, isConstant, addrSpace,
587 linkage);
588 }
589
590 cir::GetMemberOp createGetMember(mlir::Location loc, mlir::Type resultTy,
591 mlir::Value base, llvm::StringRef name,
592 unsigned index) {
593 return cir::GetMemberOp::create(*this, loc, resultTy, base, name, index);
594 }
595
596 mlir::Value createDummyValue(mlir::Location loc, mlir::Type type,
597 clang::CharUnits alignment) {
598 mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
599 auto addr = createAlloca(loc, getPointerTo(type), {}, alignmentAttr);
600 return cir::LoadOp::create(*this, loc, addr, /*isDeref=*/false,
601 /*isVolatile=*/false, /*nontemporal=*/false,
602 alignmentAttr,
603 /*sync_scope=*/{}, /*mem_order=*/{},
604 /*invariant=*/false);
605 }
606
607 cir::PtrStrideOp createPtrStride(mlir::Location loc, mlir::Value base,
608 mlir::Value stride) {
609 return cir::PtrStrideOp::create(*this, loc, base.getType(), base, stride);
610 }
611
612 //===--------------------------------------------------------------------===//
613 // Call operators
614 //===--------------------------------------------------------------------===//
615
616 cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee,
617 mlir::Type returnType, mlir::ValueRange operands,
621 cir::CallingConv callingConv = cir::CallingConv::C) {
622 auto op = cir::CallOp::create(*this, loc, callee, returnType, operands);
623 op->setAttrs(attrs);
624 if (callingConv != cir::CallingConv::C)
625 op.setCallingConv(callingConv);
626
627 if (!argAttrs.empty()) {
628 llvm::SmallVector<mlir::Attribute> argDictAttrs;
629 argDictAttrs.reserve(argAttrs.size());
630
631 llvm::transform(
632 argAttrs, std::back_inserter(argDictAttrs),
633 [this](llvm::ArrayRef<mlir::NamedAttribute> singleArgAttrs) {
634 return mlir::DictionaryAttr::get(getContext(), singleArgAttrs);
635 });
636
637 op.setArgAttrsAttr(mlir::ArrayAttr::get(getContext(), argDictAttrs));
638 }
639
640 if (!resAttrs.empty()) {
641 auto resultDictAttr = mlir::DictionaryAttr::get(getContext(), resAttrs);
642 op.setResAttrsAttr(mlir::ArrayAttr::get(getContext(), resultDictAttr));
643 }
644 return op;
645 }
646
647 cir::CallOp createCallOp(mlir::Location loc, cir::FuncOp callee,
648 mlir::ValueRange operands,
652 cir::CallingConv callingConv = cir::CallingConv::C) {
653 return createCallOp(loc, mlir::SymbolRefAttr::get(callee),
654 callee.getFunctionType().getReturnType(), operands,
655 attrs, argAttrs, resAttrs, callingConv);
656 }
657
658 cir::CallOp
659 createIndirectCallOp(mlir::Location loc, mlir::Value indirectTarget,
660 cir::FuncType funcType, mlir::ValueRange operands,
664 cir::CallingConv callingConv = cir::CallingConv::C) {
665 llvm::SmallVector<mlir::Value> resOperands{indirectTarget};
666 resOperands.append(operands.begin(), operands.end());
667
668 return createCallOp(loc, mlir::SymbolRefAttr(), funcType.getReturnType(),
669 resOperands, attrs, argAttrs, resAttrs, callingConv);
670 }
671
672 cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee,
673 mlir::ValueRange operands = mlir::ValueRange(),
677 return createCallOp(loc, callee, cir::VoidType(), operands, attrs, argAttrs,
678 resAttrs);
679 }
680
681 //===--------------------------------------------------------------------===//
682 // Cast/Conversion Operators
683 //===--------------------------------------------------------------------===//
684
685 mlir::Value createCast(mlir::Location loc, cir::CastKind kind,
686 mlir::Value src, mlir::Type newTy) {
687 if (newTy == src.getType())
688 return src;
689 return cir::CastOp::create(*this, loc, newTy, kind, src);
690 }
691
692 mlir::Value createCast(cir::CastKind kind, mlir::Value src,
693 mlir::Type newTy) {
694 if (newTy == src.getType())
695 return src;
696 return createCast(src.getLoc(), kind, src, newTy);
697 }
698
699 // Creates a cast from bool or int to an integer type.
700 mlir::Value createBoolIntToIntCast(mlir::Value src, mlir::Type newTy) {
701 if (newTy == src.getType())
702 return src;
703 if (src.getType() == getBoolTy())
704 return createBoolToInt(src, newTy);
705 return createIntCast(src, newTy);
706 }
707
708 mlir::Value createIntCast(mlir::Value src, mlir::Type newTy) {
709 return createCast(cir::CastKind::integral, src, newTy);
710 }
711
712 mlir::Value createBuiltinIntCast(mlir::Location loc, mlir::Value src,
713 mlir::Type newTy) {
714 return cir::BuiltinIntCastOp::create(*this, loc, newTy, src);
715 }
716
717 mlir::Value createBuiltinIntCast(mlir::Value src, mlir::Type newTy) {
718 return createBuiltinIntCast(src.getLoc(), src, newTy);
719 }
720
721 mlir::Value createIntToPtr(mlir::Value src, mlir::Type newTy) {
722 return createCast(cir::CastKind::int_to_ptr, src, newTy);
723 }
724
725 mlir::Value createPtrToInt(mlir::Value src, mlir::Type newTy) {
726 return createCast(cir::CastKind::ptr_to_int, src, newTy);
727 }
728
729 mlir::Value createPtrToBoolCast(mlir::Value v) {
730 return createCast(cir::CastKind::ptr_to_bool, v, getBoolTy());
731 }
732
733 mlir::Value createBoolToInt(mlir::Value src, mlir::Type newTy) {
734 return createCast(cir::CastKind::bool_to_int, src, newTy);
735 }
736
737 mlir::Value createBitcast(mlir::Value src, mlir::Type newTy) {
738 return createCast(cir::CastKind::bitcast, src, newTy);
739 }
740
741 mlir::Value createBitcast(mlir::Location loc, mlir::Value src,
742 mlir::Type newTy) {
743 return createCast(loc, cir::CastKind::bitcast, src, newTy);
744 }
745
746 mlir::Value createPtrBitcast(mlir::Value src, mlir::Type newPointeeTy) {
747 assert(mlir::isa<cir::PointerType>(src.getType()) && "expected ptr src");
748 cir::PointerType srcPtrTy = mlir::cast<cir::PointerType>(src.getType());
749 return createBitcast(src,
750 getPointerTo(newPointeeTy, srcPtrTy.getAddrSpace()));
751 }
752
753 mlir::Value createPtrIsNull(mlir::Value ptr) {
754 mlir::Value nullPtr = getNullPtr(ptr.getType(), ptr.getLoc());
755 return createCompare(ptr.getLoc(), cir::CmpOpKind::eq, ptr, nullPtr);
756 }
757
758 mlir::Value createPtrIsNotNull(mlir::Value ptr) {
759 mlir::Value nullPtr = getNullPtr(ptr.getType(), ptr.getLoc());
760 return createCompare(ptr.getLoc(), cir::CmpOpKind::ne, ptr, nullPtr);
761 }
762
763 mlir::Value createAddrSpaceCast(mlir::Location loc, mlir::Value src,
764 mlir::Type newTy) {
765 return createCast(loc, cir::CastKind::address_space, src, newTy);
766 }
767
768 mlir::Value createAddrSpaceCast(mlir::Value src, mlir::Type newTy) {
769 return createAddrSpaceCast(src.getLoc(), src, newTy);
770 }
771
772 //===--------------------------------------------------------------------===//
773 // Other Instructions
774 //===--------------------------------------------------------------------===//
775
776 mlir::Value createExtractElement(mlir::Location loc, mlir::Value vec,
777 uint64_t idx) {
778 mlir::Value idxVal =
779 getConstAPInt(loc, getUIntNTy(64), llvm::APInt(64, idx));
780 return cir::VecExtractOp::create(*this, loc, vec, idxVal);
781 }
782
783 mlir::Value createInsertElement(mlir::Location loc, mlir::Value vec,
784 mlir::Value newElt, uint64_t idx) {
785 mlir::Value idxVal =
786 getConstAPInt(loc, getUIntNTy(64), llvm::APInt(64, idx));
787 return cir::VecInsertOp::create(*this, loc, vec, newElt, idxVal);
788 }
789
790 cir::SignBitOp createSignBit(mlir::Location loc, mlir::Value val) {
791 auto resTy = cir::BoolType::get(getContext());
792 return cir::SignBitOp::create(*this, loc, resTy, val);
793 }
794
795 //===--------------------------------------------------------------------===//
796 // Binary Operators
797 //===--------------------------------------------------------------------===//
798
799 mlir::Value createLowBitsSet(mlir::Location loc, unsigned size,
800 unsigned bits) {
801 llvm::APInt val = llvm::APInt::getLowBitsSet(size, bits);
802 auto type = cir::IntType::get(getContext(), size, /*isSigned=*/false);
803 return getConstAPInt(loc, type, val);
804 }
805
806 mlir::Value createAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
807 return cir::AndOp::create(*this, loc, lhs, rhs);
808 }
809
810 mlir::Value createOr(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
811 return cir::OrOp::create(*this, loc, lhs, rhs);
812 }
813
814 mlir::Value createSelect(mlir::Location loc, mlir::Value condition,
815 mlir::Value trueValue, mlir::Value falseValue) {
816 assert(trueValue.getType() == falseValue.getType() &&
817 "trueValue and falseValue should have the same type");
818 return cir::SelectOp::create(*this, loc, trueValue.getType(), condition,
819 trueValue, falseValue);
820 }
821
822 mlir::Value createLogicalAnd(mlir::Location loc, mlir::Value lhs,
823 mlir::Value rhs) {
824 return createSelect(loc, lhs, rhs, getBool(false, loc));
825 }
826
827 mlir::Value createLogicalOr(mlir::Location loc, mlir::Value lhs,
828 mlir::Value rhs) {
829 return createSelect(loc, lhs, getBool(true, loc), rhs);
830 }
831
832 mlir::Value createMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
834 auto op = cir::MulOp::create(*this, loc, lhs, rhs);
835 op.setNoUnsignedWrap(testFlag(ob, OverflowBehavior::NoUnsignedWrap));
836 op.setNoSignedWrap(testFlag(ob, OverflowBehavior::NoSignedWrap));
837 return op;
838 }
839 mlir::Value createNSWMul(mlir::Location loc, mlir::Value lhs,
840 mlir::Value rhs) {
841 return createMul(loc, lhs, rhs, OverflowBehavior::NoSignedWrap);
842 }
843 mlir::Value createNUWAMul(mlir::Location loc, mlir::Value lhs,
844 mlir::Value rhs) {
845 return createMul(loc, lhs, rhs, OverflowBehavior::NoUnsignedWrap);
846 }
847
848 mlir::Value createSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
850 auto op = cir::SubOp::create(*this, loc, lhs, rhs);
851 op.setNoUnsignedWrap(testFlag(ob, OverflowBehavior::NoUnsignedWrap));
852 op.setNoSignedWrap(testFlag(ob, OverflowBehavior::NoSignedWrap));
853 op.setSaturated(testFlag(ob, OverflowBehavior::Saturated));
854 return op;
855 }
856
857 mlir::Value createNSWSub(mlir::Location loc, mlir::Value lhs,
858 mlir::Value rhs) {
859 return createSub(loc, lhs, rhs, OverflowBehavior::NoSignedWrap);
860 }
861
862 mlir::Value createNUWSub(mlir::Location loc, mlir::Value lhs,
863 mlir::Value rhs) {
864 return createSub(loc, lhs, rhs, OverflowBehavior::NoUnsignedWrap);
865 }
866
867 mlir::Value createAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
869 auto op = cir::AddOp::create(*this, loc, lhs, rhs);
870 op.setNoUnsignedWrap(testFlag(ob, OverflowBehavior::NoUnsignedWrap));
871 op.setNoSignedWrap(testFlag(ob, OverflowBehavior::NoSignedWrap));
872 op.setSaturated(testFlag(ob, OverflowBehavior::Saturated));
873 return op;
874 }
875
876 mlir::Value createNSWAdd(mlir::Location loc, mlir::Value lhs,
877 mlir::Value rhs) {
878 return createAdd(loc, lhs, rhs, OverflowBehavior::NoSignedWrap);
879 }
880
881 mlir::Value createNUWAdd(mlir::Location loc, mlir::Value lhs,
882 mlir::Value rhs) {
883 return createAdd(loc, lhs, rhs, OverflowBehavior::NoUnsignedWrap);
884 }
885
886 mlir::Value createDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
887 return cir::DivOp::create(*this, loc, lhs, rhs);
888 }
889
890 mlir::Value createRem(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
891 return cir::RemOp::create(*this, loc, lhs, rhs);
892 }
893
894 mlir::Value createFAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
897 return cir::FAddOp::create(*this, loc, lhs, rhs, getConstrainedFPAttr());
898 }
899
900 mlir::Value createFSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
903 return cir::FSubOp::create(*this, loc, lhs, rhs, getConstrainedFPAttr());
904 }
905
906 mlir::Value createFMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
909 return cir::FMulOp::create(*this, loc, lhs, rhs, getConstrainedFPAttr());
910 }
911
912 mlir::Value createFDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
915 return cir::FDivOp::create(*this, loc, lhs, rhs, getConstrainedFPAttr());
916 }
917
918 mlir::Value createFRem(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
921 return cir::FRemOp::create(*this, loc, lhs, rhs, getConstrainedFPAttr());
922 }
923
924 mlir::Value createFNeg(mlir::Location loc, mlir::Value operand) {
925 assert(cir::isFPOrVectorOfFPType(operand.getType()) &&
926 "expected floating-point or vector-of-float type");
929 // fneg does not raise FP exceptions or depend on the rounding mode, so it
930 // never carries an fenv attribute.
931 return cir::FNegOp::create(*this, loc, operand);
932 }
933
934 mlir::Value createXor(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
935 return cir::XorOp::create(*this, loc, lhs, rhs);
936 }
937
938 mlir::Value createMax(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
939 return cir::MaxOp::create(*this, loc, lhs, rhs);
940 }
941
942 mlir::Value createMin(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
943 return cir::MinOp::create(*this, loc, lhs, rhs);
944 }
945
946 cir::CmpOp createCompare(mlir::Location loc, cir::CmpOpKind kind,
947 mlir::Value lhs, mlir::Value rhs) {
948 cir::FenvAttr fenv;
949 if (cir::isAnyFloatingPointType(lhs.getType()))
950 fenv = getConstrainedFPAttr();
951 return cir::CmpOp::create(*this, loc, kind, lhs, rhs, fenv);
952 }
953
954 /// Compares \p lhs and \p rhs element-wise. Each result element is a
955 /// signed integer of the operand element's bit width. That is not the
956 /// result an FP80 element needs, so an FP80 compare names its result type
957 /// with the overload below.
958 cir::VecCmpOp createVecCompare(mlir::Location loc, cir::CmpOpKind kind,
959 mlir::Value lhs, mlir::Value rhs) {
960 VectorType vecCast = mlir::cast<VectorType>(lhs.getType());
961 mlir::Type elemTy = vecCast.getElementType();
962 assert(!(mlir::isa<cir::FPTypeInterface>(elemTy) &&
963 &mlir::cast<cir::FPTypeInterface>(elemTy).getFloatSemantics() ==
964 &llvm::APFloat::x87DoubleExtended()) &&
965 "an FP80 vector compare must name its result type");
966 IntType integralTy = getSIntNTy(getCIRIntOrFloatBitWidth(elemTy));
967 return createVecCompare(loc,
968 cir::VectorType::get(integralTy, vecCast.getSize()),
969 kind, lhs, rhs);
970 }
971
972 /// Compares \p lhs and \p rhs element-wise, producing \p resultTy, which
973 /// must be a vector of integers or bools with as many elements as \p lhs.
974 /// The result element width can then differ from the operand element's
975 /// bit width, as for FP80, whose result elements are 128 bits.
976 cir::VecCmpOp createVecCompare(mlir::Location loc, VectorType resultTy,
977 cir::CmpOpKind kind, mlir::Value lhs,
978 mlir::Value rhs) {
979 assert(mlir::cast<VectorType>(lhs.getType()).getSize() ==
980 resultTy.getSize() &&
981 cir::isIntOrBoolType(resultTy.getElementType()) &&
982 "vector compare result must be an int or bool vector of the "
983 "operand length");
984 cir::FenvAttr fenv;
985 if (cir::isFPOrVectorOfFPType(lhs.getType()))
986 fenv = getConstrainedFPAttr();
987 return cir::VecCmpOp::create(*this, loc, resultTy, kind, lhs, rhs, fenv);
988 }
989
990 mlir::Value createIsNaN(mlir::Location loc, mlir::Value operand) {
991 return createCompare(loc, cir::CmpOpKind::ne, operand, operand);
992 }
993
994 mlir::Value createShift(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
995 bool isShiftLeft) {
996 return cir::ShiftOp::create(*this, loc, lhs.getType(), lhs, rhs,
997 isShiftLeft);
998 }
999
1000 mlir::Value createShift(mlir::Location loc, mlir::Value lhs,
1001 const llvm::APInt &rhs, bool isShiftLeft) {
1002 return createShift(loc, lhs, getConstAPInt(loc, lhs.getType(), rhs),
1003 isShiftLeft);
1004 }
1005
1006 mlir::Value createShift(mlir::Location loc, mlir::Value lhs, unsigned bits,
1007 bool isShiftLeft) {
1008 auto width = mlir::dyn_cast<cir::IntType>(lhs.getType()).getWidth();
1009 auto shift = llvm::APInt(width, bits);
1010 return createShift(loc, lhs, shift, isShiftLeft);
1011 }
1012
1013 mlir::Value createShiftLeft(mlir::Location loc, mlir::Value lhs,
1014 unsigned bits) {
1015 return createShift(loc, lhs, bits, true);
1016 }
1017
1018 mlir::Value createShiftRight(mlir::Location loc, mlir::Value lhs,
1019 unsigned bits) {
1020 return createShift(loc, lhs, bits, false);
1021 }
1022
1023 mlir::Value createShiftLeft(mlir::Location loc, mlir::Value lhs,
1024 mlir::Value rhs) {
1025 return createShift(loc, lhs, rhs, true);
1026 }
1027
1028 mlir::Value createShiftRight(mlir::Location loc, mlir::Value lhs,
1029 mlir::Value rhs) {
1030 return createShift(loc, lhs, rhs, false);
1031 }
1032
1033 /// Returns `void (T...)` as a cir::FuncType.
1034 cir::FuncType getVoidFnTy(mlir::TypeRange argTypes = {}) {
1035 return cir::FuncType::get(llvm::to_vector(argTypes), getVoidTy());
1036 }
1037
1038 /// Returns `void (*)(T...)` as a cir::PointerType.
1039 cir::PointerType getVoidFnPtrTy(mlir::TypeRange argTypes = {}) {
1040 return getPointerTo(getVoidFnTy(argTypes));
1041 }
1042
1043 //
1044 // Block handling helpers
1045 // ----------------------
1046 //
1047 static OpBuilder::InsertPoint getBestAllocaInsertPoint(mlir::Block *block) {
1048 auto last =
1049 std::find_if(block->rbegin(), block->rend(), [](mlir::Operation &op) {
1050 return mlir::isa<cir::AllocaOp, cir::LabelOp>(&op);
1051 });
1052
1053 if (last != block->rend())
1054 return OpBuilder::InsertPoint(block, ++mlir::Block::iterator(&*last));
1055 return OpBuilder::InsertPoint(block, block->begin());
1056 };
1057
1058 //
1059 // Alignment and size helpers
1060 //
1061
1062 // Note that mlir::IntegerType is used instead of cir::IntType here because we
1063 // don't need sign information for these to be useful, so keep it simple.
1064
1065 // For 0 alignment, any overload of `getAlignmentAttr` returns an empty
1066 // attribute.
1067 mlir::IntegerAttr getAlignmentAttr(clang::CharUnits alignment) {
1068 return getAlignmentAttr(alignment.getQuantity());
1069 }
1070
1071 mlir::IntegerAttr getAlignmentAttr(llvm::Align alignment) {
1072 return getAlignmentAttr(alignment.value());
1073 }
1074
1075 mlir::IntegerAttr getAlignmentAttr(int64_t alignment) {
1076 return alignment ? getI64IntegerAttr(alignment) : mlir::IntegerAttr();
1077 }
1078
1079 // Materialize an alignment value as a CIR integer constant of the given
1080 // integer type.
1081 cir::ConstantOp getAlignment(mlir::Location loc, mlir::Type t,
1082 clang::CharUnits alignment) {
1083 return getConstantInt(loc, t, alignment.getQuantity());
1084 }
1085
1086 mlir::IntegerAttr getSizeFromCharUnits(clang::CharUnits size) {
1087 return getI64IntegerAttr(size.getQuantity());
1088 }
1089
1090 // Creates constant nullptr for pointer type ty.
1091 cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc) {
1093 return cir::ConstantOp::create(*this, loc, getConstPtrAttr(ty, 0));
1094 }
1095
1096 /// Create a loop condition.
1097 cir::ConditionOp createCondition(mlir::Value condition) {
1098 return cir::ConditionOp::create(*this, condition.getLoc(), condition);
1099 }
1100
1101 /// Create a yield operation.
1102 cir::YieldOp createYield(mlir::Location loc, mlir::ValueRange value = {}) {
1103 return cir::YieldOp::create(*this, loc, value);
1104 }
1105
1107 mlir::Value callee;
1108 mlir::Value adjustedThis;
1109 };
1110
1111 GetMethodResults createGetMethod(mlir::Location loc, mlir::Value method,
1112 mlir::Value objectPtr) {
1113 // Build the callee function type.
1114 auto methodFuncTy =
1115 mlir::cast<cir::MethodType>(method.getType()).getMemberFuncTy();
1116 auto methodFuncInputTypes = methodFuncTy.getInputs();
1117
1118 auto objectPtrTy = mlir::cast<cir::PointerType>(objectPtr.getType());
1119 mlir::Type adjustedThisTy = getVoidPtrTy(objectPtrTy.getAddrSpace());
1120
1121 llvm::SmallVector<mlir::Type> calleeFuncInputTypes{adjustedThisTy};
1122 // The member function type's first parameter is the implicit 'this'
1123 // pointer. The callee takes an adjusted void* receiver instead.
1124 if (methodFuncInputTypes.size() > 1)
1125 calleeFuncInputTypes.insert(calleeFuncInputTypes.end(),
1126 methodFuncInputTypes.begin() + 1,
1127 methodFuncInputTypes.end());
1128 cir::FuncType calleeFuncTy =
1129 methodFuncTy.clone(calleeFuncInputTypes, methodFuncTy.getReturnType());
1130 // TODO(cir): consider the address space of the callee.
1132 cir::PointerType calleeTy = getPointerTo(calleeFuncTy);
1133
1134 auto op = cir::GetMethodOp::create(*this, loc, calleeTy, adjustedThisTy,
1135 method, objectPtr);
1136 return {op.getCallee(), op.getAdjustedThis()};
1137 }
1138};
1139
1140} // namespace cir
1141
1142#endif
Provides definitions for the various language-specific address spaces.
Defines the clang::LangOptions interface.
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a an optional score condition
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
mlir::Value createNSWSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::ConstantOp getBool(bool state, mlir::Location loc)
mlir::Value createShift(mlir::Location loc, mlir::Value lhs, unsigned bits, bool isShiftLeft)
cir::StoreOp createFlagStore(mlir::Location loc, bool val, mlir::Value dst)
cir::WhileOp createWhile(mlir::Location loc, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> condBuilder, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> bodyBuilder)
Create a while operation.
mlir::Value createDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType, llvm::StringRef name, mlir::IntegerAttr alignment)
mlir::Value createComplexMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, cir::ComplexRangeKind rangeKind)
cir::VecCmpOp createVecCompare(mlir::Location loc, VectorType resultTy, cir::CmpOpKind kind, mlir::Value lhs, mlir::Value rhs)
Compares lhs and rhs element-wise, producing resultTy, which must be a vector of integers or bools wi...
cir::BreakOp createBreak(mlir::Location loc)
Create a break operation.
mlir::TypedAttr getConstNullPtrAttr(mlir::Type t)
cir::FenvAttr getConstrainedFPAttr()
Build the #cir.fenv attribute describing the constrained floating-point environment currently in effe...
cir::PointerType getVoidPtrTy(mlir::ptr::MemorySpaceAttrInterface as)
mlir::IntegerAttr getAlignmentAttr(int64_t alignment)
mlir::Value createDec(mlir::Location loc, mlir::Value input, bool nsw=false)
mlir::Value createShift(mlir::Location loc, mlir::Value lhs, const llvm::APInt &rhs, bool isShiftLeft)
mlir::Value getConstAPInt(mlir::Location loc, mlir::Type typ, const llvm::APInt &val)
mlir::Value createBuiltinIntCast(mlir::Value src, mlir::Type newTy)
mlir::Value createCast(cir::CastKind kind, mlir::Value src, mlir::Type newTy)
mlir::Value createLogicalOr(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createShift(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, bool isShiftLeft)
mlir::Value createSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
cir::ConditionOp createCondition(mlir::Value condition)
Create a loop condition.
clang::LangOptions::FPExceptionModeKind getDefaultConstrainedExcept() const
Get the exception handling used with constrained floating point.
mlir::Value createLowBitsSet(mlir::Location loc, unsigned size, unsigned bits)
mlir::Value createInc(mlir::Location loc, mlir::Value input, bool nsw=false)
cir::CopyOp createCopy(mlir::Value dst, mlir::Value src, bool isVolatile=false, bool skipTailPadding=false)
Create a copy with inferred length.
mlir::Value createNSWAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::GlobalViewAttr getGlobalViewAttr(cir::GlobalOp globalOp, mlir::ArrayAttr indices={})
Get constant address of a global variable as an MLIR attribute.
cir::MethodAttr getMethodAttr(cir::MethodType ty, cir::FuncOp methodFuncOp)
cir::VoidType getVoidTy()
cir::ConstantOp getNullValue(mlir::Type ty, mlir::Location loc)
cir::BoolAttr getCIRBoolAttr(bool state)
mlir::Value createBoolToInt(mlir::Value src, mlir::Type newTy)
cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr)
cir::MethodAttr getNullMethodAttr(cir::MethodType ty)
mlir::Value createNUWAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createOr(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createPtrIsNull(mlir::Value ptr)
mlir::Value createShiftLeft(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::SignBitOp createSignBit(mlir::Location loc, mlir::Value val)
mlir::Value createCast(mlir::Location loc, cir::CastKind kind, mlir::Value src, mlir::Type newTy)
mlir::IntegerAttr getSizeFromCharUnits(clang::CharUnits size)
cir::PointerType getVoidFnPtrTy(mlir::TypeRange argTypes={})
Returns void (*)(T...) as a cir::PointerType.
cir::ForOp createFor(mlir::Location loc, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> condBuilder, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> bodyBuilder, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> stepBuilder, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> cleanupBuilder, cir::CleanupKind cleanupKind)
Create a for operation with a per-iteration cleanup region.
cir::PtrStrideOp createPtrStride(mlir::Location loc, mlir::Value base, mlir::Value stride)
mlir::Value createIntToPtr(mlir::Value src, mlir::Type newTy)
mlir::Value createRem(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::ForOp createFor(mlir::Location loc, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> condBuilder, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> bodyBuilder, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> stepBuilder)
Create a for operation.
cir::GlobalViewAttr getGlobalViewAttr(cir::PointerType type, cir::GlobalOp globalOp, mlir::ArrayAttr indices={}, bool addressPoint=false)
Get constant address of a global variable as an MLIR attribute.
static OpBuilder::InsertPoint getBestAllocaInsertPoint(mlir::Block *block)
mlir::Value createPtrToInt(mlir::Value src, mlir::Type newTy)
mlir::Value createFDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createNUWSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::ConstantOp getFalse(mlir::Location loc)
cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee, mlir::ValueRange operands=mlir::ValueRange(), llvm::ArrayRef< mlir::NamedAttribute > attrs={}, llvm::ArrayRef< mlir::NamedAttrList > argAttrs={}, llvm::ArrayRef< mlir::NamedAttribute > resAttrs={})
mlir::Value createAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
cir::GetMemberOp createGetMember(mlir::Location loc, mlir::Type resultTy, mlir::Value base, llvm::StringRef name, unsigned index)
cir::PointerType getPointerTo(mlir::Type ty)
mlir::Value createFNeg(mlir::Location loc, mlir::Value operand)
mlir::Value createComplexSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType, llvm::StringRef name, clang::CharUnits alignment)
mlir::Value createNot(mlir::Value value)
cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee, mlir::Type returnType, mlir::ValueRange operands, llvm::ArrayRef< mlir::NamedAttribute > attrs={}, llvm::ArrayRef< mlir::NamedAttrList > argAttrs={}, llvm::ArrayRef< mlir::NamedAttribute > resAttrs={}, cir::CallingConv callingConv=cir::CallingConv::C)
mlir::Value createFAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand)
cir::ConstantOp getTrue(mlir::Location loc)
mlir::Value createNSWMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc)
cir::CallOp createCallOp(mlir::Location loc, cir::FuncOp callee, mlir::ValueRange operands, llvm::ArrayRef< mlir::NamedAttribute > attrs={}, llvm::ArrayRef< mlir::NamedAttrList > argAttrs={}, llvm::ArrayRef< mlir::NamedAttribute > resAttrs={}, cir::CallingConv callingConv=cir::CallingConv::C)
cir::GetGlobalOp createGetGlobal(cir::GlobalOp global, bool threadLocal=false)
cir::IntType getUIntNTy(int n)
mlir::Value createComplexDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, cir::ComplexRangeKind rangeKind)
cir::DoWhileOp createDoWhile(mlir::Location loc, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> condBuilder, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> bodyBuilder)
Create a do-while operation.
mlir::Value createNUWAMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createPtrBitcast(mlir::Value src, mlir::Type newPointeeTy)
cir::GetGlobalOp createGetGlobal(mlir::Location loc, cir::GlobalOp global, bool threadLocal=false)
mlir::Value createShiftLeft(mlir::Location loc, mlir::Value lhs, unsigned bits)
mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType, llvm::StringRef name, mlir::IntegerAttr alignment, mlir::Value dynAllocSize)
cir::LoadOp createLoad(mlir::Location loc, mlir::Value ptr, bool isVolatile=false, uint64_t alignment=0, bool isNontemporal=false)
mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType, mlir::Type type, llvm::StringRef name, clang::CharUnits alignment, mlir::Value dynAllocSize)
mlir::Value getSignedInt(mlir::Location loc, int64_t val, unsigned numBits)
cir::WhileOp createWhile(mlir::Location loc, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> condBuilder, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> bodyBuilder, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> cleanupBuilder, cir::CleanupKind cleanupKind)
Create a while operation with a per-iteration cleanup region.
mlir::Value createMax(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::PointerType getPointerTo(mlir::Type ty, clang::LangAS langAS)
mlir::Value createExtractElement(mlir::Location loc, mlir::Value vec, uint64_t idx)
cir::VecCmpOp createVecCompare(mlir::Location loc, cir::CmpOpKind kind, mlir::Value lhs, mlir::Value rhs)
Compares lhs and rhs element-wise.
mlir::Value createIntCast(mlir::Value src, mlir::Type newTy)
mlir::Value createInsertElement(mlir::Location loc, mlir::Value vec, mlir::Value newElt, uint64_t idx)
cir::GlobalViewAttr getGlobalViewAttr(cir::PointerType type, cir::GlobalOp globalOp, llvm::ArrayRef< int64_t > indices, bool addressPoint=false)
Get constant address of a global variable as an MLIR attribute.
llvm::RoundingMode defaultConstrainedRounding
mlir::Value createBitcast(mlir::Value src, mlir::Type newTy)
mlir::Value createFMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
CIRBaseBuilderTy(mlir::MLIRContext &mlirContext)
mlir::Value createBitcast(mlir::Location loc, mlir::Value src, mlir::Type newTy)
cir::FuncType getVoidFnTy(mlir::TypeRange argTypes={})
Returns void (T...) as a cir::FuncType.
mlir::TypedAttr getNullDataMemberAttr(cir::DataMemberType ty)
mlir::Value createBuiltinIntCast(mlir::Location loc, mlir::Value src, mlir::Type newTy)
clang::LangOptions::FPExceptionModeKind defaultConstrainedExcept
cir::CallOp createIndirectCallOp(mlir::Location loc, mlir::Value indirectTarget, cir::FuncType funcType, mlir::ValueRange operands, llvm::ArrayRef< mlir::NamedAttribute > attrs={}, llvm::ArrayRef< mlir::NamedAttrList > argAttrs={}, llvm::ArrayRef< mlir::NamedAttribute > resAttrs={}, cir::CallingConv callingConv=cir::CallingConv::C)
cir::CmpOp createCompare(mlir::Location loc, cir::CmpOpKind kind, mlir::Value lhs, mlir::Value rhs)
mlir::IntegerAttr getAlignmentAttr(clang::CharUnits alignment)
mlir::Value createNot(mlir::Location loc, mlir::Value value)
void setIsFPConstrained(bool isCon)
Enable/Disable use of constrained floating point math.
mlir::Value createMin(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createSelect(mlir::Location loc, mlir::Value condition, mlir::Value trueValue, mlir::Value falseValue)
cir::ContinueOp createContinue(mlir::Location loc)
Create a continue operation.
llvm::RoundingMode getDefaultConstrainedRounding() const
Get the rounding mode handling used with constrained floating point.
mlir::Value createMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
cir::PointerType getPointerTo(mlir::Type ty, mlir::ptr::MemorySpaceAttrInterface as)
mlir::TypedAttr getZeroInitAttr(mlir::Type ty)
mlir::Value createMinus(mlir::Location loc, mlir::Value input, bool nsw=false)
CIRBaseBuilderTy(mlir::OpBuilder &builder)
mlir::Value createPtrIsNotNull(mlir::Value ptr)
static unsigned getCIRIntOrFloatBitWidth(mlir::Type eltTy)
cir::ConstantOp getConstantInt(mlir::Location loc, mlir::Type ty, int64_t value)
mlir::Value createComplexCreate(mlir::Location loc, mlir::Value real, mlir::Value imag)
mlir::Value createBoolIntToIntCast(mlir::Value src, mlir::Type newTy)
mlir::Value createAddrSpaceCast(mlir::Value src, mlir::Type newTy)
mlir::Value createComplexConj(mlir::Location loc, mlir::Value operand)
mlir::Value createPtrToBoolCast(mlir::Value v)
cir::BoolAttr getTrueAttr()
cir::PointerType getVoidPtrTy(clang::LangAS langAS=clang::LangAS::Default)
mlir::Value createFRem(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createShiftRight(mlir::Location loc, mlir::Value lhs, unsigned bits)
mlir::Value createIsNaN(mlir::Location loc, mlir::Value operand)
cir::IntType getSIntNTy(int n)
void setDefaultConstrainedExcept(clang::LangOptions::FPExceptionModeKind newExcept)
Set the exception handling to be used with constrained floating point.
mlir::Value createAlignedLoad(mlir::Location loc, mlir::Value ptr, uint64_t alignment)
bool getIsFPConstrained() const
Query for the use of constrained floating point math.
mlir::TypedAttr getConstPtrAttr(mlir::Type type, int64_t value)
mlir::Value createAddrSpaceCast(mlir::Location loc, mlir::Value src, mlir::Type newTy)
mlir::Value createDummyValue(mlir::Location loc, mlir::Type type, clang::CharUnits alignment)
cir::BoolAttr getFalseAttr()
void setDefaultConstrainedRounding(llvm::RoundingMode newRounding)
Set the rounding mode handling to be used with constrained floating point.
mlir::Value createShiftRight(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createXor(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::YieldOp createYield(mlir::Location loc, mlir::ValueRange value={})
Create a yield operation.
cir::ConstantOp getAlignment(mlir::Location loc, mlir::Type t, clang::CharUnits alignment)
mlir::Value createLogicalAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::GlobalOp createGlobal(mlir::ModuleOp mlirModule, mlir::Location loc, mlir::StringRef name, mlir::Type type, bool isConstant, cir::GlobalLinkageKind linkage, mlir::ptr::MemorySpaceAttrInterface addrSpace)
mlir::IntegerAttr getAlignmentAttr(llvm::Align alignment)
mlir::Value createFSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
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::LoadOp createFlagLoad(mlir::Location loc, mlir::Value addr)
Emit a load from an boolean flag variable.
cir::BoolType getBoolTy()
mlir::Value createComplexAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value getUnsignedInt(mlir::Location loc, uint64_t val, unsigned numBits)
GetMethodResults createGetMethod(mlir::Location loc, mlir::Value method, mlir::Value objectPtr)
mlir::Value createComplexReal(mlir::Location loc, mlir::Value operand)
This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
QuantityType getQuantity() const
Get the raw integer representation of this quantity.
Definition CharUnits.h:155
FPExceptionModeKind
Possible floating point exception behavior.
@ FPE_Strict
Strictly preserve the floating-point exception semantics.
@ FPE_MayTrap
Transformations do not cause new exceptions but may hide some.
@ FPE_Ignore
Assume that floating-point exceptions are masked.
constexpr OverflowBehavior operator|(OverflowBehavior a, OverflowBehavior b)
constexpr OverflowBehavior operator&(OverflowBehavior a, OverflowBehavior b)
constexpr OverflowBehavior & operator|=(OverflowBehavior &a, OverflowBehavior b)
constexpr OverflowBehavior & operator&=(OverflowBehavior &a, OverflowBehavior b)
mlir::ptr::MemorySpaceAttrInterface toCIRAddressSpaceAttr(mlir::MLIRContext &ctx, clang::LangAS langAS)
Convert an AST LangAS to the appropriate CIR address space attribute interface.
OverflowBehavior
constexpr bool testFlag(OverflowBehavior ob, OverflowBehavior flag)
LangAS
Defines the address space values used by the address space qualifier of QualType.
static bool metaDataNode()
static bool addressSpace()
static bool targetCodeGenInfoGetNullPointer()
static bool fastMathFlags()