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