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 createComplexConj(mlir::Location loc, mlir::Value operand) {
332 return cir::ComplexConjOp::create(*this, loc, operand.getType(), operand);
333 }
334
335 cir::LoadOp createLoad(mlir::Location loc, mlir::Value ptr,
336 bool isVolatile = false, uint64_t alignment = 0,
337 bool isNontemporal = false) {
338 mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
339 return cir::LoadOp::create(*this, loc, ptr, /*isDeref=*/false, isVolatile,
340 isNontemporal, alignmentAttr,
341 cir::SyncScopeKindAttr{}, cir::MemOrderAttr{},
342 /*invariant=*/false);
343 }
344
345 mlir::Value createAlignedLoad(mlir::Location loc, mlir::Value ptr,
346 uint64_t alignment) {
347 return createLoad(loc, ptr, /*isVolatile=*/false, alignment);
348 }
349
350 mlir::Value createNot(mlir::Location loc, mlir::Value value) {
351 return cir::NotOp::create(*this, loc, value);
352 }
353
354 mlir::Value createNot(mlir::Value value) {
355 return createNot(value.getLoc(), value);
356 }
357
358 /// Create a do-while operation.
359 cir::DoWhileOp createDoWhile(
360 mlir::Location loc,
361 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> condBuilder,
362 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> bodyBuilder) {
363 return cir::DoWhileOp::create(*this, loc, condBuilder, bodyBuilder);
364 }
365
366 /// Create a while operation.
367 cir::WhileOp createWhile(
368 mlir::Location loc,
369 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> condBuilder,
370 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> bodyBuilder) {
371 return cir::WhileOp::create(*this, loc, condBuilder, bodyBuilder);
372 }
373
374 /// Create a while operation with a per-iteration cleanup region.
375 cir::WhileOp createWhile(
376 mlir::Location loc,
377 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> condBuilder,
378 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> bodyBuilder,
379 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)>
380 cleanupBuilder,
381 cir::CleanupKind cleanupKind) {
382 return cir::WhileOp::create(*this, loc, condBuilder, bodyBuilder,
383 cleanupBuilder, cleanupKind);
384 }
385
386 /// Create a for operation.
387 cir::ForOp createFor(
388 mlir::Location loc,
389 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> condBuilder,
390 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> bodyBuilder,
391 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> stepBuilder) {
392 return cir::ForOp::create(*this, loc, condBuilder, bodyBuilder,
393 stepBuilder);
394 }
395
396 /// Create a for operation with a per-iteration cleanup region.
397 cir::ForOp createFor(
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 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> stepBuilder,
402 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)>
403 cleanupBuilder,
404 cir::CleanupKind cleanupKind) {
405 return cir::ForOp::create(*this, loc, condBuilder, bodyBuilder, stepBuilder,
406 cleanupBuilder, cleanupKind);
407 }
408
409 /// Create a break operation.
410 cir::BreakOp createBreak(mlir::Location loc) {
411 return cir::BreakOp::create(*this, loc);
412 }
413
414 /// Create a continue operation.
415 cir::ContinueOp createContinue(mlir::Location loc) {
416 return cir::ContinueOp::create(*this, loc);
417 }
418
419 mlir::Value createInc(mlir::Location loc, mlir::Value input,
420 bool nsw = false) {
421 return cir::IncOp::create(*this, loc, input, nsw);
422 }
423
424 mlir::Value createDec(mlir::Location loc, mlir::Value input,
425 bool nsw = false) {
426 return cir::DecOp::create(*this, loc, input, nsw);
427 }
428
429 mlir::Value createMinus(mlir::Location loc, mlir::Value input,
430 bool nsw = false) {
431 return cir::MinusOp::create(*this, loc, input, nsw);
432 }
433
434 mlir::TypedAttr getConstPtrAttr(mlir::Type type, int64_t value) {
435 return cir::ConstPtrAttr::get(type, getI64IntegerAttr(value));
436 }
437
438 mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
439 llvm::StringRef name, mlir::IntegerAttr alignment,
440 mlir::Value dynAllocSize) {
441 return cir::AllocaOp::create(*this, loc, addrType, name, alignment,
442 dynAllocSize);
443 }
444
445 mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
446 mlir::Type type, llvm::StringRef name,
447 clang::CharUnits alignment,
448 mlir::Value dynAllocSize) {
449 mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
450 return createAlloca(loc, addrType, name, alignmentAttr, dynAllocSize);
451 }
452
453 mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
454 llvm::StringRef name, mlir::IntegerAttr alignment) {
455 return cir::AllocaOp::create(*this, loc, addrType, name, alignment);
456 }
457
458 mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
459 llvm::StringRef name, clang::CharUnits alignment) {
460 mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
461 return createAlloca(loc, addrType, name, alignmentAttr);
462 }
463
464 /// Get constant address of a global variable as an MLIR attribute.
465 /// This wrapper infers the attribute type through the global op.
466 cir::GlobalViewAttr getGlobalViewAttr(cir::GlobalOp globalOp,
467 mlir::ArrayAttr indices = {}) {
468 cir::PointerType type = getPointerTo(globalOp.getSymType());
469 return getGlobalViewAttr(type, globalOp, indices);
470 }
471
472 /// Get constant address of a global variable as an MLIR attribute.
473 cir::GlobalViewAttr getGlobalViewAttr(cir::PointerType type,
474 cir::GlobalOp globalOp,
475 mlir::ArrayAttr indices = {}) {
476 auto symbol = mlir::FlatSymbolRefAttr::get(globalOp.getSymNameAttr());
477 return cir::GlobalViewAttr::get(type, symbol, indices);
478 }
479
480 /// Get constant address of a global variable as an MLIR attribute.
481 /// This overload converts raw int64_t indices to an ArrayAttr.
482 cir::GlobalViewAttr getGlobalViewAttr(cir::PointerType type,
483 cir::GlobalOp globalOp,
484 llvm::ArrayRef<int64_t> indices) {
486 for (int64_t ind : indices)
487 attrs.push_back(getI64IntegerAttr(ind));
488 mlir::ArrayAttr arAttr = mlir::ArrayAttr::get(getContext(), attrs);
489 return getGlobalViewAttr(type, globalOp, arAttr);
490 }
491
492 cir::GetGlobalOp createGetGlobal(mlir::Location loc, cir::GlobalOp global,
493 bool threadLocal = false) {
494 return cir::GetGlobalOp::create(
495 *this, loc,
496 getPointerTo(global.getSymType(), global.getAddrSpaceAttr()),
497 global.getSymNameAttr(), threadLocal);
498 }
499
500 cir::GetGlobalOp createGetGlobal(cir::GlobalOp global,
501 bool threadLocal = false) {
502 return createGetGlobal(global.getLoc(), global, threadLocal);
503 }
504
505 /// Create a copy with inferred length.
506 cir::CopyOp createCopy(mlir::Value dst, mlir::Value src,
507 bool isVolatile = false,
508 bool skipTailPadding = false) {
509 return cir::CopyOp::create(*this, dst.getLoc(), dst, src,
510 /*dst_alignment=*/{}, /*src_alignment=*/{},
511 isVolatile, skipTailPadding);
512 }
513
514 cir::StoreOp createStore(mlir::Location loc, mlir::Value val, mlir::Value dst,
515 bool isVolatile = false, bool isNontemporal = false,
516 mlir::IntegerAttr align = {},
517 cir::SyncScopeKindAttr scope = {},
518 cir::MemOrderAttr order = {}) {
519 if (mlir::cast<cir::PointerType>(dst.getType()).getPointee() !=
520 val.getType())
521 dst = createPtrBitcast(dst, val.getType());
522 return cir::StoreOp::create(*this, loc, val, dst, isVolatile, isNontemporal,
523 align, scope, order);
524 }
525
526 /// Emit a load from an boolean flag variable.
527 cir::LoadOp createFlagLoad(mlir::Location loc, mlir::Value addr) {
528 mlir::Type boolTy = getBoolTy();
529 if (boolTy != mlir::cast<cir::PointerType>(addr.getType()).getPointee())
530 addr = createPtrBitcast(addr, boolTy);
531 return createLoad(loc, addr, /*isVolatile=*/false, /*alignment=*/1);
532 }
533
534 cir::StoreOp createFlagStore(mlir::Location loc, bool val, mlir::Value dst) {
535 mlir::Value flag = getBool(val, loc);
536 return CIRBaseBuilderTy::createStore(loc, flag, dst);
537 }
538
539 [[nodiscard]] cir::GlobalOp
540 createGlobal(mlir::ModuleOp mlirModule, mlir::Location loc,
541 mlir::StringRef name, mlir::Type type, bool isConstant,
542 cir::GlobalLinkageKind linkage,
543 mlir::ptr::MemorySpaceAttrInterface addrSpace) {
544 mlir::OpBuilder::InsertionGuard guard(*this);
545 setInsertionPointToStart(mlirModule.getBody());
546 return cir::GlobalOp::create(*this, loc, name, type, isConstant, addrSpace,
547 linkage);
548 }
549
550 cir::GetMemberOp createGetMember(mlir::Location loc, mlir::Type resultTy,
551 mlir::Value base, llvm::StringRef name,
552 unsigned index) {
553 return cir::GetMemberOp::create(*this, loc, resultTy, base, name, index);
554 }
555
556 mlir::Value createDummyValue(mlir::Location loc, mlir::Type type,
557 clang::CharUnits alignment) {
558 mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
559 auto addr = createAlloca(loc, getPointerTo(type), {}, alignmentAttr);
560 return cir::LoadOp::create(*this, loc, addr, /*isDeref=*/false,
561 /*isVolatile=*/false, /*nontemporal=*/false,
562 alignmentAttr,
563 /*sync_scope=*/{}, /*mem_order=*/{},
564 /*invariant=*/false);
565 }
566
567 cir::PtrStrideOp createPtrStride(mlir::Location loc, mlir::Value base,
568 mlir::Value stride) {
569 return cir::PtrStrideOp::create(*this, loc, base.getType(), base, stride);
570 }
571
572 //===--------------------------------------------------------------------===//
573 // Call operators
574 //===--------------------------------------------------------------------===//
575
576 cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee,
577 mlir::Type returnType, mlir::ValueRange operands,
581 auto op = cir::CallOp::create(*this, loc, callee, returnType, operands);
582 op->setAttrs(attrs);
583
584 if (!argAttrs.empty()) {
585 llvm::SmallVector<mlir::Attribute> argDictAttrs;
586 argDictAttrs.reserve(argAttrs.size());
587
588 llvm::transform(
589 argAttrs, std::back_inserter(argDictAttrs),
590 [this](llvm::ArrayRef<mlir::NamedAttribute> singleArgAttrs) {
591 return mlir::DictionaryAttr::get(getContext(), singleArgAttrs);
592 });
593
594 op.setArgAttrsAttr(mlir::ArrayAttr::get(getContext(), argDictAttrs));
595 }
596
597 if (!resAttrs.empty()) {
598 auto resultDictAttr = mlir::DictionaryAttr::get(getContext(), resAttrs);
599 op.setResAttrsAttr(mlir::ArrayAttr::get(getContext(), resultDictAttr));
600 }
601 return op;
602 }
603
604 cir::CallOp createCallOp(mlir::Location loc, cir::FuncOp callee,
605 mlir::ValueRange operands,
609 return createCallOp(loc, mlir::SymbolRefAttr::get(callee),
610 callee.getFunctionType().getReturnType(), operands,
611 attrs, argAttrs, resAttrs);
612 }
613
614 cir::CallOp
615 createIndirectCallOp(mlir::Location loc, mlir::Value indirectTarget,
616 cir::FuncType funcType, mlir::ValueRange operands,
620 llvm::SmallVector<mlir::Value> resOperands{indirectTarget};
621 resOperands.append(operands.begin(), operands.end());
622
623 return createCallOp(loc, mlir::SymbolRefAttr(), funcType.getReturnType(),
624 resOperands, attrs, argAttrs, resAttrs);
625 }
626
627 cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee,
628 mlir::ValueRange operands = mlir::ValueRange(),
632 return createCallOp(loc, callee, cir::VoidType(), operands, attrs, argAttrs,
633 resAttrs);
634 }
635
636 //===--------------------------------------------------------------------===//
637 // Cast/Conversion Operators
638 //===--------------------------------------------------------------------===//
639
640 mlir::Value createCast(mlir::Location loc, cir::CastKind kind,
641 mlir::Value src, mlir::Type newTy) {
642 if (newTy == src.getType())
643 return src;
644 return cir::CastOp::create(*this, loc, newTy, kind, src);
645 }
646
647 mlir::Value createCast(cir::CastKind kind, mlir::Value src,
648 mlir::Type newTy) {
649 if (newTy == src.getType())
650 return src;
651 return createCast(src.getLoc(), kind, src, newTy);
652 }
653
654 // Creates a cast from bool or int to an integer type.
655 mlir::Value createBoolIntToIntCast(mlir::Value src, mlir::Type newTy) {
656 if (newTy == src.getType())
657 return src;
658 if (src.getType() == getBoolTy())
659 return createBoolToInt(src, newTy);
660 return createIntCast(src, newTy);
661 }
662
663 mlir::Value createIntCast(mlir::Value src, mlir::Type newTy) {
664 return createCast(cir::CastKind::integral, src, newTy);
665 }
666
667 mlir::Value createBuiltinIntCast(mlir::Location loc, mlir::Value src,
668 mlir::Type newTy) {
669 return cir::BuiltinIntCastOp::create(*this, loc, newTy, src);
670 }
671
672 mlir::Value createBuiltinIntCast(mlir::Value src, mlir::Type newTy) {
673 return createBuiltinIntCast(src.getLoc(), src, newTy);
674 }
675
676 mlir::Value createIntToPtr(mlir::Value src, mlir::Type newTy) {
677 return createCast(cir::CastKind::int_to_ptr, src, newTy);
678 }
679
680 mlir::Value createPtrToInt(mlir::Value src, mlir::Type newTy) {
681 return createCast(cir::CastKind::ptr_to_int, src, newTy);
682 }
683
684 mlir::Value createPtrToBoolCast(mlir::Value v) {
685 return createCast(cir::CastKind::ptr_to_bool, v, getBoolTy());
686 }
687
688 mlir::Value createBoolToInt(mlir::Value src, mlir::Type newTy) {
689 return createCast(cir::CastKind::bool_to_int, src, newTy);
690 }
691
692 mlir::Value createBitcast(mlir::Value src, mlir::Type newTy) {
693 return createCast(cir::CastKind::bitcast, src, newTy);
694 }
695
696 mlir::Value createBitcast(mlir::Location loc, mlir::Value src,
697 mlir::Type newTy) {
698 return createCast(loc, cir::CastKind::bitcast, src, newTy);
699 }
700
701 mlir::Value createPtrBitcast(mlir::Value src, mlir::Type newPointeeTy) {
702 assert(mlir::isa<cir::PointerType>(src.getType()) && "expected ptr src");
703 cir::PointerType srcPtrTy = mlir::cast<cir::PointerType>(src.getType());
704 return createBitcast(src,
705 getPointerTo(newPointeeTy, srcPtrTy.getAddrSpace()));
706 }
707
708 mlir::Value createPtrIsNull(mlir::Value ptr) {
709 mlir::Value nullPtr = getNullPtr(ptr.getType(), ptr.getLoc());
710 return createCompare(ptr.getLoc(), cir::CmpOpKind::eq, ptr, nullPtr);
711 }
712
713 mlir::Value createPtrIsNotNull(mlir::Value ptr) {
714 mlir::Value nullPtr = getNullPtr(ptr.getType(), ptr.getLoc());
715 return createCompare(ptr.getLoc(), cir::CmpOpKind::ne, ptr, nullPtr);
716 }
717
718 mlir::Value createAddrSpaceCast(mlir::Location loc, mlir::Value src,
719 mlir::Type newTy) {
720 return createCast(loc, cir::CastKind::address_space, src, newTy);
721 }
722
723 mlir::Value createAddrSpaceCast(mlir::Value src, mlir::Type newTy) {
724 return createAddrSpaceCast(src.getLoc(), src, newTy);
725 }
726
727 //===--------------------------------------------------------------------===//
728 // Other Instructions
729 //===--------------------------------------------------------------------===//
730
731 mlir::Value createExtractElement(mlir::Location loc, mlir::Value vec,
732 uint64_t idx) {
733 mlir::Value idxVal =
734 getConstAPInt(loc, getUIntNTy(64), llvm::APInt(64, idx));
735 return cir::VecExtractOp::create(*this, loc, vec, idxVal);
736 }
737
738 mlir::Value createInsertElement(mlir::Location loc, mlir::Value vec,
739 mlir::Value newElt, uint64_t idx) {
740 mlir::Value idxVal =
741 getConstAPInt(loc, getUIntNTy(64), llvm::APInt(64, idx));
742 return cir::VecInsertOp::create(*this, loc, vec, newElt, idxVal);
743 }
744
745 cir::SignBitOp createSignBit(mlir::Location loc, mlir::Value val) {
746 auto resTy = cir::BoolType::get(getContext());
747 return cir::SignBitOp::create(*this, loc, resTy, val);
748 }
749
750 //===--------------------------------------------------------------------===//
751 // Binary Operators
752 //===--------------------------------------------------------------------===//
753
754 mlir::Value createLowBitsSet(mlir::Location loc, unsigned size,
755 unsigned bits) {
756 llvm::APInt val = llvm::APInt::getLowBitsSet(size, bits);
757 auto type = cir::IntType::get(getContext(), size, /*isSigned=*/false);
758 return getConstAPInt(loc, type, val);
759 }
760
761 mlir::Value createAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
762 return cir::AndOp::create(*this, loc, lhs, rhs);
763 }
764
765 mlir::Value createOr(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
766 return cir::OrOp::create(*this, loc, lhs, rhs);
767 }
768
769 mlir::Value createSelect(mlir::Location loc, mlir::Value condition,
770 mlir::Value trueValue, mlir::Value falseValue) {
771 assert(trueValue.getType() == falseValue.getType() &&
772 "trueValue and falseValue should have the same type");
773 return cir::SelectOp::create(*this, loc, trueValue.getType(), condition,
774 trueValue, falseValue);
775 }
776
777 mlir::Value createLogicalAnd(mlir::Location loc, mlir::Value lhs,
778 mlir::Value rhs) {
779 return createSelect(loc, lhs, rhs, getBool(false, loc));
780 }
781
782 mlir::Value createLogicalOr(mlir::Location loc, mlir::Value lhs,
783 mlir::Value rhs) {
784 return createSelect(loc, lhs, getBool(true, loc), rhs);
785 }
786
787 mlir::Value createMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
789 auto op = cir::MulOp::create(*this, loc, lhs, rhs);
790 op.setNoUnsignedWrap(testFlag(ob, OverflowBehavior::NoUnsignedWrap));
791 op.setNoSignedWrap(testFlag(ob, OverflowBehavior::NoSignedWrap));
792 return op;
793 }
794 mlir::Value createNSWMul(mlir::Location loc, mlir::Value lhs,
795 mlir::Value rhs) {
796 return createMul(loc, lhs, rhs, OverflowBehavior::NoSignedWrap);
797 }
798 mlir::Value createNUWAMul(mlir::Location loc, mlir::Value lhs,
799 mlir::Value rhs) {
800 return createMul(loc, lhs, rhs, OverflowBehavior::NoUnsignedWrap);
801 }
802
803 mlir::Value createSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
805 auto op = cir::SubOp::create(*this, loc, lhs, rhs);
806 op.setNoUnsignedWrap(testFlag(ob, OverflowBehavior::NoUnsignedWrap));
807 op.setNoSignedWrap(testFlag(ob, OverflowBehavior::NoSignedWrap));
808 op.setSaturated(testFlag(ob, OverflowBehavior::Saturated));
809 return op;
810 }
811
812 mlir::Value createNSWSub(mlir::Location loc, mlir::Value lhs,
813 mlir::Value rhs) {
814 return createSub(loc, lhs, rhs, OverflowBehavior::NoSignedWrap);
815 }
816
817 mlir::Value createNUWSub(mlir::Location loc, mlir::Value lhs,
818 mlir::Value rhs) {
819 return createSub(loc, lhs, rhs, OverflowBehavior::NoUnsignedWrap);
820 }
821
822 mlir::Value createAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
824 auto op = cir::AddOp::create(*this, loc, lhs, rhs);
825 op.setNoUnsignedWrap(testFlag(ob, OverflowBehavior::NoUnsignedWrap));
826 op.setNoSignedWrap(testFlag(ob, OverflowBehavior::NoSignedWrap));
827 op.setSaturated(testFlag(ob, OverflowBehavior::Saturated));
828 return op;
829 }
830
831 mlir::Value createNSWAdd(mlir::Location loc, mlir::Value lhs,
832 mlir::Value rhs) {
833 return createAdd(loc, lhs, rhs, OverflowBehavior::NoSignedWrap);
834 }
835
836 mlir::Value createNUWAdd(mlir::Location loc, mlir::Value lhs,
837 mlir::Value rhs) {
838 return createAdd(loc, lhs, rhs, OverflowBehavior::NoUnsignedWrap);
839 }
840
841 mlir::Value createDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
842 return cir::DivOp::create(*this, loc, lhs, rhs);
843 }
844
845 mlir::Value createRem(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
846 return cir::RemOp::create(*this, loc, lhs, rhs);
847 }
848
849 mlir::Value createFAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
852 return cir::FAddOp::create(*this, loc, lhs, rhs, getConstrainedFPAttr());
853 }
854
855 mlir::Value createFSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
858 return cir::FSubOp::create(*this, loc, lhs, rhs, getConstrainedFPAttr());
859 }
860
861 mlir::Value createFMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
864 return cir::FMulOp::create(*this, loc, lhs, rhs, getConstrainedFPAttr());
865 }
866
867 mlir::Value createFDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
870 return cir::FDivOp::create(*this, loc, lhs, rhs, getConstrainedFPAttr());
871 }
872
873 mlir::Value createFRem(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
876 return cir::FRemOp::create(*this, loc, lhs, rhs, getConstrainedFPAttr());
877 }
878
879 mlir::Value createFNeg(mlir::Location loc, mlir::Value operand) {
880 assert(cir::isFPOrVectorOfFPType(operand.getType()) &&
881 "expected floating-point or vector-of-float type");
884 // fneg does not raise FP exceptions or depend on the rounding mode, so it
885 // never carries an fenv attribute.
886 return cir::FNegOp::create(*this, loc, operand);
887 }
888
889 mlir::Value createXor(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
890 return cir::XorOp::create(*this, loc, lhs, rhs);
891 }
892
893 mlir::Value createMax(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
894 return cir::MaxOp::create(*this, loc, lhs, rhs);
895 }
896
897 mlir::Value createMin(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
898 return cir::MinOp::create(*this, loc, lhs, rhs);
899 }
900
901 cir::CmpOp createCompare(mlir::Location loc, cir::CmpOpKind kind,
902 mlir::Value lhs, mlir::Value rhs) {
903 cir::FenvAttr fenv;
904 if (cir::isAnyFloatingPointType(lhs.getType()))
905 fenv = getConstrainedFPAttr();
906 return cir::CmpOp::create(*this, loc, kind, lhs, rhs, fenv);
907 }
908
909 cir::VecCmpOp createVecCompare(mlir::Location loc, cir::CmpOpKind kind,
910 mlir::Value lhs, mlir::Value rhs) {
911 VectorType vecCast = mlir::cast<VectorType>(lhs.getType());
912 IntType integralTy =
913 getSIntNTy(getCIRIntOrFloatBitWidth(vecCast.getElementType()));
914 VectorType integralVecTy =
915 cir::VectorType::get(integralTy, vecCast.getSize());
916 cir::FenvAttr fenv;
917 if (cir::isFPOrVectorOfFPType(lhs.getType()))
918 fenv = getConstrainedFPAttr();
919 return cir::VecCmpOp::create(*this, loc, integralVecTy, kind, lhs, rhs,
920 fenv);
921 }
922
923 mlir::Value createIsNaN(mlir::Location loc, mlir::Value operand) {
924 return createCompare(loc, cir::CmpOpKind::ne, operand, operand);
925 }
926
927 mlir::Value createShift(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
928 bool isShiftLeft) {
929 return cir::ShiftOp::create(*this, loc, lhs.getType(), lhs, rhs,
930 isShiftLeft);
931 }
932
933 mlir::Value createShift(mlir::Location loc, mlir::Value lhs,
934 const llvm::APInt &rhs, bool isShiftLeft) {
935 return createShift(loc, lhs, getConstAPInt(loc, lhs.getType(), rhs),
936 isShiftLeft);
937 }
938
939 mlir::Value createShift(mlir::Location loc, mlir::Value lhs, unsigned bits,
940 bool isShiftLeft) {
941 auto width = mlir::dyn_cast<cir::IntType>(lhs.getType()).getWidth();
942 auto shift = llvm::APInt(width, bits);
943 return createShift(loc, lhs, shift, isShiftLeft);
944 }
945
946 mlir::Value createShiftLeft(mlir::Location loc, mlir::Value lhs,
947 unsigned bits) {
948 return createShift(loc, lhs, bits, true);
949 }
950
951 mlir::Value createShiftRight(mlir::Location loc, mlir::Value lhs,
952 unsigned bits) {
953 return createShift(loc, lhs, bits, false);
954 }
955
956 mlir::Value createShiftLeft(mlir::Location loc, mlir::Value lhs,
957 mlir::Value rhs) {
958 return createShift(loc, lhs, rhs, true);
959 }
960
961 mlir::Value createShiftRight(mlir::Location loc, mlir::Value lhs,
962 mlir::Value rhs) {
963 return createShift(loc, lhs, rhs, false);
964 }
965
966 /// Returns `void (T...)` as a cir::FuncType.
967 cir::FuncType getVoidFnTy(mlir::TypeRange argTypes = {}) {
968 return cir::FuncType::get(llvm::to_vector(argTypes), getVoidTy());
969 }
970
971 /// Returns `void (*)(T...)` as a cir::PointerType.
972 cir::PointerType getVoidFnPtrTy(mlir::TypeRange argTypes = {}) {
973 return getPointerTo(getVoidFnTy(argTypes));
974 }
975
976 //
977 // Block handling helpers
978 // ----------------------
979 //
980 static OpBuilder::InsertPoint getBestAllocaInsertPoint(mlir::Block *block) {
981 auto last =
982 std::find_if(block->rbegin(), block->rend(), [](mlir::Operation &op) {
983 return mlir::isa<cir::AllocaOp, cir::LabelOp>(&op);
984 });
985
986 if (last != block->rend())
987 return OpBuilder::InsertPoint(block, ++mlir::Block::iterator(&*last));
988 return OpBuilder::InsertPoint(block, block->begin());
989 };
990
991 //
992 // Alignment and size helpers
993 //
994
995 // Note that mlir::IntegerType is used instead of cir::IntType here because we
996 // don't need sign information for these to be useful, so keep it simple.
997
998 // For 0 alignment, any overload of `getAlignmentAttr` returns an empty
999 // attribute.
1000 mlir::IntegerAttr getAlignmentAttr(clang::CharUnits alignment) {
1001 return getAlignmentAttr(alignment.getQuantity());
1002 }
1003
1004 mlir::IntegerAttr getAlignmentAttr(llvm::Align alignment) {
1005 return getAlignmentAttr(alignment.value());
1006 }
1007
1008 mlir::IntegerAttr getAlignmentAttr(int64_t alignment) {
1009 return alignment ? getI64IntegerAttr(alignment) : mlir::IntegerAttr();
1010 }
1011
1012 // Materialize an alignment value as a CIR integer constant of the given
1013 // integer type.
1014 cir::ConstantOp getAlignment(mlir::Location loc, mlir::Type t,
1015 clang::CharUnits alignment) {
1016 return getConstantInt(loc, t, alignment.getQuantity());
1017 }
1018
1019 mlir::IntegerAttr getSizeFromCharUnits(clang::CharUnits size) {
1020 return getI64IntegerAttr(size.getQuantity());
1021 }
1022
1023 // Creates constant nullptr for pointer type ty.
1024 cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc) {
1026 return cir::ConstantOp::create(*this, loc, getConstPtrAttr(ty, 0));
1027 }
1028
1029 /// Create a loop condition.
1030 cir::ConditionOp createCondition(mlir::Value condition) {
1031 return cir::ConditionOp::create(*this, condition.getLoc(), condition);
1032 }
1033
1034 /// Create a yield operation.
1035 cir::YieldOp createYield(mlir::Location loc, mlir::ValueRange value = {}) {
1036 return cir::YieldOp::create(*this, loc, value);
1037 }
1038
1040 mlir::Value callee;
1041 mlir::Value adjustedThis;
1042 };
1043
1044 GetMethodResults createGetMethod(mlir::Location loc, mlir::Value method,
1045 mlir::Value objectPtr) {
1046 // Build the callee function type.
1047 auto methodFuncTy =
1048 mlir::cast<cir::MethodType>(method.getType()).getMemberFuncTy();
1049 auto methodFuncInputTypes = methodFuncTy.getInputs();
1050
1051 auto objectPtrTy = mlir::cast<cir::PointerType>(objectPtr.getType());
1052 mlir::Type adjustedThisTy = getVoidPtrTy(objectPtrTy.getAddrSpace());
1053
1054 llvm::SmallVector<mlir::Type> calleeFuncInputTypes{adjustedThisTy};
1055 // The member function type's first parameter is the implicit 'this'
1056 // pointer. The callee takes an adjusted void* receiver instead.
1057 if (methodFuncInputTypes.size() > 1)
1058 calleeFuncInputTypes.insert(calleeFuncInputTypes.end(),
1059 methodFuncInputTypes.begin() + 1,
1060 methodFuncInputTypes.end());
1061 cir::FuncType calleeFuncTy =
1062 methodFuncTy.clone(calleeFuncInputTypes, methodFuncTy.getReturnType());
1063 // TODO(cir): consider the address space of the callee.
1065 cir::PointerType calleeTy = getPointerTo(calleeFuncTy);
1066
1067 auto op = cir::GetMethodOp::create(*this, loc, calleeTy, adjustedThisTy,
1068 method, objectPtr);
1069 return {op.getCallee(), op.getAdjustedThis()};
1070 }
1071};
1072
1073} // namespace cir
1074
1075#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)
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)
cir::GlobalViewAttr getGlobalViewAttr(cir::PointerType type, cir::GlobalOp globalOp, mlir::ArrayAttr indices={})
Get constant address of a global variable as an MLIR attribute.
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.
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 createAlloca(mlir::Location loc, cir::PointerType addrType, llvm::StringRef name, clang::CharUnits alignment)
mlir::Value createNot(mlir::Value value)
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::GetGlobalOp createGetGlobal(cir::GlobalOp global, bool threadLocal=false)
cir::IntType getUIntNTy(int n)
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)
mlir::Value createIntCast(mlir::Value src, mlir::Type newTy)
mlir::Value createInsertElement(mlir::Location loc, mlir::Value vec, mlir::Value newElt, uint64_t idx)
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::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::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::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)
cir::GlobalViewAttr getGlobalViewAttr(cir::PointerType type, cir::GlobalOp globalOp, llvm::ArrayRef< int64_t > indices)
Get constant address of a global variable as an MLIR attribute.
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)
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={})
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::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::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 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:153
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()