147 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9// This class provides a simple wrapper for a pair of a pointer and an10// alignment.11//12//===----------------------------------------------------------------------===//13 14#ifndef CLANG_LIB_CIR_ADDRESS_H15#define CLANG_LIB_CIR_ADDRESS_H16 17#include "mlir/IR/Value.h"18#include "clang/AST/CharUnits.h"19#include "clang/CIR/Dialect/IR/CIRAttrs.h"20#include "clang/CIR/Dialect/IR/CIRTypes.h"21#include "clang/CIR/MissingFeatures.h"22#include "llvm/ADT/PointerIntPair.h"23#include "llvm/Support/Casting.h"24 25namespace clang::CIRGen {26 27// Forward declaration to avoid a circular dependency28class CIRGenBuilderTy;29 30class Address {31 32 // The boolean flag indicates whether the pointer is known to be non-null.33 llvm::PointerIntPair<mlir::Value, 1, bool> pointerAndKnownNonNull;34 35 /// The expected CIR type of the pointer. Carrying accurate element type36 /// information in Address makes it more convenient to work with Address37 /// values and allows frontend assertions to catch simple mistakes.38 mlir::Type elementType;39 40 clang::CharUnits alignment;41 42protected:43 Address(std::nullptr_t) : elementType(nullptr) {}44 45public:46 Address(mlir::Value pointer, mlir::Type elementType,47 clang::CharUnits alignment)48 : pointerAndKnownNonNull(pointer, false), elementType(elementType),49 alignment(alignment) {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::isa<cir::PointerType>(pointer.getType()) &&55 "Expected cir.ptr type");56 57 assert(mlir::cast<cir::PointerType>(pointer.getType()).getPointee() ==58 elementType);59 }60 61 Address(mlir::Value pointer, clang::CharUnits alignment)62 : Address(pointer,63 mlir::cast<cir::PointerType>(pointer.getType()).getPointee(),64 alignment) {65 assert((!alignment.isZero() || pointer == nullptr) &&66 "creating valid address with invalid alignment");67 }68 69 static Address invalid() { return Address(nullptr); }70 bool isValid() const {71 return pointerAndKnownNonNull.getPointer() != nullptr;72 }73 74 /// Return address with different pointer, but same element type and75 /// alignment.76 Address withPointer(mlir::Value newPtr) const {77 return Address(newPtr, getElementType(), getAlignment());78 }79 80 /// Return address with different alignment, but same pointer and element81 /// type.82 Address withAlignment(clang::CharUnits newAlignment) const {83 return Address(getPointer(), getElementType(), newAlignment);84 }85 86 /// Return address with different element type, a bitcast pointer, and87 /// the same alignment.88 Address withElementType(CIRGenBuilderTy &builder, mlir::Type ElemTy) const;89 90 mlir::Value getPointer() const {91 assert(isValid());92 return pointerAndKnownNonNull.getPointer();93 }94 95 mlir::Value getBasePointer() const {96 // TODO(cir): Remove the version above when we catchup with OG codegen on97 // ptr auth.98 assert(isValid() && "pointer isn't valid");99 return getPointer();100 }101 102 /// Return the pointer contained in this class after authenticating it and103 /// adding offset to it if necessary.104 mlir::Value emitRawPointer() const {105 assert(!cir::MissingFeatures::addressPointerAuthInfo());106 return getBasePointer();107 }108 109 mlir::Type getType() const {110 assert(mlir::cast<cir::PointerType>(111 pointerAndKnownNonNull.getPointer().getType())112 .getPointee() == elementType);113 114 return mlir::cast<cir::PointerType>(getPointer().getType());115 }116 117 mlir::Type getElementType() const {118 assert(isValid());119 assert(mlir::cast<cir::PointerType>(120 pointerAndKnownNonNull.getPointer().getType())121 .getPointee() == elementType);122 return elementType;123 }124 125 cir::TargetAddressSpaceAttr getAddressSpace() const {126 auto ptrTy = mlir::dyn_cast<cir::PointerType>(getType());127 return ptrTy.getAddrSpace();128 }129 130 clang::CharUnits getAlignment() const { return alignment; }131 132 /// Get the operation which defines this address.133 mlir::Operation *getDefiningOp() const {134 if (!isValid())135 return nullptr;136 return getPointer().getDefiningOp();137 }138 139 template <typename OpTy> OpTy getDefiningOp() const {140 return mlir::dyn_cast_or_null<OpTy>(getDefiningOp());141 }142};143 144} // namespace clang::CIRGen145 146#endif // CLANG_LIB_CIR_ADDRESS_H147