This is an archive of the discontinued LLVM Phabricator instance.

ELF: Add +, -, *, / and & to SECTIONS linker script command.
ClosedPublic

Authored by ruiu on Apr 18 2016, 2:04 PM.

Details

Summary

This patch is based heavily on George Rimar's patch
http://reviews.llvm.org/D19221.

In the linker script, you can write expressions to compute addresses.
Currently we only support "+" operator. This adds a few more operators.

Since this patch adds * and /, we need to handle operator precedences
properly. I implemented that using the operator-precedence grammar.

Diff Detail

Repository
rL LLVM

Event Timeline

ruiu updated this revision to Diff 54113.Apr 18 2016, 2:04 PM
ruiu retitled this revision from to ELF: Add +, -, *, / and & to SECTIONS linker script command..
ruiu updated this object.
ruiu added a reviewer: grimar.
ruiu added a subscriber: llvm-commits.
grimar edited edge metadata.Apr 19 2016, 5:10 AM

It was really interesting to debug for me.
But honestly speaking I find my version much more readable.
It does not have recursion, and it is straightforward:
it builds RPN and calculates it, 2 logically separated calls at fact.

Your code works and avoids building intermediate stuff,
but I found 3 call of parseExpr and 3 call of parsePrimary,
all from different places and also recursion involved and makes it hard to debug.
You pass MinPrec which changes because of recursion calls,
Dot is required parameter for each of 3 methods.
That does not look straightforward, in overall feels much more
complicated when debugging non trivial expressions for me.

At the same time both approach should work about the same speed
(and both are very fast), complexity of mine is also O(N),
the fact of building RPN in the middle is greatly improves readability.
Mine version has more code, but that can be solved by placing operators
handlers in one method, like you did.

So I would really prefer mine version here(after few tweaks). You deside.

grimar updated this object.Apr 19 2016, 5:23 AM
grimar edited edge metadata.
ruiu added a comment.Apr 19 2016, 8:01 AM

The operator precedence parsing is a pretty popular parsing technique to parse an operator-precedence grammar. Of course I didn't invent it, and it is not the first time for me to write it; it is a well known and well understood technique which is described in compiler textbooks. It's probably not an unreasonable assumption that readers already know it. I believe that the algorithm is usually the first choice when you are to parse an arithmetic expression, so I wonder why you want to do that differently.

grimar added a comment.EditedApr 19 2016, 8:15 AM
In D19237#405107, @ruiu wrote:

The operator precedence parsing is a pretty popular parsing technique to parse an operator-precedence grammar. Of course I didn't invent it, and it is not the first time for me to write it; it is a well known and well understood technique which is described in compiler textbooks. It's probably not an unreasonable assumption that readers already know it. I believe that the algorithm is usually the first choice when you are to parse an arithmetic expression, so I wonder why you want to do that differently.

I have no doubt its popular and was used in many compilers, I just find this implementation not so straightforward due to lots of cross calls and recursion in compare with my version. And I really see no benefits to use it then.

not so straightforward

ruiu added a comment.Apr 19 2016, 8:45 AM

It uses recursion because the grammar is recursive. Do you find the recursive-descendent parser is hard to read because it uses recursion? Even if your code does not make recursive function calls, you have to handle recursive grammar using some recursive data structure (such as hand-crafted stack rather than call stack.)

Nothing is special in my code, it is a plain operator-precedence parser. If you write a parser for a calculator-ish grammer, and if you don't need a parser tree, then I think that the operator-precedence parser is usually the first choice. It is common technique so readers don't have to take a look at every detail of the code; it can be understood just by reading the comment that this is an operator-precedence grammar, because the implementation is obvious as long as you are familiar with the theory. If we have a reason to create an intermediate representation of an expression, then doing it in your way might make sense, but I think that's not the case.

In D19237#405186, @ruiu wrote:

It uses recursion because the grammar is recursive. Do you find the recursive-descendent parser is hard to read because it uses recursion? Even if your code does not make recursive function calls, you have to handle recursive grammar using some recursive data structure (such as hand-crafted stack rather than call stack.)

Nothing is special in my code, it is a plain operator-precedence parser. If you write a parser for a calculator-ish grammer, and if you don't need a parser tree, then I think that the operator-precedence parser is usually the first choice. It is common technique so readers don't have to take a look at every detail of the code; it can be understood just by reading the comment that this is an operator-precedence grammar, because the implementation is obvious as long as you are familiar with the theory. If we have a reason to create an intermediate representation of an expression, then doing it in your way might make sense, but I think that's not the case.

I can say the same about mine, RPN building and evaluating is also known and used often technique.
I see nothing bad in intermediate representation, it does not waste time to be created as complexity almost lowest possible and
I see no reasons why not to use it when overall readability is improved (IMO).
At the same time I am not sure this worth such long arguing. Lets go with your version if you want.
I`ll keep my opinion about mine one though :)

ruiu added a comment.Apr 19 2016, 9:44 AM

If you are familiar with the both algorithms, then what's the reason to choose the one that needs more data types, more internal data structures and more iterations over the same data? If I were familiar with an algorithm but not with the other, then that could be a reason to choose one from the other, but I were not, then the choice is obvious. This patch is shorter and simpler. (Note that we could create a reverse-polish expression using the operator precedence parser instead of computing the value of an expression, but we wouldn't want to do that because it is redundant.)

In D19237#405288, @ruiu wrote:

If you are familiar with the both algorithms, then what's the reason to choose the one that needs more data types, more internal data structures and more iterations over the same data?

I was not familar with your algorithm when implemented my patch. And after I read about it, reviewed and debugged it, I find my version with more types and more structures much more readable exactly because it has all af that. May be not algorithm itself but at least implementation seems to me much simplier.

In D19237#405288, @ruiu wrote:

This patch is shorter and simpler.

I don't think so.

I have no arguments to continue. My best one was "I think that my version is better" seems not to work, though I really believe so.
Will you commit your one then ?

ruiu added a comment.Apr 19 2016, 10:37 AM

I'll submit this patch since you have signed off. But I'd think you just need time to familiarize yourself with this algorithm, then you'd find this actually simpler to parse arithmetic expressions. This is really a good one. :)

This revision was automatically updated to reflect the committed changes.