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