[LLVMdev] GEP vs IntToPtr/PtrToInt
Jianzhou Zhao
jianzhou at seas.upenn.edu
Wed Apr 20 13:30:03 PDT 2011
On Wed, Apr 20, 2011 at 2:11 PM, Eli Friedman <eli.friedman at gmail.com> wrote:
> On Wed, Apr 20, 2011 at 10:21 AM, Jianzhou Zhao <jianzhou at seas.upenn.edu> wrote:
>> On Wed, Apr 20, 2011 at 12:20 PM, Eli Friedman <eli.friedman at gmail.com> wrote:
>>> On Wed, Apr 20, 2011 at 8:08 AM, Jianzhou Zhao <jianzhou at seas.upenn.edu> wrote:
>>>> I have a question about when we should apply these pointer aliasing
>>>> rules. Do the rules tell us when a load/store is safe?
>>>> "Any memory access must be done through a pointer value associated
>>>> with an address range of the memory access, otherwise the behavior is
>>>> undefined."
>>>>
>>>> So this means the conversion discussed here is still safe in terms of
>>>> memory safety, but its meaning after conversion could be weird. Am I
>>>> correct?
>>>
>>> Per http://llvm.org/docs/LangRef.html#pointeraliasing, it's undefined
>>> behavior, so it isn't safe in any sense. In practice, I can't think
>>> of a common transformation that would cause a crash, but it's best not
>>> to depend on that.
>>
>> My confusion could be what is considered to be undefined from the
>> rules. It says a memory access is defined if
>> "Any memory access must be done through a pointer value associated
>> with an address range of the memory access".
>>
>> Does this implicitly mean that the value of the pointer must be within
>> the address range of the memory access it is associated with? It seems
>> to be true to me from the rules about global variables, alloca and
>> even external pointers.
>>
>> For example
>> %p = alloca i32;
>> %q = getelementptr %p, i32 42;
>> store i32 0, i32* %q;
>>
>> Is this a fine memory access (although I don't think it is)? Here, %q
>> is based on %p, and %p is associated with the address range from
>> alloca i32. But the range of the result from alloca is definitely
>> smaller than 42. Since the LLVM IR does not state that load/store-ing
>> out-of-bound address is undefined
>> http://llvm.org/docs/LangRef.html#i_load
>> http://llvm.org/docs/LangRef.html#i_store
>> I looked into the alias-rule to find answers.
>
> That doesn't really have anything to do with aliasing, but it's
> definitely undefined. Don't know off the top of my head where that is
> stated in LangRef.
>
>> Now, come back to the inttoptr and ptrtoint questions. When we
>> consider a memory access via pointers from int is defined, do we mean
>> 1) the value of the pointer happens to equal to an address within a
>> range of an allocated object, or
>> 2) the value of the pointer happens to be based on some allocated
>> objects per these rules, but it is fine if it is out of their ranges
>> (I don' think this is true, but the rules do not explicitly tell me if
>> this is legal). Here, the intuitive meaning of based-on is like you
>> explained in the bellow.
>>
>> But I still have some questions about the 'based-on' things. It seems
>> to state an aliasing relation between pointers. Then in the case if a
>> result inttoptr is based on some objects, why can we consider this to
>> be a good memory access? Because it is very likely a pointer points
>> some other allocated objects that we don't want them to be changed. So
>> this comes to my question --- what property does a defined
>> memory-access give use?
>
> A properly-defined memory access is fully within the bounds of some
> defined object, and "based" (in the LangRef.html#pointeraliasing
> sense) on that object.
>
>>>
>>>> Then it comes to my another question. The base-on relation has this rule:
>>>> "A pointer value formed by an inttoptr is based on all pointer values
>>>> that contribute (directly or indirectly) to the computation of the
>>>> pointer's value."
>>>>
>>>> Suppose an int value 'i' is computed by a lot of int variables that
>>>> are converted from ptr (p1,p2...pn) by ptrtoint, then if we inttoptr i
>>>> to a point p, how should I decide which pointer value the 'p' forms?
>>>>
>>>> If those p_j are ptrtoint to a i_j, and the computation for i is i =
>>>> i_0 + i_1 + ... i_n, does it mean
>>>> we can take either p_j as a base pointer, and other int variables
>>>> its offset, say we take p_2 as the base pointer, and the p from i
>>>> points to
>>>> p_2 + (i_0 + i_1 + i_3 + .. i_n)
>>>> ?
>>>>
>>>> So in the transformation example, the result is different when we take
>>>> %196 or %193 as a base pointer.
>>>>
>>>> For alias-analysis, we may say the p can point to a memory any of the
>>>> p_j points to. But if we consider memory safety, should we say p is
>>>> safe to access if p is not out-of-bound no matter which p_j is taken
>>>> as a base pointer?
>>>
>>> See above.
>>>
>>>> Could anyone explain this rule more precisely? For
>>>> example, how can we find "
>>>> all pointer values that contribute (directly or indirectly)" ?
>>>
>>> There isn't any straightforward way to calculate that set. Another
>>> way of stating the rule is that if changing the numerical value of the
>>> address of some object might change the calculated value of the
>>> operand of an inttoptr, it's one of the "pointer values that
>>> contribute". It's intentionally defined a bit loosely because there's
>>> a lot of different ways for that to be the case. You can extract
>>> information about a pointer by a inttoptr, a load of part or all of
>>> the address from memory, pointer comparisons, and possibly some other
>>> ways I'm not thinking of.
>>>
>>>> This would be helpful to understand
>>>> http://llvm.org/docs/GetElementPtr.html#ptrdiff
>>>> http://llvm.org/docs/GetElementPtr.html#null
>>>> which suggest that we can do some 'wild' pointer arithmetic by
>>>> inttoptr and ptrtoint.
>>>>
>>>> For example, given a pointer p, can we safely do?
>>>> i = ptrtoint p;
>>>> j = i + null;
>>>> q = inttoptr j;
>>>> v = load q;
>>>>
>>>> Thanks a lot.
>>>
>>> inttoptr(ptrtoint(x)) is just x; inttoptr(ptrtoint(x+10)) can be
>>> safely translated to gep i8* x, 10. Translating
>>> inttoptr(ptrtoint(x+y)) to gep i8* x, y is not safe in general.
>>
>> While in http://llvm.org/docs/GetElementPtr.html#ptrdiff, the
>> difference between two pointers computed from GEP has to be a
>> variable, but not a constant, how could that work?
>
> In my example I was assuming "y" was some unknown value. I'm not sure
> what you're asking here.
>
>> Also, given p1 and p2 from GEP, if we do
>> i1 = ptrtoint p1;
>> i2 = ptrtoint p2;
>> i3 = i2 - i1;
>> i3' = f (i3); // suppose f is an identical function that
>> returns i3 directly.
>> i4 = i3' + i1;
>> p = inttoptr i4;
>> .. = load p; // is this load defined?
>>
>> http://llvm.org/docs/GetElementPtr.html#ptrdiff seems to say, we can
>> access out-of-bound memory via GEP, but it is safe to do that from
>> inttoptr or ptrtoint as long as the result points an allocated object.
>> Is this the right way to understand it ?
>
> I assume this is supposed to be "we cannot access out-of-bounds memory via GEP".
Yes.
>
> The load in the given code is well-defined, and equivalent to a load
> directly from p2. The issue with translating i3' + i1 into gep p1,
> i3' is that you end up with a load from a pointer into p2 that is not
> "based" on p2.
Is it supposed to be "end up with a load from a pointer into p2 that
is "based" on p2"? Otherwise this is not well-defined. Because
" A properly-defined memory access is fully within the bounds of some
defined object, and "based" (in the LangRef.html#pointeraliasing
sense) on that object."
I think p2 contributes to the computation of p, because changing the
value at p2 affects the value at p. By the intuitive meaning of
base-on you stated, p1 also contributes if we analyze this by a coarse
alias-analysis.
>
> -Eli
>
--
Jianzhou
More information about the llvm-dev
mailing list