-
Notifications
You must be signed in to change notification settings - Fork 175
[CIR][CIRGen] Support mutable and recursive named records #303
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
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This allows a named StructType to be mutated after it has been created,
if it is identified and incomplete.
The motivation for this is to improve the codegen of CIR in certain
scenarios where an incomplete type is used and later completed. These
usually leave the IR in an inconsistent state, where there are two
records types with the same identifier but different definitions (one
complete the other incomplete).
For example:
```c++
struct Node {
Node *next;
};
void test(struct Node n) {}
```
Generates:
```mlir
!temp_struct = !cir.struct<struct "Node" incomplete>
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!temp_struct>}>
```
To generate the `Node` struct type, its members must be created first.
However, the `next` member is a recursive reference, so it can only be
completed after its parent. This generates a temporary incomplete
definition of the `Node` type that remains in the code even after the
type to which it refers is completed. As a consequence, accessing the
`next` member of a `Node` value fetches the old incomplete version of
the type which affects CIR's type-checking capabilities.
This patch ensures that, once the parent is fully visited, the `next`
member can be completed in place, automatically updating any references
to it at a low cost. To represent recursive types, the StructType now
is equipped with self-references. These are represented by a
`cir.struct` type with just the name of the parent struct that it
refers to. The same snippet of code will not generate the following
CIR IR:
```mlir
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!cir.struct<struct "Node">>}>
```
Summary of the changes made:
- Named records are now uniquely identified by their name. An attempt
to create a new record with the same will fail.
- Anonymous records are uniquely identified by members and other
relevant attributes.
- StructType has a new `mutate` method that allows it to be mutated
after it has been created. Each type can only be mutated if it is
identified and incomplete, rendering further changes impossible.
- When building a new name StructType, the builder will try to first
create, then complete the type, ensuring that:
- Inexistent types are created
- Existing incomplete types are completed
- Existing complete types with matching attributes are reused
- Existing complete types with different attributes raise errors
- StructType now uses the CyclicParser/Printer guard to avoid infinite
recursion and identify when it should print/parse a self-reference.
[ghstack-poisoned]
sitio-couto
added a commit
that referenced
this pull request
Nov 2, 2023
This allows a named StructType to be mutated after it has been created,
if it is identified and incomplete.
The motivation for this is to improve the codegen of CIR in certain
scenarios where an incomplete type is used and later completed. These
usually leave the IR in an inconsistent state, where there are two
records types with the same identifier but different definitions (one
complete the other incomplete).
For example:
```c++
struct Node {
Node *next;
};
void test(struct Node n) {}
```
Generates:
```mlir
!temp_struct = !cir.struct<struct "Node" incomplete>
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!temp_struct>}>
```
To generate the `Node` struct type, its members must be created first.
However, the `next` member is a recursive reference, so it can only be
completed after its parent. This generates a temporary incomplete
definition of the `Node` type that remains in the code even after the
type to which it refers is completed. As a consequence, accessing the
`next` member of a `Node` value fetches the old incomplete version of
the type which affects CIR's type-checking capabilities.
This patch ensures that, once the parent is fully visited, the `next`
member can be completed in place, automatically updating any references
to it at a low cost. To represent recursive types, the StructType now
is equipped with self-references. These are represented by a
`cir.struct` type with just the name of the parent struct that it
refers to. The same snippet of code will not generate the following
CIR IR:
```mlir
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!cir.struct<struct "Node">>}>
```
Summary of the changes made:
- Named records are now uniquely identified by their name. An attempt
to create a new record with the same will fail.
- Anonymous records are uniquely identified by members and other
relevant attributes.
- StructType has a new `mutate` method that allows it to be mutated
after it has been created. Each type can only be mutated if it is
identified and incomplete, rendering further changes impossible.
- When building a new name StructType, the builder will try to first
create, then complete the type, ensuring that:
- Inexistent types are created
- Existing incomplete types are completed
- Existing complete types with matching attributes are reused
- Existing complete types with different attributes raise errors
- StructType now uses the CyclicParser/Printer guard to avoid infinite
recursion and identify when it should print/parse a self-reference.
ghstack-source-id: bdee2a3
Pull Request resolved: #303
|
@gitoleg this might interest you! |
bcardosolopes
requested changes
Nov 2, 2023
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.
Cool, thanks for improving this!
This allows a named StructType to be mutated after it has been created,
if it is identified and incomplete.
The motivation for this is to improve the codegen of CIR in certain
scenarios where an incomplete type is used and later completed. These
usually leave the IR in an inconsistent state, where there are two
records types with the same identifier but different definitions (one
complete the other incomplete).
For example:
```c++
struct Node {
Node *next;
};
void test(struct Node n) {}
```
Generates:
```mlir
!temp_struct = !cir.struct<struct "Node" incomplete>
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!temp_struct>}>
```
To generate the `Node` struct type, its members must be created first.
However, the `next` member is a recursive reference, so it can only be
completed after its parent. This generates a temporary incomplete
definition of the `Node` type that remains in the code even after the
type to which it refers is completed. As a consequence, accessing the
`next` member of a `Node` value fetches the old incomplete version of
the type which affects CIR's type-checking capabilities.
This patch ensures that, once the parent is fully visited, the `next`
member can be completed in place, automatically updating any references
to it at a low cost. To represent recursive types, the StructType now
is equipped with self-references. These are represented by a
`cir.struct` type with just the name of the parent struct that it
refers to. The same snippet of code will not generate the following
CIR IR:
```mlir
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!cir.struct<struct "Node">>}>
```
Summary of the changes made:
- Named records are now uniquely identified by their name. An attempt
to create a new record with the same will fail.
- Anonymous records are uniquely identified by members and other
relevant attributes.
- StructType has a new `mutate` method that allows it to be mutated
after it has been created. Each type can only be mutated if it is
identified and incomplete, rendering further changes impossible.
- When building a new name StructType, the builder will try to first
create, then complete the type, ensuring that:
- Inexistent types are created
- Existing incomplete types are completed
- Existing complete types with matching attributes are reused
- Existing complete types with different attributes raise errors
- StructType now uses the CyclicParser/Printer guard to avoid infinite
recursion and identify when it should print/parse a self-reference.
[ghstack-poisoned]
sitio-couto
added a commit
that referenced
this pull request
Nov 3, 2023
This allows a named StructType to be mutated after it has been created,
if it is identified and incomplete.
The motivation for this is to improve the codegen of CIR in certain
scenarios where an incomplete type is used and later completed. These
usually leave the IR in an inconsistent state, where there are two
records types with the same identifier but different definitions (one
complete the other incomplete).
For example:
```c++
struct Node {
Node *next;
};
void test(struct Node n) {}
```
Generates:
```mlir
!temp_struct = !cir.struct<struct "Node" incomplete>
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!temp_struct>}>
```
To generate the `Node` struct type, its members must be created first.
However, the `next` member is a recursive reference, so it can only be
completed after its parent. This generates a temporary incomplete
definition of the `Node` type that remains in the code even after the
type to which it refers is completed. As a consequence, accessing the
`next` member of a `Node` value fetches the old incomplete version of
the type which affects CIR's type-checking capabilities.
This patch ensures that, once the parent is fully visited, the `next`
member can be completed in place, automatically updating any references
to it at a low cost. To represent recursive types, the StructType now
is equipped with self-references. These are represented by a
`cir.struct` type with just the name of the parent struct that it
refers to. The same snippet of code will not generate the following
CIR IR:
```mlir
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!cir.struct<struct "Node">>}>
```
Summary of the changes made:
- Named records are now uniquely identified by their name. An attempt
to create a new record with the same will fail.
- Anonymous records are uniquely identified by members and other
relevant attributes.
- StructType has a new `mutate` method that allows it to be mutated
after it has been created. Each type can only be mutated if it is
identified and incomplete, rendering further changes impossible.
- When building a new name StructType, the builder will try to first
create, then complete the type, ensuring that:
- Inexistent types are created
- Existing incomplete types are completed
- Existing complete types with matching attributes are reused
- Existing complete types with different attributes raise errors
- StructType now uses the CyclicParser/Printer guard to avoid infinite
recursion and identify when it should print/parse a self-reference.
ghstack-source-id: d138d70
Pull Request resolved: #303
bcardosolopes
approved these changes
Nov 3, 2023
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.
LGTM with one minor comment.
This allows a named StructType to be mutated after it has been created,
if it is identified and incomplete.
The motivation for this is to improve the codegen of CIR in certain
scenarios where an incomplete type is used and later completed. These
usually leave the IR in an inconsistent state, where there are two
records types with the same identifier but different definitions (one
complete the other incomplete).
For example:
```c++
struct Node {
Node *next;
};
void test(struct Node n) {}
```
Generates:
```mlir
!temp_struct = !cir.struct<struct "Node" incomplete>
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!temp_struct>}>
```
To generate the `Node` struct type, its members must be created first.
However, the `next` member is a recursive reference, so it can only be
completed after its parent. This generates a temporary incomplete
definition of the `Node` type that remains in the code even after the
type to which it refers is completed. As a consequence, accessing the
`next` member of a `Node` value fetches the old incomplete version of
the type which affects CIR's type-checking capabilities.
This patch ensures that, once the parent is fully visited, the `next`
member can be completed in place, automatically updating any references
to it at a low cost. To represent recursive types, the StructType now
is equipped with self-references. These are represented by a
`cir.struct` type with just the name of the parent struct that it
refers to. The same snippet of code will not generate the following
CIR IR:
```mlir
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!cir.struct<struct "Node">>}>
```
Summary of the changes made:
- Named records are now uniquely identified by their name. An attempt
to create a new record with the same will fail.
- Anonymous records are uniquely identified by members and other
relevant attributes.
- StructType has a new `mutate` method that allows it to be mutated
after it has been created. Each type can only be mutated if it is
identified and incomplete, rendering further changes impossible.
- When building a new name StructType, the builder will try to first
create, then complete the type, ensuring that:
- Inexistent types are created
- Existing incomplete types are completed
- Existing complete types with matching attributes are reused
- Existing complete types with different attributes raise errors
- StructType now uses the CyclicParser/Printer guard to avoid infinite
recursion and identify when it should print/parse a self-reference.
[ghstack-poisoned]
sitio-couto
added a commit
that referenced
this pull request
Nov 3, 2023
This allows a named StructType to be mutated after it has been created,
if it is identified and incomplete.
The motivation for this is to improve the codegen of CIR in certain
scenarios where an incomplete type is used and later completed. These
usually leave the IR in an inconsistent state, where there are two
records types with the same identifier but different definitions (one
complete the other incomplete).
For example:
```c++
struct Node {
Node *next;
};
void test(struct Node n) {}
```
Generates:
```mlir
!temp_struct = !cir.struct<struct "Node" incomplete>
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!temp_struct>}>
```
To generate the `Node` struct type, its members must be created first.
However, the `next` member is a recursive reference, so it can only be
completed after its parent. This generates a temporary incomplete
definition of the `Node` type that remains in the code even after the
type to which it refers is completed. As a consequence, accessing the
`next` member of a `Node` value fetches the old incomplete version of
the type which affects CIR's type-checking capabilities.
This patch ensures that, once the parent is fully visited, the `next`
member can be completed in place, automatically updating any references
to it at a low cost. To represent recursive types, the StructType now
is equipped with self-references. These are represented by a
`cir.struct` type with just the name of the parent struct that it
refers to. The same snippet of code will not generate the following
CIR IR:
```mlir
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!cir.struct<struct "Node">>}>
```
Summary of the changes made:
- Named records are now uniquely identified by their name. An attempt
to create a new record with the same will fail.
- Anonymous records are uniquely identified by members and other
relevant attributes.
- StructType has a new `mutate` method that allows it to be mutated
after it has been created. Each type can only be mutated if it is
identified and incomplete, rendering further changes impossible.
- When building a new name StructType, the builder will try to first
create, then complete the type, ensuring that:
- Inexistent types are created
- Existing incomplete types are completed
- Existing complete types with matching attributes are reused
- Existing complete types with different attributes raise errors
- StructType now uses the CyclicParser/Printer guard to avoid infinite
recursion and identify when it should print/parse a self-reference.
ghstack-source-id: 58a270f
Pull Request resolved: #303
This allows a named StructType to be mutated after it has been created,
if it is identified and incomplete.
The motivation for this is to improve the codegen of CIR in certain
scenarios where an incomplete type is used and later completed. These
usually leave the IR in an inconsistent state, where there are two
records types with the same identifier but different definitions (one
complete the other incomplete).
For example:
```c++
struct Node {
Node *next;
};
void test(struct Node n) {}
```
Generates:
```mlir
!temp_struct = !cir.struct<struct "Node" incomplete>
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!temp_struct>}>
```
To generate the `Node` struct type, its members must be created first.
However, the `next` member is a recursive reference, so it can only be
completed after its parent. This generates a temporary incomplete
definition of the `Node` type that remains in the code even after the
type to which it refers is completed. As a consequence, accessing the
`next` member of a `Node` value fetches the old incomplete version of
the type which affects CIR's type-checking capabilities.
This patch ensures that, once the parent is fully visited, the `next`
member can be completed in place, automatically updating any references
to it at a low cost. To represent recursive types, the StructType now
is equipped with self-references. These are represented by a
`cir.struct` type with just the name of the parent struct that it
refers to. The same snippet of code will not generate the following
CIR IR:
```mlir
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!cir.struct<struct "Node">>}>
```
Summary of the changes made:
- Named records are now uniquely identified by their name. An attempt
to create a new record with the same will fail.
- Anonymous records are uniquely identified by members and other
relevant attributes.
- StructType has a new `mutate` method that allows it to be mutated
after it has been created. Each type can only be mutated if it is
identified and incomplete, rendering further changes impossible.
- When building a new name StructType, the builder will try to first
create, then complete the type, ensuring that:
- Inexistent types are created
- Existing incomplete types are completed
- Existing complete types with matching attributes are reused
- Existing complete types with different attributes raise errors
- StructType now uses the CyclicParser/Printer guard to avoid infinite
recursion and identify when it should print/parse a self-reference.
[ghstack-poisoned]
sitio-couto
added a commit
that referenced
this pull request
Nov 3, 2023
This allows a named StructType to be mutated after it has been created,
if it is identified and incomplete.
The motivation for this is to improve the codegen of CIR in certain
scenarios where an incomplete type is used and later completed. These
usually leave the IR in an inconsistent state, where there are two
records types with the same identifier but different definitions (one
complete the other incomplete).
For example:
```c++
struct Node {
Node *next;
};
void test(struct Node n) {}
```
Generates:
```mlir
!temp_struct = !cir.struct<struct "Node" incomplete>
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!temp_struct>}>
```
To generate the `Node` struct type, its members must be created first.
However, the `next` member is a recursive reference, so it can only be
completed after its parent. This generates a temporary incomplete
definition of the `Node` type that remains in the code even after the
type to which it refers is completed. As a consequence, accessing the
`next` member of a `Node` value fetches the old incomplete version of
the type which affects CIR's type-checking capabilities.
This patch ensures that, once the parent is fully visited, the `next`
member can be completed in place, automatically updating any references
to it at a low cost. To represent recursive types, the StructType now
is equipped with self-references. These are represented by a
`cir.struct` type with just the name of the parent struct that it
refers to. The same snippet of code will not generate the following
CIR IR:
```mlir
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!cir.struct<struct "Node">>}>
```
Summary of the changes made:
- Named records are now uniquely identified by their name. An attempt
to create a new record with the same will fail.
- Anonymous records are uniquely identified by members and other
relevant attributes.
- StructType has a new `mutate` method that allows it to be mutated
after it has been created. Each type can only be mutated if it is
identified and incomplete, rendering further changes impossible.
- When building a new name StructType, the builder will try to first
create, then complete the type, ensuring that:
- Inexistent types are created
- Existing incomplete types are completed
- Existing complete types with matching attributes are reused
- Existing complete types with different attributes raise errors
- StructType now uses the CyclicParser/Printer guard to avoid infinite
recursion and identify when it should print/parse a self-reference.
ghstack-source-id: a6d4f65
Pull Request resolved: #303
sitio-couto
added a commit
that referenced
this pull request
Nov 3, 2023
This allows a named StructType to be mutated after it has been created,
if it is identified and incomplete.
The motivation for this is to improve the codegen of CIR in certain
scenarios where an incomplete type is used and later completed. These
usually leave the IR in an inconsistent state, where there are two
records types with the same identifier but different definitions (one
complete the other incomplete).
For example:
```c++
struct Node {
Node *next;
};
void test(struct Node n) {}
```
Generates:
```mlir
!temp_struct = !cir.struct<struct "Node" incomplete>
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!temp_struct>}>
```
To generate the `Node` struct type, its members must be created first.
However, the `next` member is a recursive reference, so it can only be
completed after its parent. This generates a temporary incomplete
definition of the `Node` type that remains in the code even after the
type to which it refers is completed. As a consequence, accessing the
`next` member of a `Node` value fetches the old incomplete version of
the type which affects CIR's type-checking capabilities.
This patch ensures that, once the parent is fully visited, the `next`
member can be completed in place, automatically updating any references
to it at a low cost. To represent recursive types, the StructType now
is equipped with self-references. These are represented by a
`cir.struct` type with just the name of the parent struct that it
refers to. The same snippet of code will not generate the following
CIR IR:
```mlir
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!cir.struct<struct "Node">>}>
```
Summary of the changes made:
- Named records are now uniquely identified by their name. An attempt
to create a new record with the same will fail.
- Anonymous records are uniquely identified by members and other
relevant attributes.
- StructType has a new `mutate` method that allows it to be mutated
after it has been created. Each type can only be mutated if it is
identified and incomplete, rendering further changes impossible.
- When building a new name StructType, the builder will try to first
create, then complete the type, ensuring that:
- Inexistent types are created
- Existing incomplete types are completed
- Existing complete types with matching attributes are reused
- Existing complete types with different attributes raise errors
- StructType now uses the CyclicParser/Printer guard to avoid infinite
recursion and identify when it should print/parse a self-reference.
ghstack-source-id: a6d4f65
Pull Request resolved: #303
bcardosolopes
pushed a commit
that referenced
this pull request
Nov 22, 2023
I think it's time to claim that CIR supports recursive types (many thanks to #303 and to @sitio-couto :) ) And we can bring back the `get_member` verification back, with no checks for incomplete types. What do you think? And we can close #256 as well
lanza
pushed a commit
that referenced
this pull request
Dec 20, 2023
This allows a named StructType to be mutated after it has been created,
if it is identified and incomplete.
The motivation for this is to improve the codegen of CIR in certain
scenarios where an incomplete type is used and later completed. These
usually leave the IR in an inconsistent state, where there are two
records types with the same identifier but different definitions (one
complete the other incomplete).
For example:
```c++
struct Node {
Node *next;
};
void test(struct Node n) {}
```
Generates:
```mlir
!temp_struct = !cir.struct<struct "Node" incomplete>
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!temp_struct>}>
```
To generate the `Node` struct type, its members must be created first.
However, the `next` member is a recursive reference, so it can only be
completed after its parent. This generates a temporary incomplete
definition of the `Node` type that remains in the code even after the
type to which it refers is completed. As a consequence, accessing the
`next` member of a `Node` value fetches the old incomplete version of
the type which affects CIR's type-checking capabilities.
This patch ensures that, once the parent is fully visited, the `next`
member can be completed in place, automatically updating any references
to it at a low cost. To represent recursive types, the StructType now
is equipped with self-references. These are represented by a
`cir.struct` type with just the name of the parent struct that it
refers to. The same snippet of code will not generate the following
CIR IR:
```mlir
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!cir.struct<struct "Node">>}>
```
Summary of the changes made:
- Named records are now uniquely identified by their name. An attempt
to create a new record with the same will fail.
- Anonymous records are uniquely identified by members and other
relevant attributes.
- StructType has a new `mutate` method that allows it to be mutated
after it has been created. Each type can only be mutated if it is
identified and incomplete, rendering further changes impossible.
- When building a new name StructType, the builder will try to first
create, then complete the type, ensuring that:
- Inexistent types are created
- Existing incomplete types are completed
- Existing complete types with matching attributes are reused
- Existing complete types with different attributes raise errors
- StructType now uses the CyclicParser/Printer guard to avoid infinite
recursion and identify when it should print/parse a self-reference.
ghstack-source-id: a6d4f65
Pull Request resolved: #303
lanza
pushed a commit
that referenced
this pull request
Dec 20, 2023
I think it's time to claim that CIR supports recursive types (many thanks to #303 and to @sitio-couto :) ) And we can bring back the `get_member` verification back, with no checks for incomplete types. What do you think? And we can close #256 as well
lanza
pushed a commit
that referenced
this pull request
Jan 29, 2024
This allows a named StructType to be mutated after it has been created,
if it is identified and incomplete.
The motivation for this is to improve the codegen of CIR in certain
scenarios where an incomplete type is used and later completed. These
usually leave the IR in an inconsistent state, where there are two
records types with the same identifier but different definitions (one
complete the other incomplete).
For example:
```c++
struct Node {
Node *next;
};
void test(struct Node n) {}
```
Generates:
```mlir
!temp_struct = !cir.struct<struct "Node" incomplete>
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!temp_struct>}>
```
To generate the `Node` struct type, its members must be created first.
However, the `next` member is a recursive reference, so it can only be
completed after its parent. This generates a temporary incomplete
definition of the `Node` type that remains in the code even after the
type to which it refers is completed. As a consequence, accessing the
`next` member of a `Node` value fetches the old incomplete version of
the type which affects CIR's type-checking capabilities.
This patch ensures that, once the parent is fully visited, the `next`
member can be completed in place, automatically updating any references
to it at a low cost. To represent recursive types, the StructType now
is equipped with self-references. These are represented by a
`cir.struct` type with just the name of the parent struct that it
refers to. The same snippet of code will not generate the following
CIR IR:
```mlir
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!cir.struct<struct "Node">>}>
```
Summary of the changes made:
- Named records are now uniquely identified by their name. An attempt
to create a new record with the same will fail.
- Anonymous records are uniquely identified by members and other
relevant attributes.
- StructType has a new `mutate` method that allows it to be mutated
after it has been created. Each type can only be mutated if it is
identified and incomplete, rendering further changes impossible.
- When building a new name StructType, the builder will try to first
create, then complete the type, ensuring that:
- Inexistent types are created
- Existing incomplete types are completed
- Existing complete types with matching attributes are reused
- Existing complete types with different attributes raise errors
- StructType now uses the CyclicParser/Printer guard to avoid infinite
recursion and identify when it should print/parse a self-reference.
ghstack-source-id: a6d4f65
Pull Request resolved: #303
lanza
pushed a commit
that referenced
this pull request
Jan 29, 2024
I think it's time to claim that CIR supports recursive types (many thanks to #303 and to @sitio-couto :) ) And we can bring back the `get_member` verification back, with no checks for incomplete types. What do you think? And we can close #256 as well
lanza
pushed a commit
that referenced
this pull request
Mar 23, 2024
This allows a named StructType to be mutated after it has been created,
if it is identified and incomplete.
The motivation for this is to improve the codegen of CIR in certain
scenarios where an incomplete type is used and later completed. These
usually leave the IR in an inconsistent state, where there are two
records types with the same identifier but different definitions (one
complete the other incomplete).
For example:
```c++
struct Node {
Node *next;
};
void test(struct Node n) {}
```
Generates:
```mlir
!temp_struct = !cir.struct<struct "Node" incomplete>
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!temp_struct>}>
```
To generate the `Node` struct type, its members must be created first.
However, the `next` member is a recursive reference, so it can only be
completed after its parent. This generates a temporary incomplete
definition of the `Node` type that remains in the code even after the
type to which it refers is completed. As a consequence, accessing the
`next` member of a `Node` value fetches the old incomplete version of
the type which affects CIR's type-checking capabilities.
This patch ensures that, once the parent is fully visited, the `next`
member can be completed in place, automatically updating any references
to it at a low cost. To represent recursive types, the StructType now
is equipped with self-references. These are represented by a
`cir.struct` type with just the name of the parent struct that it
refers to. The same snippet of code will not generate the following
CIR IR:
```mlir
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!cir.struct<struct "Node">>}>
```
Summary of the changes made:
- Named records are now uniquely identified by their name. An attempt
to create a new record with the same will fail.
- Anonymous records are uniquely identified by members and other
relevant attributes.
- StructType has a new `mutate` method that allows it to be mutated
after it has been created. Each type can only be mutated if it is
identified and incomplete, rendering further changes impossible.
- When building a new name StructType, the builder will try to first
create, then complete the type, ensuring that:
- Inexistent types are created
- Existing incomplete types are completed
- Existing complete types with matching attributes are reused
- Existing complete types with different attributes raise errors
- StructType now uses the CyclicParser/Printer guard to avoid infinite
recursion and identify when it should print/parse a self-reference.
ghstack-source-id: a6d4f65
Pull Request resolved: #303
lanza
pushed a commit
that referenced
this pull request
Mar 23, 2024
I think it's time to claim that CIR supports recursive types (many thanks to #303 and to @sitio-couto :) ) And we can bring back the `get_member` verification back, with no checks for incomplete types. What do you think? And we can close #256 as well
eZWALT
pushed a commit
to eZWALT/clangir
that referenced
this pull request
Mar 24, 2024
I think it's time to claim that CIR supports recursive types (many thanks to llvm#303 and to @sitio-couto :) ) And we can bring back the `get_member` verification back, with no checks for incomplete types. What do you think? And we can close llvm#256 as well
eZWALT
pushed a commit
to eZWALT/clangir
that referenced
this pull request
Mar 24, 2024
This allows a named StructType to be mutated after it has been created,
if it is identified and incomplete.
The motivation for this is to improve the codegen of CIR in certain
scenarios where an incomplete type is used and later completed. These
usually leave the IR in an inconsistent state, where there are two
records types with the same identifier but different definitions (one
complete the other incomplete).
For example:
```c++
struct Node {
Node *next;
};
void test(struct Node n) {}
```
Generates:
```mlir
!temp_struct = !cir.struct<struct "Node" incomplete>
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!temp_struct>}>
```
To generate the `Node` struct type, its members must be created first.
However, the `next` member is a recursive reference, so it can only be
completed after its parent. This generates a temporary incomplete
definition of the `Node` type that remains in the code even after the
type to which it refers is completed. As a consequence, accessing the
`next` member of a `Node` value fetches the old incomplete version of
the type which affects CIR's type-checking capabilities.
This patch ensures that, once the parent is fully visited, the `next`
member can be completed in place, automatically updating any references
to it at a low cost. To represent recursive types, the StructType now
is equipped with self-references. These are represented by a
`cir.struct` type with just the name of the parent struct that it
refers to. The same snippet of code will not generate the following
CIR IR:
```mlir
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!cir.struct<struct "Node">>}>
```
Summary of the changes made:
- Named records are now uniquely identified by their name. An attempt
to create a new record with the same will fail.
- Anonymous records are uniquely identified by members and other
relevant attributes.
- StructType has a new `mutate` method that allows it to be mutated
after it has been created. Each type can only be mutated if it is
identified and incomplete, rendering further changes impossible.
- When building a new name StructType, the builder will try to first
create, then complete the type, ensuring that:
- Inexistent types are created
- Existing incomplete types are completed
- Existing complete types with matching attributes are reused
- Existing complete types with different attributes raise errors
- StructType now uses the CyclicParser/Printer guard to avoid infinite
recursion and identify when it should print/parse a self-reference.
ghstack-source-id: a6d4f65
Pull Request resolved: llvm#303
eZWALT
pushed a commit
to eZWALT/clangir
that referenced
this pull request
Mar 24, 2024
I think it's time to claim that CIR supports recursive types (many thanks to llvm#303 and to @sitio-couto :) ) And we can bring back the `get_member` verification back, with no checks for incomplete types. What do you think? And we can close llvm#256 as well
lanza
pushed a commit
that referenced
this pull request
Apr 29, 2024
This allows a named StructType to be mutated after it has been created,
if it is identified and incomplete.
The motivation for this is to improve the codegen of CIR in certain
scenarios where an incomplete type is used and later completed. These
usually leave the IR in an inconsistent state, where there are two
records types with the same identifier but different definitions (one
complete the other incomplete).
For example:
```c++
struct Node {
Node *next;
};
void test(struct Node n) {}
```
Generates:
```mlir
!temp_struct = !cir.struct<struct "Node" incomplete>
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!temp_struct>}>
```
To generate the `Node` struct type, its members must be created first.
However, the `next` member is a recursive reference, so it can only be
completed after its parent. This generates a temporary incomplete
definition of the `Node` type that remains in the code even after the
type to which it refers is completed. As a consequence, accessing the
`next` member of a `Node` value fetches the old incomplete version of
the type which affects CIR's type-checking capabilities.
This patch ensures that, once the parent is fully visited, the `next`
member can be completed in place, automatically updating any references
to it at a low cost. To represent recursive types, the StructType now
is equipped with self-references. These are represented by a
`cir.struct` type with just the name of the parent struct that it
refers to. The same snippet of code will not generate the following
CIR IR:
```mlir
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!cir.struct<struct "Node">>}>
```
Summary of the changes made:
- Named records are now uniquely identified by their name. An attempt
to create a new record with the same will fail.
- Anonymous records are uniquely identified by members and other
relevant attributes.
- StructType has a new `mutate` method that allows it to be mutated
after it has been created. Each type can only be mutated if it is
identified and incomplete, rendering further changes impossible.
- When building a new name StructType, the builder will try to first
create, then complete the type, ensuring that:
- Inexistent types are created
- Existing incomplete types are completed
- Existing complete types with matching attributes are reused
- Existing complete types with different attributes raise errors
- StructType now uses the CyclicParser/Printer guard to avoid infinite
recursion and identify when it should print/parse a self-reference.
ghstack-source-id: a6d4f65
Pull Request resolved: #303
lanza
pushed a commit
that referenced
this pull request
Apr 29, 2024
I think it's time to claim that CIR supports recursive types (many thanks to #303 and to @sitio-couto :) ) And we can bring back the `get_member` verification back, with no checks for incomplete types. What do you think? And we can close #256 as well
lanza
pushed a commit
that referenced
this pull request
Apr 29, 2024
This allows a named StructType to be mutated after it has been created,
if it is identified and incomplete.
The motivation for this is to improve the codegen of CIR in certain
scenarios where an incomplete type is used and later completed. These
usually leave the IR in an inconsistent state, where there are two
records types with the same identifier but different definitions (one
complete the other incomplete).
For example:
```c++
struct Node {
Node *next;
};
void test(struct Node n) {}
```
Generates:
```mlir
!temp_struct = !cir.struct<struct "Node" incomplete>
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!temp_struct>}>
```
To generate the `Node` struct type, its members must be created first.
However, the `next` member is a recursive reference, so it can only be
completed after its parent. This generates a temporary incomplete
definition of the `Node` type that remains in the code even after the
type to which it refers is completed. As a consequence, accessing the
`next` member of a `Node` value fetches the old incomplete version of
the type which affects CIR's type-checking capabilities.
This patch ensures that, once the parent is fully visited, the `next`
member can be completed in place, automatically updating any references
to it at a low cost. To represent recursive types, the StructType now
is equipped with self-references. These are represented by a
`cir.struct` type with just the name of the parent struct that it
refers to. The same snippet of code will not generate the following
CIR IR:
```mlir
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!cir.struct<struct "Node">>}>
```
Summary of the changes made:
- Named records are now uniquely identified by their name. An attempt
to create a new record with the same will fail.
- Anonymous records are uniquely identified by members and other
relevant attributes.
- StructType has a new `mutate` method that allows it to be mutated
after it has been created. Each type can only be mutated if it is
identified and incomplete, rendering further changes impossible.
- When building a new name StructType, the builder will try to first
create, then complete the type, ensuring that:
- Inexistent types are created
- Existing incomplete types are completed
- Existing complete types with matching attributes are reused
- Existing complete types with different attributes raise errors
- StructType now uses the CyclicParser/Printer guard to avoid infinite
recursion and identify when it should print/parse a self-reference.
ghstack-source-id: a6d4f65
Pull Request resolved: #303
lanza
pushed a commit
that referenced
this pull request
Apr 29, 2024
I think it's time to claim that CIR supports recursive types (many thanks to #303 and to @sitio-couto :) ) And we can bring back the `get_member` verification back, with no checks for incomplete types. What do you think? And we can close #256 as well
eZWALT
pushed a commit
to eZWALT/clangir
that referenced
this pull request
Apr 29, 2024
This allows a named StructType to be mutated after it has been created,
if it is identified and incomplete.
The motivation for this is to improve the codegen of CIR in certain
scenarios where an incomplete type is used and later completed. These
usually leave the IR in an inconsistent state, where there are two
records types with the same identifier but different definitions (one
complete the other incomplete).
For example:
```c++
struct Node {
Node *next;
};
void test(struct Node n) {}
```
Generates:
```mlir
!temp_struct = !cir.struct<struct "Node" incomplete>
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!temp_struct>}>
```
To generate the `Node` struct type, its members must be created first.
However, the `next` member is a recursive reference, so it can only be
completed after its parent. This generates a temporary incomplete
definition of the `Node` type that remains in the code even after the
type to which it refers is completed. As a consequence, accessing the
`next` member of a `Node` value fetches the old incomplete version of
the type which affects CIR's type-checking capabilities.
This patch ensures that, once the parent is fully visited, the `next`
member can be completed in place, automatically updating any references
to it at a low cost. To represent recursive types, the StructType now
is equipped with self-references. These are represented by a
`cir.struct` type with just the name of the parent struct that it
refers to. The same snippet of code will not generate the following
CIR IR:
```mlir
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!cir.struct<struct "Node">>}>
```
Summary of the changes made:
- Named records are now uniquely identified by their name. An attempt
to create a new record with the same will fail.
- Anonymous records are uniquely identified by members and other
relevant attributes.
- StructType has a new `mutate` method that allows it to be mutated
after it has been created. Each type can only be mutated if it is
identified and incomplete, rendering further changes impossible.
- When building a new name StructType, the builder will try to first
create, then complete the type, ensuring that:
- Inexistent types are created
- Existing incomplete types are completed
- Existing complete types with matching attributes are reused
- Existing complete types with different attributes raise errors
- StructType now uses the CyclicParser/Printer guard to avoid infinite
recursion and identify when it should print/parse a self-reference.
ghstack-source-id: a6d4f65
Pull Request resolved: llvm#303
eZWALT
pushed a commit
to eZWALT/clangir
that referenced
this pull request
Apr 29, 2024
I think it's time to claim that CIR supports recursive types (many thanks to llvm#303 and to @sitio-couto :) ) And we can bring back the `get_member` verification back, with no checks for incomplete types. What do you think? And we can close llvm#256 as well
lanza
pushed a commit
that referenced
this pull request
Apr 29, 2024
This allows a named StructType to be mutated after it has been created,
if it is identified and incomplete.
The motivation for this is to improve the codegen of CIR in certain
scenarios where an incomplete type is used and later completed. These
usually leave the IR in an inconsistent state, where there are two
records types with the same identifier but different definitions (one
complete the other incomplete).
For example:
```c++
struct Node {
Node *next;
};
void test(struct Node n) {}
```
Generates:
```mlir
!temp_struct = !cir.struct<struct "Node" incomplete>
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!temp_struct>}>
```
To generate the `Node` struct type, its members must be created first.
However, the `next` member is a recursive reference, so it can only be
completed after its parent. This generates a temporary incomplete
definition of the `Node` type that remains in the code even after the
type to which it refers is completed. As a consequence, accessing the
`next` member of a `Node` value fetches the old incomplete version of
the type which affects CIR's type-checking capabilities.
This patch ensures that, once the parent is fully visited, the `next`
member can be completed in place, automatically updating any references
to it at a low cost. To represent recursive types, the StructType now
is equipped with self-references. These are represented by a
`cir.struct` type with just the name of the parent struct that it
refers to. The same snippet of code will not generate the following
CIR IR:
```mlir
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!cir.struct<struct "Node">>}>
```
Summary of the changes made:
- Named records are now uniquely identified by their name. An attempt
to create a new record with the same will fail.
- Anonymous records are uniquely identified by members and other
relevant attributes.
- StructType has a new `mutate` method that allows it to be mutated
after it has been created. Each type can only be mutated if it is
identified and incomplete, rendering further changes impossible.
- When building a new name StructType, the builder will try to first
create, then complete the type, ensuring that:
- Inexistent types are created
- Existing incomplete types are completed
- Existing complete types with matching attributes are reused
- Existing complete types with different attributes raise errors
- StructType now uses the CyclicParser/Printer guard to avoid infinite
recursion and identify when it should print/parse a self-reference.
ghstack-source-id: a6d4f65
Pull Request resolved: #303
lanza
pushed a commit
that referenced
this pull request
Apr 29, 2024
I think it's time to claim that CIR supports recursive types (many thanks to #303 and to @sitio-couto :) ) And we can bring back the `get_member` verification back, with no checks for incomplete types. What do you think? And we can close #256 as well
pysuxing
pushed a commit
to pysuxing/llvm-project
that referenced
this pull request
Jul 17, 2024
This allows a named StructType to be mutated after it has been created,
if it is identified and incomplete.
The motivation for this is to improve the codegen of CIR in certain
scenarios where an incomplete type is used and later completed. These
usually leave the IR in an inconsistent state, where there are two
records types with the same identifier but different definitions (one
complete the other incomplete).
For example:
```c++
struct Node {
Node *next;
};
void test(struct Node n) {}
```
Generates:
```mlir
!temp_struct = !cir.struct<struct "Node" incomplete>
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!temp_struct>}>
```
To generate the `Node` struct type, its members must be created first.
However, the `next` member is a recursive reference, so it can only be
completed after its parent. This generates a temporary incomplete
definition of the `Node` type that remains in the code even after the
type to which it refers is completed. As a consequence, accessing the
`next` member of a `Node` value fetches the old incomplete version of
the type which affects CIR's type-checking capabilities.
This patch ensures that, once the parent is fully visited, the `next`
member can be completed in place, automatically updating any references
to it at a low cost. To represent recursive types, the StructType now
is equipped with self-references. These are represented by a
`cir.struct` type with just the name of the parent struct that it
refers to. The same snippet of code will not generate the following
CIR IR:
```mlir
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!cir.struct<struct "Node">>}>
```
Summary of the changes made:
- Named records are now uniquely identified by their name. An attempt
to create a new record with the same will fail.
- Anonymous records are uniquely identified by members and other
relevant attributes.
- StructType has a new `mutate` method that allows it to be mutated
after it has been created. Each type can only be mutated if it is
identified and incomplete, rendering further changes impossible.
- When building a new name StructType, the builder will try to first
create, then complete the type, ensuring that:
- Inexistent types are created
- Existing incomplete types are completed
- Existing complete types with matching attributes are reused
- Existing complete types with different attributes raise errors
- StructType now uses the CyclicParser/Printer guard to avoid infinite
recursion and identify when it should print/parse a self-reference.
ghstack-source-id: a6d4f650515cbf2d7f6e27d45aae6f768ba44f92
Pull Request resolved: llvm/clangir#303
bruteforceboy
pushed a commit
to bruteforceboy/clangir
that referenced
this pull request
Oct 2, 2024
I think it's time to claim that CIR supports recursive types (many thanks to llvm#303 and to @sitio-couto :) ) And we can bring back the `get_member` verification back, with no checks for incomplete types. What do you think? And we can close llvm#256 as well
Hugobros3
pushed a commit
to shady-gang/clangir
that referenced
this pull request
Oct 2, 2024
This allows a named StructType to be mutated after it has been created,
if it is identified and incomplete.
The motivation for this is to improve the codegen of CIR in certain
scenarios where an incomplete type is used and later completed. These
usually leave the IR in an inconsistent state, where there are two
records types with the same identifier but different definitions (one
complete the other incomplete).
For example:
```c++
struct Node {
Node *next;
};
void test(struct Node n) {}
```
Generates:
```mlir
!temp_struct = !cir.struct<struct "Node" incomplete>
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!temp_struct>}>
```
To generate the `Node` struct type, its members must be created first.
However, the `next` member is a recursive reference, so it can only be
completed after its parent. This generates a temporary incomplete
definition of the `Node` type that remains in the code even after the
type to which it refers is completed. As a consequence, accessing the
`next` member of a `Node` value fetches the old incomplete version of
the type which affects CIR's type-checking capabilities.
This patch ensures that, once the parent is fully visited, the `next`
member can be completed in place, automatically updating any references
to it at a low cost. To represent recursive types, the StructType now
is equipped with self-references. These are represented by a
`cir.struct` type with just the name of the parent struct that it
refers to. The same snippet of code will not generate the following
CIR IR:
```mlir
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!cir.struct<struct "Node">>}>
```
Summary of the changes made:
- Named records are now uniquely identified by their name. An attempt
to create a new record with the same will fail.
- Anonymous records are uniquely identified by members and other
relevant attributes.
- StructType has a new `mutate` method that allows it to be mutated
after it has been created. Each type can only be mutated if it is
identified and incomplete, rendering further changes impossible.
- When building a new name StructType, the builder will try to first
create, then complete the type, ensuring that:
- Inexistent types are created
- Existing incomplete types are completed
- Existing complete types with matching attributes are reused
- Existing complete types with different attributes raise errors
- StructType now uses the CyclicParser/Printer guard to avoid infinite
recursion and identify when it should print/parse a self-reference.
ghstack-source-id: a6d4f65
Pull Request resolved: llvm#303
Hugobros3
pushed a commit
to shady-gang/clangir
that referenced
this pull request
Oct 2, 2024
I think it's time to claim that CIR supports recursive types (many thanks to llvm#303 and to @sitio-couto :) ) And we can bring back the `get_member` verification back, with no checks for incomplete types. What do you think? And we can close llvm#256 as well
keryell
pushed a commit
to keryell/clangir
that referenced
this pull request
Oct 19, 2024
This allows a named StructType to be mutated after it has been created,
if it is identified and incomplete.
The motivation for this is to improve the codegen of CIR in certain
scenarios where an incomplete type is used and later completed. These
usually leave the IR in an inconsistent state, where there are two
records types with the same identifier but different definitions (one
complete the other incomplete).
For example:
```c++
struct Node {
Node *next;
};
void test(struct Node n) {}
```
Generates:
```mlir
!temp_struct = !cir.struct<struct "Node" incomplete>
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!temp_struct>}>
```
To generate the `Node` struct type, its members must be created first.
However, the `next` member is a recursive reference, so it can only be
completed after its parent. This generates a temporary incomplete
definition of the `Node` type that remains in the code even after the
type to which it refers is completed. As a consequence, accessing the
`next` member of a `Node` value fetches the old incomplete version of
the type which affects CIR's type-checking capabilities.
This patch ensures that, once the parent is fully visited, the `next`
member can be completed in place, automatically updating any references
to it at a low cost. To represent recursive types, the StructType now
is equipped with self-references. These are represented by a
`cir.struct` type with just the name of the parent struct that it
refers to. The same snippet of code will not generate the following
CIR IR:
```mlir
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!cir.struct<struct "Node">>}>
```
Summary of the changes made:
- Named records are now uniquely identified by their name. An attempt
to create a new record with the same will fail.
- Anonymous records are uniquely identified by members and other
relevant attributes.
- StructType has a new `mutate` method that allows it to be mutated
after it has been created. Each type can only be mutated if it is
identified and incomplete, rendering further changes impossible.
- When building a new name StructType, the builder will try to first
create, then complete the type, ensuring that:
- Inexistent types are created
- Existing incomplete types are completed
- Existing complete types with matching attributes are reused
- Existing complete types with different attributes raise errors
- StructType now uses the CyclicParser/Printer guard to avoid infinite
recursion and identify when it should print/parse a self-reference.
ghstack-source-id: a6d4f65
Pull Request resolved: llvm#303
keryell
pushed a commit
to keryell/clangir
that referenced
this pull request
Oct 19, 2024
I think it's time to claim that CIR supports recursive types (many thanks to llvm#303 and to @sitio-couto :) ) And we can bring back the `get_member` verification back, with no checks for incomplete types. What do you think? And we can close llvm#256 as well
lanza
pushed a commit
that referenced
this pull request
Nov 5, 2024
This allows a named StructType to be mutated after it has been created,
if it is identified and incomplete.
The motivation for this is to improve the codegen of CIR in certain
scenarios where an incomplete type is used and later completed. These
usually leave the IR in an inconsistent state, where there are two
records types with the same identifier but different definitions (one
complete the other incomplete).
For example:
```c++
struct Node {
Node *next;
};
void test(struct Node n) {}
```
Generates:
```mlir
!temp_struct = !cir.struct<struct "Node" incomplete>
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!temp_struct>}>
```
To generate the `Node` struct type, its members must be created first.
However, the `next` member is a recursive reference, so it can only be
completed after its parent. This generates a temporary incomplete
definition of the `Node` type that remains in the code even after the
type to which it refers is completed. As a consequence, accessing the
`next` member of a `Node` value fetches the old incomplete version of
the type which affects CIR's type-checking capabilities.
This patch ensures that, once the parent is fully visited, the `next`
member can be completed in place, automatically updating any references
to it at a low cost. To represent recursive types, the StructType now
is equipped with self-references. These are represented by a
`cir.struct` type with just the name of the parent struct that it
refers to. The same snippet of code will not generate the following
CIR IR:
```mlir
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!cir.struct<struct "Node">>}>
```
Summary of the changes made:
- Named records are now uniquely identified by their name. An attempt
to create a new record with the same will fail.
- Anonymous records are uniquely identified by members and other
relevant attributes.
- StructType has a new `mutate` method that allows it to be mutated
after it has been created. Each type can only be mutated if it is
identified and incomplete, rendering further changes impossible.
- When building a new name StructType, the builder will try to first
create, then complete the type, ensuring that:
- Inexistent types are created
- Existing incomplete types are completed
- Existing complete types with matching attributes are reused
- Existing complete types with different attributes raise errors
- StructType now uses the CyclicParser/Printer guard to avoid infinite
recursion and identify when it should print/parse a self-reference.
ghstack-source-id: a6d4f65
Pull Request resolved: #303
lanza
pushed a commit
that referenced
this pull request
Nov 5, 2024
I think it's time to claim that CIR supports recursive types (many thanks to #303 and to @sitio-couto :) ) And we can bring back the `get_member` verification back, with no checks for incomplete types. What do you think? And we can close #256 as well
lanza
pushed a commit
that referenced
this pull request
Mar 18, 2025
This allows a named StructType to be mutated after it has been created,
if it is identified and incomplete.
The motivation for this is to improve the codegen of CIR in certain
scenarios where an incomplete type is used and later completed. These
usually leave the IR in an inconsistent state, where there are two
records types with the same identifier but different definitions (one
complete the other incomplete).
For example:
```c++
struct Node {
Node *next;
};
void test(struct Node n) {}
```
Generates:
```mlir
!temp_struct = !cir.struct<struct "Node" incomplete>
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!temp_struct>}>
```
To generate the `Node` struct type, its members must be created first.
However, the `next` member is a recursive reference, so it can only be
completed after its parent. This generates a temporary incomplete
definition of the `Node` type that remains in the code even after the
type to which it refers is completed. As a consequence, accessing the
`next` member of a `Node` value fetches the old incomplete version of
the type which affects CIR's type-checking capabilities.
This patch ensures that, once the parent is fully visited, the `next`
member can be completed in place, automatically updating any references
to it at a low cost. To represent recursive types, the StructType now
is equipped with self-references. These are represented by a
`cir.struct` type with just the name of the parent struct that it
refers to. The same snippet of code will not generate the following
CIR IR:
```mlir
!full_struct = !cir.struct<struct "Node" {!cir.ptr<!cir.struct<struct "Node">>}>
```
Summary of the changes made:
- Named records are now uniquely identified by their name. An attempt
to create a new record with the same will fail.
- Anonymous records are uniquely identified by members and other
relevant attributes.
- StructType has a new `mutate` method that allows it to be mutated
after it has been created. Each type can only be mutated if it is
identified and incomplete, rendering further changes impossible.
- When building a new name StructType, the builder will try to first
create, then complete the type, ensuring that:
- Inexistent types are created
- Existing incomplete types are completed
- Existing complete types with matching attributes are reused
- Existing complete types with different attributes raise errors
- StructType now uses the CyclicParser/Printer guard to avoid infinite
recursion and identify when it should print/parse a self-reference.
ghstack-source-id: a6d4f65
Pull Request resolved: #303
lanza
pushed a commit
that referenced
this pull request
Mar 18, 2025
I think it's time to claim that CIR supports recursive types (many thanks to #303 and to @sitio-couto :) ) And we can bring back the `get_member` verification back, with no checks for incomplete types. What do you think? And we can close #256 as well
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Stack from ghstack (oldest at bottom):
This allows a named StructType to be mutated after it has been created,
if it is identified and incomplete.
The motivation for this is to improve the codegen of CIR in certain
scenarios where an incomplete type is used and later completed. These
usually leave the IR in an inconsistent state, where there are two
records types with the same identifier but different definitions (one
complete the other incomplete).
For example:
Generates:
To generate the
Nodestruct type, its members must be created first.However, the
nextmember is a recursive reference, so it can only becompleted after its parent. This generates a temporary incomplete
definition of the
Nodetype that remains in the code even after thetype to which it refers is completed. As a consequence, accessing the
nextmember of aNodevalue fetches the old incomplete version ofthe type which affects CIR's type-checking capabilities.
This patch ensures that, once the parent is fully visited, the
nextmember can be completed in place, automatically updating any references
to it at a low cost. To represent recursive types, the StructType now
is equipped with self-references. These are represented by a
cir.structtype with just the name of the parent struct that itrefers to. The same snippet of code will not generate the following
CIR IR:
Summary of the changes made:
Named records are now uniquely identified by their name. An attempt
to create a new record with the same will fail.
Anonymous records are uniquely identified by members and other
relevant attributes.
StructType has a new
mutatemethod that allows it to be mutatedafter it has been created. Each type can only be mutated if it is
identified and incomplete, rendering further changes impossible.
When building a new name StructType, the builder will try to first
create, then complete the type, ensuring that:
StructType now uses the CyclicParser/Printer guard to avoid infinite
recursion and identify when it should print/parse a self-reference.