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" 13 #include "clang/CIR/Dialect/IR/CIRAttrs.h" 14 #include "clang/CIR/Dialect/IR/CIRDialect.h" 15 #include "clang/CIR/Dialect/IR/CIRTypes.h" 16 #include "clang/CIR/MissingFeatures.h" 17 #include "llvm/ADT/STLForwardCompat.h" 18 #include "llvm/Support/ErrorHandling.h" 19 20 #include "mlir/IR/Builders.h" 21 #include "mlir/IR/BuiltinAttributes.h" 22 #include "mlir/IR/BuiltinTypes.h" 23 #include "mlir/IR/Location.h" 24 #include "mlir/IR/Types.h" 25 26 namespace cir { 27 28 enum class OverflowBehavior { 29 None = 0, 30 NoSignedWrap = 1 << 0, 31 NoUnsignedWrap = 1 << 1, 32 Saturated = 1 << 2, 33 }; 34 35 constexpr OverflowBehavior operator|(OverflowBehavior a, OverflowBehavior b) { 36 return static_cast<OverflowBehavior>(llvm::to_underlying(a) | 37 llvm::to_underlying(b)); 38 } 39 40 constexpr OverflowBehavior operator&(OverflowBehavior a, OverflowBehavior b) { 41 return static_cast<OverflowBehavior>(llvm::to_underlying(a) & 42 llvm::to_underlying(b)); 43 } 44 45 constexpr OverflowBehavior &operator|=(OverflowBehavior &a, 46 OverflowBehavior b) { 47 a = a | b; 48 return a; 49 } 50 51 constexpr OverflowBehavior &operator&=(OverflowBehavior &a, 52 OverflowBehavior b) { 53 a = a & b; 54 return a; 55 } 56 57 class CIRBaseBuilderTy : public mlir::OpBuilder { 58 59 public: CIRBaseBuilderTy(mlir::MLIRContext & mlirContext)60 CIRBaseBuilderTy(mlir::MLIRContext &mlirContext) 61 : mlir::OpBuilder(&mlirContext) {} CIRBaseBuilderTy(mlir::OpBuilder & builder)62 CIRBaseBuilderTy(mlir::OpBuilder &builder) : mlir::OpBuilder(builder) {} 63 getConstAPInt(mlir::Location loc,mlir::Type typ,const llvm::APInt & val)64 mlir::Value getConstAPInt(mlir::Location loc, mlir::Type typ, 65 const llvm::APInt &val) { 66 return create<cir::ConstantOp>(loc, cir::IntAttr::get(typ, val)); 67 } 68 getConstant(mlir::Location loc,mlir::TypedAttr attr)69 cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr) { 70 return create<cir::ConstantOp>(loc, attr); 71 } 72 getConstantInt(mlir::Location loc,mlir::Type ty,int64_t value)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 // Creates constant null value for integral type ty. getNullValue(mlir::Type ty,mlir::Location loc)79 cir::ConstantOp getNullValue(mlir::Type ty, mlir::Location loc) { 80 return getConstant(loc, getZeroInitAttr(ty)); 81 } 82 getConstNullPtrAttr(mlir::Type t)83 mlir::TypedAttr getConstNullPtrAttr(mlir::Type t) { 84 assert(mlir::isa<cir::PointerType>(t) && "expected cir.ptr"); 85 return getConstPtrAttr(t, 0); 86 } 87 getZeroInitAttr(mlir::Type ty)88 mlir::TypedAttr getZeroInitAttr(mlir::Type ty) { 89 if (mlir::isa<cir::IntType>(ty)) 90 return cir::IntAttr::get(ty, 0); 91 if (cir::isAnyFloatingPointType(ty)) 92 return cir::FPAttr::getZero(ty); 93 if (auto complexType = mlir::dyn_cast<cir::ComplexType>(ty)) 94 return cir::ZeroAttr::get(complexType); 95 if (auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty)) 96 return cir::ZeroAttr::get(arrTy); 97 if (auto vecTy = mlir::dyn_cast<cir::VectorType>(ty)) 98 return cir::ZeroAttr::get(vecTy); 99 if (auto ptrTy = mlir::dyn_cast<cir::PointerType>(ty)) 100 return getConstNullPtrAttr(ptrTy); 101 if (auto recordTy = mlir::dyn_cast<cir::RecordType>(ty)) 102 return cir::ZeroAttr::get(recordTy); 103 if (mlir::isa<cir::BoolType>(ty)) { 104 return getFalseAttr(); 105 } 106 llvm_unreachable("Zero initializer for given type is NYI"); 107 } 108 getBool(bool state,mlir::Location loc)109 cir::ConstantOp getBool(bool state, mlir::Location loc) { 110 return create<cir::ConstantOp>(loc, getCIRBoolAttr(state)); 111 } getFalse(mlir::Location loc)112 cir::ConstantOp getFalse(mlir::Location loc) { return getBool(false, loc); } getTrue(mlir::Location loc)113 cir::ConstantOp getTrue(mlir::Location loc) { return getBool(true, loc); } 114 getBoolTy()115 cir::BoolType getBoolTy() { return cir::BoolType::get(getContext()); } 116 getPointerTo(mlir::Type ty)117 cir::PointerType getPointerTo(mlir::Type ty) { 118 return cir::PointerType::get(ty); 119 } 120 getVoidPtrTy()121 cir::PointerType getVoidPtrTy() { 122 return getPointerTo(cir::VoidType::get(getContext())); 123 } 124 getCIRBoolAttr(bool state)125 cir::BoolAttr getCIRBoolAttr(bool state) { 126 return cir::BoolAttr::get(getContext(), state); 127 } 128 getTrueAttr()129 cir::BoolAttr getTrueAttr() { return getCIRBoolAttr(true); } getFalseAttr()130 cir::BoolAttr getFalseAttr() { return getCIRBoolAttr(false); } 131 createNot(mlir::Value value)132 mlir::Value createNot(mlir::Value value) { 133 return create<cir::UnaryOp>(value.getLoc(), value.getType(), 134 cir::UnaryOpKind::Not, value); 135 } 136 137 /// Create a do-while operation. createDoWhile(mlir::Location loc,llvm::function_ref<void (mlir::OpBuilder &,mlir::Location)> condBuilder,llvm::function_ref<void (mlir::OpBuilder &,mlir::Location)> bodyBuilder)138 cir::DoWhileOp createDoWhile( 139 mlir::Location loc, 140 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> condBuilder, 141 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> bodyBuilder) { 142 return create<cir::DoWhileOp>(loc, condBuilder, bodyBuilder); 143 } 144 145 /// Create a while operation. createWhile(mlir::Location loc,llvm::function_ref<void (mlir::OpBuilder &,mlir::Location)> condBuilder,llvm::function_ref<void (mlir::OpBuilder &,mlir::Location)> bodyBuilder)146 cir::WhileOp createWhile( 147 mlir::Location loc, 148 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> condBuilder, 149 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> bodyBuilder) { 150 return create<cir::WhileOp>(loc, condBuilder, bodyBuilder); 151 } 152 153 /// Create a for operation. 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)154 cir::ForOp createFor( 155 mlir::Location loc, 156 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> condBuilder, 157 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> bodyBuilder, 158 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)> stepBuilder) { 159 return create<cir::ForOp>(loc, condBuilder, bodyBuilder, stepBuilder); 160 } 161 162 /// Create a break operation. createBreak(mlir::Location loc)163 cir::BreakOp createBreak(mlir::Location loc) { 164 return create<cir::BreakOp>(loc); 165 } 166 167 /// Create a continue operation. createContinue(mlir::Location loc)168 cir::ContinueOp createContinue(mlir::Location loc) { 169 return create<cir::ContinueOp>(loc); 170 } 171 getConstPtrAttr(mlir::Type type,int64_t value)172 mlir::TypedAttr getConstPtrAttr(mlir::Type type, int64_t value) { 173 return cir::ConstPtrAttr::get(type, getI64IntegerAttr(value)); 174 } 175 createAlloca(mlir::Location loc,cir::PointerType addrType,mlir::Type type,llvm::StringRef name,mlir::IntegerAttr alignment)176 mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType, 177 mlir::Type type, llvm::StringRef name, 178 mlir::IntegerAttr alignment) { 179 return create<cir::AllocaOp>(loc, addrType, type, name, alignment); 180 } 181 createGetGlobal(mlir::Location loc,cir::GlobalOp global)182 mlir::Value createGetGlobal(mlir::Location loc, cir::GlobalOp global) { 183 assert(!cir::MissingFeatures::addressSpace()); 184 return create<cir::GetGlobalOp>(loc, getPointerTo(global.getSymType()), 185 global.getSymName()); 186 } 187 createGetGlobal(cir::GlobalOp global)188 mlir::Value createGetGlobal(cir::GlobalOp global) { 189 return createGetGlobal(global.getLoc(), global); 190 } 191 192 cir::StoreOp createStore(mlir::Location loc, mlir::Value val, mlir::Value dst, 193 mlir::IntegerAttr align = {}) { 194 return create<cir::StoreOp>(loc, val, dst, align); 195 } 196 createGlobal(mlir::ModuleOp mlirModule,mlir::Location loc,mlir::StringRef name,mlir::Type type,cir::GlobalLinkageKind linkage)197 [[nodiscard]] cir::GlobalOp createGlobal(mlir::ModuleOp mlirModule, 198 mlir::Location loc, 199 mlir::StringRef name, 200 mlir::Type type, 201 cir::GlobalLinkageKind linkage) { 202 mlir::OpBuilder::InsertionGuard guard(*this); 203 setInsertionPointToStart(mlirModule.getBody()); 204 return create<cir::GlobalOp>(loc, name, type, linkage); 205 } 206 createGetMember(mlir::Location loc,mlir::Type resultTy,mlir::Value base,llvm::StringRef name,unsigned index)207 cir::GetMemberOp createGetMember(mlir::Location loc, mlir::Type resultTy, 208 mlir::Value base, llvm::StringRef name, 209 unsigned index) { 210 return create<cir::GetMemberOp>(loc, resultTy, base, name, index); 211 } 212 createDummyValue(mlir::Location loc,mlir::Type type,clang::CharUnits alignment)213 mlir::Value createDummyValue(mlir::Location loc, mlir::Type type, 214 clang::CharUnits alignment) { 215 mlir::IntegerAttr alignmentAttr = getAlignmentAttr(alignment); 216 auto addr = createAlloca(loc, getPointerTo(type), type, {}, alignmentAttr); 217 return create<cir::LoadOp>(loc, addr, /*isDeref=*/false, alignmentAttr); 218 } 219 createPtrStride(mlir::Location loc,mlir::Value base,mlir::Value stride)220 cir::PtrStrideOp createPtrStride(mlir::Location loc, mlir::Value base, 221 mlir::Value stride) { 222 return create<cir::PtrStrideOp>(loc, base.getType(), base, stride); 223 } 224 225 //===--------------------------------------------------------------------===// 226 // Call operators 227 //===--------------------------------------------------------------------===// 228 229 cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee, 230 mlir::Type returnType, mlir::ValueRange operands, 231 llvm::ArrayRef<mlir::NamedAttribute> attrs = {}) { 232 auto op = create<cir::CallOp>(loc, callee, returnType, operands); 233 op->setAttrs(attrs); 234 return op; 235 } 236 237 cir::CallOp createCallOp(mlir::Location loc, cir::FuncOp callee, 238 mlir::ValueRange operands, 239 llvm::ArrayRef<mlir::NamedAttribute> attrs = {}) { 240 return createCallOp(loc, mlir::SymbolRefAttr::get(callee), 241 callee.getFunctionType().getReturnType(), operands, 242 attrs); 243 } 244 245 cir::CallOp 246 createIndirectCallOp(mlir::Location loc, mlir::Value indirectTarget, 247 cir::FuncType funcType, mlir::ValueRange operands, 248 llvm::ArrayRef<mlir::NamedAttribute> attrs = {}) { 249 llvm::SmallVector<mlir::Value> resOperands{indirectTarget}; 250 resOperands.append(operands.begin(), operands.end()); 251 return createCallOp(loc, mlir::SymbolRefAttr(), funcType.getReturnType(), 252 resOperands, attrs); 253 } 254 255 //===--------------------------------------------------------------------===// 256 // Cast/Conversion Operators 257 //===--------------------------------------------------------------------===// 258 createCast(mlir::Location loc,cir::CastKind kind,mlir::Value src,mlir::Type newTy)259 mlir::Value createCast(mlir::Location loc, cir::CastKind kind, 260 mlir::Value src, mlir::Type newTy) { 261 if (newTy == src.getType()) 262 return src; 263 return create<cir::CastOp>(loc, newTy, kind, src); 264 } 265 createCast(cir::CastKind kind,mlir::Value src,mlir::Type newTy)266 mlir::Value createCast(cir::CastKind kind, mlir::Value src, 267 mlir::Type newTy) { 268 if (newTy == src.getType()) 269 return src; 270 return createCast(src.getLoc(), kind, src, newTy); 271 } 272 createIntCast(mlir::Value src,mlir::Type newTy)273 mlir::Value createIntCast(mlir::Value src, mlir::Type newTy) { 274 return createCast(cir::CastKind::integral, src, newTy); 275 } 276 createIntToPtr(mlir::Value src,mlir::Type newTy)277 mlir::Value createIntToPtr(mlir::Value src, mlir::Type newTy) { 278 return createCast(cir::CastKind::int_to_ptr, src, newTy); 279 } 280 createPtrToInt(mlir::Value src,mlir::Type newTy)281 mlir::Value createPtrToInt(mlir::Value src, mlir::Type newTy) { 282 return createCast(cir::CastKind::ptr_to_int, src, newTy); 283 } 284 createPtrToBoolCast(mlir::Value v)285 mlir::Value createPtrToBoolCast(mlir::Value v) { 286 return createCast(cir::CastKind::ptr_to_bool, v, getBoolTy()); 287 } 288 createBoolToInt(mlir::Value src,mlir::Type newTy)289 mlir::Value createBoolToInt(mlir::Value src, mlir::Type newTy) { 290 return createCast(cir::CastKind::bool_to_int, src, newTy); 291 } 292 createBitcast(mlir::Value src,mlir::Type newTy)293 mlir::Value createBitcast(mlir::Value src, mlir::Type newTy) { 294 return createCast(cir::CastKind::bitcast, src, newTy); 295 } 296 createBitcast(mlir::Location loc,mlir::Value src,mlir::Type newTy)297 mlir::Value createBitcast(mlir::Location loc, mlir::Value src, 298 mlir::Type newTy) { 299 return createCast(loc, cir::CastKind::bitcast, src, newTy); 300 } 301 createPtrBitcast(mlir::Value src,mlir::Type newPointeeTy)302 mlir::Value createPtrBitcast(mlir::Value src, mlir::Type newPointeeTy) { 303 assert(mlir::isa<cir::PointerType>(src.getType()) && "expected ptr src"); 304 return createBitcast(src, getPointerTo(newPointeeTy)); 305 } 306 307 //===--------------------------------------------------------------------===// 308 // Binary Operators 309 //===--------------------------------------------------------------------===// 310 createBinop(mlir::Location loc,mlir::Value lhs,cir::BinOpKind kind,mlir::Value rhs)311 mlir::Value createBinop(mlir::Location loc, mlir::Value lhs, 312 cir::BinOpKind kind, mlir::Value rhs) { 313 return create<cir::BinOp>(loc, lhs.getType(), kind, lhs, rhs); 314 } 315 createLowBitsSet(mlir::Location loc,unsigned size,unsigned bits)316 mlir::Value createLowBitsSet(mlir::Location loc, unsigned size, 317 unsigned bits) { 318 llvm::APInt val = llvm::APInt::getLowBitsSet(size, bits); 319 auto type = cir::IntType::get(getContext(), size, /*isSigned=*/false); 320 return getConstAPInt(loc, type, val); 321 } 322 createAnd(mlir::Location loc,mlir::Value lhs,mlir::Value rhs)323 mlir::Value createAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) { 324 return createBinop(loc, lhs, cir::BinOpKind::And, rhs); 325 } 326 createOr(mlir::Location loc,mlir::Value lhs,mlir::Value rhs)327 mlir::Value createOr(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) { 328 return createBinop(loc, lhs, cir::BinOpKind::Or, rhs); 329 } 330 createSelect(mlir::Location loc,mlir::Value condition,mlir::Value trueValue,mlir::Value falseValue)331 mlir::Value createSelect(mlir::Location loc, mlir::Value condition, 332 mlir::Value trueValue, mlir::Value falseValue) { 333 assert(trueValue.getType() == falseValue.getType() && 334 "trueValue and falseValue should have the same type"); 335 return create<cir::SelectOp>(loc, trueValue.getType(), condition, trueValue, 336 falseValue); 337 } 338 createLogicalAnd(mlir::Location loc,mlir::Value lhs,mlir::Value rhs)339 mlir::Value createLogicalAnd(mlir::Location loc, mlir::Value lhs, 340 mlir::Value rhs) { 341 return createSelect(loc, lhs, rhs, getBool(false, loc)); 342 } 343 createLogicalOr(mlir::Location loc,mlir::Value lhs,mlir::Value rhs)344 mlir::Value createLogicalOr(mlir::Location loc, mlir::Value lhs, 345 mlir::Value rhs) { 346 return createSelect(loc, lhs, getBool(true, loc), rhs); 347 } 348 349 mlir::Value createMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, 350 OverflowBehavior ob = OverflowBehavior::None) { 351 auto op = 352 create<cir::BinOp>(loc, lhs.getType(), cir::BinOpKind::Mul, lhs, rhs); 353 op.setNoUnsignedWrap( 354 llvm::to_underlying(ob & OverflowBehavior::NoUnsignedWrap)); 355 op.setNoSignedWrap( 356 llvm::to_underlying(ob & OverflowBehavior::NoSignedWrap)); 357 return op; 358 } createNSWMul(mlir::Location loc,mlir::Value lhs,mlir::Value rhs)359 mlir::Value createNSWMul(mlir::Location loc, mlir::Value lhs, 360 mlir::Value rhs) { 361 return createMul(loc, lhs, rhs, OverflowBehavior::NoSignedWrap); 362 } createNUWAMul(mlir::Location loc,mlir::Value lhs,mlir::Value rhs)363 mlir::Value createNUWAMul(mlir::Location loc, mlir::Value lhs, 364 mlir::Value rhs) { 365 return createMul(loc, lhs, rhs, OverflowBehavior::NoUnsignedWrap); 366 } 367 368 mlir::Value createSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, 369 OverflowBehavior ob = OverflowBehavior::Saturated) { 370 auto op = 371 create<cir::BinOp>(loc, lhs.getType(), cir::BinOpKind::Sub, lhs, rhs); 372 op.setNoUnsignedWrap( 373 llvm::to_underlying(ob & OverflowBehavior::NoUnsignedWrap)); 374 op.setNoSignedWrap( 375 llvm::to_underlying(ob & OverflowBehavior::NoSignedWrap)); 376 op.setSaturated(llvm::to_underlying(ob & OverflowBehavior::Saturated)); 377 return op; 378 } 379 createNSWSub(mlir::Location loc,mlir::Value lhs,mlir::Value rhs)380 mlir::Value createNSWSub(mlir::Location loc, mlir::Value lhs, 381 mlir::Value rhs) { 382 return createSub(loc, lhs, rhs, OverflowBehavior::NoSignedWrap); 383 } 384 createNUWSub(mlir::Location loc,mlir::Value lhs,mlir::Value rhs)385 mlir::Value createNUWSub(mlir::Location loc, mlir::Value lhs, 386 mlir::Value rhs) { 387 return createSub(loc, lhs, rhs, OverflowBehavior::NoUnsignedWrap); 388 } 389 390 mlir::Value createAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, 391 OverflowBehavior ob = OverflowBehavior::None) { 392 auto op = 393 create<cir::BinOp>(loc, lhs.getType(), cir::BinOpKind::Add, lhs, rhs); 394 op.setNoUnsignedWrap( 395 llvm::to_underlying(ob & OverflowBehavior::NoUnsignedWrap)); 396 op.setNoSignedWrap( 397 llvm::to_underlying(ob & OverflowBehavior::NoSignedWrap)); 398 op.setSaturated(llvm::to_underlying(ob & OverflowBehavior::Saturated)); 399 return op; 400 } 401 createNSWAdd(mlir::Location loc,mlir::Value lhs,mlir::Value rhs)402 mlir::Value createNSWAdd(mlir::Location loc, mlir::Value lhs, 403 mlir::Value rhs) { 404 return createAdd(loc, lhs, rhs, OverflowBehavior::NoSignedWrap); 405 } 406 createNUWAdd(mlir::Location loc,mlir::Value lhs,mlir::Value rhs)407 mlir::Value createNUWAdd(mlir::Location loc, mlir::Value lhs, 408 mlir::Value rhs) { 409 return createAdd(loc, lhs, rhs, OverflowBehavior::NoUnsignedWrap); 410 } 411 createCompare(mlir::Location loc,cir::CmpOpKind kind,mlir::Value lhs,mlir::Value rhs)412 cir::CmpOp createCompare(mlir::Location loc, cir::CmpOpKind kind, 413 mlir::Value lhs, mlir::Value rhs) { 414 return create<cir::CmpOp>(loc, getBoolTy(), kind, lhs, rhs); 415 } 416 createShift(mlir::Location loc,mlir::Value lhs,mlir::Value rhs,bool isShiftLeft)417 mlir::Value createShift(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, 418 bool isShiftLeft) { 419 return create<cir::ShiftOp>(loc, lhs.getType(), lhs, rhs, isShiftLeft); 420 } 421 createShift(mlir::Location loc,mlir::Value lhs,const llvm::APInt & rhs,bool isShiftLeft)422 mlir::Value createShift(mlir::Location loc, mlir::Value lhs, 423 const llvm::APInt &rhs, bool isShiftLeft) { 424 return createShift(loc, lhs, getConstAPInt(loc, lhs.getType(), rhs), 425 isShiftLeft); 426 } 427 createShift(mlir::Location loc,mlir::Value lhs,unsigned bits,bool isShiftLeft)428 mlir::Value createShift(mlir::Location loc, mlir::Value lhs, unsigned bits, 429 bool isShiftLeft) { 430 auto width = mlir::dyn_cast<cir::IntType>(lhs.getType()).getWidth(); 431 auto shift = llvm::APInt(width, bits); 432 return createShift(loc, lhs, shift, isShiftLeft); 433 } 434 createShiftLeft(mlir::Location loc,mlir::Value lhs,unsigned bits)435 mlir::Value createShiftLeft(mlir::Location loc, mlir::Value lhs, 436 unsigned bits) { 437 return createShift(loc, lhs, bits, true); 438 } 439 createShiftRight(mlir::Location loc,mlir::Value lhs,unsigned bits)440 mlir::Value createShiftRight(mlir::Location loc, mlir::Value lhs, 441 unsigned bits) { 442 return createShift(loc, lhs, bits, false); 443 } 444 createShiftLeft(mlir::Location loc,mlir::Value lhs,mlir::Value rhs)445 mlir::Value createShiftLeft(mlir::Location loc, mlir::Value lhs, 446 mlir::Value rhs) { 447 return createShift(loc, lhs, rhs, true); 448 } 449 createShiftRight(mlir::Location loc,mlir::Value lhs,mlir::Value rhs)450 mlir::Value createShiftRight(mlir::Location loc, mlir::Value lhs, 451 mlir::Value rhs) { 452 return createShift(loc, lhs, rhs, false); 453 } 454 455 // 456 // Block handling helpers 457 // ---------------------- 458 // getBestAllocaInsertPoint(mlir::Block * block)459 static OpBuilder::InsertPoint getBestAllocaInsertPoint(mlir::Block *block) { 460 auto last = 461 std::find_if(block->rbegin(), block->rend(), [](mlir::Operation &op) { 462 // TODO: Add LabelOp missing feature here 463 return mlir::isa<cir::AllocaOp>(&op); 464 }); 465 466 if (last != block->rend()) 467 return OpBuilder::InsertPoint(block, ++mlir::Block::iterator(&*last)); 468 return OpBuilder::InsertPoint(block, block->begin()); 469 }; 470 471 // 472 // Alignment and size helpers 473 // 474 475 // Note that mlir::IntegerType is used instead of cir::IntType here because we 476 // don't need sign information for these to be useful, so keep it simple. 477 478 // For 0 alignment, any overload of `getAlignmentAttr` returns an empty 479 // attribute. getAlignmentAttr(clang::CharUnits alignment)480 mlir::IntegerAttr getAlignmentAttr(clang::CharUnits alignment) { 481 return getAlignmentAttr(alignment.getQuantity()); 482 } 483 getAlignmentAttr(llvm::Align alignment)484 mlir::IntegerAttr getAlignmentAttr(llvm::Align alignment) { 485 return getAlignmentAttr(alignment.value()); 486 } 487 getAlignmentAttr(int64_t alignment)488 mlir::IntegerAttr getAlignmentAttr(int64_t alignment) { 489 return alignment ? getI64IntegerAttr(alignment) : mlir::IntegerAttr(); 490 } 491 getSizeFromCharUnits(clang::CharUnits size)492 mlir::IntegerAttr getSizeFromCharUnits(clang::CharUnits size) { 493 return getI64IntegerAttr(size.getQuantity()); 494 } 495 496 /// Create a loop condition. createCondition(mlir::Value condition)497 cir::ConditionOp createCondition(mlir::Value condition) { 498 return create<cir::ConditionOp>(condition.getLoc(), condition); 499 } 500 501 /// Create a yield operation. 502 cir::YieldOp createYield(mlir::Location loc, mlir::ValueRange value = {}) { 503 return create<cir::YieldOp>(loc, value); 504 } 505 }; 506 507 } // namespace cir 508 509 #endif 510