xref: /freebsd/contrib/llvm-project/clang/lib/CIR/CodeGen/Address.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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