On 12/15/2024 5:22 PM, Thiago Adams wrote:
Em 12/15/2024 7:22 PM, Lawrence D'Oliveiro escreveu:
On Sun, 15 Dec 2024 07:44:34 -0300, Thiago Adams wrote:
>
I also think LLVM is too big.
>
How about QBE, then <https://c9x.me/compile/>.
QBE is just for linux and it does not generate code directly. C is everywhere.
But I am reading QBE docs to see what is necessary in a IL.
I agree that both LLVM and GCC are too big.
I am not sure the minimum size of a usable C compiler, my current estimate is probably somewhere in the area of 50-100 kLOC.
My current compiler is a bit bigger than this, and my own past attempt to implement a C compiler in under 30k lines had failed.
My current compiler use to be smaller, but multiple backends and similar did make it bigger:
SH-2, SH-4, BJX1 (older)
BJX2, RISC-V (current)
If I were to estimate a feature set for a 3AC IL:
Basic UNARY and BINARY operators;
Also COMPARE and similar;
Load and Store Index operators;
With support for an immediate index;
GOTO
IF-GOTO
CALL (with a list of argument variables and a target variable).
One doesn't need any higher-level control flow constructs.
Any built-in support for "switch()" can be optional (the main reason to have so is that it can make switch a little faster, but isn't required).
Earlier on, my compiler didn't have any backend support for this, and would instead decompose the switch into "if/else/goto" logic. You can then use recursive binary subdivision to implement the list of case labels (or linear probes if N is small).
BGBCC still uses binary subdivide if the case-labels don't satisfy the constraints for a branch-table (Say, needs to be 16..256 case labels with a density over 75%).
As can be noted though, BGBCC uses a stack IL, with the 3AC IR currently only existing in the backend. But, there are possible merits to a 3AC IR, and I had almost considered jumping over a few times, but was largely held back by inertia.
As noted though, not too long ago did relicense it to MIT-NA.
...
Oh well, have been distracted recently:
New filesystem for my project;
Have started work on trying to build a printable-electronics printer.
Essentially, the printer will be a very non-standard form of inkjet printer with a construction more like that of a CNC mill mixed with a 3D printer, but much lighter-duty. Partly realizing that a paper printer wouldn't really work (though, TBD if basically "the cheapest drill-press x/y table I could find" will be sufficient for the X/Y base). Resembles a mill table, but made out of aluminum and uses allthread and hex-nuts for the X and Y axes. CNC converting it mostly with parts I am making out of 3D printed plastic.
Will hold off on the PEDOT:PSS ink for now, this is likely to be the most expensive part of the project (then again, did burn a good chunk of the cost of this ink on getting a 3D printer and filament, but at least these will have other uses; whereas there is a big dependency ladder to climb, and until all dependencies are met, having a bottle of PEDOT:PSS ink would be kinda useless).
Even then, it would be limited to PMOS logic (both NMOS and CMOS would require materials currently outside of my price range).
So, likely test case is to build the printer and use it for CMYK printing and similar (can verify operation, and CMYK inks are at least affordable).
A difficult part of the process will be converting netlist output from a Verilog compiler into actual logic. Current plans are to tell the tools it is targeting a funky version of an ECP5 (one pretty much entirely lacking in block-memory or hard multipliers). Pretty much everything will need to be LUT4's, FFs, and some amount of distributed RAM (though, not yet sure how this will work; will effectively need to implement something with 2-ports, 4-bit address, and 1-bit wide).
Some of this (such as trying to figure out how to best construct a LUTRAM) seems too complicated to try throwing at a genetic algorithm. Though, could simplify the task (for a GA) if its view of everything is as operating on a subset of logic gates (AND, OR, NAND, NOR, NOT, ...; would exclude XOR and XNOR as these can't easily be fit into the same footprint).
Granted, another possible strategy being to rewrite the netlist to decompose all of the higher-level logic into basic logic gates, and then run the place-and-route logic purely in terms of gates (AND/OR/NAND/NOR). So, say, if one requests a CARRY, it is first decomposed into the more basic logic gates, which can be more easily mapped to a uniform grid.
Granted, this sort of thing is likely to be overly niche.
Would be slower than an FPGA, and non reprogrammable, but per-unit could be cheaper than using FPGAs, and still viable for running off individual and small numbers of devices (unlike ASIC) and could be made within the realm of affordability for a hobbyist (more so if the requisite machines could be mass-produced, similar to the situation with 3D printers; nevermind the cost of the needed inks).
Dunno, possibly (besides Verilog), a lower-level possibility would be to expose the gates more directly. Could almost express it in a similar form to an early form of Minecraft's "redstone logic", except slightly less limited.
Some similar strategies would likely apply, say, for example, if one created "master clock" by building a big ring of NOT gates (with an odd number of NOT gates), or BUF gates (with a single NOT gate), and whatever speed the ring of not-gates goes, is ones clock-pulse.
OTOH, Filesystem thing, as noted:
Structure partly resembles a hybrid of NTFS and EXT2;
Uses an inode table where the inode table is itself an inode;
The inodes consist of multiple tagged structures (like NTFS);
Uses fixed-size directory entries (sorta like FAT);
Directories use a variant of AVL trees.
Has file compression, currently applies to larger virtual blocks;
Has symlinks and the ability to inline small items into the inodes.
Size limit for inline storage is 128 bytes with 256 byte inodes.
Currently, I have an implementation in around 3.5 kLOC, which is slightly less than my FAT32/VFAT driver.
Still pretty experimental, and pretty much no other OS could access it.
It exists mostly because none of the other filesystems seemingly both have the feature-set I wanted, while also not being horridly over-complicated.
Granted, AVL trees are possibly more complicated than ideal, and trying to debug it, dealing with this had been a significant source of bugs.
B-Trees are more popular here, but B-Trees have more up-front complexity cost.
Granted, linear search or hash chaining would have been simpler; but doesn't scale as well O(n) vs O(log n).
...