Yeah, but how did they compile the first compiler? Just a simple thought I had that led to a really interesting exploration of fully self-hosted languages (like C). When your language's compiler is compiled in the language it supports, what happens when you go back in time to the first compiler? Well, you find "hand written" assembly code, of course. Keep going. How is that assembly then compiled into machine code? Somewhere down the line you get to just some person punching holes in a card. And that code lives on in everything we have today. Fascinating.
How did the first compiler get compiled? A journey from assembly to machine code.
More Relevant Posts
-
Bugs love hidden changes. Most languages let you mutate input parameters by default. That’s convenient—until a function changes something it shouldn’t. Treat inputs as readonly by default. Change should be intentional, not accidental. ✅ Predictable behavior ✅ Easier debugging ✅ Safer concurrency Great code doesn’t wait for compiler rules. Immutable by habit. Mutable by necessity.
To view or add a comment, sign in
-
#rust One more Rust hidden secret. Is it feasible to boost this Rust code performance? Hard to see at 1st sight. However it's doable! The secret is that arr is a so called "long reference". It contains a ref to the memory allocated for the array *and* an array length. The compiler guards each array element access with check if the index is in array bound. If not it panics the thread. Let's add one code line at the function beginning: if arr.len() < 5 { return; } and the function's performance is boosted! The trick is that the compiler recognises the explicit array boundary check and omits checks at following array element operations. Same happens with a regular cycle over array elements: the compiler doesn't perform per element check in that case. Thanks to Bitωise from YouTube for this great example!
To view or add a comment, sign in
-
-
Type systems don’t just prevent bugs - they also power compiler optimizations. This post breaks down type-based alias analysis in C and C++, explaining how aliasing affects performance, why undefined behavior plays a role, and how the restrict keyword helps compilers generate faster code: https://lnkd.in/erju4J-v #Cpp #Compilers #Optimization
To view or add a comment, sign in
-
Progress on my compiler: Changed the syntax around for easier parsing. Removed semi colons Added pointers, arrays, and strings Added an optional 'finally' block to function bodies Added an assert-not-zero feature. eg: const mem : byte* = malloc(100) mem! "Failed to allocate" which jumps to the finally block To compliment that, an 'if not zero' syntactic sugar eg: function main() : void { const mem: byte* = malloc(100) mem! "Failed to allocate" } finally { mem? free(mem) } C standard library functions are working straight out of the box as intended
To view or add a comment, sign in
-
-
ReadOnlyComposable annotation tells the compiler your function won’t write to the composition 🧠 Compiler can skip creating unnecessary groups, making it faster. Perfect for simple reads like LocalContext or theme values⚡️
To view or add a comment, sign in
-
𝐖𝐞 𝐚𝐫𝐞 𝐞𝐧𝐚𝐛𝐥𝐢𝐧𝐠 𝐞𝐱𝐩𝐞𝐫𝐢𝐦𝐞𝐧𝐭𝐚𝐥 𝐚𝐬𝐬𝐞𝐫𝐭-𝐚𝐬-𝐚𝐬𝐮𝐦𝐞 for our release builds 1. Every DBUG_ASSERT(x) now becomes [[assume(x)]] by default. 2. Some cases are opted out. Sometimes we have code like: DBUG_ASSERT(x); if (x) return error; // failsafe production case --^ Assuming `x` will not work as expected here. 3. It only targets `main` branch, meaning it's only for the major release. Here's one curious case. The simplified code: 𝚋𝚘𝚘𝚕 𝚏𝚘𝚞𝚗𝚍 = 𝚏𝚊𝚕𝚜𝚎; 𝚏𝚘𝚛 (𝚜𝚒𝚣𝚎_𝚝 𝚒= 0; 𝚒 < 𝚊𝚛𝚛𝚊𝚢->𝚎𝚕𝚎𝚖𝚎𝚗𝚝𝚜; 𝚒++) 𝚒𝚏 (𝚙𝚝𝚛 == *𝚍𝚢𝚗𝚊𝚖𝚒𝚌_𝚎𝚕𝚎𝚖𝚎𝚗𝚝(𝚊𝚛𝚛𝚊𝚢, 𝚒, 𝚟𝚘𝚒𝚍**)) { 𝚍𝚎𝚕𝚎𝚝𝚎_𝚍𝚢𝚗𝚊𝚖𝚒𝚌_𝚎𝚕𝚎𝚖𝚎𝚗𝚝(𝚊𝚛𝚛𝚊𝚢, 𝚒); 𝙸𝙵_𝙳𝙱𝚄𝙶(𝚏𝚘𝚞𝚗𝚍= 𝚝𝚛𝚞𝚎); // 𝚊𝚜𝚜𝚒𝚐𝚗𝚖𝚎𝚗𝚝 𝚑𝚊𝚙𝚙𝚎𝚗𝚜 𝚘𝚗𝚕𝚢 𝚒𝚗 𝚍𝚎𝚋𝚞𝚐 𝚖𝚘𝚍𝚎 } 𝙳𝙱𝚄𝙶_𝙰𝚂𝚂𝙴𝚁𝚃(𝚏𝚘𝚞𝚗𝚍); // 𝚏𝚘𝚞𝚗𝚍 𝚒𝚜 𝚗𝚘𝚝 𝚏𝚞𝚛𝚝𝚑𝚎𝚛 𝚞𝚜𝚎𝚍. In the release mode, found=true assignment wasn't present, which eventually led to a crash. Why though? `found` does not intervene the loop, so the reason is not so obvious. Here is a sketch example, showing the problem core: https://lnkd.in/dsGY4G3y We can see there what the compiler thinks: 1. bool found = false; assume(found) means assume(false) 2. Having assume(false), this point in code is 𝘂𝗻𝗿𝗲𝗮𝗰𝗵𝗮𝗯𝗹𝗲 3. 𝘈𝘴 𝘴𝘶𝘤𝘩, 𝘐 𝘤𝘢𝘯 𝘤𝘰𝘯𝘴𝘪𝘥𝘦𝘳 𝘵𝘩𝘦 𝘭𝘰𝘰𝘱 𝘢𝘣𝘰𝘷𝘦 𝘪𝘯𝘧𝘪𝘯𝘪𝘵𝘦 Fascinating! Indeed, the godbolt link above shows that an unconditional jmp command was generated. This case shows how effective the assumption mechanism can be on practice. #mariadb #performance #coding
To view or add a comment, sign in
-
🌀 Day 101/∞: Partition Array Into Two Arrays to Minimize Sum Difference Continuing my coding reset with Problem-265: Partition Array Into Two Arrays to Minimize Sum Difference 🧠 No IDE. No syntax highlighting. No compiler. Just logic, focus, and a blank document. This marks Day 101 of my ∞-Day No Compiler Challenge — a raw, brain-first approach to coding. Let’s see how far I can go with this! #DaysOfCode #NoCompilerChallenge #LearningInPublic #BrainBeforeCode #CodeWithoutIDE #DP
To view or add a comment, sign in
-
🚀 The next deep-dive is live! We’ve already explored how the Go compiler kicks off with the lexer — now it’s time to dive in deeper: Go compiler’s parser phase. 👉 Understanding the Go compiler: The Parser 🔗 https://lnkd.in/dbfrS2iH In this post we follow the journey of a flat token stream — the output of the lexer — and see how it’s turned into a structured Abstract Syntax Tree (AST). We’ll explore how the parser creates nodes for packages, imports, functions, expressions, and more. It’s your inside look at how Go’s compiler transforms code into meaning. If you enjoy pulling back the curtain on how things really work under the hood, remember that you can subscribe to the newsletter.
To view or add a comment, sign in
-
Your code's wrong, and the compiler knows -- but won't tell you💥 Meet IFNDR (Ill‑Formed, 𝐍𝐨 𝐃𝐢𝐚𝐠𝐧𝐨𝐬𝐭𝐢𝐜 𝐑𝐞𝐪𝐮𝐢𝐫𝐞𝐝): C++ allows compilers to accept certain broken programs without telling you. A classic example here 👉https://lnkd.in/eFcU4UjX A constructor-delegation cycle -- GCC (-Wall) accepts it and you hit a stack overflow at runtime; Clang rejects it. This looks like a stupid example, but I use delegating constructors a lot, and a new overload from a PR merge/conflict resolution can sneak in. How to avoid it * Pick one "primary" constructor that actually initializes the object. * Make every other constructor delegate into that one (one-way chain). * Prefer explicit on converting ctors to limit accidental hops. * In CI, build with both GCC and Clang (even if your target uses only one). * UBSan won’t catch IFNDR; run ASan on host builds to catch the stack overflow.
To view or add a comment, sign in
-
Let's write some code!
1moAlways a fascinating journey!