Adding memory spaces to types

Good to hear. I had proceeded with this approach and have some simple cases working (all the way through LLVM back end and generating assembly, not bad for 2 evenings work!). I had to make some guesses about all the functions that need to see “through” the ASQualType, but I figured it would be mostly similar to other types that wrap another type (Complex, Vector, etc.) with a few additions.

Also, address space qualifiers need to be parsed like other type CVR qualifiers, rather than using an attribute, because attributes seem to apply to the entire Decl irrespective of where in Decl the attribute occurs (is this purposeful, or just the current state?).

_SpaceA int * foo;
is not
int * _SpaceA foo;

Also, the TR specifies that the names of address spaces are in the type namespace. My question is, does that mean there also needs to be an AddressSpaceType class?

The LLVM infrastructure supports a limited number of address spaces (N) and I was planning on having built in support for qualifiers of the form ‘_AddressSpace#’ for all N. The TR says that a means to define new address spaces may be provided by the compiler, and if there are in-fact AddressSpaceType’s would it be reasonable to think that a typedef would be the correct means of binding a name to a numbered AddressSpace?

allowing:
typedef _AddressSpace12 twelfth_space;
typedef _AddressSpace12 space_12;

also, this would allow the compiler to be “preloaded” with typedefs for memory spaces based on the target, would it not?

However, this optimization for CVR qualifiers doesn't impact other "qualifiers". It would be very reasonable to have an AddressSpaceQualifiedType class, which takes an address space ID and a QualType. This combines the space/time efficiency niceties of QualType with the generality of having explicit classes for all of these.

Good to hear. I had proceeded with this approach and have some simple cases working (all the way through LLVM back end and generating assembly, not bad for 2 evenings work!). I had to make some guesses about all the functions that need to see "through" the ASQualType, but I figured it would be mostly similar to other types that wrap another type (Complex, Vector, etc.) with a few additions.

Nice!

Also, address space qualifiers need to be parsed like other type CVR qualifiers,

Right.

rather than using an attribute, because attributes seem to apply to the entire Decl irrespective of where in Decl the attribute occurs (is this purposeful, or just the current state?).

I don't recall off-hand. Steve is the guru of attributes, though Nate may also know. It would certainly be nice to have these be typedefs or #defines for __attribute__ syntax, just to avoid having to tweak the parser for each device that needs address spaces.

_SpaceA int * foo;
is not
int * _SpaceA foo;

If attributes don't support this mechanism right now, I think we should extend them to work with it. A specific attribute (e.g. "address_space" in __attribute__((address_space(1)))) should be markable as applying to the type instead of the decl.

Also, the TR specifies that the names of address spaces are in the type namespace. My question is, does that mean there also needs to be an AddressSpaceType class?

I haven't read the TR closely, but if it says this, it is very strange :). I think this means that _SpaceA can't be either a macro or a typedef. The issue is that it being a type means that this should be legal (assuming _SpaceA is a valid space for the current target:

_SpaceA int * foo;

void bar() {
   typedef int _SpaceA;
   _SpaceA y; // int y.
}

Is this really intended?

The LLVM infrastructure supports a limited number of address spaces (N) and I was planning on having built in support for qualifiers of the form '_AddressSpace#' for all N. The TR says that a means to define new address spaces may be provided by the compiler, and if there are in-fact AddressSpaceType's would it be reasonable to think that a typedef would be the correct means of binding a name to a numbered AddressSpace?

I don't think that a typedef will work here. A typedef can't appear in this case:

int * _mytypedef * var;

allowing:
typedef _AddressSpace12 twelfth_space;
typedef _AddressSpace12 space_12;

also, this would allow the compiler to be "preloaded" with typedefs for memory spaces based on the target, would it not?

I would strongly prefer some way for the various target-specific memory spaces to be handled without having to hack the parser, I don't know if this is possible though.

-Chris

However, this optimization for CVR qualifiers doesn’t impact other “qualifiers”. It would be very reasonable to have an AddressSpaceQualifiedType class, which takes an address space ID and a QualType. This combines the space/time efficiency niceties of QualType with the generality of having explicit classes for all of these.

Good to hear. I had proceeded with this approach and have some simple cases working (all the way through LLVM back end and generating assembly, not bad for 2 evenings work!). I had to make some guesses about all the functions that need to see “through” the ASQualType, but I figured it would be mostly similar to other types that wrap another type (Complex, Vector, etc.) with a few additions.

Nice!

Also, address space qualifiers need to be parsed like other type CVR qualifiers,

Right.

rather than using an attribute, because attributes seem to apply to the entire Decl irrespective of where in Decl the attribute occurs (is this purposeful, or just the current state?).

I don’t recall off-hand. Steve is the guru of attributes, though Nate may also know. It would certainly be nice to have these be typedefs or #defines for attribute syntax, just to avoid having to tweak the parser for each device that needs address spaces.

I wholeheartedly agree. My first implementation used attributes, but fails the test below. I looked at what it would take to get the parser to understand otherwise and it seemed very non-trivial. Especially because the number and name of keywords is target specific it’d need something akin to attribute parsing, but just for namespaces. Doesn’t seem worth it.

_SpaceA int * foo;
is not
int * _SpaceA foo;

If attributes don’t support this mechanism right now, I think we should extend them to work with it. A specific attribute (e.g. “address_space” in attribute((address_space(1)))) should be markable as applying to the type instead of the decl.

Named address spaces were implemented using attributes successfully by Codeplay in the VectorC compiler that I have experience with, so I agree that it would be good to have this functionality.

Also, the TR specifies that the names of address spaces are in the type namespace. My question is, does that mean there also needs to be an AddressSpaceType class?

I haven’t read the TR closely, but if it says this, it is very strange :). I think this means that _SpaceA can’t be either a macro or a typedef. The issue is that it being a type means that this should be legal (assuming _SpaceA is a valid space for the current target:

_SpaceA int * foo;

void bar() {
typedef int _SpaceA;
_SpaceA y; // int y.
}

Is this really intended?

Here’s the specific language. I misread it.

5.1.2 Address-space type qualifiers

Each address space other than the generic one has a unique name in the form of an identifier.
Address space names are ordinary identifiers, sharing the same name space as variables and
typedef names. Any such names follow the same rules for scope as other ordinary identifiers (such
as typedef names). An implementation may provide an implementation-defined set of intrinsic
address spaces that are, in effect, predefined at the start of every translation unit. The names of
intrinsic address spaces must be reserved identifiers (beginning with an underscore and an
uppercase letter or with two underscores). An implementation may also optionally support a means
for new address space names to be defined within a translation unit.

I would strongly prefer some way for the various target-specific memory spaces to be handled without having to hack the parser, I don’t know if this is possible though.

I prefer less parser hacking as well. I’m voting for being able to apply attributes to types as well as the whole decl. =)

Syntactically, attributes can be on the "DeclSpec" or the "Declarator" (see DeclSpec.h for some more comments). This models what GCC does.

Semantically, all the attributes are (currently) associated with the Declarator. Since we haven't implemented many attributes yet, it's entirely possible that we need to associate "DeclSpec" attributes with the eventual type.

snaroff

Also, the TR specifies that the names of address spaces are in the type namespace. My question is, does that mean there also needs to be an AddressSpaceType class?

I haven’t read the TR closely, but if it says this, it is very strange :). I think this means that _SpaceA can’t be either a macro or a typedef. The issue is that it being a type means that this should be legal (assuming _SpaceA is a valid space for the current target:

_SpaceA int * foo;

void bar() {
typedef int _SpaceA;
_SpaceA y; // int y.
}

Is this really intended?

Here’s the specific language. I misread it.

5.1.2 Address-space type qualifiers

Each address space other than the generic one has a unique name in the form of an identifier.
Address space names are ordinary identifiers, sharing the same name space as variables and
typedef names. Any such names follow the same rules for scope as other ordinary identifiers (such
as typedef names). An implementation may provide an implementation-defined set of intrinsic
address spaces that are, in effect, predefined at the start of every translation unit. The names of
intrinsic address spaces must be reserved identifiers (beginning with an underscore and an
uppercase letter or with two underscores). An implementation may also optionally support a means
for new address space names to be defined within a translation unit.

Okay, this is goodness. This means the builtin ones can just be macros that expand out to an attribute, or anything else convenient.

I don’t recall off-hand. Steve is the guru of attributes, though Nate may also know. It would certainly be nice to have these be typedefs or #defines for attribute syntax, just to avoid having to tweak the parser for each device that needs address spaces.

I wholeheartedly agree. My first implementation used attributes, but fails the test below. I looked at what it would take to get the parser to understand otherwise and it seemed very non-trivial. Especially because the number and name of keywords is target specific it’d need something akin to attribute parsing, but just for namespaces. Doesn’t seem worth it.

Yep.

_SpaceA int * foo;
is not
int * _SpaceA foo;

If attributes don’t support this mechanism right now, I think we should extend them to work with it. A specific attribute (e.g. “address_space” in attribute((address_space(1)))) should be markable as applying to the type instead of the decl.

Named address spaces were implemented using attributes successfully by Codeplay in the VectorC compiler that I have experience with, so I agree that it would be good to have this functionality.

Ok, so it sounds like the right approach is to extend our current attribute support to allow them to be applied in-place to the types as they are parsed.

-Chris