digitalmars.D.learn - Reducing source code: weak+alias values in array
- Jens Bauer (39/39) Apr 27 2015 I was wondering if there's a way to reduce my bulky startup files
- Artur Skawina via Digitalmars-d-learn (45/83) Apr 29 2015 Just create a helper module, which the startup files can all
- Jens Bauer (7/19) Apr 29 2015 That is very cool and quite short. Thank you!
- Jens Bauer (47/52) May 01 2015 {snip}
- Artur Skawina via Digitalmars-d-learn (14/36) May 01 2015 My fault; I only looked at the generated code, but never actually tested...
- Jens Bauer (26/44) May 01 2015 Here's my resulting code-snippet:
- Jens Bauer (13/26) May 01 2015 For some reason, my build time has increased dramatically...
- Jens Bauer (3/13) May 01 2015 Here's the source code for the file I'm building:
- Artur Skawina via Digitalmars-d-learn (10/25) May 02 2015 Apparently CTFE can be very inefficient sometimes -- compiler
- Jens Bauer (10/32) May 02 2015 I'll try and make a few experiments to see if there's something
I was wondering if there's a way to reduce my bulky startup files a bit. If using the GNU Assembler (GAS), then one can reduce the code using a macro like this: /* The EXC macro makes a weak+alias for the * symbol 'value', then it stores the value in memory: */ .macro EXC value,defaultValue .ifnb \defaultValue .weakref \value,\defaultValue .else .weakref \value,defaultExceptionVector .endif .4byte \value .endm /* The exception vector now looks quite simple: */ isr_vector: .4byte _stack EXC Reset_Handler,defaultResetHandler EXC NMI_Handler EXC HardFault_Handler EXC MemManage_Handler EXC BusFault_Handler EXC UsageFault_Handler .4byte 0 .4byte 0 .4byte 0 .4byte 0 EXC SVC_Handler EXC DebugMon_Handler .4byte 0 EXC PendSV_Handler EXC SysTick_Handler An example on one of my bulky startup files: https://github.com/jens-gpio/MCU/blob/master/startup/stm/stm32f439_startup.d I was thinking about alias (Tuple) or similar, but I'm not sure it would work if not declaring the label weak+alias in advance. Any thoughts ? (Other suggestions on how to reduce the source code size are also welcome).
Apr 27 2015
On 04/27/15 19:49, Jens Bauer via Digitalmars-d-learn wrote:I was wondering if there's a way to reduce my bulky startup files a bit. If using the GNU Assembler (GAS), then one can reduce the code using a macro like this: /* The EXC macro makes a weak+alias for the * symbol 'value', then it stores the value in memory: */ .macro EXC value,defaultValue .ifnb \defaultValue .weakref \value,\defaultValue .else .weakref \value,defaultExceptionVector .endif .4byte \value .endm /* The exception vector now looks quite simple: */ isr_vector: .4byte _stack EXC Reset_Handler,defaultResetHandler EXC NMI_Handler EXC HardFault_Handler EXC MemManage_Handler EXC BusFault_Handler EXC UsageFault_Handler .4byte 0 .4byte 0 .4byte 0 .4byte 0 EXC SVC_Handler EXC DebugMon_Handler .4byte 0 EXC PendSV_Handler EXC SysTick_Handler An example on one of my bulky startup files: https://github.com/jens-gpio/MCU/blob/master/startup/stm/stm32f439_startup.dJust create a helper module, which the startup files can all use to generate the data from a dsl. Eg import my.helper.mod; mixin(VectorFuncs!(q{ PTR stack = {`_stack`}; EXC Reset_Handler = {`defaultResetHandler`}; EXC NMI_Handler; EXC HardFault_Handler; PAD pad01; PAD pad02; //... })); // Then, in my.helper.mod: property /* section("discard.etc")*/ VectorFuncs(string dsl)() { static struct A { struct PTR { string n; property s() {return `cast(VectorFunc)&`~n;} } struct PAD { string n; property s() {return `cast(VectorFunc)null`;} } struct EXC { string n = `defaultExceptionHandler`; property s() {return null;} } mixin(dsl); } string code; foreach (I, M; A.init.tupleof) static if (is(typeof(M)==A.EXC)) code ~= ` weakalias("`~M.n~`") extern (C) void ` ~ __traits(identifier, A.tupleof[I]) ~ "();\n"; code ~= "\n isr_vector VectorFunc[] g_pfnVectors = [\n"; foreach (I, M; A.init.tupleof) code ~= " " ~ (M.s?M.s:"&"~__traits(identifier, A.tupleof[I])) ~ ",\n"; code ~= "];\n"; return code; } and what the compiler will see when building the startup modules will look like weakalias("defaultResetHandler") extern (C) void Reset_Handler(); weakalias("defaultExceptionHandler") extern (C) void NMI_Handler(); weakalias("defaultExceptionHandler") extern (C) void HardFault_Handler(); isr_vector VectorFunc[] g_pfnVectors = [ cast(VectorFunc)&_stack, &Reset_Handler, &NMI_Handler, &HardFault_Handler, cast(VectorFunc)null, cast(VectorFunc)null, ]; artur
Apr 29 2015
On Wednesday, 29 April 2015 at 13:58:14 UTC, Artur Skawina wrote:On 04/27/15 19:49, Jens Bauer via Digitalmars-d-learn wrote:{snip}I was wondering if there's a way to reduce my bulky startup files a bit. If using the GNU Assembler (GAS), then one can reduce the code using a macro like this:That is very cool and quite short. Thank you! I'll try it out ... I'm already starting to understand some of what's going on, but it'll probably be clearer when I've typed the code (I do not just do copy-and-paste, as I've found out that I learn better by forcing each letter through my brain).An example on one of my bulky startup files: https://github.com/jens-gpio/MCU/blob/master/startup/stm/stm32f439_startup.dJust create a helper module, which the startup files can all use to generate the data from a dsl. Eg
Apr 29 2015
On Wednesday, 29 April 2015 at 13:58:14 UTC, Artur Skawina wrote:On 04/27/15 19:49, Jens Bauer via Digitalmars-d-learn wrote:{snip}I was wondering if there's a way to reduce my bulky startup files a bit.Just create a helper module, which the startup files can all use to generate the data from a dsl. Eg{snip} I've experimented a little with the code, but ran into two minor problems. code ~= ` weakalias("`~M.n~`") extern (C) void ` ~ __traits(identifier, A.tupleof[I]) ~ "();\n"; The above part gives me some problems; I do not know how to create the weakalias. I can make a exc (which defaults to defaultExceptionVector) and rst (which defaults to defaultResetHandler), but I have not yet succeeded in making a universal weakalias. alias Tuple(A...) = A; alias rst = Tuple!(weak, gcc.attribute.attribute("alias", "defaultResetHandler")); alias exc = Tuple!(weak, gcc.attribute.attribute("alias", "defaultExceptionHandler")); ... I tried messing with changing the above code, but no luck so far: code ~= ` weak gcc.attribute.attribute("alias", "`~M.n~`") extern (C) void ` ~ __traits(identifier, A.tupleof[I]) ~ "();\n"; If I modify the above to ... foreach (I, M; A.init.tupleof) { static if (is(typeof(M)==A.RST)) code ~= ` rst extern (C) void ` ~ __traits(identifier, A.tupleof[I]) ~ "();\n"; static if (is(typeof(M)==A.EXC)) code ~= ` exc extern (C) void ` ~ __traits(identifier, A.tupleof[I]) ~ "();\n"; } ... then it will build and produce the expected results. That requires replacing the EXC for the ResetHandler by RST, I like the original code much better, though. :) I also had some trouble with the exception vectors not being generated, and it turned out that my array was dynamic instead of static. For now, I've just made the array a constant size (100 elements); eg. changed ... code ~= "\n isr_vector VectorFunc[] g_pfnVectors = [\n"; ... to ... code ~= "\n isr_vector VectorFunc[100] g_pfnVectors = [\n"; ... Is it possible to generate a static array without specifying a fixed array size ? Apart from the above two mentioned problems, the code builds and produces the expected results. I even started to understand some parts of it, and I find it pretty awesome. ;)
May 01 2015
On 05/01/15 22:29, Jens Bauer via Digitalmars-d-learn wrote:On Wednesday, 29 April 2015 at 13:58:14 UTC, Artur Skawina wrote:My fault; I only looked at the generated code, but never actually tested it. Use ` weakalias!"blah"` instead: enum weakalias(string A) = gcc.attribute.attribute("alias", A); weakalias!"defaultResetHandler" extern (C) void Reset_Handler();On 04/27/15 19:49, Jens Bauer via Digitalmars-d-learn wrote:{snip}I was wondering if there's a way to reduce my bulky startup files a bit.Just create a helper module, which the startup files can all use to generate the data from a dsl. Eg{snip} I've experimented a little with the code, but ran into two minor problems. code ~= ` weakalias("`~M.n~`") extern (C) void ` ~ __traits(identifier, A.tupleof[I]) ~ "();\n"; The above part gives me some problems; I do not know how to create the weakalias.I also had some trouble with the exception vectors not being generated, and it turned out that my array was dynamic instead of static. For now, I've just made the array a constant size (100 elements); eg. changed ... code ~= "\n isr_vector VectorFunc[] g_pfnVectors = [\n"; ... to ... code ~= "\n isr_vector VectorFunc[100] g_pfnVectors = [\n"; ... Is it possible to generate a static array without specifying a fixed array size ?No, but you can just do: code ~= "\n isr_vector VectorFunc[" ~ A.tupleof.length.stringof ~ "] g_pfnVectors = [\n";Apart from the above two mentioned problems, the code builds and produces the expected results. I even started to understand some parts of it, and I find it pretty awesome. ;)(Ab)using the compiler for the DSL parsing gets really awesome once you use other D features like multiple named member initializers, lambdas and/or static-ifs etc /inside/ the DSL. Next thing you know you'll be using DSLs that generate other DSLs that emit plain D code, with a few layers of expression templates in between... :) artur
May 01 2015
On Friday, 1 May 2015 at 21:36:29 UTC, Artur Skawina wrote:On 05/01/15 22:29, Jens Bauer via Digitalmars-d-learn wrote:Here's my resulting code-snippet: enum weak = gcc.attribute.attribute("weak"); alias Tuple(A...) = A; alias weakalias(string A) = Tuple!(weak, gcc.attribute.attribute("alias", A)); ... foreach (I, M; A.init.tupleof) { static if (is(typeof(M)==A.EXC)) code ~= ` weakalias!"`~M.n~`" extern (C) void ` ~ __traits(identifier, A.tupleof[I]) ~ "();\n"; } ... because the 'alias' attribute does not automcatically include the 'weak' attribute. It seems to work, but did I write the code correctly ?On Wednesday, 29 April 2015 at 13:58:14 UTC, Artur Skawina wrote:Use ` weakalias!"blah"` instead: enum weakalias(string A) = gcc.attribute.attribute("alias", A); weakalias!"defaultResetHandler" extern (C) void Reset_Handler();That works great. Thank you for your valuable help. :)... Is it possible to generate a static array without specifying a fixed array size ?No, but you can just do: code ~= "\n isr_vector VectorFunc[" ~ A.tupleof.length.stringof ~ "] g_pfnVectors = [\n";I remember the Atari 130XE (and thus the Atari 600XL/800XL) were able to auto-generate basic-code, saving a lot of typing. Though different, this really reminds me of those days. :) I've never touched a C++ template, but I've been using #define in C. Though #define is a neat feature, it does not beat this, and as I've never had enough reason to use C++ templates, I expect they're not as powerful as D's ability to generate code at compile-time.Apart from the above two mentioned problems, the code builds and produces the expected results. I even started to understand some parts of it, and I find it pretty awesome. ;)(Ab)using the compiler for the DSL parsing gets really awesome {snip}
May 01 2015
On 04/27/15 19:49, Jens Bauer via Digitalmars-d-learn wrote:On Wednesday, 29 April 2015 at 13:58:14 UTC, Artur Skawina wrote:I was wondering if there's a way to reduce my bulky startup files a bit.mixin(VectorFuncs!(q{ PTR stack = {`_stack`}; EXC Reset_Handler = {`defaultResetHandler`}; EXC NMI_Handler; EXC HardFault_Handler; PAD pad01; PAD pad02; //... }));For some reason, my build time has increased dramatically... Building with 1 vector takes 0.6 seconds. Building with 2 vector takes 0.7 seconds. Building with 4 vector takes 0.9 seconds. Building with 8 vector takes 1.1 seconds. Building with 16 vectors takes 1.7 seconds. Building with 32 vectors takes 3.4 seconds. Building with 64 vectors takes 12.4 seconds. Building with 112 vectors takes 55.5 seconds. Building with 113 vectors takes 56.7 seconds. ... Two foreach loops shouldn't take that long, right ? The generated code appears to be correct, though.
May 01 2015
On Saturday, 2 May 2015 at 03:21:38 UTC, Jens Bauer wrote:For some reason, my build time has increased dramatically... Building with 1 vector takes 0.6 seconds. Building with 2 vector takes 0.7 seconds. Building with 4 vector takes 0.9 seconds. Building with 8 vector takes 1.1 seconds. Building with 16 vectors takes 1.7 seconds. Building with 32 vectors takes 3.4 seconds. Building with 64 vectors takes 12.4 seconds. Building with 112 vectors takes 55.5 seconds. Building with 113 vectors takes 56.7 seconds.Here's the source code for the file I'm building: http://pastebin.com/pCh9e7hQ
May 01 2015
On 05/02/15 05:28, Jens Bauer via Digitalmars-d-learn wrote:On Saturday, 2 May 2015 at 03:21:38 UTC, Jens Bauer wrote:Apparently CTFE can be very inefficient sometimes -- compiler issue. Can't think of a workaround right now; manually parsing (instead of using mixins) might help, but that would make the solution less obvious...For some reason, my build time has increased dramatically... Building with 1 vector takes 0.6 seconds. Building with 2 vector takes 0.7 seconds. Building with 4 vector takes 0.9 seconds. Building with 8 vector takes 1.1 seconds. Building with 16 vectors takes 1.7 seconds. Building with 32 vectors takes 3.4 seconds. Building with 64 vectors takes 12.4 seconds. Building with 112 vectors takes 55.5 seconds. Building with 113 vectors takes 56.7 seconds.Here's the source code for the file I'm building: http://pastebin.com/pCh9e7hQFor some reason I was never really affected by the horrible CTFE perf. For example, your code from that link, after a few tweaks to get it to build, compiles in ~3s for me. (64 bit x86 linux gdc build) artur
May 02 2015
On Saturday, 2 May 2015 at 13:08:27 UTC, Artur Skawina wrote:On 05/02/15 05:28, Jens Bauer via Digitalmars-d-learn wrote:I'll try and make a few experiments to see if there's something that helps speeding it up.On Saturday, 2 May 2015 at 03:21:38 UTC, Jens Bauer wrote:Apparently CTFE can be very inefficient sometimes -- compiler issue. Can't think of a workaround right now; manually parsing (instead of using mixins) might help, but that would make the solution less obvious...For some reason, my build time has increased dramatically... Building with 1 vector takes 0.6 seconds. Building with 2 vector takes 0.7 seconds. Building with 4 vector takes 0.9 seconds. Building with 8 vector takes 1.1 seconds. Building with 16 vectors takes 1.7 seconds. Building with 32 vectors takes 3.4 seconds. Building with 64 vectors takes 12.4 seconds. Building with 112 vectors takes 55.5 seconds. Building with 113 vectors takes 56.7 seconds.That's quick. I'd expect your computer to be a bit faster than mine. ;) I have a QuadCore 2.5GHz PowerMac G5. But I'll also be building on a Dual 2GHz ARM Cortex-A7 based CubieBoard2 if I succeed building a D compiler for it; this. I think it's important for the user that the compilation time is kept low, because many people will be building on Cortex-A based devices.http://pastebin.com/pCh9e7hQFor some reason I was never really affected by the horrible CTFE perf. For example, your code from that link, after a few tweaks to get it to build, compiles in ~3s for me. (64 bit x86 linux gdc build)
May 02 2015