clang 23.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"
18#include "llvm/ADT/STLForwardCompat.h"
19#include "llvm/Support/ErrorHandling.h"
20
21#include "mlir/IR/Builders.h"
22#include "mlir/IR/BuiltinAttributes.h"
23#include "mlir/IR/Location.h"
24#include "mlir/IR/Types.h"
25
26namespace cir {
27
28enum class OverflowBehavior {
29 None = 0,
30 NoSignedWrap = 1 << 0,
32 Saturated = 1 << 2,
33};
34
36 return static_cast<OverflowBehavior>(llvm::to_underlying(a) |
37 llvm::to_underlying(b));
38}
39
41 return static_cast<OverflowBehavior>(llvm::to_underlying(a) &
42 llvm::to_underlying(b));
43}
44
47 a = a | b;
48 return a;
49}
50
53 a = a & b;
54 return a;
55}
56
57class CIRBaseBuilderTy : public mlir::OpBuilder {
58
59public:
60 CIRBaseBuilderTy(mlir::MLIRContext &mlirContext)
61 : mlir::OpBuilder(&mlirContext) {}
62 CIRBaseBuilderTy(mlir::OpBuilder &builder) : mlir::OpBuilder(builder) {}
63
64 mlir::Value getConstAPInt(mlir::Location loc, mlir::Type typ,
65 const llvm::APInt &val) {
66 return cir::ConstantOp::create(*this, loc, cir::IntAttr::get(typ, val));
67 }
68
69 cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr) {
70 return cir::ConstantOp::create(*this, loc, attr);
71 }
72
73 cir::ConstantOp getConstantInt(mlir::Location loc, mlir::Type ty,
74 int64_t value) {
75 return getConstant(loc, cir::IntAttr::get(ty, value));
76 }
77
78 mlir::Value getSignedInt(mlir::Location loc, int64_t val, unsigned numBits) {
79 auto type = cir::IntType::get(getContext(), numBits, /*isSigned=*/true);
80 return getConstAPInt(loc, type,
81 llvm::APInt(numBits, val, /*isSigned=*/true));
82 }
83
84 mlir::Value getUnsignedInt(mlir::Location loc, uint64_t val,
85 unsigned numBits) {
86 auto type = cir::IntType::get(getContext(), numBits, /*isSigned=*/false);
87 return getConstAPInt(loc, type, llvm::APInt(numBits, val));
88 }
89
90 // Creates constant null value for integral type ty.
91 cir::ConstantOp getNullValue(mlir::Type ty, mlir::Location loc) {
92 return getConstant(loc, getZeroInitAttr(ty));
93 }
94
95 mlir::TypedAttr getConstNullPtrAttr(mlir::Type t) {
96 assert(mlir::isa<cir::PointerType>(t) && "expected cir.ptr");
97 return getConstPtrAttr(t, 0);
98 }
99
100 mlir::TypedAttr getNullDataMemberAttr(cir::DataMemberType ty) {
101 return cir::DataMemberAttr::get(ty);
102 }
103
104 mlir::TypedAttr getZeroInitAttr(mlir::Type ty) {
105 if (mlir::isa<cir::IntType>(ty))
106 return cir::IntAttr::get(ty, 0);
107 if (cir::isAnyFloatingPointType(ty))
108 return cir::FPAttr::getZero(ty);
109 if (auto complexType = mlir::dyn_cast<cir::ComplexType>(ty))
110 return cir::ZeroAttr::get(complexType);
111 if (auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty))
112 return cir::ZeroAttr::get(arrTy);
113 if (auto vecTy = mlir::dyn_cast<cir::VectorType>(ty))
114 return cir::ZeroAttr::get(vecTy);
115 if (auto ptrTy = mlir::dyn_cast<cir::PointerType>(ty))
116 return getConstNullPtrAttr(ptrTy);
117 if (auto recordTy = mlir::dyn_cast<cir::RecordType>(ty))
118 return cir::ZeroAttr::get(recordTy);
119 if (auto dataMemberTy = mlir::dyn_cast<cir::DataMemberType>(ty))
120 return getNullDataMemberAttr(dataMemberTy);
121 if (mlir::isa<cir::BoolType>(ty)) {
122 return getFalseAttr();
123 }
124 llvm_unreachable("Zero initializer for given type is NYI");
125 }
126
127 cir::ConstantOp getBool(bool state, mlir::Location loc) {
128 return cir::ConstantOp::create(*this, loc, getCIRBoolAttr(state));
129 }
130 cir::ConstantOp getFalse(mlir::Location loc) { return getBool(false, loc); }
131 cir::ConstantOp getTrue(mlir::Location loc) { return getBool(true, loc); }
132
133 cir::BoolType getBoolTy() { return cir::BoolType::get(getContext()); }
134 cir::VoidType getVoidTy() { return cir::VoidType::get(getContext()); }
135
136 cir::IntType getUIntNTy(int n) {
137 return cir::IntType::get(getContext(), n, false);
138 }
139
140 static unsigned getCIRIntOrFloatBitWidth(mlir::Type eltTy) {
141 if (auto intType = mlir::dyn_cast<cir::IntTypeInterface>(eltTy))
142 return intType.getWidth();
143 if (auto floatType = mlir::dyn_cast<cir::FPTypeInterface>(eltTy))
144 return floatType.getWidth();
145
146 llvm_unreachable("Unsupported type in getCIRIntOrFloatBitWidth");
147 }
148 cir::IntType getSIntNTy(int n) {
149 return cir::IntType::get(getContext(), n, true);
150 }
151
152 cir::PointerType getPointerTo(mlir::Type ty) {
153 return cir::PointerType::get(ty);
154 }
155
156 cir::PointerType getPointerTo(mlir::Type ty, cir::TargetAddressSpaceAttr as) {
157 return cir::PointerType::get(ty, as);
158 }
159
160 cir::PointerType getPointerTo(mlir::Type ty, clang::LangAS langAS) {
161 if (langAS == clang::LangAS::Default) // Default address space.
162 return getPointerTo(ty);
163
164 if (clang::isTargetAddressSpace(langAS)) {
165 unsigned addrSpace = clang::toTargetAddressSpace(langAS);
166 auto asAttr = cir::TargetAddressSpaceAttr::get(
167 getContext(), getUI32IntegerAttr(addrSpace));
168 return getPointerTo(ty, asAttr);
169 }
170
171 llvm_unreachable("language-specific address spaces NYI");
172 }
173
175 return getPointerTo(cir::VoidType::get(getContext()), langAS);
176 }
177
178 cir::PointerType getVoidPtrTy(cir::TargetAddressSpaceAttr as) {
179 return getPointerTo(cir::VoidType::get(getContext()), as);
180 }
181
182 cir::MethodAttr getMethodAttr(cir::MethodType ty, cir::FuncOp methodFuncOp) {
183 auto methodFuncSymbolRef = mlir::FlatSymbolRefAttr::get(methodFuncOp);
184 return cir::MethodAttr::get(ty, methodFuncSymbolRef);
185 }
186
187 cir::MethodAttr getNullMethodAttr(cir::MethodType ty) {
188 return cir::MethodAttr::get(ty);
189 }
190
191 cir::BoolAttr getCIRBoolAttr(bool state) {
192 return cir::BoolAttr::get(getContext(), state);
193 }
194
195 cir::BoolAttr getTrueAttr() { return getCIRBoolAttr(true); }
196 cir::BoolAttr getFalseAttr() { return getCIRBoolAttr(false); }
197
198 mlir::Value createComplexCreate(mlir::Location loc, mlir::Value real,
199 mlir::Value imag) {
200 auto resultComplexTy = cir::ComplexType::get(real.getType());
201 return cir::ComplexCreateOp::create(*this, loc, resultComplexTy, real,
202 imag);
203 }
204
205 mlir::Value createComplexReal(mlir::Location loc, mlir::Value operand) {
206 auto resultType = operand.getType();
207 if (auto complexResultType = mlir::dyn_cast<cir::ComplexType>(resultType))
208 resultType = complexResultType.getElementType();
209 return cir::ComplexRealOp::create(*this, loc, resultType, operand);
210 }
211
212 mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand) {
213 auto resultType = operand.getType();
214 if (auto complexResultType = mlir::dyn_cast<cir::ComplexType>(resultType))
215 resultType = complexResultType.getElementType();
216 return cir::ComplexImagOp::create(*this, loc, resultType, operand);
217 }
218
219 cir::LoadOp createLoad(mlir::Location loc, mlir::Value ptr,
220 bool isVolatile = false, uint64_t alignment = 0) {
221 mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
222 return cir::LoadOp::create(*this, loc, ptr, /*isDeref=*/false, isVolatile,
223 alignmentAttr, cir::SyncScopeKindAttr{},
224 cir::MemOrderAttr{});
225 }
226
227 mlir::Value createAlignedLoad(mlir::Location loc, mlir::Value ptr,
228 uint64_t alignment) {
229 return createLoad(loc, ptr, /*isVolatile=*/false, alignment);
230 }
231
232 mlir::Value createNot(mlir::Value value) {
233 return cir::UnaryOp::create(*this, value.getLoc(), value.getType(),
234 cir::UnaryOpKind::Not, value);
235 }
236
237 /// Create a do-while operation.
238 cir::DoWhileOp createDoWhile(
239 mlir::Location loc,
240 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> condBuilder,
241 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> bodyBuilder) {
242 return cir::DoWhileOp::create(*this, loc, condBuilder, bodyBuilder);
243 }
244
245 /// Create a while operation.
246 cir::WhileOp createWhile(
247 mlir::Location loc,
248 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> condBuilder,
249 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> bodyBuilder) {
250 return cir::WhileOp::create(*this, loc, condBuilder, bodyBuilder);
251 }
252
253 /// Create a for operation.
254 cir::ForOp createFor(
255 mlir::Location loc,
256 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> condBuilder,
257 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> bodyBuilder,
258 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> stepBuilder) {
259 return cir::ForOp::create(*this, loc, condBuilder, bodyBuilder,
260 stepBuilder);
261 }
262
263 /// Create a break operation.
264 cir::BreakOp createBreak(mlir::Location loc) {
265 return cir::BreakOp::create(*this, loc);
266 }
267
268 /// Create a continue operation.
269 cir::ContinueOp createContinue(mlir::Location loc) {
270 return cir::ContinueOp::create(*this, loc);
271 }
272
273 mlir::Value createUnaryOp(mlir::Location loc, cir::UnaryOpKind kind,
274 mlir::Value operand) {
275 return cir::UnaryOp::create(*this, loc, kind, operand);
276 }
277
278 mlir::TypedAttr getConstPtrAttr(mlir::Type type, int64_t value) {
279 return cir::ConstPtrAttr::get(type, getI64IntegerAttr(value));
280 }
281
282 mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
283 mlir::Type type, llvm::StringRef name,
284 mlir::IntegerAttr alignment,
285 mlir::Value dynAllocSize) {
286 return cir::AllocaOp::create(*this, loc, addrType, type, name, alignment,
287 dynAllocSize);
288 }
289
290 mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
291 mlir::Type type, llvm::StringRef name,
292 clang::CharUnits alignment,
293 mlir::Value dynAllocSize) {
294 mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
295 return createAlloca(loc, addrType, type, name, alignmentAttr, dynAllocSize);
296 }
297
298 mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
299 mlir::Type type, llvm::StringRef name,
300 mlir::IntegerAttr alignment) {
301 return cir::AllocaOp::create(*this, loc, addrType, type, name, alignment);
302 }
303
304 mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
305 mlir::Type type, llvm::StringRef name,
306 clang::CharUnits alignment) {
307 mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
308 return createAlloca(loc, addrType, type, name, alignmentAttr);
309 }
310
311 /// Get constant address of a global variable as an MLIR attribute.
312 /// This wrapper infers the attribute type through the global op.
313 cir::GlobalViewAttr getGlobalViewAttr(cir::GlobalOp globalOp,
314 mlir::ArrayAttr indices = {}) {
315 cir::PointerType type = getPointerTo(globalOp.getSymType());
316 return getGlobalViewAttr(type, globalOp, indices);
317 }
318
319 /// Get constant address of a global variable as an MLIR attribute.
320 cir::GlobalViewAttr getGlobalViewAttr(cir::PointerType type,
321 cir::GlobalOp globalOp,
322 mlir::ArrayAttr indices = {}) {
323 auto symbol = mlir::FlatSymbolRefAttr::get(globalOp.getSymNameAttr());
324 return cir::GlobalViewAttr::get(type, symbol, indices);
325 }
326
327 mlir::Value createGetGlobal(mlir::Location loc, cir::GlobalOp global,
328 bool threadLocal = false) {
330 return cir::GetGlobalOp::create(*this, loc,
331 getPointerTo(global.getSymType()),
332 global.getSymNameAttr(), threadLocal);
333 }
334
335 mlir::Value createGetGlobal(cir::GlobalOp global, bool threadLocal = false) {
336 return createGetGlobal(global.getLoc(), global, threadLocal);
337 }
338
339 /// Create a copy with inferred length.
340 cir::CopyOp createCopy(mlir::Value dst, mlir::Value src,
341 bool isVolatile = false) {
342 return cir::CopyOp::create(*this, dst.getLoc(), dst, src, isVolatile);
343 }
344
345 cir::StoreOp createStore(mlir::Location loc, mlir::Value val, mlir::Value dst,
346 bool isVolatile = false,
347 mlir::IntegerAttr align = {},
348 cir::SyncScopeKindAttr scope = {},
349 cir::MemOrderAttr order = {}) {
350 return cir::StoreOp::create(*this, loc, val, dst, isVolatile, align, scope,
351 order);
352 }
353
354 /// Emit a load from an boolean flag variable.
355 cir::LoadOp createFlagLoad(mlir::Location loc, mlir::Value addr) {
356 mlir::Type boolTy = getBoolTy();
357 if (boolTy != mlir::cast<cir::PointerType>(addr.getType()).getPointee())
358 addr = createPtrBitcast(addr, boolTy);
359 return createLoad(loc, addr, /*isVolatile=*/false, /*alignment=*/1);
360 }
361
362 cir::StoreOp createFlagStore(mlir::Location loc, bool val, mlir::Value dst) {
363 mlir::Value flag = getBool(val, loc);
364 return CIRBaseBuilderTy::createStore(loc, flag, dst);
365 }
366
367 [[nodiscard]] cir::GlobalOp createGlobal(mlir::ModuleOp mlirModule,
368 mlir::Location loc,
369 mlir::StringRef name,
370 mlir::Type type, bool isConstant,
371 cir::GlobalLinkageKind linkage) {
372 mlir::OpBuilder::InsertionGuard guard(*this);
373 setInsertionPointToStart(mlirModule.getBody());
374 return cir::GlobalOp::create(*this, loc, name, type, isConstant, linkage);
375 }
376
377 cir::GetMemberOp createGetMember(mlir::Location loc, mlir::Type resultTy,
378 mlir::Value base, llvm::StringRef name,
379 unsigned index) {
380 return cir::GetMemberOp::create(*this, loc, resultTy, base, name, index);
381 }
382
383 mlir::Value createDummyValue(mlir::Location loc, mlir::Type type,
384 clang::CharUnits alignment) {
385 mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment);
386 auto addr = createAlloca(loc, getPointerTo(type), type, {}, alignmentAttr);
387 return cir::LoadOp::create(*this, loc, addr, /*isDeref=*/false,
388 /*isVolatile=*/false, alignmentAttr,
389 /*sync_scope=*/{}, /*mem_order=*/{});
390 }
391
392 cir::PtrStrideOp createPtrStride(mlir::Location loc, mlir::Value base,
393 mlir::Value stride) {
394 return cir::PtrStrideOp::create(*this, loc, base.getType(), base, stride);
395 }
396
397 //===--------------------------------------------------------------------===//
398 // Call operators
399 //===--------------------------------------------------------------------===//
400
401 cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee,
402 mlir::Type returnType, mlir::ValueRange operands,
404 auto op = cir::CallOp::create(*this, loc, callee, returnType, operands);
405 op->setAttrs(attrs);
406 return op;
407 }
408
409 cir::CallOp createCallOp(mlir::Location loc, cir::FuncOp callee,
410 mlir::ValueRange operands,
412 return createCallOp(loc, mlir::SymbolRefAttr::get(callee),
413 callee.getFunctionType().getReturnType(), operands,
414 attrs);
415 }
416
417 cir::CallOp
418 createIndirectCallOp(mlir::Location loc, mlir::Value indirectTarget,
419 cir::FuncType funcType, mlir::ValueRange operands,
421 llvm::SmallVector<mlir::Value> resOperands{indirectTarget};
422 resOperands.append(operands.begin(), operands.end());
423 return createCallOp(loc, mlir::SymbolRefAttr(), funcType.getReturnType(),
424 resOperands, attrs);
425 }
426
427 cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee,
428 mlir::ValueRange operands = mlir::ValueRange(),
430 return createCallOp(loc, callee, cir::VoidType(), operands, attrs);
431 }
432
433 //===--------------------------------------------------------------------===//
434 // Cast/Conversion Operators
435 //===--------------------------------------------------------------------===//
436
437 mlir::Value createCast(mlir::Location loc, cir::CastKind kind,
438 mlir::Value src, mlir::Type newTy) {
439 if (newTy == src.getType())
440 return src;
441 return cir::CastOp::create(*this, loc, newTy, kind, src);
442 }
443
444 mlir::Value createCast(cir::CastKind kind, mlir::Value src,
445 mlir::Type newTy) {
446 if (newTy == src.getType())
447 return src;
448 return createCast(src.getLoc(), kind, src, newTy);
449 }
450
451 mlir::Value createIntCast(mlir::Value src, mlir::Type newTy) {
452 return createCast(cir::CastKind::integral, src, newTy);
453 }
454
455 mlir::Value createIntToPtr(mlir::Value src, mlir::Type newTy) {
456 return createCast(cir::CastKind::int_to_ptr, src, newTy);
457 }
458
459 mlir::Value createPtrToInt(mlir::Value src, mlir::Type newTy) {
460 return createCast(cir::CastKind::ptr_to_int, src, newTy);
461 }
462
463 mlir::Value createPtrToBoolCast(mlir::Value v) {
464 return createCast(cir::CastKind::ptr_to_bool, v, getBoolTy());
465 }
466
467 mlir::Value createBoolToInt(mlir::Value src, mlir::Type newTy) {
468 return createCast(cir::CastKind::bool_to_int, src, newTy);
469 }
470
471 mlir::Value createBitcast(mlir::Value src, mlir::Type newTy) {
472 return createCast(cir::CastKind::bitcast, src, newTy);
473 }
474
475 mlir::Value createBitcast(mlir::Location loc, mlir::Value src,
476 mlir::Type newTy) {
477 return createCast(loc, cir::CastKind::bitcast, src, newTy);
478 }
479
480 mlir::Value createPtrBitcast(mlir::Value src, mlir::Type newPointeeTy) {
481 assert(mlir::isa<cir::PointerType>(src.getType()) && "expected ptr src");
482 return createBitcast(src, getPointerTo(newPointeeTy));
483 }
484
485 mlir::Value createPtrIsNull(mlir::Value ptr) {
486 mlir::Value nullPtr = getNullPtr(ptr.getType(), ptr.getLoc());
487 return createCompare(ptr.getLoc(), cir::CmpOpKind::eq, ptr, nullPtr);
488 }
489
490 mlir::Value createAddrSpaceCast(mlir::Location loc, mlir::Value src,
491 mlir::Type newTy) {
492 return createCast(loc, cir::CastKind::address_space, src, newTy);
493 }
494
495 mlir::Value createAddrSpaceCast(mlir::Value src, mlir::Type newTy) {
496 return createAddrSpaceCast(src.getLoc(), src, newTy);
497 }
498
499 //===--------------------------------------------------------------------===//
500 // Other Instructions
501 //===--------------------------------------------------------------------===//
502
503 mlir::Value createExtractElement(mlir::Location loc, mlir::Value vec,
504 uint64_t idx) {
505 mlir::Value idxVal =
506 getConstAPInt(loc, getUIntNTy(64), llvm::APInt(64, idx));
507 return cir::VecExtractOp::create(*this, loc, vec, idxVal);
508 }
509
510 mlir::Value createInsertElement(mlir::Location loc, mlir::Value vec,
511 mlir::Value newElt, uint64_t idx) {
512 mlir::Value idxVal =
513 getConstAPInt(loc, getUIntNTy(64), llvm::APInt(64, idx));
514 return cir::VecInsertOp::create(*this, loc, vec, newElt, idxVal);
515 }
516
517 //===--------------------------------------------------------------------===//
518 // Binary Operators
519 //===--------------------------------------------------------------------===//
520
521 mlir::Value createBinop(mlir::Location loc, mlir::Value lhs,
522 cir::BinOpKind kind, mlir::Value rhs) {
523 return cir::BinOp::create(*this, loc, lhs.getType(), kind, lhs, rhs);
524 }
525
526 mlir::Value createLowBitsSet(mlir::Location loc, unsigned size,
527 unsigned bits) {
528 llvm::APInt val = llvm::APInt::getLowBitsSet(size, bits);
529 auto type = cir::IntType::get(getContext(), size, /*isSigned=*/false);
530 return getConstAPInt(loc, type, val);
531 }
532
533 mlir::Value createAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
534 return createBinop(loc, lhs, cir::BinOpKind::And, rhs);
535 }
536
537 mlir::Value createOr(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
538 return createBinop(loc, lhs, cir::BinOpKind::Or, rhs);
539 }
540
541 mlir::Value createSelect(mlir::Location loc, mlir::Value condition,
542 mlir::Value trueValue, mlir::Value falseValue) {
543 assert(trueValue.getType() == falseValue.getType() &&
544 "trueValue and falseValue should have the same type");
545 return cir::SelectOp::create(*this, loc, trueValue.getType(), condition,
546 trueValue, falseValue);
547 }
548
549 mlir::Value createLogicalAnd(mlir::Location loc, mlir::Value lhs,
550 mlir::Value rhs) {
551 return createSelect(loc, lhs, rhs, getBool(false, loc));
552 }
553
554 mlir::Value createLogicalOr(mlir::Location loc, mlir::Value lhs,
555 mlir::Value rhs) {
556 return createSelect(loc, lhs, getBool(true, loc), rhs);
557 }
558
559 mlir::Value createMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
561 auto op = cir::BinOp::create(*this, loc, lhs.getType(), cir::BinOpKind::Mul,
562 lhs, rhs);
563 op.setNoUnsignedWrap(
564 llvm::to_underlying(ob & OverflowBehavior::NoUnsignedWrap));
565 op.setNoSignedWrap(
566 llvm::to_underlying(ob & OverflowBehavior::NoSignedWrap));
567 return op;
568 }
569 mlir::Value createNSWMul(mlir::Location loc, mlir::Value lhs,
570 mlir::Value rhs) {
571 return createMul(loc, lhs, rhs, OverflowBehavior::NoSignedWrap);
572 }
573 mlir::Value createNUWAMul(mlir::Location loc, mlir::Value lhs,
574 mlir::Value rhs) {
575 return createMul(loc, lhs, rhs, OverflowBehavior::NoUnsignedWrap);
576 }
577
578 mlir::Value createSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
580 auto op = cir::BinOp::create(*this, loc, lhs.getType(), cir::BinOpKind::Sub,
581 lhs, rhs);
582 op.setNoUnsignedWrap(
583 llvm::to_underlying(ob & OverflowBehavior::NoUnsignedWrap));
584 op.setNoSignedWrap(
585 llvm::to_underlying(ob & OverflowBehavior::NoSignedWrap));
586 op.setSaturated(llvm::to_underlying(ob & OverflowBehavior::Saturated));
587 return op;
588 }
589
590 mlir::Value createNSWSub(mlir::Location loc, mlir::Value lhs,
591 mlir::Value rhs) {
592 return createSub(loc, lhs, rhs, OverflowBehavior::NoSignedWrap);
593 }
594
595 mlir::Value createNUWSub(mlir::Location loc, mlir::Value lhs,
596 mlir::Value rhs) {
597 return createSub(loc, lhs, rhs, OverflowBehavior::NoUnsignedWrap);
598 }
599
600 mlir::Value createAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
602 auto op = cir::BinOp::create(*this, loc, lhs.getType(), cir::BinOpKind::Add,
603 lhs, rhs);
604 op.setNoUnsignedWrap(
605 llvm::to_underlying(ob & OverflowBehavior::NoUnsignedWrap));
606 op.setNoSignedWrap(
607 llvm::to_underlying(ob & OverflowBehavior::NoSignedWrap));
608 op.setSaturated(llvm::to_underlying(ob & OverflowBehavior::Saturated));
609 return op;
610 }
611
612 mlir::Value createNSWAdd(mlir::Location loc, mlir::Value lhs,
613 mlir::Value rhs) {
614 return createAdd(loc, lhs, rhs, OverflowBehavior::NoSignedWrap);
615 }
616
617 mlir::Value createNUWAdd(mlir::Location loc, mlir::Value lhs,
618 mlir::Value rhs) {
619 return createAdd(loc, lhs, rhs, OverflowBehavior::NoUnsignedWrap);
620 }
621
622 cir::CmpOp createCompare(mlir::Location loc, cir::CmpOpKind kind,
623 mlir::Value lhs, mlir::Value rhs) {
624 return cir::CmpOp::create(*this, loc, kind, lhs, rhs);
625 }
626
627 cir::VecCmpOp createVecCompare(mlir::Location loc, cir::CmpOpKind kind,
628 mlir::Value lhs, mlir::Value rhs) {
629 VectorType vecCast = mlir::cast<VectorType>(lhs.getType());
630 IntType integralTy =
631 getSIntNTy(getCIRIntOrFloatBitWidth(vecCast.getElementType()));
632 VectorType integralVecTy =
633 cir::VectorType::get(integralTy, vecCast.getSize());
634 return cir::VecCmpOp::create(*this, loc, integralVecTy, kind, lhs, rhs);
635 }
636
637 mlir::Value createIsNaN(mlir::Location loc, mlir::Value operand) {
638 return createCompare(loc, cir::CmpOpKind::ne, operand, operand);
639 }
640
641 mlir::Value createShift(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
642 bool isShiftLeft) {
643 return cir::ShiftOp::create(*this, loc, lhs.getType(), lhs, rhs,
644 isShiftLeft);
645 }
646
647 mlir::Value createShift(mlir::Location loc, mlir::Value lhs,
648 const llvm::APInt &rhs, bool isShiftLeft) {
649 return createShift(loc, lhs, getConstAPInt(loc, lhs.getType(), rhs),
650 isShiftLeft);
651 }
652
653 mlir::Value createShift(mlir::Location loc, mlir::Value lhs, unsigned bits,
654 bool isShiftLeft) {
655 auto width = mlir::dyn_cast<cir::IntType>(lhs.getType()).getWidth();
656 auto shift = llvm::APInt(width, bits);
657 return createShift(loc, lhs, shift, isShiftLeft);
658 }
659
660 mlir::Value createShiftLeft(mlir::Location loc, mlir::Value lhs,
661 unsigned bits) {
662 return createShift(loc, lhs, bits, true);
663 }
664
665 mlir::Value createShiftRight(mlir::Location loc, mlir::Value lhs,
666 unsigned bits) {
667 return createShift(loc, lhs, bits, false);
668 }
669
670 mlir::Value createShiftLeft(mlir::Location loc, mlir::Value lhs,
671 mlir::Value rhs) {
672 return createShift(loc, lhs, rhs, true);
673 }
674
675 mlir::Value createShiftRight(mlir::Location loc, mlir::Value lhs,
676 mlir::Value rhs) {
677 return createShift(loc, lhs, rhs, false);
678 }
679
680 //
681 // Block handling helpers
682 // ----------------------
683 //
684 static OpBuilder::InsertPoint getBestAllocaInsertPoint(mlir::Block *block) {
685 auto last =
686 std::find_if(block->rbegin(), block->rend(), [](mlir::Operation &op) {
687 return mlir::isa<cir::AllocaOp, cir::LabelOp>(&op);
688 });
689
690 if (last != block->rend())
691 return OpBuilder::InsertPoint(block, ++mlir::Block::iterator(&*last));
692 return OpBuilder::InsertPoint(block, block->begin());
693 };
694
695 //
696 // Alignment and size helpers
697 //
698
699 // Note that mlir::IntegerType is used instead of cir::IntType here because we
700 // don't need sign information for these to be useful, so keep it simple.
701
702 // For 0 alignment, any overload of `getAlignmentAttr` returns an empty
703 // attribute.
704 mlir::IntegerAttr getAlignmentAttr(clang::CharUnits alignment) {
705 return getAlignmentAttr(alignment.getQuantity());
706 }
707
708 mlir::IntegerAttr getAlignmentAttr(llvm::Align alignment) {
709 return getAlignmentAttr(alignment.value());
710 }
711
712 mlir::IntegerAttr getAlignmentAttr(int64_t alignment) {
713 return alignment ? getI64IntegerAttr(alignment) : mlir::IntegerAttr();
714 }
715
716 mlir::IntegerAttr getSizeFromCharUnits(clang::CharUnits size) {
717 return getI64IntegerAttr(size.getQuantity());
718 }
719
720 // Creates constant nullptr for pointer type ty.
721 cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc) {
723 return cir::ConstantOp::create(*this, loc, getConstPtrAttr(ty, 0));
724 }
725
726 /// Create a loop condition.
727 cir::ConditionOp createCondition(mlir::Value condition) {
728 return cir::ConditionOp::create(*this, condition.getLoc(), condition);
729 }
730
731 /// Create a yield operation.
732 cir::YieldOp createYield(mlir::Location loc, mlir::ValueRange value = {}) {
733 return cir::YieldOp::create(*this, loc, value);
734 }
735
737 mlir::Value callee;
738 mlir::Value adjustedThis;
739 };
740
741 GetMethodResults createGetMethod(mlir::Location loc, mlir::Value method,
742 mlir::Value objectPtr) {
743 // Build the callee function type.
744 auto methodFuncTy =
745 mlir::cast<cir::MethodType>(method.getType()).getMemberFuncTy();
746 auto methodFuncInputTypes = methodFuncTy.getInputs();
747
748 auto objectPtrTy = mlir::cast<cir::PointerType>(objectPtr.getType());
749 mlir::Type adjustedThisTy = getVoidPtrTy(objectPtrTy.getAddrSpace());
750
751 llvm::SmallVector<mlir::Type> calleeFuncInputTypes{adjustedThisTy};
752 calleeFuncInputTypes.insert(calleeFuncInputTypes.end(),
753 methodFuncInputTypes.begin(),
754 methodFuncInputTypes.end());
755 cir::FuncType calleeFuncTy =
756 methodFuncTy.clone(calleeFuncInputTypes, methodFuncTy.getReturnType());
757 // TODO(cir): consider the address space of the callee.
759 cir::PointerType calleeTy = getPointerTo(calleeFuncTy);
760
761 auto op = cir::GetMethodOp::create(*this, loc, calleeTy, adjustedThisTy,
762 method, objectPtr);
763 return {op.getCallee(), op.getAdjustedThis()};
764 }
765};
766
767} // namespace cir
768
769#endif
Provides definitions for the various language-specific address spaces.
*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
__device__ __2f16 b
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.
cir::BreakOp createBreak(mlir::Location loc)
Create a break operation.
mlir::TypedAttr getConstNullPtrAttr(mlir::Type t)
mlir::IntegerAttr getAlignmentAttr(int64_t alignment)
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)
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)
cir::ConditionOp createCondition(mlir::Value condition)
Create a loop condition.
mlir::Value createLowBitsSet(mlir::Location loc, unsigned size, unsigned bits)
mlir::Value createNSWAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createGetGlobal(cir::GlobalOp global, bool threadLocal=false)
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::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee, mlir::ValueRange operands=mlir::ValueRange(), llvm::ArrayRef< mlir::NamedAttribute > attrs={})
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)
mlir::Value createCast(mlir::Location loc, cir::CastKind kind, mlir::Value src, mlir::Type newTy)
mlir::IntegerAttr getSizeFromCharUnits(clang::CharUnits size)
cir::PtrStrideOp createPtrStride(mlir::Location loc, mlir::Value base, mlir::Value stride)
mlir::Value createIntToPtr(mlir::Value src, mlir::Type newTy)
cir::CallOp createCallOp(mlir::Location loc, cir::FuncOp callee, mlir::ValueRange operands, llvm::ArrayRef< mlir::NamedAttribute > attrs={})
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 createNUWSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::ConstantOp getFalse(mlir::Location loc)
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 createNot(mlir::Value value)
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::IntType getUIntNTy(int n)
cir::PointerType getVoidPtrTy(cir::TargetAddressSpaceAttr as)
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)
cir::CopyOp createCopy(mlir::Value dst, mlir::Value src, bool isVolatile=false)
Create a copy with inferred length.
cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee, mlir::Type returnType, mlir::ValueRange operands, llvm::ArrayRef< mlir::NamedAttribute > attrs={})
mlir::Value createPtrBitcast(mlir::Value src, mlir::Type newPointeeTy)
mlir::Value createShiftLeft(mlir::Location loc, mlir::Value lhs, unsigned bits)
mlir::Value createSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::Saturated)
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)
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)
mlir::Value createBitcast(mlir::Value src, mlir::Type newTy)
CIRBaseBuilderTy(mlir::MLIRContext &mlirContext)
mlir::Value createBitcast(mlir::Location loc, mlir::Value src, mlir::Type newTy)
mlir::TypedAttr getNullDataMemberAttr(cir::DataMemberType ty)
cir::GlobalOp createGlobal(mlir::ModuleOp mlirModule, mlir::Location loc, mlir::StringRef name, mlir::Type type, bool isConstant, cir::GlobalLinkageKind linkage)
mlir::Value createGetGlobal(mlir::Location loc, cir::GlobalOp global, bool threadLocal=false)
cir::CmpOp createCompare(mlir::Location loc, cir::CmpOpKind kind, mlir::Value lhs, mlir::Value rhs)
mlir::IntegerAttr getAlignmentAttr(clang::CharUnits alignment)
mlir::Value createBinop(mlir::Location loc, mlir::Value lhs, cir::BinOpKind kind, mlir::Value rhs)
mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType, mlir::Type type, llvm::StringRef name, mlir::IntegerAttr alignment)
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.
mlir::Value createMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
mlir::TypedAttr getZeroInitAttr(mlir::Type ty)
cir::LoadOp createLoad(mlir::Location loc, mlir::Value ptr, bool isVolatile=false, uint64_t alignment=0)
mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType, mlir::Type type, llvm::StringRef name, clang::CharUnits alignment)
cir::CallOp createIndirectCallOp(mlir::Location loc, mlir::Value indirectTarget, cir::FuncType funcType, mlir::ValueRange operands, llvm::ArrayRef< mlir::NamedAttribute > attrs={})
CIRBaseBuilderTy(mlir::OpBuilder &builder)
static unsigned getCIRIntOrFloatBitWidth(mlir::Type eltTy)
cir::ConstantOp getConstantInt(mlir::Location loc, mlir::Type ty, int64_t value)
mlir::Value createComplexCreate(mlir::Location loc, mlir::Value real, mlir::Value imag)
mlir::Value createAddrSpaceCast(mlir::Value src, mlir::Type newTy)
cir::PointerType getPointerTo(mlir::Type ty, cir::TargetAddressSpaceAttr as)
mlir::Value createPtrToBoolCast(mlir::Value v)
cir::BoolAttr getTrueAttr()
cir::PointerType getVoidPtrTy(clang::LangAS langAS=clang::LangAS::Default)
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)
mlir::Value createAlignedLoad(mlir::Location loc, mlir::Value ptr, uint64_t alignment)
mlir::TypedAttr getConstPtrAttr(mlir::Type type, int64_t value)
mlir::Value createAddrSpaceCast(mlir::Location loc, mlir::Value src, mlir::Type newTy)
mlir::Value createDummyValue(mlir::Location loc, mlir::Type type, clang::CharUnits alignment)
cir::BoolAttr getFalseAttr()
mlir::Value createShiftRight(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, mlir::Value dst, bool isVolatile=false, mlir::IntegerAttr align={}, cir::SyncScopeKindAttr scope={}, cir::MemOrderAttr order={})
cir::YieldOp createYield(mlir::Location loc, mlir::ValueRange value={})
Create a yield operation.
mlir::Value createLogicalAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createUnaryOp(mlir::Location loc, cir::UnaryOpKind kind, mlir::Value operand)
mlir::IntegerAttr getAlignmentAttr(llvm::Align alignment)
cir::LoadOp createFlagLoad(mlir::Location loc, mlir::Value addr)
Emit a load from an boolean flag variable.
mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType, mlir::Type type, llvm::StringRef name, mlir::IntegerAttr alignment, mlir::Value dynAllocSize)
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
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)
OverflowBehavior
bool isTargetAddressSpace(LangAS AS)
unsigned toTargetAddressSpace(LangAS AS)
LangAS
Defines the address space values used by the address space qualifier of QualType.
static bool addressSpace()
static bool targetCodeGenInfoGetNullPointer()