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 (mlir::isa<cir::IntType>(ty))
120 return cir::IntAttr::get(ty, 0);
121 if (cir::isAnyFloatingPointType(ty))
122 return cir::FPAttr::getZero(ty);
123 if (auto complexType = mlir::dyn_cast<cir::ComplexType>(ty))
124 return cir::ZeroAttr::get(complexType);
125 if (auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty))
126 return cir::ZeroAttr::get(arrTy);
127 if (auto vecTy = mlir::dyn_cast<cir::VectorType>(ty))
128 return cir::ZeroAttr::get(vecTy);
129 if (auto ptrTy = mlir::dyn_cast<cir::PointerType>(ty))
130 return getConstNullPtrAttr(ptrTy);
131 if (auto recordTy = mlir::dyn_cast<cir::RecordType>(ty))
132 return cir::ZeroAttr::get(recordTy);
133 if (auto dataMemberTy = mlir::dyn_cast<cir::DataMemberType>(ty))
134 return getNullDataMemberAttr(dataMemberTy);
135 if (auto methodTy = mlir::dyn_cast<cir::MethodType>(ty))
136 return getNullMethodAttr(methodTy);
137 if (auto vptrTy = mlir::dyn_cast<cir::VPtrType>(ty))
138 return cir::ZeroAttr::get(vptrTy);
139 if (mlir::isa<cir::BoolType>(ty)) {
140 return getFalseAttr();
141 }
142
143 llvm_unreachable("Zero initializer for given type is NYI");
144 }
145
146 cir::ConstantOp getBool(bool state, mlir::Location loc) {
147 return cir::ConstantOp::create(*this, loc, getCIRBoolAttr(state));
148 }
149 cir::ConstantOp getFalse(mlir::Location loc) { return getBool(false, loc); }
150 cir::ConstantOp getTrue(mlir::Location loc) { return getBool(true, loc); }
151
152 cir::BoolType getBoolTy() { return cir::BoolType::get(getContext()); }
153 cir::VoidType getVoidTy() { return cir::VoidType::get(getContext()); }
154
155 cir::IntType getUIntNTy(int n) {
156 return cir::IntType::get(getContext(), n, false);
157 }
158
159 static unsigned getCIRIntOrFloatBitWidth(mlir::Type eltTy) {
160 if (auto intType = mlir::dyn_cast<cir::IntTypeInterface>(eltTy))
161 return intType.getWidth();
162 if (auto floatType = mlir::dyn_cast<cir::FPTypeInterface>(eltTy))
163 return floatType.getWidth();
164
165 llvm_unreachable("Unsupported type in getCIRIntOrFloatBitWidth");
166 }
167 cir::IntType getSIntNTy(int n) {
168 return cir::IntType::get(getContext(), n, true);
169 }
170
171 cir::PointerType getPointerTo(mlir::Type ty) {
172 return cir::PointerType::get(ty);
173 }
174
175 cir::PointerType getPointerTo(mlir::Type ty,
176 mlir::ptr::MemorySpaceAttrInterface as) {
177 return cir::PointerType::get(ty, as);
178 }
179
180 cir::PointerType getPointerTo(mlir::Type ty, clang::LangAS langAS) {
181 if (langAS == clang::LangAS::Default)
182 return getPointerTo(ty);
183
184 mlir::ptr::MemorySpaceAttrInterface addrSpaceAttr =
185 cir::toCIRAddressSpaceAttr(*getContext(), langAS);
186 return getPointerTo(ty, addrSpaceAttr);
187 }
188
190 return getPointerTo(cir::VoidType::get(getContext()), langAS);
191 }
192
193 cir::PointerType getVoidPtrTy(mlir::ptr::MemorySpaceAttrInterface as) {
194 return getPointerTo(cir::VoidType::get(getContext()), as);
195 }
196
197 cir::MethodAttr getMethodAttr(cir::MethodType ty, cir::FuncOp methodFuncOp) {
198 auto methodFuncSymbolRef = mlir::FlatSymbolRefAttr::get(methodFuncOp);
199 return cir::MethodAttr::get(ty, methodFuncSymbolRef);
200 }
201
202 cir::MethodAttr getNullMethodAttr(cir::MethodType ty) {
203 return cir::MethodAttr::get(ty);
204 }
205
206 cir::BoolAttr getCIRBoolAttr(bool state) {
207 return cir::BoolAttr::get(getContext(), state);
208 }
209
210 cir::BoolAttr getTrueAttr() { return getCIRBoolAttr(true); }
211 cir::BoolAttr getFalseAttr() { return getCIRBoolAttr(false); }
212
213 //
214 // Floating point specific helpers
215 // -------------------------------
216 //
217
218 /// Enable/Disable use of constrained floating point math. When enabled the
219 /// CreateF<op>() calls instead create constrained floating point intrinsic
220 /// calls. Fast math flags are unaffected by this setting.
221 void setIsFPConstrained(bool isCon) { isFPConstrained = isCon; }
222
223 /// Query for the use of constrained floating point math
224 bool getIsFPConstrained() const { return isFPConstrained; }
225
226 /// Set the exception handling to be used with constrained floating point
231
232 /// Get the exception handling used with constrained floating point
236
237 /// Set the rounding mode handling to be used with constrained floating point
238 void setDefaultConstrainedRounding(llvm::RoundingMode newRounding) {
239 defaultConstrainedRounding = newRounding;
240 }
241
242 /// Get the rounding mode handling used with constrained floating point
243 llvm::RoundingMode getDefaultConstrainedRounding() const {
245 }
246
247 /// Build the `#cir.fenv` attribute describing the constrained floating-point
248 /// environment currently in effect. This is attached to floating-point
249 /// operations that support it to capture the rounding and exception
250 /// behavior. Returns a null attribute when constrained floating-point is not
251 /// enabled, in which case no attribute should be attached.
252 cir::FenvAttr getConstrainedFPAttr() {
253 if (!isFPConstrained)
254 return {};
255
256 cir::FPDynamicRoundingMode roundingMode;
258 case llvm::RoundingMode::NearestTiesToEven:
259 roundingMode = cir::FPDynamicRoundingMode::ToNearest;
260 break;
261 case llvm::RoundingMode::TowardNegative:
262 roundingMode = cir::FPDynamicRoundingMode::Downward;
263 break;
264 case llvm::RoundingMode::TowardPositive:
265 roundingMode = cir::FPDynamicRoundingMode::Upward;
266 break;
267 case llvm::RoundingMode::TowardZero:
268 roundingMode = cir::FPDynamicRoundingMode::UpwardZero;
269 break;
270 case llvm::RoundingMode::NearestTiesToAway:
271 roundingMode = cir::FPDynamicRoundingMode::ToNearestAway;
272 break;
273 case llvm::RoundingMode::Dynamic:
274 roundingMode = cir::FPDynamicRoundingMode::Unknown;
275 break;
276 default:
277 llvm_unreachable("unexpected constrained rounding mode");
278 }
279
280 cir::FPExceptionMode exceptMode;
281 bool strictExcept;
282 switch (defaultConstrainedExcept) {
284 exceptMode = cir::FPExceptionMode::Masked;
285 strictExcept = false;
286 break;
288 exceptMode = cir::FPExceptionMode::Unknown;
289 strictExcept = false;
290 break;
292 exceptMode = cir::FPExceptionMode::Unknown;
293 strictExcept = true;
294 break;
295 default:
296 llvm_unreachable("unexpected constrained exception mode");
297 }
298
299 return cir::FenvAttr::get(getContext(), roundingMode, exceptMode,
300 mlir::BoolAttr::get(getContext(), strictExcept));
301 }
302
303 mlir::Value createComplexCreate(mlir::Location loc, mlir::Value real,
304 mlir::Value imag) {
305 auto resultComplexTy = cir::ComplexType::get(real.getType());
306 return cir::ComplexCreateOp::create(*this, loc, resultComplexTy, real,
307 imag);
308 }
309
310 mlir::Value createComplexReal(mlir::Location loc, mlir::Value operand) {
311 auto resultType = operand.getType();
312 if (auto complexResultType = mlir::dyn_cast<cir::ComplexType>(resultType))
313 resultType = complexResultType.getElementType();
314 return cir::ComplexRealOp::create(*this, loc, resultType, operand);
315 }
316
317 mlir::Value createComplexImag(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::ComplexImagOp::create(*this, loc, resultType, operand);
322 }
323
324 mlir::Value createComplexConj(mlir::Location loc, mlir::Value operand) {
325 return cir::ComplexConjOp::create(*this, loc, operand.getType(), operand);
326 }
327
328 cir::LoadOp createLoad(mlir::Location loc, mlir::Value ptr,
329 bool isVolatile = false, uint64_t alignment = 0,
330 bool isNontemporal = false) {
331 mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
332 return cir::LoadOp::create(*this, loc, ptr, /*isDeref=*/false, isVolatile,
333 isNontemporal, alignmentAttr,
334 cir::SyncScopeKindAttr{}, cir::MemOrderAttr{},
335 /*invariant=*/false);
336 }
337
338 mlir::Value createAlignedLoad(mlir::Location loc, mlir::Value ptr,
339 uint64_t alignment) {
340 return createLoad(loc, ptr, /*isVolatile=*/false, alignment);
341 }
342
343 mlir::Value createNot(mlir::Location loc, mlir::Value value) {
344 return cir::NotOp::create(*this, loc, value);
345 }
346
347 mlir::Value createNot(mlir::Value value) {
348 return createNot(value.getLoc(), value);
349 }
350
351 /// Create a do-while operation.
352 cir::DoWhileOp createDoWhile(
353 mlir::Location loc,
354 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> condBuilder,
355 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> bodyBuilder) {
356 return cir::DoWhileOp::create(*this, loc, condBuilder, bodyBuilder);
357 }
358
359 /// Create a while operation.
360 cir::WhileOp createWhile(
361 mlir::Location loc,
362 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> condBuilder,
363 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> bodyBuilder) {
364 return cir::WhileOp::create(*this, loc, condBuilder, bodyBuilder);
365 }
366
367 /// Create a while operation with a per-iteration cleanup region.
368 cir::WhileOp createWhile(
369 mlir::Location loc,
370 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> condBuilder,
371 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> bodyBuilder,
372 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)>
373 cleanupBuilder,
374 cir::CleanupKind cleanupKind) {
375 return cir::WhileOp::create(*this, loc, condBuilder, bodyBuilder,
376 cleanupBuilder, cleanupKind);
377 }
378
379 /// Create a for operation.
380 cir::ForOp createFor(
381 mlir::Location loc,
382 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> condBuilder,
383 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> bodyBuilder,
384 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> stepBuilder) {
385 return cir::ForOp::create(*this, loc, condBuilder, bodyBuilder,
386 stepBuilder);
387 }
388
389 /// Create a for operation with a per-iteration cleanup region.
390 cir::ForOp createFor(
391 mlir::Location loc,
392 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> condBuilder,
393 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> bodyBuilder,
394 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> stepBuilder,
395 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)>
396 cleanupBuilder,
397 cir::CleanupKind cleanupKind) {
398 return cir::ForOp::create(*this, loc, condBuilder, bodyBuilder, stepBuilder,
399 cleanupBuilder, cleanupKind);
400 }
401
402 /// Create a break operation.
403 cir::BreakOp createBreak(mlir::Location loc) {
404 return cir::BreakOp::create(*this, loc);
405 }
406
407 /// Create a continue operation.
408 cir::ContinueOp createContinue(mlir::Location loc) {
409 return cir::ContinueOp::create(*this, loc);
410 }
411
412 mlir::Value createInc(mlir::Location loc, mlir::Value input,
413 bool nsw = false) {
414 return cir::IncOp::create(*this, loc, input, nsw);
415 }
416
417 mlir::Value createDec(mlir::Location loc, mlir::Value input,
418 bool nsw = false) {
419 return cir::DecOp::create(*this, loc, input, nsw);
420 }
421
422 mlir::Value createMinus(mlir::Location loc, mlir::Value input,
423 bool nsw = false) {
424 return cir::MinusOp::create(*this, loc, input, nsw);
425 }
426
427 mlir::TypedAttr getConstPtrAttr(mlir::Type type, int64_t value) {
428 return cir::ConstPtrAttr::get(type, getI64IntegerAttr(value));
429 }
430
431 mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
432 llvm::StringRef name, mlir::IntegerAttr alignment,
433 mlir::Value dynAllocSize) {
434 return cir::AllocaOp::create(*this, loc, addrType, name, alignment,
435 dynAllocSize);
436 }
437
438 mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
439 mlir::Type type, llvm::StringRef name,
440 clang::CharUnits alignment,
441 mlir::Value dynAllocSize) {
442 mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
443 return createAlloca(loc, addrType, name, alignmentAttr, dynAllocSize);
444 }
445
446 mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
447 llvm::StringRef name, mlir::IntegerAttr alignment) {
448 return cir::AllocaOp::create(*this, loc, addrType, name, alignment);
449 }
450
451 mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
452 llvm::StringRef name, clang::CharUnits alignment) {
453 mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
454 return createAlloca(loc, addrType, name, alignmentAttr);
455 }
456
457 /// Get constant address of a global variable as an MLIR attribute.
458 /// This wrapper infers the attribute type through the global op.
459 cir::GlobalViewAttr getGlobalViewAttr(cir::GlobalOp globalOp,
460 mlir::ArrayAttr indices = {}) {
461 cir::PointerType type = getPointerTo(globalOp.getSymType());
462 return getGlobalViewAttr(type, globalOp, indices);
463 }
464
465 /// Get constant address of a global variable as an MLIR attribute.
466 cir::GlobalViewAttr getGlobalViewAttr(cir::PointerType type,
467 cir::GlobalOp globalOp,
468 mlir::ArrayAttr indices = {}) {
469 auto symbol = mlir::FlatSymbolRefAttr::get(globalOp.getSymNameAttr());
470 return cir::GlobalViewAttr::get(type, symbol, indices);
471 }
472
473 /// Get constant address of a global variable as an MLIR attribute.
474 /// This overload converts raw int64_t indices to an ArrayAttr.
475 cir::GlobalViewAttr getGlobalViewAttr(cir::PointerType type,
476 cir::GlobalOp globalOp,
477 llvm::ArrayRef<int64_t> indices) {
479 for (int64_t ind : indices)
480 attrs.push_back(getI64IntegerAttr(ind));
481 mlir::ArrayAttr arAttr = mlir::ArrayAttr::get(getContext(), attrs);
482 return getGlobalViewAttr(type, globalOp, arAttr);
483 }
484
485 cir::GetGlobalOp createGetGlobal(mlir::Location loc, cir::GlobalOp global,
486 bool threadLocal = false) {
488 return cir::GetGlobalOp::create(*this, loc,
489 getPointerTo(global.getSymType()),
490 global.getSymNameAttr(), threadLocal);
491 }
492
493 cir::GetGlobalOp createGetGlobal(cir::GlobalOp global,
494 bool threadLocal = false) {
495 return createGetGlobal(global.getLoc(), global, threadLocal);
496 }
497
498 /// Create a copy with inferred length.
499 cir::CopyOp createCopy(mlir::Value dst, mlir::Value src,
500 bool isVolatile = false,
501 bool skipTailPadding = false) {
502 return cir::CopyOp::create(*this, dst.getLoc(), dst, src,
503 /*dst_alignment=*/{}, /*src_alignment=*/{},
504 isVolatile, skipTailPadding);
505 }
506
507 cir::StoreOp createStore(mlir::Location loc, mlir::Value val, mlir::Value dst,
508 bool isVolatile = false, bool isNontemporal = false,
509 mlir::IntegerAttr align = {},
510 cir::SyncScopeKindAttr scope = {},
511 cir::MemOrderAttr order = {}) {
512 if (mlir::cast<cir::PointerType>(dst.getType()).getPointee() !=
513 val.getType())
514 dst = createPtrBitcast(dst, val.getType());
515 return cir::StoreOp::create(*this, loc, val, dst, isVolatile, isNontemporal,
516 align, scope, order);
517 }
518
519 /// Emit a load from an boolean flag variable.
520 cir::LoadOp createFlagLoad(mlir::Location loc, mlir::Value addr) {
521 mlir::Type boolTy = getBoolTy();
522 if (boolTy != mlir::cast<cir::PointerType>(addr.getType()).getPointee())
523 addr = createPtrBitcast(addr, boolTy);
524 return createLoad(loc, addr, /*isVolatile=*/false, /*alignment=*/1);
525 }
526
527 cir::StoreOp createFlagStore(mlir::Location loc, bool val, mlir::Value dst) {
528 mlir::Value flag = getBool(val, loc);
529 return CIRBaseBuilderTy::createStore(loc, flag, dst);
530 }
531
532 [[nodiscard]] cir::GlobalOp
533 createGlobal(mlir::ModuleOp mlirModule, mlir::Location loc,
534 mlir::StringRef name, mlir::Type type, bool isConstant,
535 cir::GlobalLinkageKind linkage,
536 mlir::ptr::MemorySpaceAttrInterface addrSpace) {
537 mlir::OpBuilder::InsertionGuard guard(*this);
538 setInsertionPointToStart(mlirModule.getBody());
539 return cir::GlobalOp::create(*this, loc, name, type, isConstant, addrSpace,
540 linkage);
541 }
542
543 cir::GetMemberOp createGetMember(mlir::Location loc, mlir::Type resultTy,
544 mlir::Value base, llvm::StringRef name,
545 unsigned index) {
546 return cir::GetMemberOp::create(*this, loc, resultTy, base, name, index);
547 }
548
549 mlir::Value createDummyValue(mlir::Location loc, mlir::Type type,
550 clang::CharUnits alignment) {
551 mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
552 auto addr = createAlloca(loc, getPointerTo(type), {}, alignmentAttr);
553 return cir::LoadOp::create(*this, loc, addr, /*isDeref=*/false,
554 /*isVolatile=*/false, /*nontemporal=*/false,
555 alignmentAttr,
556 /*sync_scope=*/{}, /*mem_order=*/{},
557 /*invariant=*/false);
558 }
559
560 cir::PtrStrideOp createPtrStride(mlir::Location loc, mlir::Value base,
561 mlir::Value stride) {
562 return cir::PtrStrideOp::create(*this, loc, base.getType(), base, stride);
563 }
564
565 //===--------------------------------------------------------------------===//
566 // Call operators
567 //===--------------------------------------------------------------------===//
568
569 cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee,
570 mlir::Type returnType, mlir::ValueRange operands,
574 auto op = cir::CallOp::create(*this, loc, callee, returnType, operands);
575 op->setAttrs(attrs);
576
577 if (!argAttrs.empty()) {
578 llvm::SmallVector<mlir::Attribute> argDictAttrs;
579 argDictAttrs.reserve(argAttrs.size());
580
581 llvm::transform(
582 argAttrs, std::back_inserter(argDictAttrs),
583 [this](llvm::ArrayRef<mlir::NamedAttribute> singleArgAttrs) {
584 return mlir::DictionaryAttr::get(getContext(), singleArgAttrs);
585 });
586
587 op.setArgAttrsAttr(mlir::ArrayAttr::get(getContext(), argDictAttrs));
588 }
589
590 if (!resAttrs.empty()) {
591 auto resultDictAttr = mlir::DictionaryAttr::get(getContext(), resAttrs);
592 op.setResAttrsAttr(mlir::ArrayAttr::get(getContext(), resultDictAttr));
593 }
594 return op;
595 }
596
597 cir::CallOp createCallOp(mlir::Location loc, cir::FuncOp callee,
598 mlir::ValueRange operands,
602 return createCallOp(loc, mlir::SymbolRefAttr::get(callee),
603 callee.getFunctionType().getReturnType(), operands,
604 attrs, argAttrs, resAttrs);
605 }
606
607 cir::CallOp
608 createIndirectCallOp(mlir::Location loc, mlir::Value indirectTarget,
609 cir::FuncType funcType, mlir::ValueRange operands,
613 llvm::SmallVector<mlir::Value> resOperands{indirectTarget};
614 resOperands.append(operands.begin(), operands.end());
615
616 return createCallOp(loc, mlir::SymbolRefAttr(), funcType.getReturnType(),
617 resOperands, attrs, argAttrs, resAttrs);
618 }
619
620 cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee,
621 mlir::ValueRange operands = mlir::ValueRange(),
625 return createCallOp(loc, callee, cir::VoidType(), operands, attrs, argAttrs,
626 resAttrs);
627 }
628
629 //===--------------------------------------------------------------------===//
630 // Cast/Conversion Operators
631 //===--------------------------------------------------------------------===//
632
633 mlir::Value createCast(mlir::Location loc, cir::CastKind kind,
634 mlir::Value src, mlir::Type newTy) {
635 if (newTy == src.getType())
636 return src;
637 return cir::CastOp::create(*this, loc, newTy, kind, src);
638 }
639
640 mlir::Value createCast(cir::CastKind kind, mlir::Value src,
641 mlir::Type newTy) {
642 if (newTy == src.getType())
643 return src;
644 return createCast(src.getLoc(), kind, src, newTy);
645 }
646
647 // Creates a cast from bool or int to an integer type.
648 mlir::Value createBoolIntToIntCast(mlir::Value src, mlir::Type newTy) {
649 if (newTy == src.getType())
650 return src;
651 if (src.getType() == getBoolTy())
652 return createBoolToInt(src, newTy);
653 return createIntCast(src, newTy);
654 }
655
656 mlir::Value createIntCast(mlir::Value src, mlir::Type newTy) {
657 return createCast(cir::CastKind::integral, src, newTy);
658 }
659
660 mlir::Value createBuiltinIntCast(mlir::Location loc, mlir::Value src,
661 mlir::Type newTy) {
662 return cir::BuiltinIntCastOp::create(*this, loc, newTy, src);
663 }
664
665 mlir::Value createBuiltinIntCast(mlir::Value src, mlir::Type newTy) {
666 return createBuiltinIntCast(src.getLoc(), src, newTy);
667 }
668
669 mlir::Value createIntToPtr(mlir::Value src, mlir::Type newTy) {
670 return createCast(cir::CastKind::int_to_ptr, src, newTy);
671 }
672
673 mlir::Value createPtrToInt(mlir::Value src, mlir::Type newTy) {
674 return createCast(cir::CastKind::ptr_to_int, src, newTy);
675 }
676
677 mlir::Value createPtrToBoolCast(mlir::Value v) {
678 return createCast(cir::CastKind::ptr_to_bool, v, getBoolTy());
679 }
680
681 mlir::Value createBoolToInt(mlir::Value src, mlir::Type newTy) {
682 return createCast(cir::CastKind::bool_to_int, src, newTy);
683 }
684
685 mlir::Value createBitcast(mlir::Value src, mlir::Type newTy) {
686 return createCast(cir::CastKind::bitcast, src, newTy);
687 }
688
689 mlir::Value createBitcast(mlir::Location loc, mlir::Value src,
690 mlir::Type newTy) {
691 return createCast(loc, cir::CastKind::bitcast, src, newTy);
692 }
693
694 mlir::Value createPtrBitcast(mlir::Value src, mlir::Type newPointeeTy) {
695 assert(mlir::isa<cir::PointerType>(src.getType()) && "expected ptr src");
696 cir::PointerType srcPtrTy = mlir::cast<cir::PointerType>(src.getType());
697 return createBitcast(src,
698 getPointerTo(newPointeeTy, srcPtrTy.getAddrSpace()));
699 }
700
701 mlir::Value createPtrIsNull(mlir::Value ptr) {
702 mlir::Value nullPtr = getNullPtr(ptr.getType(), ptr.getLoc());
703 return createCompare(ptr.getLoc(), cir::CmpOpKind::eq, ptr, nullPtr);
704 }
705
706 mlir::Value createPtrIsNotNull(mlir::Value ptr) {
707 mlir::Value nullPtr = getNullPtr(ptr.getType(), ptr.getLoc());
708 return createCompare(ptr.getLoc(), cir::CmpOpKind::ne, ptr, nullPtr);
709 }
710
711 mlir::Value createAddrSpaceCast(mlir::Location loc, mlir::Value src,
712 mlir::Type newTy) {
713 return createCast(loc, cir::CastKind::address_space, src, newTy);
714 }
715
716 mlir::Value createAddrSpaceCast(mlir::Value src, mlir::Type newTy) {
717 return createAddrSpaceCast(src.getLoc(), src, newTy);
718 }
719
720 //===--------------------------------------------------------------------===//
721 // Other Instructions
722 //===--------------------------------------------------------------------===//
723
724 mlir::Value createExtractElement(mlir::Location loc, mlir::Value vec,
725 uint64_t idx) {
726 mlir::Value idxVal =
727 getConstAPInt(loc, getUIntNTy(64), llvm::APInt(64, idx));
728 return cir::VecExtractOp::create(*this, loc, vec, idxVal);
729 }
730
731 mlir::Value createInsertElement(mlir::Location loc, mlir::Value vec,
732 mlir::Value newElt, uint64_t idx) {
733 mlir::Value idxVal =
734 getConstAPInt(loc, getUIntNTy(64), llvm::APInt(64, idx));
735 return cir::VecInsertOp::create(*this, loc, vec, newElt, idxVal);
736 }
737
738 cir::SignBitOp createSignBit(mlir::Location loc, mlir::Value val) {
739 auto resTy = cir::BoolType::get(getContext());
740 return cir::SignBitOp::create(*this, loc, resTy, val);
741 }
742
743 //===--------------------------------------------------------------------===//
744 // Binary Operators
745 //===--------------------------------------------------------------------===//
746
747 mlir::Value createLowBitsSet(mlir::Location loc, unsigned size,
748 unsigned bits) {
749 llvm::APInt val = llvm::APInt::getLowBitsSet(size, bits);
750 auto type = cir::IntType::get(getContext(), size, /*isSigned=*/false);
751 return getConstAPInt(loc, type, val);
752 }
753
754 mlir::Value createAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
755 return cir::AndOp::create(*this, loc, lhs, rhs);
756 }
757
758 mlir::Value createOr(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
759 return cir::OrOp::create(*this, loc, lhs, rhs);
760 }
761
762 mlir::Value createSelect(mlir::Location loc, mlir::Value condition,
763 mlir::Value trueValue, mlir::Value falseValue) {
764 assert(trueValue.getType() == falseValue.getType() &&
765 "trueValue and falseValue should have the same type");
766 return cir::SelectOp::create(*this, loc, trueValue.getType(), condition,
767 trueValue, falseValue);
768 }
769
770 mlir::Value createLogicalAnd(mlir::Location loc, mlir::Value lhs,
771 mlir::Value rhs) {
772 return createSelect(loc, lhs, rhs, getBool(false, loc));
773 }
774
775 mlir::Value createLogicalOr(mlir::Location loc, mlir::Value lhs,
776 mlir::Value rhs) {
777 return createSelect(loc, lhs, getBool(true, loc), rhs);
778 }
779
780 mlir::Value createMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
782 auto op = cir::MulOp::create(*this, loc, lhs, rhs);
783 op.setNoUnsignedWrap(testFlag(ob, OverflowBehavior::NoUnsignedWrap));
784 op.setNoSignedWrap(testFlag(ob, OverflowBehavior::NoSignedWrap));
785 return op;
786 }
787 mlir::Value createNSWMul(mlir::Location loc, mlir::Value lhs,
788 mlir::Value rhs) {
789 return createMul(loc, lhs, rhs, OverflowBehavior::NoSignedWrap);
790 }
791 mlir::Value createNUWAMul(mlir::Location loc, mlir::Value lhs,
792 mlir::Value rhs) {
793 return createMul(loc, lhs, rhs, OverflowBehavior::NoUnsignedWrap);
794 }
795
796 mlir::Value createSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
798 auto op = cir::SubOp::create(*this, loc, lhs, rhs);
799 op.setNoUnsignedWrap(testFlag(ob, OverflowBehavior::NoUnsignedWrap));
800 op.setNoSignedWrap(testFlag(ob, OverflowBehavior::NoSignedWrap));
801 op.setSaturated(testFlag(ob, OverflowBehavior::Saturated));
802 return op;
803 }
804
805 mlir::Value createNSWSub(mlir::Location loc, mlir::Value lhs,
806 mlir::Value rhs) {
807 return createSub(loc, lhs, rhs, OverflowBehavior::NoSignedWrap);
808 }
809
810 mlir::Value createNUWSub(mlir::Location loc, mlir::Value lhs,
811 mlir::Value rhs) {
812 return createSub(loc, lhs, rhs, OverflowBehavior::NoUnsignedWrap);
813 }
814
815 mlir::Value createAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
817 auto op = cir::AddOp::create(*this, loc, lhs, rhs);
818 op.setNoUnsignedWrap(testFlag(ob, OverflowBehavior::NoUnsignedWrap));
819 op.setNoSignedWrap(testFlag(ob, OverflowBehavior::NoSignedWrap));
820 op.setSaturated(testFlag(ob, OverflowBehavior::Saturated));
821 return op;
822 }
823
824 mlir::Value createNSWAdd(mlir::Location loc, mlir::Value lhs,
825 mlir::Value rhs) {
826 return createAdd(loc, lhs, rhs, OverflowBehavior::NoSignedWrap);
827 }
828
829 mlir::Value createNUWAdd(mlir::Location loc, mlir::Value lhs,
830 mlir::Value rhs) {
831 return createAdd(loc, lhs, rhs, OverflowBehavior::NoUnsignedWrap);
832 }
833
834 mlir::Value createDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
835 return cir::DivOp::create(*this, loc, lhs, rhs);
836 }
837
838 mlir::Value createRem(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
839 return cir::RemOp::create(*this, loc, lhs, rhs);
840 }
841
842 mlir::Value createFAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
845 return cir::FAddOp::create(*this, loc, lhs, rhs, getConstrainedFPAttr());
846 }
847
848 mlir::Value createFSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
851 return cir::FSubOp::create(*this, loc, lhs, rhs, getConstrainedFPAttr());
852 }
853
854 mlir::Value createFMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
857 return cir::FMulOp::create(*this, loc, lhs, rhs, getConstrainedFPAttr());
858 }
859
860 mlir::Value createFDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
863 return cir::FDivOp::create(*this, loc, lhs, rhs, getConstrainedFPAttr());
864 }
865
866 mlir::Value createFRem(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
869 return cir::FRemOp::create(*this, loc, lhs, rhs, getConstrainedFPAttr());
870 }
871
872 mlir::Value createFNeg(mlir::Location loc, mlir::Value operand) {
873 assert(cir::isFPOrVectorOfFPType(operand.getType()) &&
874 "expected floating-point or vector-of-float type");
877 // fneg does not raise FP exceptions or depend on the rounding mode, so it
878 // never carries an fenv attribute.
879 return cir::FNegOp::create(*this, loc, operand);
880 }
881
882 mlir::Value createXor(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
883 return cir::XorOp::create(*this, loc, lhs, rhs);
884 }
885
886 mlir::Value createMax(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
887 return cir::MaxOp::create(*this, loc, lhs, rhs);
888 }
889
890 cir::CmpOp createCompare(mlir::Location loc, cir::CmpOpKind kind,
891 mlir::Value lhs, mlir::Value rhs) {
892 cir::FenvAttr fenv;
893 if (cir::isAnyFloatingPointType(lhs.getType()))
894 fenv = getConstrainedFPAttr();
895 return cir::CmpOp::create(*this, loc, kind, lhs, rhs, fenv);
896 }
897
898 cir::VecCmpOp createVecCompare(mlir::Location loc, cir::CmpOpKind kind,
899 mlir::Value lhs, mlir::Value rhs) {
900 VectorType vecCast = mlir::cast<VectorType>(lhs.getType());
901 IntType integralTy =
902 getSIntNTy(getCIRIntOrFloatBitWidth(vecCast.getElementType()));
903 VectorType integralVecTy =
904 cir::VectorType::get(integralTy, vecCast.getSize());
905 cir::FenvAttr fenv;
906 if (cir::isFPOrVectorOfFPType(lhs.getType()))
907 fenv = getConstrainedFPAttr();
908 return cir::VecCmpOp::create(*this, loc, integralVecTy, kind, lhs, rhs,
909 fenv);
910 }
911
912 mlir::Value createIsNaN(mlir::Location loc, mlir::Value operand) {
913 return createCompare(loc, cir::CmpOpKind::ne, operand, operand);
914 }
915
916 mlir::Value createShift(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
917 bool isShiftLeft) {
918 return cir::ShiftOp::create(*this, loc, lhs.getType(), lhs, rhs,
919 isShiftLeft);
920 }
921
922 mlir::Value createShift(mlir::Location loc, mlir::Value lhs,
923 const llvm::APInt &rhs, bool isShiftLeft) {
924 return createShift(loc, lhs, getConstAPInt(loc, lhs.getType(), rhs),
925 isShiftLeft);
926 }
927
928 mlir::Value createShift(mlir::Location loc, mlir::Value lhs, unsigned bits,
929 bool isShiftLeft) {
930 auto width = mlir::dyn_cast<cir::IntType>(lhs.getType()).getWidth();
931 auto shift = llvm::APInt(width, bits);
932 return createShift(loc, lhs, shift, isShiftLeft);
933 }
934
935 mlir::Value createShiftLeft(mlir::Location loc, mlir::Value lhs,
936 unsigned bits) {
937 return createShift(loc, lhs, bits, true);
938 }
939
940 mlir::Value createShiftRight(mlir::Location loc, mlir::Value lhs,
941 unsigned bits) {
942 return createShift(loc, lhs, bits, false);
943 }
944
945 mlir::Value createShiftLeft(mlir::Location loc, mlir::Value lhs,
946 mlir::Value rhs) {
947 return createShift(loc, lhs, rhs, true);
948 }
949
950 mlir::Value createShiftRight(mlir::Location loc, mlir::Value lhs,
951 mlir::Value rhs) {
952 return createShift(loc, lhs, rhs, false);
953 }
954
955 /// Returns `void (T...)` as a cir::FuncType.
956 cir::FuncType getVoidFnTy(mlir::TypeRange argTypes = {}) {
957 return cir::FuncType::get(llvm::to_vector(argTypes), getVoidTy());
958 }
959
960 /// Returns `void (*)(T...)` as a cir::PointerType.
961 cir::PointerType getVoidFnPtrTy(mlir::TypeRange argTypes = {}) {
962 return getPointerTo(getVoidFnTy(argTypes));
963 }
964
965 //
966 // Block handling helpers
967 // ----------------------
968 //
969 static OpBuilder::InsertPoint getBestAllocaInsertPoint(mlir::Block *block) {
970 auto last =
971 std::find_if(block->rbegin(), block->rend(), [](mlir::Operation &op) {
972 return mlir::isa<cir::AllocaOp, cir::LabelOp>(&op);
973 });
974
975 if (last != block->rend())
976 return OpBuilder::InsertPoint(block, ++mlir::Block::iterator(&*last));
977 return OpBuilder::InsertPoint(block, block->begin());
978 };
979
980 //
981 // Alignment and size helpers
982 //
983
984 // Note that mlir::IntegerType is used instead of cir::IntType here because we
985 // don't need sign information for these to be useful, so keep it simple.
986
987 // For 0 alignment, any overload of `getAlignmentAttr` returns an empty
988 // attribute.
989 mlir::IntegerAttr getAlignmentAttr(clang::CharUnits alignment) {
990 return getAlignmentAttr(alignment.getQuantity());
991 }
992
993 mlir::IntegerAttr getAlignmentAttr(llvm::Align alignment) {
994 return getAlignmentAttr(alignment.value());
995 }
996
997 mlir::IntegerAttr getAlignmentAttr(int64_t alignment) {
998 return alignment ? getI64IntegerAttr(alignment) : mlir::IntegerAttr();
999 }
1000
1001 // Materialize an alignment value as a CIR integer constant of the given
1002 // integer type.
1003 cir::ConstantOp getAlignment(mlir::Location loc, mlir::Type t,
1004 clang::CharUnits alignment) {
1005 return getConstantInt(loc, t, alignment.getQuantity());
1006 }
1007
1008 mlir::IntegerAttr getSizeFromCharUnits(clang::CharUnits size) {
1009 return getI64IntegerAttr(size.getQuantity());
1010 }
1011
1012 // Creates constant nullptr for pointer type ty.
1013 cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc) {
1015 return cir::ConstantOp::create(*this, loc, getConstPtrAttr(ty, 0));
1016 }
1017
1018 /// Create a loop condition.
1019 cir::ConditionOp createCondition(mlir::Value condition) {
1020 return cir::ConditionOp::create(*this, condition.getLoc(), condition);
1021 }
1022
1023 /// Create a yield operation.
1024 cir::YieldOp createYield(mlir::Location loc, mlir::ValueRange value = {}) {
1025 return cir::YieldOp::create(*this, loc, value);
1026 }
1027
1029 mlir::Value callee;
1030 mlir::Value adjustedThis;
1031 };
1032
1033 GetMethodResults createGetMethod(mlir::Location loc, mlir::Value method,
1034 mlir::Value objectPtr) {
1035 // Build the callee function type.
1036 auto methodFuncTy =
1037 mlir::cast<cir::MethodType>(method.getType()).getMemberFuncTy();
1038 auto methodFuncInputTypes = methodFuncTy.getInputs();
1039
1040 auto objectPtrTy = mlir::cast<cir::PointerType>(objectPtr.getType());
1041 mlir::Type adjustedThisTy = getVoidPtrTy(objectPtrTy.getAddrSpace());
1042
1043 llvm::SmallVector<mlir::Type> calleeFuncInputTypes{adjustedThisTy};
1044 // The member function type's first parameter is the implicit 'this'
1045 // pointer. The callee takes an adjusted void* receiver instead.
1046 if (methodFuncInputTypes.size() > 1)
1047 calleeFuncInputTypes.insert(calleeFuncInputTypes.end(),
1048 methodFuncInputTypes.begin() + 1,
1049 methodFuncInputTypes.end());
1050 cir::FuncType calleeFuncTy =
1051 methodFuncTy.clone(calleeFuncInputTypes, methodFuncTy.getReturnType());
1052 // TODO(cir): consider the address space of the callee.
1054 cir::PointerType calleeTy = getPointerTo(calleeFuncTy);
1055
1056 auto op = cir::GetMethodOp::create(*this, loc, calleeTy, adjustedThisTy,
1057 method, objectPtr);
1058 return {op.getCallee(), op.getAdjustedThis()};
1059 }
1060};
1061
1062} // namespace cir
1063
1064#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 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)
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition CharUnits.h:185
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()