Languages for standalone

Programming, for all ages and all languages.
sj95126
Member
Member
Posts: 151
Joined: Tue Aug 11, 2020 12:14 pm

Re: Languages for standalone

Post by sj95126 »

bzt wrote:
sj95126 wrote:My kernel is built with gcc and doesn't use libgcc.
Mine neither. I've deliberately eliminated all compiler-specific libraries (wasn't easy, but possible). Now I can compile my OS with both gcc and CLang as-is (and possibly with many other ANSI C compilers too).
Technically, mine does use code that's not of my own creation by using the builtin va_* functions for the kprintf() I wrote, but gcc is inlining whatever code it adds. There are no function calls generated.
bzt wrote:
sj95126 wrote:To be *really* pedantic, you could conceivably compile simple C code into a standalone flat binary and never use a stack either.
On the other hand I don't think this is possible (not on all architectures that is). Regardless to the ABI, on x86 some CPU instructions need the stack (like "call" or "ret" for example), and I don't think you can convince a C compiler not to use such instructions.
Well, that's why I said "simple C code". :-) A main() that doesn't invoke any functions shouldn't need any call instructions. Theoretically, you could implement simple "subroutines" with gotos. There may be architectures I don't know in detail where this can't work.

I didn't say it was practical, just possible.
nullplan
Member
Member
Posts: 1766
Joined: Wed Aug 30, 2017 8:24 am

Re: Languages for standalone

Post by nullplan »

nexos wrote:Overall, C itself appears to be a freestanding language with no dependencies.
What do you mean by dependency here? A library you always have to link in or else the thing doesn't work? Because all C implementations I know have those. And if not, then I really don't know what you'd describe, say, FreePascal's runtime as. There is no difference, other than size.
sj95126 wrote: main() that doesn't invoke any functions shouldn't need any call instructions. Theoretically, you could implement simple "subroutines" with gotos. There may be architectures I don't know in detail where this can't work.
Even then, stack is required for the code that will end up calling the main() function. Depending on architecture, call instructions (or closest equivalent) are going to be necessary to establish GOT pointers, or else you cannot even access your global variables. And your automatic variables might end up on stack anyway, depending on architecture, available registers, and whether or not the compiler decides to spill. Thanks to the ABI, the decision may be out of the compiler's and, anyway. Remember, the i386 ABI gives you 3 free registers to work with. Even if you have lots of registers (like on PowerPC, where you have 32 registers), you might be hobbled by the ABI, which only allows you to use 11 of them without saving. main() might be the outermost layer of your application, but there is still something that called that function from the implementation, and therefore most ABIs make absolutely no special exception for main() regarding register usage.

So yes, even the simplest programs will require stack.

Besides, without something like a Wheeler jump being possible (and it isn't possible portably in C), your "subroutines" cannot return from whence they came. They can only "return" to a single place.
Carpe diem!
sj95126
Member
Member
Posts: 151
Joined: Tue Aug 11, 2020 12:14 pm

Re: Languages for standalone

Post by sj95126 »

nullplan wrote:Even then, stack is required for the code that will end up calling the main() function. Depending on architecture, call instructions (or closest equivalent) are going to be necessary to establish GOT pointers, or else you cannot even access your global variables. And your automatic variables might end up on stack anyway, depending on architecture, available registers, and whether or not the compiler decides to spill.
OK, but all of that is about *implementation* not the language itself. If you search the 700 pages of the ISO/IEC 9899:201x specification document, you will not find the word "stack" anywhere.
nullplan wrote:Besides, without something like a Wheeler jump being possible (and it isn't possible portably in C), your "subroutines" cannot return from whence they came. They can only "return" to a single place.
It wouldn't be easy, true. But you could implement some ugly switch/case logic that determines your original program flow as well as flow after return from the subroutine (which would end with a goto to that switch/case).

Again, I didn't say it was practical, only possible.
nexos
Member
Member
Posts: 1078
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

Re: Languages for standalone

Post by nexos »

I can see this turning into a flame war....
Anyway, all I am saying is that in theory, all of the C language itself, excluding all the standard headers, could be dependency free. An arch could do without the stack and use registers. BSS, the GOT and PLT, and all that stuff aren't required. The only language that can easily be made to be standalone that I can think of off the top of my head is Assembly.
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
moonchild
Member
Member
Posts: 73
Joined: Wed Apr 01, 2020 4:59 pm
Libera.chat IRC: moon-child

Re: Languages for standalone

Post by moonchild »

bzt wrote:
nullplan wrote:For example, GCC compiled C code can make calls to libgcc functions, and calls to memcpy, memmove, or memcmp. So something must implement those. And at least the mem* functions aren't going to fall from the sky.
In freestanding mode without optimization, no C compiler will make such calls (neither gcc, nor Clang, nor TCC, nor MSVC etc.).
I submit for your perusal: http://ix.io/2AK5
nexos
Member
Member
Posts: 1078
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

Re: Languages for standalone

Post by nexos »

@moonchild, does it do the same with -ffreestanding?
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
moonchild
Member
Member
Posts: 73
Joined: Wed Apr 01, 2020 4:59 pm
Libera.chat IRC: moon-child

Re: Languages for standalone

Post by moonchild »

Yes.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: Languages for standalone

Post by Solar »

--no-builtin...?!?

This still leaves those functions with "__builtin_..." to be used by the compiler for efficiency, but I am not quite clear on how this qualifies as "required runtime support".
Every good solution is obvious once you've found it.
nullplan
Member
Member
Posts: 1766
Joined: Wed Aug 30, 2017 8:24 am

Re: Languages for standalone

Post by nullplan »

Solar wrote:--no-builtin...?!?
No change. But, why would you think this would solve the problem? --no-builtin prevents the compiler from recognizing builtin functions as such, unless they use the __builtin_ prefix. Or at least that is what it is documented to do. But first of all, there is no call to memcpy() in the source code, so there is nothing for the compiler to recognize, and second of all, if the compiler fails to inline a memory copy without that switch, then it definitely won't start because its recognition of memcpy() as a builtin has been turned off.

By the way, I have refined the idea a bit. According to godbolt, the following version calls memcpy() on all optimization levels:

Code: Select all

struct block { char c[1024];};

struct block blockcopy(struct block y)
{
    return y;
}
Solar wrote:This still leaves those functions with "__builtin_..." to be used by the compiler for efficiency, but I am not quite clear on how this qualifies as "required runtime support".
I am currently unclear on what qualifies as that at all. Apparently libraries don't, or at least that is my understanding from this thread. That means that essentially all compiled languages qualify as standalone languages, since all of them merely require a library to provide the necessary support functions. And a loader to setup the environment, which is apparently also permissible. So the only things that don't qualify as standalone languages are things like Java, which require ongoing support from an interpreter (post 1.5, Java cannot be compiled ahead of time anymore). And even those have been made to run operating systems. I know of a few Java, Perl, and LISP operating systems. Those pretty much just ported the interpreter onto bare metal and ran with that.
Carpe diem!
User avatar
eekee
Member
Member
Posts: 872
Joined: Mon May 22, 2017 5:56 am
Location: Kerbin
Discord: eekee
Contact:

Re: Languages for standalone

Post by eekee »

PeterX wrote:- Can Go?
Go was initially released without the capacity for dynamic linking at all. Its authors initially argued against adding it. I don't know what the current situation is, having lost interest after a couple of years.
Kaph — a modular OS intended to be easy and fun to administer and code for.
"May wisdom, fun, and the greater good shine forth in all your work." — Leo Brodie
User avatar
bzt
Member
Member
Posts: 1584
Joined: Thu Oct 13, 2016 4:55 pm
Contact:

Re: Languages for standalone

Post by bzt »

eekee wrote:
PeterX wrote:- Can Go?
Go was initially released without the capacity for dynamic linking at all. Its authors initially argued against adding it. I don't know what the current situation is, having lost interest after a couple of years.
I've just found this: https://github.com/icexin/eggos

The loader is written in Asm and C (which is stolen from XV6, all licensing and attributions removed... so the developer is a d*ck), but the kernel's main function (and everything else) is written in Go. It has lots of runtime dependencies (like the GC for example), but looks like everything has been implemented to run a Go application natively.
Go's runtime provides some basic operating system abstractions. Goroutine corresponds to processes and channel corresponds to inter-process communication. In addition, go has its own virtual memory management, so the idea of running Go programs on bare metal was born.
Cheers,
bzt
User avatar
eekee
Member
Member
Posts: 872
Joined: Mon May 22, 2017 5:56 am
Location: Kerbin
Discord: eekee
Contact:

Re: Languages for standalone

Post by eekee »

Ah, it's finally happened. :) Go was conceived as a systems language to rival C++, so it's not really a surprise to me. (C++ programmers didn't want it, which surprised the Go team early on, but they adapted to its adoption as a web-dev language.) In fact, the toolchain early-on included a bare-metal target. I forget if it was x86 or ARM. This was before gcc-go, back when Go was written in C and came with C compilers related to Plan 9's. And the optimizer was in the linker. If I liked the language, I'd consider forking that early toolchain and calling it Stop. ;) In fact, I did consider much the same architecture: goroutines as processes and channels for IPC. My IPC plans still bear a resemblance to channels, and I haven't forgotten the phrase, "Don't share memory to communicate, communicate to share memory."
Kaph — a modular OS intended to be easy and fun to administer and code for.
"May wisdom, fun, and the greater good shine forth in all your work." — Leo Brodie
User avatar
bzt
Member
Member
Posts: 1584
Joined: Thu Oct 13, 2016 4:55 pm
Contact:

Re: Languages for standalone

Post by bzt »

sj95126 wrote:Technically, mine does use code that's not of my own creation by using the builtin va_* functions for the kprintf() I wrote
Okay, va_* functions are a completely different kind of beasts. No portable solution exists with macros unless the compiler provides va_* builtins. I've spent a month with that problem, and ended up with this stdarg.h. Luckily such builtins are implemented in all C compilers.
sj95126 wrote:but gcc is inlining whatever code it adds. There are no function calls generated.
You can't know that! Not all architecture implements va as pointers! For example on AArch64 you can't pass a NULL list. Since this problem appeared with both Clang and gcc, I assume this has something to do with the va ABI implemented as a function and not as a pointer. Don't take for granted that all va_* will be inlined (or that va_arg is actually a pointer dereference) on all architectures!
sj95126 wrote:I didn't say it was practical, just possible.
Yep, that's correct :-) But there are other CPU functions that rely on a stack: exceptions, interrupts etc. so the actual usability of a stack-less single main() is highly questionable. But possible :-)

Cheers,
bzt
User avatar
eekee
Member
Member
Posts: 872
Joined: Mon May 22, 2017 5:56 am
Location: Kerbin
Discord: eekee
Contact:

Re: Languages for standalone

Post by eekee »

You know, I don't think Plain English Programming has much runtime. The package you get includes just 5 files of source, and that's sufficient to rebuild itself. To build other programs with it, you only need to include one of those files. In other words, the entire language runtime is in one file.

On the negative side, all the low-level stuff is in machine code, represented in hex, but you won't have to touch most of it, it's broken up into very short pieces, and there are only 1841 bytes of machine code in total. There's probably more in the compiler, but you'd only have to touch the part where the executable is put together, which I'm certain is as simple as possible. It doesn't have a separate linker. (It's x86/32 only.)

https://osmosianplainenglishprogramming.blog/

I find it much easier to learn than other languages. I find Forth fairly easy to learn too, but the stack management often gets to be a headache even in some simple jobs. Lisp is fairly easy too if I remember right, but PEP is actually closer to the machine than Lisp is.
Kaph — a modular OS intended to be easy and fun to administer and code for.
"May wisdom, fun, and the greater good shine forth in all your work." — Leo Brodie
User avatar
bloodline
Member
Member
Posts: 264
Joined: Tue Sep 15, 2020 8:07 am
Location: London, UK

Re: Languages for standalone

Post by bloodline »

eekee wrote:You know, I don't think Plain English Programming has much runtime. The package you get includes just 5 files of source, and that's sufficient to rebuild itself. To build other programs with it, you only need to include one of those files. In other words, the entire language runtime is in one file.

https://osmosianplainenglishprogramming.blog/
Goodness! This looks like a fun language, I’ve never heard of it before, thanks for sharing. I’ll have fun reading about this language later :D
CuriOS: A single address space GUI based operating system built upon a fairly pure Microkernel/Nanokernel. Download latest bootable x86 Disk Image: https://github.com/h5n1xp/CuriOS/blob/main/disk.img.zip
Discord:https://discord.gg/zn2vV2Su
Post Reply