1*700637cbSDimitry Andric //===----------------------------------------------------------------------===// 2*700637cbSDimitry Andric // 3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*700637cbSDimitry Andric // 7*700637cbSDimitry Andric //===----------------------------------------------------------------------===// 8*700637cbSDimitry Andric // 9*700637cbSDimitry Andric // This class provides a simple wrapper for a pair of a pointer and an 10*700637cbSDimitry Andric // alignment. 11*700637cbSDimitry Andric // 12*700637cbSDimitry Andric //===----------------------------------------------------------------------===// 13*700637cbSDimitry Andric 14*700637cbSDimitry Andric #ifndef CLANG_LIB_CIR_ADDRESS_H 15*700637cbSDimitry Andric #define CLANG_LIB_CIR_ADDRESS_H 16*700637cbSDimitry Andric 17*700637cbSDimitry Andric #include "mlir/IR/Value.h" 18*700637cbSDimitry Andric #include "clang/AST/CharUnits.h" 19*700637cbSDimitry Andric #include "clang/CIR/Dialect/IR/CIRTypes.h" 20*700637cbSDimitry Andric #include "llvm/ADT/PointerIntPair.h" 21*700637cbSDimitry Andric 22*700637cbSDimitry Andric namespace clang::CIRGen { 23*700637cbSDimitry Andric 24*700637cbSDimitry Andric // Forward declaration to avoid a circular dependency 25*700637cbSDimitry Andric class CIRGenBuilderTy; 26*700637cbSDimitry Andric 27*700637cbSDimitry Andric class Address { 28*700637cbSDimitry Andric 29*700637cbSDimitry Andric // The boolean flag indicates whether the pointer is known to be non-null. 30*700637cbSDimitry Andric llvm::PointerIntPair<mlir::Value, 1, bool> pointerAndKnownNonNull; 31*700637cbSDimitry Andric 32*700637cbSDimitry Andric /// The expected CIR type of the pointer. Carrying accurate element type 33*700637cbSDimitry Andric /// information in Address makes it more convenient to work with Address 34*700637cbSDimitry Andric /// values and allows frontend assertions to catch simple mistakes. 35*700637cbSDimitry Andric mlir::Type elementType; 36*700637cbSDimitry Andric 37*700637cbSDimitry Andric clang::CharUnits alignment; 38*700637cbSDimitry Andric 39*700637cbSDimitry Andric protected: Address(std::nullptr_t)40*700637cbSDimitry Andric Address(std::nullptr_t) : elementType(nullptr) {} 41*700637cbSDimitry Andric 42*700637cbSDimitry Andric public: Address(mlir::Value pointer,mlir::Type elementType,clang::CharUnits alignment)43*700637cbSDimitry Andric Address(mlir::Value pointer, mlir::Type elementType, 44*700637cbSDimitry Andric clang::CharUnits alignment) 45*700637cbSDimitry Andric : pointerAndKnownNonNull(pointer, false), elementType(elementType), 46*700637cbSDimitry Andric alignment(alignment) { 47*700637cbSDimitry Andric assert(mlir::isa<cir::PointerType>(pointer.getType()) && 48*700637cbSDimitry Andric "Expected cir.ptr type"); 49*700637cbSDimitry Andric 50*700637cbSDimitry Andric assert(pointer && "Pointer cannot be null"); 51*700637cbSDimitry Andric assert(elementType && "Element type cannot be null"); 52*700637cbSDimitry Andric assert(!alignment.isZero() && "Alignment cannot be zero"); 53*700637cbSDimitry Andric 54*700637cbSDimitry Andric assert(mlir::cast<cir::PointerType>(pointer.getType()).getPointee() == 55*700637cbSDimitry Andric elementType); 56*700637cbSDimitry Andric } 57*700637cbSDimitry Andric Address(mlir::Value pointer,clang::CharUnits alignment)58*700637cbSDimitry Andric Address(mlir::Value pointer, clang::CharUnits alignment) 59*700637cbSDimitry Andric : Address(pointer, 60*700637cbSDimitry Andric mlir::cast<cir::PointerType>(pointer.getType()).getPointee(), 61*700637cbSDimitry Andric alignment) { 62*700637cbSDimitry Andric assert((!alignment.isZero() || pointer == nullptr) && 63*700637cbSDimitry Andric "creating valid address with invalid alignment"); 64*700637cbSDimitry Andric } 65*700637cbSDimitry Andric invalid()66*700637cbSDimitry Andric static Address invalid() { return Address(nullptr); } isValid()67*700637cbSDimitry Andric bool isValid() const { 68*700637cbSDimitry Andric return pointerAndKnownNonNull.getPointer() != nullptr; 69*700637cbSDimitry Andric } 70*700637cbSDimitry Andric 71*700637cbSDimitry Andric /// Return address with different element type, a bitcast pointer, and 72*700637cbSDimitry Andric /// the same alignment. 73*700637cbSDimitry Andric Address withElementType(CIRGenBuilderTy &builder, mlir::Type ElemTy) const; 74*700637cbSDimitry Andric getPointer()75*700637cbSDimitry Andric mlir::Value getPointer() const { 76*700637cbSDimitry Andric assert(isValid()); 77*700637cbSDimitry Andric return pointerAndKnownNonNull.getPointer(); 78*700637cbSDimitry Andric } 79*700637cbSDimitry Andric getBasePointer()80*700637cbSDimitry Andric mlir::Value getBasePointer() const { 81*700637cbSDimitry Andric // TODO(cir): Remove the version above when we catchup with OG codegen on 82*700637cbSDimitry Andric // ptr auth. 83*700637cbSDimitry Andric assert(isValid() && "pointer isn't valid"); 84*700637cbSDimitry Andric return getPointer(); 85*700637cbSDimitry Andric } 86*700637cbSDimitry Andric getType()87*700637cbSDimitry Andric mlir::Type getType() const { 88*700637cbSDimitry Andric assert(mlir::cast<cir::PointerType>( 89*700637cbSDimitry Andric pointerAndKnownNonNull.getPointer().getType()) 90*700637cbSDimitry Andric .getPointee() == elementType); 91*700637cbSDimitry Andric 92*700637cbSDimitry Andric return mlir::cast<cir::PointerType>(getPointer().getType()); 93*700637cbSDimitry Andric } 94*700637cbSDimitry Andric getElementType()95*700637cbSDimitry Andric mlir::Type getElementType() const { 96*700637cbSDimitry Andric assert(isValid()); 97*700637cbSDimitry Andric assert(mlir::cast<cir::PointerType>( 98*700637cbSDimitry Andric pointerAndKnownNonNull.getPointer().getType()) 99*700637cbSDimitry Andric .getPointee() == elementType); 100*700637cbSDimitry Andric return elementType; 101*700637cbSDimitry Andric } 102*700637cbSDimitry Andric getAlignment()103*700637cbSDimitry Andric clang::CharUnits getAlignment() const { return alignment; } 104*700637cbSDimitry Andric }; 105*700637cbSDimitry Andric 106*700637cbSDimitry Andric } // namespace clang::CIRGen 107*700637cbSDimitry Andric 108*700637cbSDimitry Andric #endif // CLANG_LIB_CIR_ADDRESS_H 109