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