Discussion of eliminating the void type

Hello all,

I am willing to do “eliminating the void type” project. Is there anyone working on it?

=== Overview ===

The general concept is to replaced void with {}. And ‘ret void’ is a synonym of ‘ret {} {}.’

=== Further Implementation Details ===

  1. Deleting VoidTyID

  2. Deleting LLVMVoidTypeKind (one-to-one relation between VoidTyID and LLVMVoidTypeKind)

  3. Use StructTy* VoidTy instead of Type VoidTy
    VoidTy may be Identified struct. In addition to error occurs at test/Analysis/BasicAA/empty.ll
    because of using literal struct “{}” as VoidTy

  4. Re-implement isVoidTy().
    Test whether the address of the type equals Type::getVoidTy()

=== Request For Command ===

The constructor form of ReturnInst

Any suggestion is welcomed.

Thanks a lot

Mitnick

Hi Mitnick,

=== Overview ===

The general concept is to replaced void with {}. And 'ret void' is a synonym of
'ret {} {}.'

in a sense the concept is just to delete void and not to replace it with
anything in particular. Of course front-ends (clang, dragonegg) need to produce
something instead of void, and {} is an example of what they might produce, but
they should not be obliged to use that. For example they could use [] or {{}}
etc.

=== Further Implementation Details ===

1. Deleting VoidTyID

Yes!

2. Deleting LLVMVoidTypeKind (one-to-one relation between VoidTyID and
LLVMVoidTypeKind)

Yes!

3. Use StructTy* VoidTy instead of Type VoidTy

No! This doesn't make any sense to me. Why would having a definition for
VoidTy be needed or desirable?

     VoidTy may be Identified struct. In addition to error occurs at
test/Analysis/BasicAA/empty.ll
     because of using literal struct "{}" as VoidTy

4. Re-implement isVoidTy().

No! Just delete void type, don't try to create a canonical replacement for it.

Ciao, Duncan.

Hi Mitnick,

=== Overview ===

The general concept is to replaced void with {}. And 'ret void' is a synonym of
'ret {} {}.'

in a sense the concept is just to delete void and not to replace it with
anything in particular. Of course front-ends (clang, dragonegg) need to produce
something instead of void, and {} is an example of what they might produce, but
they should not be obliged to use that. For example they could use [] or {{}}
etc.

=== Further Implementation Details ===

1. Deleting VoidTyID

Yes!

2. Deleting LLVMVoidTypeKind (one-to-one relation between VoidTyID and
LLVMVoidTypeKind)

Yes!

3. Use StructTy* VoidTy instead of Type VoidTy

No! This doesn't make any sense to me. Why would having a definition for
VoidTy be needed or desirable?

      VoidTy may be Identified struct. In addition to error occurs at
test/Analysis/BasicAA/empty.ll
      because of using literal struct "{}" as VoidTy

4. Re-implement isVoidTy().

No! Just delete void type, don't try to create a canonical replacement for it.

The value of still having something like a VoidTy in the API is that it would reduce the amount of code that needs to change. Much of our code at Illinois uses void type; I imagine lots of other LLVM code (including code in LLVM) does as well.

Going further, it's not clear to me why people want to get rid of the void type. Is there a lot of special casing that would go away if VoidTy were removed? All of the justification in Chris's note appears, for lack of a better word, cosmetic. It's a cleaner design, but the cost of "fixing" the issue seems to outweigh its benefit.

-- John T.

Hi John,

4. Re-implement isVoidTy().

No! Just delete void type, don't try to create a canonical replacement for it.

The value of still having something like a VoidTy in the API is that it would
reduce the amount of code that needs to change. Much of our code at Illinois
uses void type; I imagine lots of other LLVM code (including code in LLVM) does
as well.

I'm not against having an IRBuilder method that produces some kind of standard
"void type", for example {}, as a convenience, but I don't think that there
should be any such thing in the core APIs.

Going further, it's not clear to me why people want to get rid of the void type.
Is there a lot of special casing that would go away if VoidTy were removed?

Probably not that much. There seem to be about 50 lines in lib/Transforms that
need to special case due to the existence of void type. Forgetting about void
type would be one mistake that it is no longer be possible to make though, which
seems worthwhile to me.

  All

of the justification in Chris's note appears, for lack of a better word,
cosmetic. It's a cleaner design, but the cost of "fixing" the issue seems to
outweigh its benefit.

In dragonegg there are only 25 lines that use VoidTy. Getting rid of VoidTy
therefore seems essentially painless to me.

Ciao, Duncan.

Is this really a good idea? I'm not going to argue at length
about it, but it is worth thinking about.

The only practical downsides of void are when newcomers take C's
syntax for functions with no arguments a little too literally, or
when they try to create pointers to void. But these problems are
quickly caught and easily corrected.

Replacing void with {} will actually make the language more
deceptive, because if newcomers think {} is LLVM's spelling for
C's void, they might be tempted to use {}* for C's void*, and
nothing will stop them except mysterious bugs if they do
arithmetic.

On the purity side, replacing void with {} has the side effect of
emphasising an odd asymmetry in the language. Conisder the return
types of functions returning 0, 1, 2, and 3 etc. values:

0: {}
1: i32
2: {i32,i32}
3: {i32,i32,i32}
etc.

Why is 1 special-cased? Argument lists don't have a corresponding
special case, after all.

Dan

Hi Dan,

I am willing to do "eliminating the void type" project.

Is this really a good idea? I'm not going to argue at length
about it, but it is worth thinking about.

The only practical downsides of void are when newcomers take C's
syntax for functions with no arguments a little too literally, or
when they try to create pointers to void. But these problems are
quickly caught and easily corrected.

there's a difference between users of LLVM (which you discuss here)
and developers of LLVM (people writing transforms etc). I agree
that for users it just changes one oddity for another. However for
developers it should make things simpler by making the IR more uniform.

Replacing void with {} will actually make the language more
deceptive, because if newcomers think {} is LLVM's spelling for
C's void, they might be tempted to use {}* for C's void*, and
nothing will stop them except mysterious bugs if they do
arithmetic.

I think this is a dubious argument. Being able to do pointer arithmetic
on void * was only an odd GCC extension as far as I know, not a general
C feature. Anyone who makes this mistake will pretty much instantly
discover that there is a problem. Anyway, conceptually the idea is not
to replace void with {}, it's to remove void because there are alternatives
such as {}, {{}} etc.

On the purity side, replacing void with {} has the side effect of
emphasising an odd asymmetry in the language. Conisder the return
types of functions returning 0, 1, 2, and 3 etc. values:

0: {}
1: i32
2: {i32,i32}
3: {i32,i32,i32}
etc.

Why is 1 special-cased? Argument lists don't have a corresponding
special case, after all.

You could return one value as {i32}. But you are right, there is an asymmetry.
It already existed, I don't see how eliminating void makes things worse, it
only makes things more regular by no longer distinguishing between the 0 case
and the 2, 3, ... case.

Ciao, Duncan.

Hello Duncan,

There is a discussion with Chris Lattner:
http://old.nabble.com/Eliminating-the-‘void’-type-td33726468.html
In the discussion, Chris Lattner suggest Type::getVoidTy() should
still exist and
return {} for API continuity. If VoidTy and isVoidTy() go away, how do deal with
the isVoidTy() function call in LLVM source tree? Another issue is: What should
ReturnInst constructor looks like with VoidTy or not?

Thanks

Mitnick

Hi Mitnick,

There is a discussion with Chris Lattner:
http://old.nabble.com/Eliminating-the-‘void’-type-td33726468.html
In the discussion, Chris Lattner suggest Type::getVoidTy() should
still exist and
return {} for API continuity.

don't listen to that Chris guy! :slight_smile: I think that that's a mistake, and it would
be better to eliminate the void concept entirely from the LLVM core. Instead I
reckon that IRBuilder (which already has some convenience methods for getting
hold of types) should gain methods getVoidTy, returning {}, and getVoidPtrTy,
returning i8* (with a comment explaining why it is not returning {}*). Summary:
the core should be kept conceptually clean and uniform, convenience wrappers
should go in IRBuilder.

  If VoidTy and isVoidTy() go away, how do deal with

the isVoidTy() function call in LLVM source tree?

Replace it with false everywhere, which in general will just mean deleting that
bit of code. After all, the existing code already has to handle {} correctly,
since people can already write this, and that returns false for isVoidTy.
[I could change dragonegg today to output {} whereever it uses void right now,
and it should work, though bugs are always possible].

I suggest you go about things like this: first convert the clang front-end to
use {} everywhere instead of void (maybe enhancing IRBuilder by adding helpful
methods). I'm happy to do the same for dragonegg. This may require fixing
some bugs in LLVM, i.e. code that doesn't handle {} properly (code that was
already broken but no-one noticed). Once front-ends simply aren't producing
void type any more, you can delete VoidTy and replace every use of isVoidTy
with false (which is correct since it can never return true since there will be
no void type in any IR any more).

  Another issue is: What should

ReturnInst constructor looks like with VoidTy or not?

I didn't understand the question. Are you asking whether there should be some
convenience constructors which result in returning {}, while previously they
would return void? In my opinion there should be no such constructors. Any
such convenience methods should be in IRBuilder. That already has CreateRetVoid
which can now create a "return {} {}" instead.

Ciao, Duncan.

As a developer, it would be mildly nice to give stores names.
However, that may be more than offset by the fact that store instructions
would be able to have users. It'd always be safe to RAUW a store with
undef {}, but that's a nuisance.

Dan

Hi Dan,

there's a difference between users of LLVM (which you discuss here)
and developers of LLVM (people writing transforms etc). I agree
that for users it just changes one oddity for another. However for
developers it should make things simpler by making the IR more uniform.

As a developer, it would be mildly nice to give stores names.
However, that may be more than offset by the fact that store instructions
would be able to have users. It'd always be safe to RAUW a store with
undef {}, but that's a nuisance.

at this point I should confess that I was only thinking of function return
types when talking about void type, and forgot that StoreInst returns a
type, void type. How about having getType return null for StoreInst and
similar?

Ciao, Duncan.

That sounds like it would be an awkward special case.

Dan

there's a difference between users of LLVM (which you discuss here)
and developers of LLVM (people writing transforms etc). I agree
that for users it just changes one oddity for another. However for
developers it should make things simpler by making the IR more uniform.

As a developer, it would be mildly nice to give stores names.
However, that may be more than offset by the fact that store instructions
would be able to have users. It'd always be safe to RAUW a store with
undef {}, but that's a nuisance.

at this point I should confess that I was only thinking of function return
types when talking about void type, and forgot that StoreInst returns a
type, void type. How about having getType return null for StoreInst and
similar?

That sounds like it would be an awkward special case.

Yes, in fact this issue has put me off the whole idea of getting rid of void
type.

Ciao, Duncan.

Hello Duncan, Dan

According to the thread, I am wondering to know whether the current design is relatively better than getting rid of void type, which means the idea "eliminating the void type" may be removed from LLVM random notes?

Thanks a lot

Mitnick

I have to confess that I find the whole idea crazy. It seems a lot of pain for everyone for very little gain.

Evan

Evan Cheng wrote:

I have to confess that I find the whole idea crazy. It seems a lot of pain for everyone for very little gain.

IIRC, part of the point of removing void was so that we could have users of store/br/unreachable/etc. and allow the instructions to have names. The users would be restricted to being metadata.

Nick