cowgol icon indicating copy to clipboard operation
cowgol copied to clipboard

Strings can't be const? Duplicate strings go unnoticed.

Open ibara opened this issue 4 years ago • 4 comments

Hello --

I wrote an 8080 disassembler in Cowgol: https://github.com/ibara/cowgol-utilities/blob/main/cowdis.cow

I was a little hesitant to write a massive array in Cowgol, so I opted for a big switch statement. Originally, for the OneByte(), TwoByte(), and ThreeByte() calls within Disassemble() I wrote the strings in directly as arguments. But I noticed the generated CP/M binary was larger than anticipated, so I ran my hexdump utility on it. I discovered that Cowgol was unable to notice that I was using the same strings over and over again (e.g., "mov", "add", etc.) and so it had many copies of the strings in the binary. So I figured I would turn them into variables. But then I thought it would make more sense to mark them const. However, Cowgol forbids marking strings const, giving an error saying "only constant values are allowed here."

Just making sure I didn't miss anything. It's ok if these items are future planned or not slated for development. I really just want to make sure I'm writing Cowgol code best practice.

ibara avatar Nov 16 '20 02:11 ibara

Yeah, const variables have to be untyped, which is why they can't be string constants --- they're expanded inline during compilation (similar to #defines). Strings aren't deduped because that require keeping every string in memory to do so, although thinking about it maybe that could be done in cowlink, where there's plenty of room.

The cheapest way of making a string constant should be:

var something[] := "String here";

...but I don't recall off the top of my head whether that's actually implemented or not yet.

davidgiven avatar Nov 16 '20 10:11 davidgiven

I figured that was the reason for no dedup. I'm ok with the way I did it. I was mainly just curious.

var something[] := "String here";

seems not to be working, I get an error unexpected OPENSQ when I try it.

My

var something: [uint8] := "String here";

solution is fine for me. It brought the size of the disassembler down 1.5 KB (9 KB when using hardcoded non-deduped strings to 7.5 KB with variable strings) which is more than enough for my needs.

ibara avatar Nov 16 '20 15:11 ibara

Okay, that's something I need to fix.

The reason why the former's preferable is that the second is a pointer to a string, and so to get the string address the pointer needs to be dereferenced. Getting the address of an array is a simple constant load, as in C.

davidgiven avatar Nov 16 '20 15:11 davidgiven

That makes sense, thanks.

ibara avatar Nov 16 '20 15:11 ibara