All of lore.kernel.org
 help / color / mirror / Atom feed
* Output from linearize and LLVM error
@ 2017-01-27 14:00 Dibyendu Majumdar
  2017-01-27 14:29 ` Dibyendu Majumdar
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Dibyendu Majumdar @ 2017-01-27 14:00 UTC (permalink / raw)
  To: linux-sparse

Hi

I am investigating some assertion failures I am getting from LLVM when
trying to compile some test code. Following is a simple test program
that is failing.

typedef unsigned long long size_t;
extern void *malloc(size_t);
struct foo {
        int i;
};
typedef struct foo foo;
foo*  testfunc(void);
foo* testfunc(void) {
        foo *p = (foo *) malloc(sizeof(struct foo));
        return p;
}

There were two failures. First one occurs in the result of the
sizeof() expression - it seems the builder tries to create an integer
constant but passes LLVM a 'char *' as the type, which causes an
assertion failure in LLVM. This error occurs in pseudo_to_value()
function in sparse-llvm.c for the case PSEUDO_VAL. I worked around
this by checking if the type is a pointer and then asking LLVM to
create an integer constant of appropriate size (not sure why the type
is a pointer type here).

Here is the output from test-linearize:

testfunc:
.L0x7ffae85d1010:
 <entry-point>
 call.64     %r1 <- malloc, $4
 cast.64     %r2 <- (64) %r1
 ret.64      %r2

The second LLVM assertion failure occurs in the cast to (64).

My question is this - does this cast look correct? Should it not be a
pointer cast rather than an integer cast?

Also the output from test-linearize and test-parsing do not seem to
dump the types. How can I get the types dumped out as well?

Thanks and Regards
Dibyendu

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Output from linearize and LLVM error
  2017-01-27 14:00 Output from linearize and LLVM error Dibyendu Majumdar
@ 2017-01-27 14:29 ` Dibyendu Majumdar
  2017-01-27 15:09 ` Dibyendu Majumdar
  2017-01-27 15:59 ` Van Oostenryck Luc
  2 siblings, 0 replies; 12+ messages in thread
From: Dibyendu Majumdar @ 2017-01-27 14:29 UTC (permalink / raw)
  To: linux-sparse

On 27 January 2017 at 14:00, Dibyendu Majumdar <mobile@majumdar.org.uk> wrote:
>         foo *p = (foo *) malloc(sizeof(struct foo));

> There were two failures. First one occurs in the result of the
> sizeof() expression - it seems the builder tries to create an integer
> constant but passes LLVM a 'char *' as the type, which causes an
> assertion failure in LLVM. This error occurs in pseudo_to_value()
> function in sparse-llvm.c for the case PSEUDO_VAL. I worked around
> this by checking if the type is a pointer and then asking LLVM to
> create an integer constant of appropriate size (not sure why the type
> is a pointer type here).
>

It seems that the sparse-llvm code is using the symbol associated with
the instruction to work out the type of the PSEUDO_VAL which is
incorrect? From what I can see PSEUDO_VAL is just an integer constant
- is there a type associated with it?

Thanks and Regards
Dibyendu

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Output from linearize and LLVM error
  2017-01-27 14:00 Output from linearize and LLVM error Dibyendu Majumdar
  2017-01-27 14:29 ` Dibyendu Majumdar
@ 2017-01-27 15:09 ` Dibyendu Majumdar
  2017-01-27 15:59 ` Van Oostenryck Luc
  2 siblings, 0 replies; 12+ messages in thread
From: Dibyendu Majumdar @ 2017-01-27 15:09 UTC (permalink / raw)
  To: linux-sparse

On 27 January 2017 at 14:00, Dibyendu Majumdar <mobile@majumdar.org.uk> wrote:
> struct foo {
>         int i;
> };
> typedef struct foo foo;
> foo*  testfunc(void);
> foo* testfunc(void) {
>         foo *p = (foo *) malloc(sizeof(struct foo));
>         return p;
> }
>
> Here is the output from test-linearize:
>
> testfunc:
> .L0x7ffae85d1010:
>  <entry-point>
>  call.64     %r1 <- malloc, $4
>  cast.64     %r2 <- (64) %r1
>  ret.64      %r2
>
> The second LLVM assertion failure occurs in the cast to (64).
>

In linearize.c:

static struct instruction *alloc_cast_instruction(struct symbol *src,
struct symbol *ctype)
{
 int opcode = OP_CAST;
 struct symbol *base = src;
 if (base->ctype.modifiers & MOD_SIGNED)
  opcode = OP_SCAST;
 if (base->type == SYM_NODE)
  base = base->ctype.base_type;
 if (base->type == SYM_PTR) {
  base = base->ctype.base_type;
  if (base != &void_ctype)
   opcode = OP_PTRCAST;
 }
 if (base->ctype.base_type == &fp_type)
  opcode = OP_FPCAST;
 return alloc_typed_instruction(opcode, ctype);
}

So if base->type is SYM_PTR but base->c.type.base_type is not void
then the cast instruction is left as OP_CAST, but it should be
OP_PTRCAST regardless?

Thanks and Regards
Dibyendu

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Output from linearize and LLVM error
  2017-01-27 14:00 Output from linearize and LLVM error Dibyendu Majumdar
  2017-01-27 14:29 ` Dibyendu Majumdar
  2017-01-27 15:09 ` Dibyendu Majumdar
@ 2017-01-27 15:59 ` Van Oostenryck Luc
  2017-01-27 17:11   ` Dibyendu Majumdar
  2 siblings, 1 reply; 12+ messages in thread
From: Van Oostenryck Luc @ 2017-01-27 15:59 UTC (permalink / raw)
  To: Dibyendu Majumdar; +Cc: linux-sparse

On Fri, Jan 27, 2017 at 3:00 PM, Dibyendu Majumdar
<mobile@majumdar.org.uk> wrote:
> Hi
> I am investigating some assertion failures I am getting from LLVM when
> trying to compile some test code. Following is a simple test program
> that is failing.
>
> typedef unsigned long long size_t;
> extern void *malloc(size_t);
> struct foo {
>         int i;
> };
> typedef struct foo foo;
> foo*  testfunc(void);
> foo* testfunc(void) {
>         foo *p = (foo *) malloc(sizeof(struct foo));
>         return p;
> }
>
> There were two failures. First one occurs in the result of the
> sizeof() expression - it seems the builder tries to create an integer
> constant but passes LLVM a 'char *' as the type, which causes an
> assertion failure in LLVM. This error occurs in pseudo_to_value()
> function in sparse-llvm.c for the case PSEUDO_VAL. I worked around
> this by checking if the type is a pointer and then asking LLVM to
> create an integer constant of appropriate size (not sure why the type
> is a pointer type here).
>
> Here is the output from test-linearize:
>
> testfunc:
> .L0x7ffae85d1010:
>  <entry-point>
>  call.64     %r1 <- malloc, $4
>  cast.64     %r2 <- (64) %r1
>  ret.64      %r2
>
> The second LLVM assertion failure occurs in the cast to (64).
>
> My question is this - does this cast look correct? Should it not be a
> pointer cast rather than an integer cast?

I think both problems are already addressed but the patches haven't
yet been handled.

You may look at:
- https://patchwork.kernel.org/patch/9469701/
- https://patchwork.kernel.org/patch/9516077/

> Also the output from test-linearize and test-parsing do not seem to
> dump the types. How can I get the types dumped out as well?

Yes, it's sometimes annoying.
Generaly, I when I need this, I add a few printf( .... show_typename(sym))

Regards,
Luc Van Oostenryck

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Output from linearize and LLVM error
  2017-01-27 15:59 ` Van Oostenryck Luc
@ 2017-01-27 17:11   ` Dibyendu Majumdar
  2017-01-27 18:18     ` Dibyendu Majumdar
  0 siblings, 1 reply; 12+ messages in thread
From: Dibyendu Majumdar @ 2017-01-27 17:11 UTC (permalink / raw)
  To: Van Oostenryck Luc; +Cc: linux-sparse

Hi Luc,

On 27 January 2017 at 15:59, Van Oostenryck Luc
<luc.vanoostenryck@gmail.com> wrote:
> I think both problems are already addressed but the patches haven't
> yet been handled.
>
> You may look at:
> - https://patchwork.kernel.org/patch/9469701/
> - https://patchwork.kernel.org/patch/9516077/
>

Thank you - I will review these and any other patches.

>> Also the output from test-linearize and test-parsing do not seem to
>> dump the types. How can I get the types dumped out as well?
>
> Yes, it's sometimes annoying.
> Generaly, I when I need this, I add a few printf( .... show_typename(sym))
>

I see. I will try that.

Thanks again.

Regards
Dibyendu

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Output from linearize and LLVM error
  2017-01-27 17:11   ` Dibyendu Majumdar
@ 2017-01-27 18:18     ` Dibyendu Majumdar
  2017-01-27 19:07       ` Luc Van Oostenryck
  0 siblings, 1 reply; 12+ messages in thread
From: Dibyendu Majumdar @ 2017-01-27 18:18 UTC (permalink / raw)
  To: Van Oostenryck Luc; +Cc: linux-sparse

H Luc,

On 27 January 2017 at 17:11, Dibyendu Majumdar <mobile@majumdar.org.uk> wrote:
> On 27 January 2017 at 15:59, Van Oostenryck Luc
> <luc.vanoostenryck@gmail.com> wrote:
>> I think both problems are already addressed but the patches haven't
>> yet been handled.
>>
>> You may look at:
>> - https://patchwork.kernel.org/patch/9469701/

I had a look at the two patches. I think this one is only for
comparison operations? So the particular failure I saw will still
occur I think.

Thanks and Regards
Dibyendu

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Output from linearize and LLVM error
  2017-01-27 18:18     ` Dibyendu Majumdar
@ 2017-01-27 19:07       ` Luc Van Oostenryck
  2017-01-27 19:22         ` Dibyendu Majumdar
                           ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Luc Van Oostenryck @ 2017-01-27 19:07 UTC (permalink / raw)
  To: Dibyendu Majumdar; +Cc: linux-sparse

On Fri, Jan 27, 2017 at 06:18:07PM +0000, Dibyendu Majumdar wrote:
> H Luc,
> 
> On 27 January 2017 at 17:11, Dibyendu Majumdar <mobile@majumdar.org.uk> wrote:
> > On 27 January 2017 at 15:59, Van Oostenryck Luc
> > <luc.vanoostenryck@gmail.com> wrote:
> >> I think both problems are already addressed but the patches haven't
> >> yet been handled.
> >>
> >> You may look at:
> >> - https://patchwork.kernel.org/patch/9469701/
> 
> I had a look at the two patches. I think this one is only for
> comparison operations? So the particular failure I saw will still
> occur I think.

Yes, indeed.
I've quickly looked at your test case;
It seems to be related to a type problem, probably related to
size_t.(I see:
	... call i8* @alloc(i0 4)
and this 'i0' is very suspect.
The following also fail because of a type problem but with the pointer.
Even with replacing the pointers by void pointers it gives:
	i64  %0 = call i8* @malloc(i0 4)
where the i64 is clearly wrong.
It's possible that this late problem is a side effect of my second
patch, I'll  investigate this tommorow.

Regards,
Luc

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Output from linearize and LLVM error
  2017-01-27 19:07       ` Luc Van Oostenryck
@ 2017-01-27 19:22         ` Dibyendu Majumdar
  2017-01-27 20:43         ` Luc Van Oostenryck
  2017-01-27 20:51         ` Luc Van Oostenryck
  2 siblings, 0 replies; 12+ messages in thread
From: Dibyendu Majumdar @ 2017-01-27 19:22 UTC (permalink / raw)
  To: Luc Van Oostenryck; +Cc: linux-sparse

I also notice that LLVM assertions fail on some of the existing
backend tests. I use a debug build of LLVM which has extra type
checking of LLVM IR.

My understanding of LLVM IR is that it requires types of operands to
be strictly the same or else there needs to be explicit conversions or
bitcasts. So for example, following fails in sparse-llvm:

struct foo {
 struct foo *p;
};
void test(struct foo *Foo);
void test(struct foo *Foo) {
 Foo->p = (struct foo *) 0;
}

Thanks and Regards
Dibyendu

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Output from linearize and LLVM error
  2017-01-27 19:07       ` Luc Van Oostenryck
  2017-01-27 19:22         ` Dibyendu Majumdar
@ 2017-01-27 20:43         ` Luc Van Oostenryck
  2017-01-29  0:26           ` Dibyendu Majumdar
  2017-01-27 20:51         ` Luc Van Oostenryck
  2 siblings, 1 reply; 12+ messages in thread
From: Luc Van Oostenryck @ 2017-01-27 20:43 UTC (permalink / raw)
  To: Dibyendu Majumdar; +Cc: linux-sparse

On Fri, Jan 27, 2017 at 08:07:17PM +0100, Luc Van Oostenryck wrote:
> On Fri, Jan 27, 2017 at 06:18:07PM +0000, Dibyendu Majumdar wrote:
> > H Luc,
> > 
> > On 27 January 2017 at 17:11, Dibyendu Majumdar <mobile@majumdar.org.uk> wrote:
> > > On 27 January 2017 at 15:59, Van Oostenryck Luc
> > > <luc.vanoostenryck@gmail.com> wrote:
> > >> I think both problems are already addressed but the patches haven't
> > >> yet been handled.
> > >>
> > >> You may look at:
> > >> - https://patchwork.kernel.org/patch/9469701/
> > 
> > I had a look at the two patches. I think this one is only for
> > comparison operations? So the particular failure I saw will still
> > occur I think.
> 
> Yes, indeed.
> I've quickly looked at your test case;
> It seems to be related to a type problem, probably related to
> size_t.(I see:
> 	... call i8* @alloc(i0 4)
> and this 'i0' is very suspect.
> The following also fail because of a type problem but with the pointer.
> Even with replacing the pointers by void pointers it gives:
> 	i64  %0 = call i8* @malloc(i0 4)
> where the i64 is clearly wrong.
> It's possible that this late problem is a side effect of my second
> patch, I'll  investigate this tommorow.
> 

It seems that (at least a part of) your problem that malloc()
is called with a constant value and this is not handled correctly
by sparse-llvm. If the size is not a constant but given as argument
to testfunc() things are OK.

To get the type of malloc()'s arg and this is done by calling
pseudo_to_value() with the malloc instruction and the pseudo
for the size (but no info about this pseudo being malloc()'s arg).
LLVMConstInt() is then called with the constant value and the type
is given by calling insn_symbol_type() with the malloc instruction
but again, it's not possible to get the right type without specifying
we try to get the type of the first argument of the called function
and not the type of the result.

But maybe, you have already see this.

Luc

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Output from linearize and LLVM error
  2017-01-27 19:07       ` Luc Van Oostenryck
  2017-01-27 19:22         ` Dibyendu Majumdar
  2017-01-27 20:43         ` Luc Van Oostenryck
@ 2017-01-27 20:51         ` Luc Van Oostenryck
  2 siblings, 0 replies; 12+ messages in thread
From: Luc Van Oostenryck @ 2017-01-27 20:51 UTC (permalink / raw)
  To: Dibyendu Majumdar; +Cc: linux-sparse

On Fri, Jan 27, 2017 at 08:07:17PM +0100, Luc Van Oostenryck wrote:
> I've quickly looked at your test case;
> It seems to be related to a type problem, probably related to
> size_t.(I see:
> 	... call i8* @alloc(i0 4)
> and this 'i0' is very suspect.
> The following also fail because of a type problem but with the pointer.
> Even with replacing the pointers by void pointers it gives:
> 	i64  %0 = call i8* @malloc(i0 4)
> where the i64 is clearly wrong.
> It's possible that this late problem is a side effect of my second
> patch, I'll  investigate this tommorow.

Another problem you will have is with cast related void pointers.
For casts, sparse consider void pointers like an integer type
(because void pointers can't be used as such, they need to be casted
to a real pointer type to do something useful with them).
This means that a cast to a void pointer will produce an OP_CAST and
not an OP_PTRCAST.
And I guess this will be a problem for sparse-llvm.

Luc

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Output from linearize and LLVM error
  2017-01-27 20:43         ` Luc Van Oostenryck
@ 2017-01-29  0:26           ` Dibyendu Majumdar
  2017-01-29  9:15             ` Luc Van Oostenryck
  0 siblings, 1 reply; 12+ messages in thread
From: Dibyendu Majumdar @ 2017-01-29  0:26 UTC (permalink / raw)
  To: Luc Van Oostenryck; +Cc: linux-sparse

Hi Luc,

On 27 January 2017 at 20:43, Luc Van Oostenryck
<luc.vanoostenryck@gmail.com> wrote:
> To get the type of malloc()'s arg and this is done by calling
> pseudo_to_value() with the malloc instruction and the pseudo
> for the size (but no info about this pseudo being malloc()'s arg).
> LLVMConstInt() is then called with the constant value and the type
> is given by calling insn_symbol_type() with the malloc instruction
> but again, it's not possible to get the right type without specifying
> we try to get the type of the first argument of the called function
> and not the type of the result.
>

I think that there is a problem wherever pseudo_to_value() is being
used and the pseudo is an integer constant. Firstly the logic for
determining the size of the constant needs to cover all cases and
secondly depending upon the context the constant may need to be cast
to a pointer. So while the patch you mentioned before tries to solve
this for comparison operations, I think that the solution needs to
cater for all use cases not just those. The handling of arguments is
an example of this.

My suggestion is that pseudo_to_value() for PSEUDO_VAL should always
return an integer constant of type 'long long'  and the caller of
pseudo_to_value() should adjust the constant to right size (by
truncating or extending) or to pointer type if necessary as the caller
has more information. For instance, in the handling of OP_CALL, the
function output_op_call() knows when the call is for an argument, etc.
Currently pseudo_to_value() tries to work out the integer size, but
cannot do this correctly due to lack of information, and also even if
it did work out the size, the cast to pointer would be missed I think.

Does this make sense?

Thanks and Regards
Dibyendu

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Output from linearize and LLVM error
  2017-01-29  0:26           ` Dibyendu Majumdar
@ 2017-01-29  9:15             ` Luc Van Oostenryck
  0 siblings, 0 replies; 12+ messages in thread
From: Luc Van Oostenryck @ 2017-01-29  9:15 UTC (permalink / raw)
  To: Dibyendu Majumdar; +Cc: linux-sparse, Xi Wang, Pekka Enberg, Jeff Garzik

On Sun, Jan 29, 2017 at 12:26:40AM +0000, Dibyendu Majumdar wrote:
> Hi Luc,
> 
> On 27 January 2017 at 20:43, Luc Van Oostenryck
> <luc.vanoostenryck@gmail.com> wrote:
> > To get the type of malloc()'s arg and this is done by calling
> > pseudo_to_value() with the malloc instruction and the pseudo
> > for the size (but no info about this pseudo being malloc()'s arg).
> > LLVMConstInt() is then called with the constant value and the type
> > is given by calling insn_symbol_type() with the malloc instruction
> > but again, it's not possible to get the right type without specifying
> > we try to get the type of the first argument of the called function
> > and not the type of the result.
> >
> 
> I think that there is a problem wherever pseudo_to_value() is being
> used and the pseudo is an integer constant.

Indeed, and possibly in other cases too.

> Firstly the logic for
> determining the size of the constant needs to cover all cases and
> secondly depending upon the context the constant may need to be cast
> to a pointer. So while the patch you mentioned before tries to solve
> this for comparison operations, I think that the solution needs to
> cater for all use cases not just those. The handling of arguments is
> an example of this.

Absolutely, the patch I wrote was only to fix a sparse-llvm breakage
I saw after some changes with sparse dealing of comparisons.
I didn't realized that the problem was bigger.

> 
> My suggestion is that pseudo_to_value() for PSEUDO_VAL should always
> return an integer constant of type 'long long'  and the caller of
> pseudo_to_value() should adjust the constant to right size (by
> truncating or extending) or to pointer type if necessary as the caller
> has more information. For instance, in the handling of OP_CALL, the
> function output_op_call() knows when the call is for an argument, etc.
> Currently pseudo_to_value() tries to work out the integer size, but
> cannot do this correctly due to lack of information, and also even if
> it did work out the size, the cast to pointer would be missed I think.
> 
> Does this make sense?

Yes, it make a lot of sense but I'm not so sure about the approach.
* I'm not sure how easy it is to adjust the constant size/type.
* adjusting the constant size/type instead of gettign directly the
  right type will create a superfluous cast (not a big deal as LLVM
  will optimize it away later but well ...).
* I think that in general passing the pointer to the instruction to
  pseudo_to_value() and insn_symbol_type() is an error since what is
  really needed is the type, thus those function can only make assumptions
  about the type, maybe most of the time a correct one, but they can't do
  for all cases.
* I think that this problem would be better handled if the caller could
  directly give the type information to pseudo_to_value() instead of 
  adjusting it after the fact (but I have no idea how difficult and
  how much work it will be).
* I have no idea about the constant-to-pointer case.
* I think you will have a problem with void pointer since in this case
  sparse doesn't have the information about the real type (but maybe it
  will be easy to solve, I have no idea).

Note: I known next to nothing about LLVM
Note: I've added in CC the authors of sparse-llvm.c


Regards,
Luc Van Oostenryck

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2017-01-29  9:15 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-27 14:00 Output from linearize and LLVM error Dibyendu Majumdar
2017-01-27 14:29 ` Dibyendu Majumdar
2017-01-27 15:09 ` Dibyendu Majumdar
2017-01-27 15:59 ` Van Oostenryck Luc
2017-01-27 17:11   ` Dibyendu Majumdar
2017-01-27 18:18     ` Dibyendu Majumdar
2017-01-27 19:07       ` Luc Van Oostenryck
2017-01-27 19:22         ` Dibyendu Majumdar
2017-01-27 20:43         ` Luc Van Oostenryck
2017-01-29  0:26           ` Dibyendu Majumdar
2017-01-29  9:15             ` Luc Van Oostenryck
2017-01-27 20:51         ` Luc Van Oostenryck

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.