June 02, 2022

On Wednesday, 1 June 2022 at 14:08:24 UTC, Ola Fosheim Grøstad wrote:

>

The most sensible is to let local functions be syntax sugar for lambdas. Just make delegate variables assign-once and initialize-before-use.

I thought so until I implemented them in SDC, and it actually cause many problems. It's not fresh in my mind, so I'm not sure I can make a good case for this at the moment, but there were definitively problems.

That being said, reducing the semantic discrepancy between the two would definitively be a plus.

June 02, 2022

On Thursday, 2 June 2022 at 15:57:36 UTC, deadalnix wrote:

>

That being said, reducing the semantic discrepancy between the two would definitively be a plus.

I hope it can be resolved somehow, getting to some clean core language/high-level-IR can make interprocedural analysis realistic (suggested goal: do whatever it takes to make writing static analysis fun!).

June 02, 2022

On Thursday, 2 June 2022 at 15:15:40 UTC, deadalnix wrote:

>

On Tuesday, 31 May 2022 at 22:48:55 UTC, Don Allen wrote:

>

Well, I would argue that that kind of thinking leads to a language that is a collection of special cases, rather than a language built on a core set of principles consistently applied.

While I agree that sometime, D takes the road of many special cases, if you take a step back, you'll that this really doesn't help your case, to the contrary. You are arguing for special casing function scope to allow out of order symbol resolution in special circumstances.

I said I was done, but this really needs a response because you have gotten what I am talking about completely wrong, particularly in your last sentence above.

I repeat: I am arguing for consistent treatment of the ability to do mutual recursion, regardless of context. If D handled this the C way -- functions must be defined before they can be referenced in another function definition -- and did so in all contexts, I'd be less troubled than I am by the current situation, in which we have one treatment at module and structure level and the opposite within functions.

I could not care less about "helping my case"; my situation involves one inner function calling another, so the functions aren't even mutually recursive, and is easily resolved by just interchanging the order in which the functions are defined. My purpose in writing about this has never been about how to fix my little issue. It's concern about what I consider an error in the language design.

June 02, 2022

On Thursday, 2 June 2022 at 16:45:29 UTC, Ola Fosheim Grøstad wrote:

>

On Thursday, 2 June 2022 at 15:57:36 UTC, deadalnix wrote:

>

That being said, reducing the semantic discrepancy between the two would definitively be a plus.

I hope it can be resolved somehow, getting to some clean core language/high-level-IR can make interprocedural analysis realistic (suggested goal: do whatever it takes to make writing static analysis fun!).

I would like to know what you think about sea of node vs SSA on this front?

I'm looking at significantly changing SDC's IR now that I have a better idea of what it should look like, but I'm not quite sure which of the two would be more suitable.

June 02, 2022

On Thursday, 2 June 2022 at 21:47:06 UTC, deadalnix wrote:

>

I would like to know what you think about sea of node vs SSA on this front?

I'm looking at significantly changing SDC's IR now that I have a better idea of what it should look like, but I'm not quite sure which of the two would be more suitable.

It is very difficult to be sure about anything a priori as it will have to be designed for the passes you want to make, or maybe it should be designed so that it is easy to translate to a specialized IRs, or maybe it should be designed so that your IR can be annotated and extended for future passes that has not been decided upon yet. Many options…

It is important to retain all the type information and constraints so that they can be exploited. One weakness in Clang is that the translation to the LLVM IR has tossed away too much information (type/constraints). Maybe ask yourself if there is some information worth retaining from template expansion, like template constraints? Constraints = opportunities to deduce.

I guess one would want to start by listing the passes you wish to perform and the information you need to do so. Maybe look at what data structures Swift has landed on to support ARC passes? Another thing worth looking at is Boogie, which performs some transforms so that asserts in functions can be resolved (on a lucky day) by an SMT solver.

I wouldn't say you have to do this or that, but a graph of nodes is always the natural option when you want to allow future extensions. You can worry about performance later, I would go for something that is flexible and "bug resistant". Basic blocks can be a single node, if you want, so it might not be an either-or choice. I don't think you will be sure what is right until you write some passes.

Maybe start with something minimal (for a language subset) and try to write som passes for that minimal subset, then you get a feel for what you need. I think I would do that, so you can try different options with lower costs.

June 02, 2022

On Thursday, 2 June 2022 at 22:36:55 UTC, Ola Fosheim Grøstad wrote:

>

It is important to retain all the type information and constraints so that they can be exploited. One weakness in Clang is that the translation to the LLVM IR has tossed away too much information (type/constraints). Maybe ask yourself if there is some information worth retaining from template expansion, like template constraints? Constraints = opportunities to deduce.

You'll note that LLVM supports keeping that information around, and rust does use this, but C++'s semantic make it effectively useless for optimization anyways.

>

I guess one would want to start by listing the passes you wish to perform and the information you need to do so. Maybe look at what data structures Swift has landed on to support ARC passes? Another thing worth looking at is Boogie, which performs some transforms so that asserts in functions can be resolved (on a lucky day) by an SMT solver.

I mean, the usual suspect: Combine, CSE, GVN, DCE, simplify CFG, Inlining, etc...

As for an SMT solver, that sound like a good way to destroy your compile time.

BTW, Swift is using an SSA, but without phi nodes, then instead have basic block take arguments and branch instruction take parameters.

>

Maybe start with something minimal (for a language subset) and try to write som passes for that minimal subset, then you get a feel for what you need. I think I would do that, so you can try different options with lower costs.

SDC already has a full mid level IR that supports most of the language.

June 03, 2022

On Thursday, 2 June 2022 at 22:50:30 UTC, deadalnix wrote:

>

As for an SMT solver, that sound like a good way to destroy your compile time.

Yes, but you can cache results and compile in the background while editing and also add an option for distributed analysis (cloud solution). Most function bodies dont change frequently. All you want to cache is a list of asserts that have been proven and what that proof depends on. Besides, this is just a release optimization...

>

BTW, Swift is using an SSA, but without phi nodes, then instead have basic block take arguments and branch instruction take parameters.

Maybe tell the Swift people that you are considering something similar and ask them if they feel that the Swift IR is flexible enough, basically ask about the limitations they have seen.

>

SDC already has a full mid level IR that supports most of the language.

So, if that is simple enough after template expansion, then that would be sufficient for Boogie. Then maybe Swift is not a bad starting point if you can get some info from the Swift people.

June 03, 2022

On Friday, 3 June 2022 at 06:42:29 UTC, Ola Fosheim Grøstad wrote:

>

On Thursday, 2 June 2022 at 22:50:30 UTC, deadalnix wrote:

>

As for an SMT solver, that sound like a good way to destroy your compile time.

Yes, but you can cache results and compile in the background while editing and also add an option for distributed analysis (cloud solution). Most function bodies dont change frequently. All you want to cache is a list of asserts that have been proven and what that proof depends on. Besides, this is just a release optimization...

Anyway, this shouldn't be a priority, just make sure it is possible at a later stage. While it sounds heavy (and is), keep in mind that this can be used selectively on bottle necks or simple functions with many asserts. And since many D users seem to favour releasing with asserts in then this could be that one thing that makes SDC faster.

Also if an assert is proven and removed, then it can be assumed to hold in LLVM passes.

I guess we also could say that SDC isn't competing to win users at this stage, it is competing with DMD, GDC and LDC for the attention of D-users interested in compilers.

June 03, 2022

On Wednesday, 1 June 2022 at 00:17:50 UTC, Timon Gehr wrote:

>

There are local functions in C?

Yes.

June 03, 2022

On Friday, 3 June 2022 at 14:46:29 UTC, Iain Buclaw wrote:

>

On Wednesday, 1 June 2022 at 00:17:50 UTC, Timon Gehr wrote:

>

There are local functions in C?

Yes.

Indeed, both GCC and clang implement this, but it's non standard.

The way it is implemented is really interesting, as it doesn't generate delegate, but proper function pointers with JITted trampolines.