Skip to content

[CaptureTracking] Handle ptrtoaddr #152221

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions llvm/docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12521,6 +12521,59 @@ Example:
%Y = ptrtoint ptr %P to i64 ; yields zero extension on 32-bit architecture
%Z = ptrtoint <4 x ptr> %P to <4 x i64>; yields vector zero extension for a vector of addresses on 32-bit architecture

.. _i_ptrtoaddr:

'``ptrtoaddr .. to``' Instruction
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Syntax:
"""""""

::

<result> = ptrtoaddr <ty> <value> to <ty2> ; yields ty2

Overview:
"""""""""

The '``ptrtoaddr``' instruction converts the pointer or a vector of
pointers ``value`` to the underlying integer address (or vector of integers) of
type ``ty2``. This is different from :ref:`ptrtoint <i_ptrtoint>` in that it
only operates on the index bits of the pointer and ignores all other bits.
``ty2`` must be the integer type (or vector of integers) matching the pointer
index width of the address space of ``ty``.

Arguments:
""""""""""

The '``ptrtoaddr``' instruction takes a ``value`` to cast, which must be
a value of type :ref:`pointer <t_pointer>` or a vector of pointers, and a
type to cast it to ``ty2``, which must be an :ref:`integer <t_integer>` or
a vector of integers type.

Semantics:
""""""""""

The '``ptrtoaddr``' instruction converts ``value`` to integer type ``ty2`` by
interpreting the lowest index-width pointer representation bits as an integer.
If the address size and the pointer representation size are the same and
``value`` and ``ty2`` are the same size, then nothing is done (*no-op cast*)
other than a type change.

The ``ptrtoaddr`` instruction always :ref:`captures the address but not the provenance <pointercapture>`
of the pointer argument.

Example:
""""""""
This example assumes pointers in address space 1 are 64 bits in size with an
address width of 32 bits (``p1:64:64:64:32`` :ref:`datalayout string<langref_datalayout>`)
.. code-block:: llvm

%X = ptrtoaddr ptr addrspace(1) %P to i8 ; extracts low 32 bits and truncates
%Y = ptrtoaddr ptr addrspace(1) %P to i64 ; extracts low 32 bits and zero extends
%Z = ptrtoaddr <4 x ptr addrspace(1)> %P to <4 x i64>; yields vector zero extension of low 32 bits for each pointer


.. _i_inttoptr:

'``inttoptr .. to``' Instruction
Expand Down
4 changes: 4 additions & 0 deletions llvm/docs/ReleaseNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ Makes programs 10x faster by doing Special New Thing.
Changes to the LLVM IR
----------------------

* The `ptrtoaddr` instruction was introduced. This instruction returns the
address component of a pointer type variable but unlike `ptrtoint` does not
capture provenance ([#125687](https://github.com/llvm/llvm-project/pull/125687)).

Changes to LLVM infrastructure
------------------------------

Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm-c/Core.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ typedef enum {
LLVMFPTrunc = 37,
LLVMFPExt = 38,
LLVMPtrToInt = 39,
LLVMPtrToAddr = 69,
LLVMIntToPtr = 40,
LLVMBitCast = 41,
LLVMAddrSpaceCast = 60,
Expand Down
7 changes: 7 additions & 0 deletions llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,12 @@ class TargetTransformInfoImplBase {
return 0;
break;
}
case Instruction::PtrToAddr: {
unsigned DstSize = Dst->getScalarSizeInBits();
if (DL.isLegalInteger(DstSize) && DstSize >= DL.getAddressSizeInBits(Src))
return 0;
break;
}
case Instruction::PtrToInt: {
unsigned DstSize = Dst->getScalarSizeInBits();
if (DL.isLegalInteger(DstSize) &&
Expand Down Expand Up @@ -1437,6 +1443,7 @@ class TargetTransformInfoImplCRTPBase : public TargetTransformInfoImplBase {
Op2Info, Operands, I);
}
case Instruction::IntToPtr:
case Instruction::PtrToAddr:
case Instruction::PtrToInt:
case Instruction::SIToFP:
case Instruction::UIToFP:
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/AsmParser/LLToken.h
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@ enum Kind {
kw_fptoui,
kw_fptosi,
kw_inttoptr,
kw_ptrtoaddr,
kw_ptrtoint,
kw_bitcast,
kw_addrspacecast,
Expand Down
3 changes: 2 additions & 1 deletion llvm/include/llvm/Bitcode/LLVMBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,8 @@ enum CastOpcodes {
CAST_PTRTOINT = 9,
CAST_INTTOPTR = 10,
CAST_BITCAST = 11,
CAST_ADDRSPACECAST = 12
CAST_ADDRSPACECAST = 12,
CAST_PTRTOADDR = 13,
};

/// UnaryOpcodes - These are values used in the bitcode files to encode which
Expand Down
4 changes: 4 additions & 0 deletions llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,10 @@ class IRTranslator : public MachineFunctionPass {
bool translatePtrToInt(const User &U, MachineIRBuilder &MIRBuilder) {
return translateCast(TargetOpcode::G_PTRTOINT, U, MIRBuilder);
}
bool translatePtrToAddr(const User &U, MachineIRBuilder &MIRBuilder) {
// FIXME: this is not correct for pointers with addr width != pointer width
return translatePtrToInt(U, MIRBuilder);
}
bool translateTrunc(const User &U, MachineIRBuilder &MIRBuilder) {
return translateCast(TargetOpcode::G_TRUNC, U, MIRBuilder);
}
Expand Down
2 changes: 2 additions & 0 deletions llvm/include/llvm/IR/Constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -1158,6 +1158,8 @@ class ConstantExpr : public Constant {
LLVM_ABI static Constant *getXor(Constant *C1, Constant *C2);
LLVM_ABI static Constant *getTrunc(Constant *C, Type *Ty,
bool OnlyIfReduced = false);
LLVM_ABI static Constant *getPtrToAddr(Constant *C, Type *Ty,
bool OnlyIfReduced = false);
LLVM_ABI static Constant *getPtrToInt(Constant *C, Type *Ty,
bool OnlyIfReduced = false);
LLVM_ABI static Constant *getIntToPtr(Constant *C, Type *Ty,
Expand Down
5 changes: 4 additions & 1 deletion llvm/include/llvm/IR/IRBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -2192,7 +2192,10 @@ class IRBuilderBase {
return CreateCast(Instruction::FPExt, V, DestTy, Name, FPMathTag,
FMFSource);
}

Value *CreatePtrToAddr(Value *V, const Twine &Name = "") {
return CreateCast(Instruction::PtrToInt, V,
BB->getDataLayout().getAddressType(V->getType()), Name);
}
Value *CreatePtrToInt(Value *V, Type *DestTy,
const Twine &Name = "") {
return CreateCast(Instruction::PtrToInt, V, DestTy, Name);
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/IR/InstVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ class InstVisitor {
RetTy visitUIToFPInst(UIToFPInst &I) { DELEGATE(CastInst);}
RetTy visitSIToFPInst(SIToFPInst &I) { DELEGATE(CastInst);}
RetTy visitPtrToIntInst(PtrToIntInst &I) { DELEGATE(CastInst);}
RetTy visitPtrToAddrInst(PtrToAddrInst &I) { DELEGATE(CastInst);}
RetTy visitIntToPtrInst(IntToPtrInst &I) { DELEGATE(CastInst);}
RetTy visitBitCastInst(BitCastInst &I) { DELEGATE(CastInst);}
RetTy visitAddrSpaceCastInst(AddrSpaceCastInst &I) { DELEGATE(CastInst);}
Expand Down
53 changes: 27 additions & 26 deletions llvm/include/llvm/IR/Instruction.def
Original file line number Diff line number Diff line change
Expand Up @@ -190,35 +190,36 @@ HANDLE_CAST_INST(43, UIToFP , UIToFPInst ) // UInt -> floating point
HANDLE_CAST_INST(44, SIToFP , SIToFPInst ) // SInt -> floating point
HANDLE_CAST_INST(45, FPTrunc , FPTruncInst ) // Truncate floating point
HANDLE_CAST_INST(46, FPExt , FPExtInst ) // Extend floating point
HANDLE_CAST_INST(47, PtrToInt, PtrToIntInst) // Pointer -> Integer
HANDLE_CAST_INST(48, IntToPtr, IntToPtrInst) // Integer -> Pointer
HANDLE_CAST_INST(49, BitCast , BitCastInst ) // Type cast
HANDLE_CAST_INST(50, AddrSpaceCast, AddrSpaceCastInst) // addrspace cast
LAST_CAST_INST(50)
HANDLE_CAST_INST(47, PtrToInt, PtrToIntInst) // Pointer -> Integer (bitcast)
HANDLE_CAST_INST(48, PtrToAddr, PtrToAddrInst) // Pointer -> Address
HANDLE_CAST_INST(49, IntToPtr, IntToPtrInst) // Integer -> Pointer
HANDLE_CAST_INST(50, BitCast , BitCastInst ) // Type cast
HANDLE_CAST_INST(51, AddrSpaceCast, AddrSpaceCastInst) // addrspace cast
LAST_CAST_INST(51)

FIRST_FUNCLETPAD_INST(51)
HANDLE_FUNCLETPAD_INST(51, CleanupPad, CleanupPadInst)
HANDLE_FUNCLETPAD_INST(52, CatchPad , CatchPadInst)
LAST_FUNCLETPAD_INST(52)
FIRST_FUNCLETPAD_INST(52)
HANDLE_FUNCLETPAD_INST(52, CleanupPad, CleanupPadInst)
HANDLE_FUNCLETPAD_INST(53, CatchPad , CatchPadInst)
LAST_FUNCLETPAD_INST(53)

// Other operators...
FIRST_OTHER_INST(53)
HANDLE_OTHER_INST(53, ICmp , ICmpInst ) // Integer comparison instruction
HANDLE_OTHER_INST(54, FCmp , FCmpInst ) // Floating point comparison instr.
HANDLE_OTHER_INST(55, PHI , PHINode ) // PHI node instruction
HANDLE_OTHER_INST(56, Call , CallInst ) // Call a function
HANDLE_OTHER_INST(57, Select , SelectInst ) // select instruction
HANDLE_USER_INST (58, UserOp1, Instruction) // May be used internally in a pass
HANDLE_USER_INST (59, UserOp2, Instruction) // Internal to passes only
HANDLE_OTHER_INST(60, VAArg , VAArgInst ) // vaarg instruction
HANDLE_OTHER_INST(61, ExtractElement, ExtractElementInst)// extract from vector
HANDLE_OTHER_INST(62, InsertElement, InsertElementInst) // insert into vector
HANDLE_OTHER_INST(63, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
HANDLE_OTHER_INST(64, ExtractValue, ExtractValueInst)// extract from aggregate
HANDLE_OTHER_INST(65, InsertValue, InsertValueInst) // insert into aggregate
HANDLE_OTHER_INST(66, LandingPad, LandingPadInst) // Landing pad instruction.
HANDLE_OTHER_INST(67, Freeze, FreezeInst) // Freeze instruction.
LAST_OTHER_INST(67)
FIRST_OTHER_INST(54)
HANDLE_OTHER_INST(54, ICmp , ICmpInst ) // Integer comparison instruction
HANDLE_OTHER_INST(55, FCmp , FCmpInst ) // Floating point comparison instr.
HANDLE_OTHER_INST(56, PHI , PHINode ) // PHI node instruction
HANDLE_OTHER_INST(57, Call , CallInst ) // Call a function
HANDLE_OTHER_INST(58, Select , SelectInst ) // select instruction
HANDLE_USER_INST (59, UserOp1, Instruction) // May be used internally in a pass
HANDLE_USER_INST (60, UserOp2, Instruction) // Internal to passes only
HANDLE_OTHER_INST(61, VAArg , VAArgInst ) // vaarg instruction
HANDLE_OTHER_INST(62, ExtractElement, ExtractElementInst)// extract from vector
HANDLE_OTHER_INST(63, InsertElement, InsertElementInst) // insert into vector
HANDLE_OTHER_INST(64, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
HANDLE_OTHER_INST(65, ExtractValue, ExtractValueInst)// extract from aggregate
HANDLE_OTHER_INST(66, InsertValue, InsertValueInst) // insert into aggregate
HANDLE_OTHER_INST(67, LandingPad, LandingPadInst) // Landing pad instruction.
HANDLE_OTHER_INST(68, Freeze, FreezeInst) // Freeze instruction.
LAST_OTHER_INST(68)

#undef FIRST_TERM_INST
#undef HANDLE_TERM_INST
Expand Down
40 changes: 40 additions & 0 deletions llvm/include/llvm/IR/Instructions.h
Original file line number Diff line number Diff line change
Expand Up @@ -4949,6 +4949,46 @@ class PtrToIntInst : public CastInst {
}
};

/// This class represents a cast from a pointer to an address (non-capturing
/// ptrtoint).
class PtrToAddrInst : public CastInst {
protected:
// Note: Instruction needs to be a friend here to call cloneImpl.
friend class Instruction;

/// Clone an identical PtrToAddrInst.
PtrToAddrInst *cloneImpl() const;

public:
/// Constructor with insert-before-instruction semantics
PtrToAddrInst(Value *S, ///< The value to be converted
Type *Ty, ///< The type to convert to
const Twine &NameStr = "", ///< A name for the new instruction
InsertPosition InsertBefore =
nullptr ///< Where to insert the new instruction
);

/// Gets the pointer operand.
Value *getPointerOperand() { return getOperand(0); }
/// Gets the pointer operand.
const Value *getPointerOperand() const { return getOperand(0); }
/// Gets the operand index of the pointer operand.
static unsigned getPointerOperandIndex() { return 0U; }

/// Returns the address space of the pointer operand.
unsigned getPointerAddressSpace() const {
return getPointerOperand()->getType()->getPointerAddressSpace();
}

// Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const Instruction *I) {
return I->getOpcode() == PtrToAddr;
}
static bool classof(const Value *V) {
return isa<Instruction>(V) && classof(cast<Instruction>(V));
}
};

//===----------------------------------------------------------------------===//
// BitCastInst Class
//===----------------------------------------------------------------------===//
Expand Down
31 changes: 31 additions & 0 deletions llvm/include/llvm/IR/Operator.h
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,37 @@ struct OperandTraits<PtrToIntOperator>

DEFINE_TRANSPARENT_OPERAND_ACCESSORS(PtrToIntOperator, Value)

class PtrToAddrOperator
: public ConcreteOperator<Operator, Instruction::PtrToAddr> {
friend class PtrToAddr;
friend class ConstantExpr;

public:
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);

Value *getPointerOperand() { return getOperand(0); }
const Value *getPointerOperand() const { return getOperand(0); }

static unsigned getPointerOperandIndex() {
return 0U; // get index for modifying correct operand
}

/// Method to return the pointer operand as a PointerType.
Type *getPointerOperandType() const { return getPointerOperand()->getType(); }

/// Method to return the address space of the pointer operand.
unsigned getPointerAddressSpace() const {
return cast<PointerType>(getPointerOperandType())->getAddressSpace();
}
};

template <>
struct OperandTraits<PtrToAddrOperator>
: public FixedNumOperandTraits<PtrToAddrOperator, 1> {};

DEFINE_TRANSPARENT_OPERAND_ACCESSORS(PtrToAddrOperator, Value)

class BitCastOperator
: public ConcreteOperator<Operator, Instruction::BitCast> {
friend class BitCastInst;
Expand Down
4 changes: 4 additions & 0 deletions llvm/include/llvm/SandboxIR/Instruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -2278,6 +2278,8 @@ class CastInst : public UnaryInstruction {
return Opcode::FPToSI;
case llvm::Instruction::FPExt:
return Opcode::FPExt;
case llvm::Instruction::PtrToAddr:
return Opcode::PtrToAddr;
case llvm::Instruction::PtrToInt:
return Opcode::PtrToInt;
case llvm::Instruction::IntToPtr:
Expand Down Expand Up @@ -2364,6 +2366,8 @@ class FPToUIInst final : public CastInstImpl<Instruction::Opcode::FPToUI> {};
class FPToSIInst final : public CastInstImpl<Instruction::Opcode::FPToSI> {};
class IntToPtrInst final : public CastInstImpl<Instruction::Opcode::IntToPtr> {
};
class PtrToAddrInst final
: public CastInstImpl<Instruction::Opcode::PtrToAddr> {};
class PtrToIntInst final : public CastInstImpl<Instruction::Opcode::PtrToInt> {
};
class BitCastInst final : public CastInstImpl<Instruction::Opcode::BitCast> {};
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/SandboxIR/Values.def
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ DEF_INSTR(Cast, OPCODES(\
OP(FPToUI) \
OP(FPToSI) \
OP(FPExt) \
OP(PtrToAddr) \
OP(PtrToInt) \
OP(IntToPtr) \
OP(SIToFP) \
Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/Analysis/CaptureTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,11 @@ UseCaptureInfo llvm::DetermineUseCaptureKind(const Use &U, const Value *Base) {
case Instruction::AddrSpaceCast:
// The original value is not captured via this if the new value isn't.
return UseCaptureInfo::passthrough();
case Instruction::PtrToAddr:
// FIXME: the following does not work as expected, so just assume address
// is always captured:
// return UseCaptureInfo(CaptureComponents::None, CaptureComponents::Address);
return CaptureComponents::Address;
case Instruction::ICmp: {
unsigned Idx = U.getOperandNo();
unsigned OtherIdx = 1 - Idx;
Expand Down
14 changes: 14 additions & 0 deletions llvm/lib/Analysis/ConstantFolding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1482,6 +1482,20 @@ Constant *llvm::ConstantFoldCastOperand(unsigned Opcode, Constant *C,
switch (Opcode) {
default:
llvm_unreachable("Missing case");
case Instruction::PtrToAddr:
if (auto *GEP = dyn_cast<GEPOperator>(C)) {
// For now just handle the basic case of GEPs on NULL for ptrtoaddr.
// (ptrtoaddr (gep null, x)) -> x
// (ptrtoaddr (gep (gep null, x), y) -> x + y, etc.
unsigned BitWidth = DL.getIndexTypeSizeInBits(GEP->getType());
APInt BaseOffset(BitWidth, 0);
auto *Base = cast<Constant>(GEP->stripAndAccumulateConstantOffsets(
DL, BaseOffset, /*AllowNonInbounds=*/true));
if (Base->isNullValue()) {
return ConstantInt::get(C->getContext(), BaseOffset);
}
}
break;
case Instruction::PtrToInt:
if (auto *CE = dyn_cast<ConstantExpr>(C)) {
Constant *FoldedValue = nullptr;
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/AsmParser/LLLexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,7 @@ lltok::Kind LLLexer::LexIdentifier() {
INSTKEYWORD(fptoui, FPToUI);
INSTKEYWORD(fptosi, FPToSI);
INSTKEYWORD(inttoptr, IntToPtr);
INSTKEYWORD(ptrtoaddr, PtrToAddr);
INSTKEYWORD(ptrtoint, PtrToInt);
INSTKEYWORD(bitcast, BitCast);
INSTKEYWORD(addrspacecast, AddrSpaceCast);
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/AsmParser/LLParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4273,6 +4273,7 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) {
case lltok::kw_bitcast:
case lltok::kw_addrspacecast:
case lltok::kw_inttoptr:
case lltok::kw_ptrtoaddr:
case lltok::kw_ptrtoint: {
unsigned Opc = Lex.getUIntVal();
Type *DestTy = nullptr;
Expand Down Expand Up @@ -7310,6 +7311,7 @@ int LLParser::parseInstruction(Instruction *&Inst, BasicBlock *BB,
case lltok::kw_fptoui:
case lltok::kw_fptosi:
case lltok::kw_inttoptr:
case lltok::kw_ptrtoaddr:
case lltok::kw_ptrtoint:
return parseCast(Inst, PFS, KeywordVal);
case lltok::kw_fptrunc:
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Bitcode/Reader/BitcodeReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1283,6 +1283,7 @@ static int getDecodedCastOpcode(unsigned Val) {
case bitc::CAST_SITOFP : return Instruction::SIToFP;
case bitc::CAST_FPTRUNC : return Instruction::FPTrunc;
case bitc::CAST_FPEXT : return Instruction::FPExt;
case bitc::CAST_PTRTOADDR: return Instruction::PtrToAddr;
case bitc::CAST_PTRTOINT: return Instruction::PtrToInt;
case bitc::CAST_INTTOPTR: return Instruction::IntToPtr;
case bitc::CAST_BITCAST : return Instruction::BitCast;
Expand Down
Loading