-
Notifications
You must be signed in to change notification settings - Fork 138
/
Copy pathAddress.h
153 lines (125 loc) · 4.75 KB
/
Address.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
//===-- Address.h - An aligned address -------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This class provides a simple wrapper for a pair of a pointer and an
// alignment.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LIB_CIR_ADDRESS_H
#define LLVM_CLANG_LIB_CIR_ADDRESS_H
#include "clang/AST/CharUnits.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
#include "llvm/IR/Constants.h"
#include "mlir/IR/Value.h"
namespace clang::CIRGen {
// Indicates whether a pointer is known not to be null.
enum KnownNonNull_t { NotKnownNonNull, KnownNonNull };
/// Like RawAddress, an abstract representation of an aligned address, but the
/// pointer contained in this class is possibly signed.
class Address {
llvm::PointerIntPair<mlir::Value, 1, bool> PointerAndKnownNonNull;
mlir::Type ElementType;
clang::CharUnits Alignment;
/// Offset from the base pointer. This is non-null only when the base pointer
/// is signed.
mlir::Attribute offset = nullptr;
protected:
Address(std::nullptr_t) : ElementType(nullptr) {}
public:
Address(mlir::Value pointer, mlir::Type elementType,
clang::CharUnits alignment,
KnownNonNull_t IsKnownNonNull = NotKnownNonNull)
: PointerAndKnownNonNull(pointer, IsKnownNonNull),
ElementType(elementType), Alignment(alignment) {
assert(mlir::isa<cir::PointerType>(pointer.getType()) &&
"Expected cir.ptr type");
assert(pointer && "Pointer cannot be null");
assert(elementType && "Element type cannot be null");
assert(!alignment.isZero() && "Alignment cannot be zero");
}
Address(mlir::Value pointer, clang::CharUnits alignment)
: Address(pointer,
mlir::cast<cir::PointerType>(pointer.getType()).getPointee(),
alignment) {
assert((!alignment.isZero() || pointer == nullptr) &&
"creating valid address with invalid alignment");
}
static Address invalid() { return Address(nullptr); }
bool isValid() const {
return PointerAndKnownNonNull.getPointer() != nullptr;
}
/// Return address with different pointer, but same element type and
/// alignment.
Address withPointer(mlir::Value NewPointer,
KnownNonNull_t IsKnownNonNull = NotKnownNonNull) const {
return Address(NewPointer, getElementType(), getAlignment(),
IsKnownNonNull);
}
/// Return address with different alignment, but same pointer and element
/// type.
Address withAlignment(clang::CharUnits NewAlignment) const {
return Address(getPointer(), getElementType(), NewAlignment,
isKnownNonNull());
}
/// Return address with different element type, but same pointer and
/// alignment.
Address withElementType(mlir::Type ElemTy) const {
// TODO(cir): hasOffset() check
return Address(getPointer(), ElemTy, getAlignment(), isKnownNonNull());
}
mlir::Value getPointer() const {
assert(isValid());
return PointerAndKnownNonNull.getPointer();
}
mlir::Value getBasePointer() const {
// TODO(cir): Remove the version above when we catchup with OG codegen on
// ptr auth.
assert(isValid() && "pointer isn't valid");
return getPointer();
}
/// Return the alignment of this pointer.
clang::CharUnits getAlignment() const {
// assert(isValid());
return Alignment;
}
/// Return the pointer contained in this class after authenticating it and
/// adding offset to it if necessary.
mlir::Value emitRawPointer() const {
// TODO(cir): update this class with latest traditional LLVM codegen bits
// and the replace the call below to getBasePointer().
return getPointer();
}
/// Return the type of the pointer value.
cir::PointerType getType() const {
return mlir::cast<cir::PointerType>(getPointer().getType());
}
mlir::Type getElementType() const {
assert(isValid());
return ElementType;
}
/// Whether the pointer is known not to be null.
KnownNonNull_t isKnownNonNull() const {
assert(isValid());
return (KnownNonNull_t)PointerAndKnownNonNull.getInt();
}
/// Set the non-null bit.
Address setKnownNonNull() {
assert(isValid());
PointerAndKnownNonNull.setInt(true);
return *this;
}
bool hasOffset() const { return bool(offset); }
/// Get the operation which defines this address.
mlir::Operation *getDefiningOp() const {
if (!isValid())
return nullptr;
return getPointer().getDefiningOp();
}
};
} // namespace clang::CIRGen
#endif // LLVM_CLANG_LIB_CIR_ADDRESS_H