Skip to content

GetMemberOp verification failure on recursive types #256

@gitoleg

Description

@gitoleg

Let's discuss recursive types again.

The long story short - I have a verification failure in the GetMemberOp: index out of bounds.

The code to reproduce is the following:

typedef struct SomeStruct {
    struct SomeStruct* prev;
    struct SomeStruct* next;
    int x;
} A;

typedef struct {
    A some;
} B;

void foo(B* b, A* a) {    
    a->x = 42;     // <---- getMemberOp failed
}

Note, if we swap arguments as foo(A* a, B* b) everything will be fine.

I spent a huge amount of time trying to understand the reason ( what is probably bad for me :) )
And what I came to is approximately the following.

First of all, the CIRGenTypes.cpp and CIRRecordLayoutBuilder.cpp have a similar implementation to one in clang/Codegen. But the behaviour is different. I'm sure that the difference caused by CIR StructType implementation and by the fact that instances of llvm::Type counterpart are stored by pointer and are mutable.
For example, this is how the type is updated in the CGRecordLayoutBuilder :
Ty->setBody(Builder.FieldTypes....
And how it's done in CIR:
*Ty = Builder.getStructTy(builder.fieldTypes, ... ,
i.e. we create a new instance of mlir::Type here. This is matter for the TypeCache in the CIRGenTypes: the type entry is stored by value. So when we create a new instance - nothing is reflected anywhere.

As I said, once we swap foo's arguments, everything will be fine - i.e. it depends on order in which we create types and recursively traverse them.

There are several solution I can think of:

  1. relax the verification - may be it will help, since my test code worked with the StructElementAddr before, where no verification was used.
  2. add kind of a mutability in StructType, so we will be able to actually change something during the recursive calls of ConverType. Also we will need to be careful with passing types as arguments, i.e. pass them by reference.
  3. Something else, e.g. don't cache incomplete types.

So.. what thoughts do you have? May be it's a known issue and the answer is simple one?

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions