-
Notifications
You must be signed in to change notification settings - Fork 14.6k
[IR] Introduce the ptrtoaddr
instruction
#139357
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
base: users/arichardson/spr/main.ir-introduce-the-ptrtoaddr-instruction
Are you sure you want to change the base?
Changes from all commits
73bc383
25dc175
71f9b4d
9772b51
61c5c2a
f5c65e8
769e4dd
638cb3a
f7b19f2
395a0d1
e2471cd
9d4e81e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -12505,6 +12505,61 @@ 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. | ||||||
|
||||||
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 and either truncating or zero extending that value to the size of the | ||||||
integer type. | ||||||
If the address of ``value`` is smaller than ``ty2`` then a zero extension is | ||||||
done. If the address of ``value`` is larger than ``ty2`` then a truncation is | ||||||
done. 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`` always :ref:`captures the address (but not provenance) <pointercapture>` | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Let's not put the most important part in a parenthetical :) |
||||||
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 | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -76,6 +76,10 @@ Changes to the LLVM IR | |
guaranteed to start with a `bti` or `endbr64` instruction, where | ||
those exist. | ||
|
||
* 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)). | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
Changes to LLVM infrastructure | ||
------------------------------ | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -111,6 +111,7 @@ typedef enum { | |
LLVMFPTrunc = 37, | ||
LLVMFPExt = 38, | ||
LLVMPtrToInt = 39, | ||
LLVMPtrToAddr = 69, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it would be less confusing to keep these sorted by enum values but I see that's been broken for the last few new instructions (or maybe just freeze?) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fneg and callbr also break the ordering - I think the intention in this file is to have them match the grouping in Instruction |
||
LLVMIntToPtr = 40, | ||
LLVMBitCast = 41, | ||
LLVMAddrSpaceCast = 60, | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -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 PtrToIntInst. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
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 | ||||||
//===----------------------------------------------------------------------===// | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2278,6 +2278,7 @@ class CastInst : public UnaryInstruction { | |
return Opcode::FPToSI; | ||
case llvm::Instruction::FPExt: | ||
return Opcode::FPExt; | ||
case llvm::Instruction::PtrToAddr: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should probably add it to the Values.def for SandboxIR instead? Or at least leave a FIXME. |
||
case llvm::Instruction::PtrToInt: | ||
return Opcode::PtrToInt; | ||
case llvm::Instruction::IntToPtr: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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: | ||
// ptrtoaddr not supported in constant exprs (yet?). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's something that is needed, we support that on CHERI There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (i.e. it's a TODO if not implemented here, not a question of whether it should be supported, IMO) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wasn't 100% certain we would need it since we could use a truncating How about a simple There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We do want to have constant expression support for ptrtoaddr. It can be part of a relocatable expression, so it's not part of the constant expression removal. |
||
case lltok::kw_ptrtoint: { | ||
unsigned Opc = Lex.getUIntVal(); | ||
Type *DestTy = nullptr; | ||
|
@@ -7297,6 +7298,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: | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the interest of not repeating past mistakes, let's please require
ty2
to be the index type size of the pointer, rather than having zext or trunc semantics. There's no good reason to not enforce this in the verifier, instead of having InstCombine canonicalize it but all code still having to deal with incorrect types in case it wasn't canonicalized.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a great suggestion and I much prefer forcing users to explicitly have to trunc/ext. I just kept the ptrtoint semantics since that seemed consistent. Will update to enforce index width.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a great suggestion and I much prefer forcing users to explicitly have to trunc/ext. I just kept the ptrtoint semantics since that seemed consistent. Will update to enforce index width.