//===-- 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_CODEGEN_ADDRESS_H #define LLVM_CLANG_LIB_CODEGEN_ADDRESS_H #include "clang/AST/CharUnits.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/IR/Constants.h" #include "llvm/Support/MathExtras.h" namespace clang { namespace CodeGen { // Indicates whether a pointer is known not to be null. enum KnownNonNull_t { NotKnownNonNull, KnownNonNull }; /// An aligned address. class Address { llvm::PointerIntPair PointerAndKnownNonNull; llvm::Type *ElementType; CharUnits Alignment; protected: Address(std::nullptr_t) : ElementType(nullptr) {} public: Address(llvm::Value *Pointer, llvm::Type *ElementType, CharUnits Alignment, KnownNonNull_t IsKnownNonNull = NotKnownNonNull) : PointerAndKnownNonNull(Pointer, IsKnownNonNull), ElementType(ElementType), Alignment(Alignment) { assert(Pointer != nullptr && "Pointer cannot be null"); assert(ElementType != nullptr && "Element type cannot be null"); } static Address invalid() { return Address(nullptr); } bool isValid() const { return PointerAndKnownNonNull.getPointer() != nullptr; } llvm::Value *getPointer() const { assert(isValid()); return PointerAndKnownNonNull.getPointer(); } /// Return the type of the pointer value. llvm::PointerType *getType() const { return llvm::cast(getPointer()->getType()); } /// Return the type of the values stored in this address. llvm::Type *getElementType() const { assert(isValid()); return ElementType; } /// Return the address space that this address resides in. unsigned getAddressSpace() const { return getType()->getAddressSpace(); } /// Return the IR name of the pointer value. llvm::StringRef getName() const { return getPointer()->getName(); } /// Return the alignment of this pointer. CharUnits getAlignment() const { assert(isValid()); return Alignment; } /// Return address with different pointer, but same element type and /// alignment. Address withPointer(llvm::Value *NewPointer, KnownNonNull_t IsKnownNonNull) const { return Address(NewPointer, getElementType(), getAlignment(), IsKnownNonNull); } /// Return address with different alignment, but same pointer and element /// type. Address withAlignment(CharUnits NewAlignment) const { return Address(getPointer(), getElementType(), NewAlignment, isKnownNonNull()); } /// Return address with different element type, but same pointer and /// alignment. Address withElementType(llvm::Type *ElemTy) const { return Address(getPointer(), ElemTy, getAlignment(), isKnownNonNull()); } /// 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; } }; /// A specialization of Address that requires the address to be an /// LLVM Constant. class ConstantAddress : public Address { ConstantAddress(std::nullptr_t) : Address(nullptr) {} public: ConstantAddress(llvm::Constant *pointer, llvm::Type *elementType, CharUnits alignment) : Address(pointer, elementType, alignment) {} static ConstantAddress invalid() { return ConstantAddress(nullptr); } llvm::Constant *getPointer() const { return llvm::cast(Address::getPointer()); } ConstantAddress withElementType(llvm::Type *ElemTy) const { return ConstantAddress(getPointer(), ElemTy, getAlignment()); } static bool isaImpl(Address addr) { return llvm::isa(addr.getPointer()); } static ConstantAddress castImpl(Address addr) { return ConstantAddress(llvm::cast(addr.getPointer()), addr.getElementType(), addr.getAlignment()); } }; } // Present a minimal LLVM-like casting interface. template inline U cast(CodeGen::Address addr) { return U::castImpl(addr); } template inline bool isa(CodeGen::Address addr) { return U::isaImpl(addr); } } #endif