Path: blob/main/contrib/llvm-project/clang/lib/CodeGen/Address.h
35233 views
//===-- Address.h - An aligned address -------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This class provides a simple wrapper for a pair of a pointer and an9// alignment.10//11//===----------------------------------------------------------------------===//1213#ifndef LLVM_CLANG_LIB_CODEGEN_ADDRESS_H14#define LLVM_CLANG_LIB_CODEGEN_ADDRESS_H1516#include "CGPointerAuthInfo.h"17#include "clang/AST/CharUnits.h"18#include "clang/AST/Type.h"19#include "llvm/ADT/PointerIntPair.h"20#include "llvm/IR/Constants.h"21#include "llvm/Support/MathExtras.h"2223namespace clang {24namespace CodeGen {2526class Address;27class CGBuilderTy;28class CodeGenFunction;29class CodeGenModule;3031// Indicates whether a pointer is known not to be null.32enum KnownNonNull_t { NotKnownNonNull, KnownNonNull };3334/// An abstract representation of an aligned address. This is designed to be an35/// IR-level abstraction, carrying just the information necessary to perform IR36/// operations on an address like loads and stores. In particular, it doesn't37/// carry C type information or allow the representation of things like38/// bit-fields; clients working at that level should generally be using39/// `LValue`.40/// The pointer contained in this class is known to be unsigned.41class RawAddress {42llvm::PointerIntPair<llvm::Value *, 1, bool> PointerAndKnownNonNull;43llvm::Type *ElementType;44CharUnits Alignment;4546protected:47RawAddress(std::nullptr_t) : ElementType(nullptr) {}4849public:50RawAddress(llvm::Value *Pointer, llvm::Type *ElementType, CharUnits Alignment,51KnownNonNull_t IsKnownNonNull = NotKnownNonNull)52: PointerAndKnownNonNull(Pointer, IsKnownNonNull),53ElementType(ElementType), Alignment(Alignment) {54assert(Pointer != nullptr && "Pointer cannot be null");55assert(ElementType != nullptr && "Element type cannot be null");56}5758inline RawAddress(Address Addr);5960static RawAddress invalid() { return RawAddress(nullptr); }61bool isValid() const {62return PointerAndKnownNonNull.getPointer() != nullptr;63}6465llvm::Value *getPointer() const {66assert(isValid());67return PointerAndKnownNonNull.getPointer();68}6970/// Return the type of the pointer value.71llvm::PointerType *getType() const {72return llvm::cast<llvm::PointerType>(getPointer()->getType());73}7475/// Return the type of the values stored in this address.76llvm::Type *getElementType() const {77assert(isValid());78return ElementType;79}8081/// Return the address space that this address resides in.82unsigned getAddressSpace() const {83return getType()->getAddressSpace();84}8586/// Return the IR name of the pointer value.87llvm::StringRef getName() const {88return getPointer()->getName();89}9091/// Return the alignment of this pointer.92CharUnits getAlignment() const {93assert(isValid());94return Alignment;95}9697/// Return address with different element type, but same pointer and98/// alignment.99RawAddress withElementType(llvm::Type *ElemTy) const {100return RawAddress(getPointer(), ElemTy, getAlignment(), isKnownNonNull());101}102103KnownNonNull_t isKnownNonNull() const {104assert(isValid());105return (KnownNonNull_t)PointerAndKnownNonNull.getInt();106}107};108109/// Like RawAddress, an abstract representation of an aligned address, but the110/// pointer contained in this class is possibly signed.111///112/// This is designed to be an IR-level abstraction, carrying just the113/// information necessary to perform IR operations on an address like loads and114/// stores. In particular, it doesn't carry C type information or allow the115/// representation of things like bit-fields; clients working at that level116/// should generally be using `LValue`.117///118/// An address may be either *raw*, meaning that it's an ordinary machine119/// pointer, or *signed*, meaning that the pointer carries an embedded120/// pointer-authentication signature. Representing signed pointers directly in121/// this abstraction allows the authentication to be delayed as long as possible122/// without forcing IRGen to use totally different code paths for signed and123/// unsigned values or to separately propagate signature information through124/// every API that manipulates addresses. Pointer arithmetic on signed addresses125/// (e.g. drilling down to a struct field) is accumulated into a separate offset126/// which is applied when the address is finally accessed.127class Address {128friend class CGBuilderTy;129130// The boolean flag indicates whether the pointer is known to be non-null.131llvm::PointerIntPair<llvm::Value *, 1, bool> Pointer;132133/// The expected IR type of the pointer. Carrying accurate element type134/// information in Address makes it more convenient to work with Address135/// values and allows frontend assertions to catch simple mistakes.136llvm::Type *ElementType = nullptr;137138CharUnits Alignment;139140/// The ptrauth information needed to authenticate the base pointer.141CGPointerAuthInfo PtrAuthInfo;142143/// Offset from the base pointer. This is non-null only when the base144/// pointer is signed.145llvm::Value *Offset = nullptr;146147llvm::Value *emitRawPointerSlow(CodeGenFunction &CGF) const;148149protected:150Address(std::nullptr_t) : ElementType(nullptr) {}151152public:153Address(llvm::Value *pointer, llvm::Type *elementType, CharUnits alignment,154KnownNonNull_t IsKnownNonNull = NotKnownNonNull)155: Pointer(pointer, IsKnownNonNull), ElementType(elementType),156Alignment(alignment) {157assert(pointer != nullptr && "Pointer cannot be null");158assert(elementType != nullptr && "Element type cannot be null");159assert(!alignment.isZero() && "Alignment cannot be zero");160}161162Address(llvm::Value *BasePtr, llvm::Type *ElementType, CharUnits Alignment,163CGPointerAuthInfo PtrAuthInfo, llvm::Value *Offset,164KnownNonNull_t IsKnownNonNull = NotKnownNonNull)165: Pointer(BasePtr, IsKnownNonNull), ElementType(ElementType),166Alignment(Alignment), PtrAuthInfo(PtrAuthInfo), Offset(Offset) {}167168Address(RawAddress RawAddr)169: Pointer(RawAddr.isValid() ? RawAddr.getPointer() : nullptr,170RawAddr.isValid() ? RawAddr.isKnownNonNull() : NotKnownNonNull),171ElementType(RawAddr.isValid() ? RawAddr.getElementType() : nullptr),172Alignment(RawAddr.isValid() ? RawAddr.getAlignment()173: CharUnits::Zero()) {}174175static Address invalid() { return Address(nullptr); }176bool isValid() const { return Pointer.getPointer() != nullptr; }177178/// This function is used in situations where the caller is doing some sort of179/// opaque "laundering" of the pointer.180void replaceBasePointer(llvm::Value *P) {181assert(isValid() && "pointer isn't valid");182assert(P->getType() == Pointer.getPointer()->getType() &&183"Pointer's type changed");184Pointer.setPointer(P);185assert(isValid() && "pointer is invalid after replacement");186}187188CharUnits getAlignment() const { return Alignment; }189190void setAlignment(CharUnits Value) { Alignment = Value; }191192llvm::Value *getBasePointer() const {193assert(isValid() && "pointer isn't valid");194return Pointer.getPointer();195}196197/// Return the type of the pointer value.198llvm::PointerType *getType() const {199return llvm::PointerType::get(200ElementType,201llvm::cast<llvm::PointerType>(Pointer.getPointer()->getType())202->getAddressSpace());203}204205/// Return the type of the values stored in this address.206llvm::Type *getElementType() const {207assert(isValid());208return ElementType;209}210211/// Return the address space that this address resides in.212unsigned getAddressSpace() const { return getType()->getAddressSpace(); }213214/// Return the IR name of the pointer value.215llvm::StringRef getName() const { return Pointer.getPointer()->getName(); }216217const CGPointerAuthInfo &getPointerAuthInfo() const { return PtrAuthInfo; }218void setPointerAuthInfo(const CGPointerAuthInfo &Info) { PtrAuthInfo = Info; }219220// This function is called only in CGBuilderBaseTy::CreateElementBitCast.221void setElementType(llvm::Type *Ty) {222assert(hasOffset() &&223"this funcion shouldn't be called when there is no offset");224ElementType = Ty;225}226227bool isSigned() const { return PtrAuthInfo.isSigned(); }228229/// Whether the pointer is known not to be null.230KnownNonNull_t isKnownNonNull() const {231assert(isValid());232return (KnownNonNull_t)Pointer.getInt();233}234235Address setKnownNonNull() {236assert(isValid());237Pointer.setInt(KnownNonNull);238return *this;239}240241bool hasOffset() const { return Offset; }242243llvm::Value *getOffset() const { return Offset; }244245Address getResignedAddress(const CGPointerAuthInfo &NewInfo,246CodeGenFunction &CGF) const;247248/// Return the pointer contained in this class after authenticating it and249/// adding offset to it if necessary.250llvm::Value *emitRawPointer(CodeGenFunction &CGF) const {251if (!isSigned())252return getBasePointer();253return emitRawPointerSlow(CGF);254}255256/// Return address with different pointer, but same element type and257/// alignment.258Address withPointer(llvm::Value *NewPointer,259KnownNonNull_t IsKnownNonNull) const {260return Address(NewPointer, getElementType(), getAlignment(),261IsKnownNonNull);262}263264/// Return address with different alignment, but same pointer and element265/// type.266Address withAlignment(CharUnits NewAlignment) const {267return Address(Pointer.getPointer(), getElementType(), NewAlignment,268isKnownNonNull());269}270271/// Return address with different element type, but same pointer and272/// alignment.273Address withElementType(llvm::Type *ElemTy) const {274if (!hasOffset())275return Address(getBasePointer(), ElemTy, getAlignment(),276getPointerAuthInfo(), /*Offset=*/nullptr,277isKnownNonNull());278Address A(*this);279A.ElementType = ElemTy;280return A;281}282};283284inline RawAddress::RawAddress(Address Addr)285: PointerAndKnownNonNull(Addr.isValid() ? Addr.getBasePointer() : nullptr,286Addr.isValid() ? Addr.isKnownNonNull()287: NotKnownNonNull),288ElementType(Addr.isValid() ? Addr.getElementType() : nullptr),289Alignment(Addr.isValid() ? Addr.getAlignment() : CharUnits::Zero()) {}290291/// A specialization of Address that requires the address to be an292/// LLVM Constant.293class ConstantAddress : public RawAddress {294ConstantAddress(std::nullptr_t) : RawAddress(nullptr) {}295296public:297ConstantAddress(llvm::Constant *pointer, llvm::Type *elementType,298CharUnits alignment)299: RawAddress(pointer, elementType, alignment) {}300301static ConstantAddress invalid() {302return ConstantAddress(nullptr);303}304305llvm::Constant *getPointer() const {306return llvm::cast<llvm::Constant>(RawAddress::getPointer());307}308309ConstantAddress withElementType(llvm::Type *ElemTy) const {310return ConstantAddress(getPointer(), ElemTy, getAlignment());311}312313static bool isaImpl(RawAddress addr) {314return llvm::isa<llvm::Constant>(addr.getPointer());315}316static ConstantAddress castImpl(RawAddress addr) {317return ConstantAddress(llvm::cast<llvm::Constant>(addr.getPointer()),318addr.getElementType(), addr.getAlignment());319}320};321}322323// Present a minimal LLVM-like casting interface.324template <class U> inline U cast(CodeGen::Address addr) {325return U::castImpl(addr);326}327template <class U> inline bool isa(CodeGen::Address addr) {328return U::isaImpl(addr);329}330331}332333#endif334335336