Having trouble with GEP

I'm running up against an error with this IR:

%array$str = type { i64, [0 x %str] }
%array.raw = call i8* @malloc(i64 %objsz)
%array = bitcast i8* %array.raw to %array$str*
%array.data = getelementptr %array$str* %array, i32 0, i32 1

This is kind of hand-written, but it errors out, like this:

print-var.ll:50:30: error: invalid getelementptr indices
        %array.data = getelementptr %array$str* %array, i32 0, i32 1
                                    ^
1 error generated.

I can't figure out what the problem is here. I asked in IRC, but I
haven't gotten any useful answers; some people were surprised about
the unquoted use of $ in the type name, but in my testing, that seems
to be fine (as it should be, according to the LangRef).

A hint would be much appreciated, cheers,

Dirkjan

Hi Dirkjan,

I get that error when the %str type is undefined (presumably because
LLVM doesn't know its alignment requirements so can't lay out the
array$str type properly). For example, the following complete program
works correctly for me:

%str = type {i8*, i64}
%array$str = type { i64, [0 x %str] }

declare i8* @malloc(i64)

define i64 @foo(i64 %objsz) {
  %array.raw = call i8* @malloc(i64 %objsz)
  %array = bitcast i8* %array.raw to %array$str*
  %array.data = getelementptr %array$str* %array, i32 0, i32 1
  %ret = ptrtoint [0 x %str]* %array.data to i64
  ret i64 %ret
}

But it fails if the first line is commented out. Could you give a
similar complete example that has the error you're seeing?

Tim.

Yes:

%array$str = type { i64, [0 x %str] }

declare i8* @malloc(i64)

define i64 @foo(i64 %objsz) {
    %array.raw = call i8* @malloc(i64 %objsz);
    %array = bitcast i8* %array.raw to %array$str*
    %array.data = getelementptr %array$str* %array, i32 0, i32 1
    %ret = ptrtoint [0 x %str]* %array.data to i64
    ret i64 %ret
}

%str = type {i8*, i64}

So you're right that it does have to do with the %str type not being defined.

What I'm confused about is why LLVM isn't able to generate a better
error message than this. Perhaps this is one of those cases that
hasn't been tested much because not many people write their IR without
making use of LLVM's API, which would error out sooner if I tried
this? Or is there a more fundamental reason why there's no better
error message? Is it useful to create a bug about this?

Cheers,

Dirkjan

Yes:

%array$str = type { i64, [0 x %str] }

declare i8* @malloc(i64)

define i64 @foo(i64 %objsz) {
    %array.raw = call i8* @malloc(i64 %objsz);
    %array = bitcast i8* %array.raw to %array$str*
    %array.data = getelementptr %array$str* %array, i32 0, i32 1
    %ret = ptrtoint [0 x %str]* %array.data to i64
    ret i64 %ret
}

%str = type {i8*, i64}

So you're right that it does have to do with the %str type not being defined.

What I'm confused about is why LLVM isn't able to generate a better
error message than this. Perhaps this is one of those cases that
hasn't been tested much because not many people write their IR without
making use of LLVM's API, which would error out sooner if I tried
this? Or is there a more fundamental reason why there's no better
error message? Is it useful to create a bug about this?

I think it makes sense to create a bug report. Looking at the code of
LLParser::ParseGetElementPtr, the error handling appears to be very
simplistic, so I don't think there's any fundamental reason for not
doing a better job there.

Eli

Filed http://llvm.org/bugs/show_bug.cgi?id=14965, thanks!

Cheers,

Dirkjan

Attached a proposed patch to the PR.

Eli