Page 2 of 4
Re: Languages for standalone
Posted: Tue Oct 13, 2020 8:49 pm
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.
Re: Languages for standalone
Posted: Wed Oct 14, 2020 12:08 pm
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.
Re: Languages for standalone
Posted: Wed Oct 14, 2020 12:56 pm
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.
Re: Languages for standalone
Posted: Wed Oct 14, 2020 1:10 pm
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.
Re: Languages for standalone
Posted: Wed Oct 14, 2020 5:24 pm
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
Re: Languages for standalone
Posted: Wed Oct 14, 2020 7:16 pm
by nexos
@moonchild, does it do the same with -ffreestanding?
Re: Languages for standalone
Posted: Wed Oct 14, 2020 11:13 pm
by moonchild
Yes.
Re: Languages for standalone
Posted: Thu Oct 15, 2020 12:34 am
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".
Re: Languages for standalone
Posted: Thu Oct 15, 2020 8:33 am
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.
Re: Languages for standalone
Posted: Mon Oct 19, 2020 5:16 pm
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.
Re: Languages for standalone
Posted: Thu Oct 22, 2020 10:16 am
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
Re: Languages for standalone
Posted: Fri Oct 23, 2020 12:40 pm
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."
Re: Languages for standalone
Posted: Sun Oct 25, 2020 7:17 am
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
Re: Languages for standalone
Posted: Mon Oct 26, 2020 5:38 am
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.
Re: Languages for standalone
Posted: Mon Oct 26, 2020 5:56 am
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