Linus - Garbage Code And AI Code
Written by Harry Fairhead   
Wednesday, 15 October 2025

Linus Torvalds seems to have had a bit of a relapse lately in his efforts to moderate his comments on code. One of his latest outbursts merits more than a surface analysis.

The creator of Linux is well known for his "direct" comments on other people's code and most of the time you can settle back and enjoy the show, smug in your agreement. This time, however, he has opened up a deep schism. The simple and direct versus the more elaborate. At first glance you might vote with the simple and direct - after all how could that be wrong? Well consider simple and direct assembler versus the more elaborate Python. You see my point. 

What exactly Linus was complaining about was the use of a C macro in a header file that was part of an update to RISC V support:

"This adds various garbage that isn't RISC-V specific to generic header files.

And by "garbage" I really mean it. This is stuff that nobody should ever send me, never mind late in a merge window.

Like this crazy and pointless make_u32_from_two_u16() "helper".

That thing makes the world actively a worse place to live. It's
useless garbage that makes any user incomprehensible, and actively *WORSE* than not using that stupid "helper". If you write the code out as "(a << 16) + b", you know what it does and which is the high word. Maybe you need to add a cast to make sure that 'b' doesn't have high bits that pollutes the end result, so maybe it's not going to be exactly _pretty_, but it's not going to be wrong and incomprehensible either."

The issue here is that a macro for converting two 16-bit ints to a single 32-bit int was included in a generic header file. ??The sort of thing we are talking about is:

#define U16to32(a,b) a<< 16) |b

and then we can write

c=U16to32(a,b);

rather than

c = a<<16 | b;

The difference seems slight, a real storm in a teacup, but it isn't. It reveals a fundamental split between high- and low-level thinking. 

When I'm writing a C program and I need to put two 16-bit ints into a single 32-bit int my brain ???creates a<<16 | b and I can see the bits of a in my head moving up to make space for the bits of b to OR themselves into place. It just seems natural.

I have to say that I don't like Linus's (a<<b) + b because the addition with its allowance for carrys and the fact it needs parentheses to override the operator precedence seems like more than is needed. The OR seems much more to the point and needs no parentheses, but I can still see what the bits are doing in the addition version. 

I really don't like the macro precisely because it hides the simplicity of the dance that the bits are doing. I think that Linus is of the same opinion. He also quotes the argument that U16to32(a,b) gives you no clue as how to use the macro - which is the high word and which the low word? You can change the definition to:

#define U16to32(high,low) high<< 16) |low

but you don't see this when you write U16to32(a,b) and if you do see the macro definition it is obvious which is which from the operation defined. In short, the macro adds very little and if you are capable of doing the bit manipulation in your head it actually takes much of the understanding away by hiding it.

However ....

If you suddenly decide that there is a better way to convert 2x16 bits into 1x32 bits then you can do this project-wide by simply editing the macro. For example:

#define U16to32(high,low) high<< 16) + low

Now we are doing things Linus's way without having to edit the entire code base. This is useful, but the idea of needing a change in this case is far fetched. The optimized operation is acceptable in either form and the idea that some genius is going to invent a new and better way of doing the job seems unlikely in the extreme. There are cases where a macro can make system-wide changes easier but, I don't think this is one of them. It is a bit like defining a macro for a+b:

#define  sum(a,b) a+b

And if you do want such a generally applicable macro, putting it into a task specific header file is definitely not a good idea.

Finally we have this issue of the possible cast. Do we need one?

You could protect yourself in the macro against some idiot, usually you a few hours after you created the macro, by casting and cleaning:

#define U16to32(high,low) (uint32_t)high<< 16) | 
(uint32_t) (low) & 0xFFFF

Now we are assuming that the low part could actually be a 32-bit value and we need to zero the high-order word. If you are sure  that low is a 16-bit word then you don't have to cast it because the usual arithmetic promotions mean that it will first be promoted to int, then shifted and there is no need to AND it with a mask because the high bits already have to be zero. The same is true of the high value - first promoted to 32 bits then shifted. 

So you might as well drop the casts and the mask.

Or can you?

The promotion is to int and this is not necessarily a 32-bit int.  There aren't many systems that currently define an int to be anything other than 32-bits, but they still exist - the Arduino is one of them and if you try the program:

uint16_t a=0x5555,b=0x5555;
uint32_t c;
c = a<<16 | b;

You will discover that c is 0x5555 rather than 0x55555555. The reason is that the left shift is performed as a "promoted" 16-bit shift and all of the bits are lost leaving just 0

So if you want your code to be really portable, you need at least the first cast i.e. you have to write:

    c =((uint32_t) a<<16) | b;

but you don't if you are certain that ??int is a 32-bit int.

You might be wondering where AI comes into this ??as suggested by the headline?

I asked Gemini for a few lines of C to convert two 16-bit ints to a single 32-bit int and the result was:

uint32_t combine_words(uint16_t high_word, 
uint16_t low_word) {
return ((uint32_t)high_word << 16) | low_word;
}

Well you can't argue with that, apart from the use of a function.

At end of the day, I sort of agree with Linus, but not completely. I don't think that a macro is needed, but I do think that using OR and not addition is the more meaningful way to write the code. 

If you know what the bits are doing, then there is no need for an abstraction in the form of a macro to hide what is going on.

 

tuxicon

More Information

https://lkml.org/lkml/2025/8/9/322

Related Articles

Linus Torvalds Over Flows On Overflows In C

C++ In The Linux Kernel?

Linus Returns A Reformed Character

Linux Adopts New Code of Conduct; Linus Apologizes and Takes a Break

Linus On Linux And Strong Language 

 

To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Twitter, Facebook or Linkedin.

 

Banner


Google Defends Developer Verification
01/10/2025

Google is pushing ahead with its unpopular attempt at developer verification and has recently outlined why it's not so objectionable. Is verification desirable or just another way of tightening Google [ ... ]



Apache Moves To Oak Leaf Logo
19/09/2025

Apache has unveiled its new logo to replace the long-standing feather logo. The organization will also be moving to using the name "ASF" rather than "Apache Software Foundation". 


More News

pico book

 

Comments




or email your comment to: comments@i-programmer.info

<ASIN:1871962609>

<ASIN:1871962617>

<ASIN:1871962986>

<ASIN:1871962943>

<ASIN:1871962919>

 

Last Updated ( Wednesday, 15 October 2025 )