digitalmars.D - Minimal druntime?
- Ethan (23/23) Jul 27 2019 This is another thing I see in hushed tones around here. So all
- Jonathan M Davis (3/26) Jul 27 2019 It sounds to me like what you want is -betterC.
- rikki cattermole (35/38) Jul 27 2019 Indeed.
- Ethan (13/14) Jul 27 2019 It's kind of not though.
- Kagamin (4/4) Jul 27 2019 I use this: http://dpaste.com/13HWHT0
- Jonathan M Davis (32/46) Jul 27 2019 Personally, I'd pretty much only use -betterC to help port a C/C++ libra...
- IGotD- (12/36) Jul 27 2019 I agree, why limit the D language. Always viewed -betterC as an
- JN (6/12) Jul 28 2019 I think the main appeal of betterC right now is that it's very
- Paulo Pinto (10/25) Jul 28 2019 For the same reason that C++ needs a C like subset when you want
- Ethan (13/15) Jul 28 2019 ...are you talking about extern "C" there? Because that's not at
- Paulo Pinto (5/20) Jul 28 2019 I am referring to the ISO C89 subset of the ISO C++98 programming
- Ethan (12/16) Jul 28 2019 Okay, but you understand that C++ was specifically designed as a
- Paulo Pinto (10/27) Jul 28 2019 So here goes another example, disabling exceptions and RTTI,
- Ethan (22/32) Jul 29 2019 Exceptions basically cost nothing on x64 these days. Structured
- Paulo Pinto (9/43) Jul 29 2019 To show that also C++ does not follow some high standard that
- Mike Franklin (37/41) Jul 28 2019 I generally agree and have facetiously referred to betterC as
- Mike Franklin (4/6) Jul 28 2019 Yeah, if only computers could actually think. Of course, I meant
- Mike Franklin (62/64) Jul 27 2019 This is the most minimal runtime you can use:
- Ethan (8/17) Jul 27 2019 Cheers. That's still a good start.
This is another thing I see in hushed tones around here. So all in one place, the information goes. Here's the short story for my plans for the runtime component of Smithy: extern( C++ ) all the things. Shipping Quantum Break showed me one thing: Certification processes will stop you dead in your tracks if any given platform holder's code analysis tools can't understand what your code is doing. This slots neatly in with my DMD/LDC on mobile post. If I extern( C++ ) all the things, and avoid core and std, then I should be able to write code that doesn't even need a heavy druntime initialisation. Perhaps not even an init at all. I just want to write code at that point that doesn't use typeinfo, moduleinfo, etc. Binderoo won't be linked for example, I intend on making a library that for all intents and purposes looks like it was written in C++ to every compiler in use on the platforms I'll be targeting. Making the compiler not link phobos should be easy. But the compiler expects to find druntime so it can include all its little hooks for arrays etc. So. Is there a working minimal druntime out there? Or a process that can be applied for any given DMD release?
Jul 27 2019
On Saturday, July 27, 2019 6:51:23 AM MDT Ethan via Digitalmars-d wrote:This is another thing I see in hushed tones around here. So all in one place, the information goes. Here's the short story for my plans for the runtime component of Smithy: extern( C++ ) all the things. Shipping Quantum Break showed me one thing: Certification processes will stop you dead in your tracks if any given platform holder's code analysis tools can't understand what your code is doing. This slots neatly in with my DMD/LDC on mobile post. If I extern( C++ ) all the things, and avoid core and std, then I should be able to write code that doesn't even need a heavy druntime initialisation. Perhaps not even an init at all. I just want to write code at that point that doesn't use typeinfo, moduleinfo, etc. Binderoo won't be linked for example, I intend on making a library that for all intents and purposes looks like it was written in C++ to every compiler in use on the platforms I'll be targeting. Making the compiler not link phobos should be easy. But the compiler expects to find druntime so it can include all its little hooks for arrays etc. So. Is there a working minimal druntime out there? Or a process that can be applied for any given DMD release?It sounds to me like what you want is -betterC. - Jonathan M Davis
Jul 27 2019
On 28/07/2019 1:11 AM, Jonathan M Davis wrote:It sounds to me like what you want is -betterC. - Jonathan M DavisIndeed. E.g. extern(C) void main() { Foo foo = create!Foo; foo.func(); } extern(C++) class Foo { int x; float y; this() { } this(int x) { this.x = x; } void func() { import core.stdc.stdio : printf; printf("Hello!\n"); printf("x = %d\n", x); printf("y = %f\n", y); } } T create(T, Args...)(Args args) { import core.stdc.stdlib : malloc; __gshared T Default = new T; enum Size = __traits(classInstanceSize, T); void* raw = cast(void*)Default; void* newRaw = malloc(Size); newRaw[0 .. Size] = raw[0 .. Size]; T ret = cast(T)newRaw; static if (__traits(hasMember, T, "__ctor")) { ret.__ctor(args); } return ret; }
Jul 27 2019
On Saturday, 27 July 2019 at 13:11:23 UTC, Jonathan M Davis wrote:It sounds to me like what you want is -betterC.It's kind of not though. I don't want a subset of D, I want DMD to not inject things in to my library that I just plain won't use. I'd already considered -betterC, and immediately decided it was going to be too much hassle after writing one line and finding out the compiler doesn't agree with my coding style. The code is going to compile with and without -betterC, which itself is a massive undertaking at this point. I've got a related point about the Unity guys writing High This exact argument is what I have about -betterC. If D is so good, why do I need a subset of it?
Jul 27 2019
I use this: http://dpaste.com/13HWHT0 This is posix version for ldc 1.4, no -betterC, not sure if it compiles with -betterC. Runtime was compiler specific until recently, not sure if it was fixed.
Jul 27 2019
On Saturday, July 27, 2019 8:20:52 AM MDT Ethan via Digitalmars-d wrote:On Saturday, 27 July 2019 at 13:11:23 UTC, Jonathan M Davis wrote:Personally, I'd pretty much only use -betterC to help port a C/C++ library or program to D. I sure wouldn't want to use a stripped down version of D normally. But if you want to avoid stuff like TypeInfo, or you want your library to just look like it's basically C/C++, then that's the direction you're going. To fully use D's features, you need druntime with everything that it does. In theory, druntime could be improved to be more pay-as-you-go than it is, and work is slowly being done in that area, but what druntime does really does provide language functionality, and trying to avoid parts of it basically means avoiding language functionality. It's not like D's features all come for free. I actually think that -betterC is mostly a waste of time, because I don't see enough benefit in using a stripped down version of D over just using C++ to bother, but it definitely can have benefits when porting code, and some people seem to think that it's the way to go, much as I really don't understand that. However, D _is_ a general purpose programming language, and different people have different constraints that they operate under. For the vast majority of programs, what druntime does isn't a big deal at all. Complaints over stuff like D using a GC are mostly unreasonable. But there are domains where it's more problematic than is normally the case (games being one of those, because they typically can't afford the delays from the stop-the-world GC), and when you're in that kind of environment, you do potentially need to avoid aspects of D (and would presumably have to do something similar with around some of the downsides rather than just using the language like most people would (e.g. having a separate thread that the GC has no control over to deal with real-time stuff or specifically disabling the GC in certain sections of code). And in general, when having multiple languages interact, things can get a bit entertaining and potentially require avoiding aspects of D. - Jonathan M DavisIt sounds to me like what you want is -betterC.It's kind of not though. I don't want a subset of D, I want DMD to not inject things in to my library that I just plain won't use. I'd already considered -betterC, and immediately decided it was going to be too much hassle after writing one line and finding out the compiler doesn't agree with my coding style. The code is going to compile with and without -betterC, which itself is a massive undertaking at this point. I've got a related point about the Unity guys writing High This exact argument is what I have about -betterC. If D is so good, why do I need a subset of it?
Jul 27 2019
On Saturday, 27 July 2019 at 17:57:07 UTC, Jonathan M Davis wrote:On Saturday, July 27, 2019 8:20:52 AM MDT Ethan via Digitalmars-d wrote:I agree, why limit the D language. Always viewed -betterC as an intermediate step until the "pay for what you use" implementation is in place. For most embedded systems type/module info and so on isn't really much of a problem other those really memory limited targets. I regard the type/module info a great help actually even for bare metal targets. What is the problem is the dependency to an operating system and how to make this more flexible. Hopefully in the future we can decouple the runtime language features (like classes) which doesn't really need OS support from things in the runtime that needs OS support.On Saturday, 27 July 2019 at 13:11:23 UTC, Jonathan M Davis wrote:Personally, I'd pretty much only use -betterC to help port a C/C++ library or program to D. I sure wouldn't want to use a stripped down version of D normally. But if you want to avoid stuff like TypeInfo, or you want your library to just look like it's basically C/C++, then that's the direction you're going. To fully use D's features, you need druntime with everything that it does. In theory, druntime could be improved to be more pay-as-you-go than it is, and work is slowly being done in that area, but what druntime does really does provide language functionality, and trying to avoid parts of it basically means avoiding language functionality. It's not like D's features all come for free. I actually think that -betterC is mostly a waste of time, because I don't see enough benefit in using a stripped down version of D over just using C++ to bother, but it definitely can have benefits when porting code, and some people seem to think that it's the way to go, much as I really don't understand that. - Jonathan M DavisIt sounds to me like what you want is -betterC.
Jul 27 2019
On Saturday, 27 July 2019 at 17:57:07 UTC, Jonathan M Davis wrote:I actually think that -betterC is mostly a waste of time, because I don't see enough benefit in using a stripped down version of D over just using C++ to bother, but it definitely can have benefits when porting code, and some people seem to think that it's the way to go, much as I really don't understand that.I think the main appeal of betterC right now is that it's very portable and offers new opportunities. Want to do web with D? Only BetterC can compile to WebAssembly at the moment. Want to do embedded? Usually only BetterC will be supported. Want to do mobile? In many cases it's betterC only.
Jul 28 2019
On Saturday, 27 July 2019 at 14:20:52 UTC, Ethan wrote:On Saturday, 27 July 2019 at 13:11:23 UTC, Jonathan M Davis wrote:For the same reason that C++ needs a C like subset when you want to extract the ultimate performance out of it. Magical compiler optimizers able to generate the perfect Assembly and cache usage no matter what comes to the mind of the lazy developer are still a dream pipe. Any programming language that cares about performance needs a performance oriented subset, for the use cases when the high level constructors don't deliver the desired performance and the optimizer just throws its hands up in the air.It sounds to me like what you want is -betterC.It's kind of not though. I don't want a subset of D, I want DMD to not inject things in to my library that I just plain won't use. I'd already considered -betterC, and immediately decided it was going to be too much hassle after writing one line and finding out the compiler doesn't agree with my coding style. The code is going to compile with and without -betterC, which itself is a massive undertaking at this point. I've got a related point about the Unity guys writing High it? This exact argument is what I have about -betterC. If D is so good, why do I need a subset of it?
Jul 28 2019
On Sunday, 28 July 2019 at 07:32:37 UTC, Paulo Pinto wrote:For the same reason that C++ needs a C like subset when you want to extract the ultimate performance out of it....are you talking about extern "C" there? Because that's not at all how extern "C" works in a C++ compiler. was more to do with making sure engine logic and user-facing logic was written in the same language. But it's also not really valid in relation to -betterC, which - as has been mentioned a few times in this thread - is more of a stand-in for "pay what you use of the D runtime" in lieu of DMD actually being able to do that. You don't need -betterC to nogc and do completely manual memory management for example.
Jul 28 2019
On Sunday, 28 July 2019 at 11:07:51 UTC, Ethan wrote:On Sunday, 28 July 2019 at 07:32:37 UTC, Paulo Pinto wrote:I am referring to the ISO C89 subset of the ISO C++98 programming language. which is now updated to the ISO C89 + ISO C11 libraries as of ISO C++17, and will be updated to some C90 language constructs like aggregate initializers in ISO C++20.For the same reason that C++ needs a C like subset when you want to extract the ultimate performance out of it....are you talking about extern "C" there? Because that's not at all how extern "C" works in a C++ compiler. was more to do with making sure engine logic and user-facing logic was written in the same language. But it's also not really valid in relation to -betterC, which - as has been mentioned a few times in this thread - is more of a stand-in for "pay what you use of the D runtime" in lieu of DMD actually being able to do that. You don't need -betterC to nogc and do completely manual memory management for example.
Jul 28 2019
On Sunday, 28 July 2019 at 12:00:19 UTC, Paulo Pinto wrote:I am referring to the ISO C89 subset of the ISO C++98 programming language. which is now updated to the ISO C89 + ISO C11 libraries as of ISO C++17, and will be updated to some C90 language constructs like aggregate initializers in ISO C++20.Okay, but you understand that C++ was specifically designed as a superset of C, right? It's the exact opposite of my point. C++ respective languages. Your point that C is what you use to write faster code than C++ is also misguided. I regularly write much faster code in C++ than I ever could in C thanks to heavy use of inlining and templates. This is even more true historically on (for example) 32-bit Windows systems, where the C ABI was very stack-heavy yet I could use things like __fastcall to call functions with parameters in registers and avoid the stack entirely.
Jul 28 2019
On Sunday, 28 July 2019 at 16:13:10 UTC, Ethan wrote:On Sunday, 28 July 2019 at 12:00:19 UTC, Paulo Pinto wrote:So here goes another example, disabling exceptions and RTTI, which is considered UB as per ISO C++ standard, given that the standard assumes those features cannot be turned off and the standard library (as per ISO C++ document) does require them being present. Or constraing to subsets like Embedded C++ used by Apple's IO Kit. Disabling exceptions and RTTI, coupled with an alternative library like EASTL, or Embedded C++ existance, do follow the sameI am referring to the ISO C89 subset of the ISO C++98 programming language. which is now updated to the ISO C89 + ISO C11 libraries as of ISO C++17, and will be updated to some C90 language constructs like aggregate initializers in ISO C++20.Okay, but you understand that C++ was specifically designed as a superset of C, right? It's the exact opposite of my point. their respective languages. Your point that C is what you use to write faster code than C++ is also misguided. I regularly write much faster code in C++ than I ever could in C thanks to heavy use of inlining and templates. This is even more true historically on (for example) 32-bit Windows systems, where the C ABI was very stack-heavy yet I could use things like __fastcall to call functions with parameters in registers and avoid the stack entirely.
Jul 28 2019
On Sunday, 28 July 2019 at 17:44:38 UTC, Paulo Pinto wrote:So here goes another example, disabling exceptions and RTTI, which is considered UB as per ISO C++ standard, given that the standard assumes those features cannot be turned off and the standard library (as per ISO C++ document) does require them being present. Or constraing to subsets like Embedded C++ used by Apple's IO Kit. Disabling exceptions and RTTI, coupled with an alternative library like EASTL, or Embedded C++ existance, do follow theExceptions basically cost nothing on x64 these days. Structured exception handling hardware support, baybeeeeeee. Leave exceptions on. Either way, if you never try/throw/catch then the code isn't generated. RTTI as well. Don't have virtuals in your objects? You won't get typeinfo code in your resulting binary. Don't dynamic cast? Compiler won't insert dynamic casts. This is the "Pay as you go" thing we continually mention in here. Have all the features. Don't use them? Don't pay for them. are a restrictive subset that for all intents and purposes is a different language made after the fact. Try to use a feature of the full language? Nope, not supported. No pay as you go. Just a compiler error. EASTL? It does not follow the "pay as you go" spirit. EASTL is a drop-in replacement for STL that followed the API as defined, but replaced the awful memory patterns and added extra methods in to it. Extra methods that showed up in C++ 11 standard. Why are you bringing up EASTL? That thing's ancient history and has known bugs that never got fixed. Had to patch some stuff myself many years ago for a project I was shipping.
Jul 29 2019
On Monday, 29 July 2019 at 15:05:15 UTC, Ethan wrote:On Sunday, 28 July 2019 at 17:44:38 UTC, Paulo Pinto wrote:To show that also C++ does not follow some high standard that doesn't do language subsets in specific domains. Good luck having that speech in some C++ communities that use every possible way to "write C with C++ compiler", explicitly turning off compiler features and staying at an arm's length from the standard library. C++Now, CppCon, NDC and Meeting C++ have plenty of talks how to advocate to those communities.So here goes another example, disabling exceptions and RTTI, which is considered UB as per ISO C++ standard, given that the standard assumes those features cannot be turned off and the standard library (as per ISO C++ document) does require them being present. Or constraing to subsets like Embedded C++ used by Apple's IO Kit. Disabling exceptions and RTTI, coupled with an alternative library like EASTL, or Embedded C++ existance, do follow theExceptions basically cost nothing on x64 these days. Structured exception handling hardware support, baybeeeeeee. Leave exceptions on. Either way, if you never try/throw/catch then the code isn't generated. RTTI as well. Don't have virtuals in your objects? You won't get typeinfo code in your resulting binary. Don't dynamic cast? Compiler won't insert dynamic casts. This is the "Pay as you go" thing we continually mention in here. Have all the features. Don't use them? Don't pay for them. They are a restrictive subset that for all intents and purposes is a different language made after the fact. Try to use a feature of the full language? Nope, not supported. No pay as you go. Just a compiler error. EASTL? It does not follow the "pay as you go" spirit. EASTL is a drop-in replacement for STL that followed the API as defined, but replaced the awful memory patterns and added extra methods in to it. Extra methods that showed up in C++ 11 standard. Why are you bringing up EASTL? That thing's ancient history and has known bugs that never got fixed. Had to patch some stuff myself many years ago for a project I was shipping.
Jul 29 2019
On Saturday, 27 July 2019 at 14:20:52 UTC, Ethan wrote:I've got a related point about the Unity guys writing High it? This exact argument is what I have about -betterC. If D is so good, why do I need a subset of it?I generally agree and have facetiously referred to betterC as worseD. betterC is a janky feature added to the compiler because it was too much work to modify the compiler and runtime properly. You can achieve almost the same think by importing druntime, but not link to it; with a few caveats, that's all betterC does. Consider the following minimal D program: --- main.d void main() { } Compile with `dmd -release main.d` and you get this: $ size main text data bss dec hex filename 526835 53168 2672 582675 8e413 main Compare that with an equivalent C program: $ size main text data bss dec hex filename 1274 512 8 1794 702 main Whatever D is adding to the binary is probably unnecessary. In fact, if you modify the above main.d program as... --- main.d extern(C) void _d_dso_registry() {} extern(C) void main() { } ... and then compile and link separate, you get a much more reasonable result: $ dmd -release -c main.d $ gcc test.o -o main $ size main text data bss dec hex filename 1430 544 16 1990 7c6 main Seems to be a lot of room for improvement to achieve a pay-as-you-go experience. There are some of us working to improve the compiler-runtime interface so, hopefully someday, you'll just be able to opt-in to any feature of the language by simply choosing to use it or not. I welcome others to join in and help. Mike
Jul 28 2019
On Monday, 29 July 2019 at 00:30:03 UTC, Mike Franklin wrote:can achieve almost the same think by importing druntime, butYeah, if only computers could actually think. Of course, I meant thing.$ gcc test.o -o mainShould have been `gcc main.o -o main`.
Jul 28 2019
On Saturday, 27 July 2019 at 12:51:23 UTC, Ethan wrote:So. Is there a working minimal druntime out there? Or a process that can be applied for any given DMD release?This is the most minimal runtime you can use: object.d ``` module object; ``` That's right, an empty object.d file. Unfortunately, the compiler still requires an object.d file to exist in order to get a build. I've tried a few pull requests to change that, but they've all failed scrutiny. Assuming you use the above minimal runtime, you can create the following minimal hello world program on Linux. main.d ``` private extern(C) void __d_sys_exit(long arg1) { asm { mov RAX, 60; mov RDI, arg1; syscall; } } private long __d_sys_write(long arg1, in void* arg2, long arg3) { long result; asm { mov RAX, 1; mov RDI, arg1; mov RSI, arg2; mov RDX, arg3; syscall; } return result; } void write(immutable(char)[] text) { __d_sys_write(2, text.ptr, text.length); } private extern(C) void _start() { main(); __d_sys_exit(0); } void main() { write("Hello, World!\n"); } ``` See it in action at https://run.dlang.io/is/Ix22Eo From there, the world's your oyster. Start programming in D, and if the compiler or linker can't find something, either copy it from druntime, or implement your own. I suspect that's not much use to you, but it is indeed the most "minimal runtime". The motivation for using a minimal runtime is to incrementally port D to a new platform and implement only what is needed in a pay-as-you-go fashion. Some of us are slowly improving the experience, but it still has a long way to go. It's MUCH better than it was a few years ago, though. Mike
Jul 27 2019
On Saturday, 27 July 2019 at 14:06:51 UTC, Mike Franklin wrote:This is the most minimal runtime you can use: object.d ``` module object; ``` That's right, an empty object.d file. Unfortunately, the compiler still requires an object.d file to exist in order to get a build. I've tried a few pull requests to change that, but they've all failed scrutiny.Cheers. That's still a good start. I also like the way the compiler is going, by templatising all this stuff. Which should mean that when the job is done it's just a matter of providing your own templates and customising the code gen that way. That'll be a massive help for getting ARC at a compiler level instead of a library solution (assuming it's being done the way I imagine).
Jul 27 2019