Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dialects: riscv-func add initial function call lowering #929

Merged
merged 30 commits into from Jun 1, 2023

Conversation

eymay
Copy link
Contributor

@eymay eymay commented May 8, 2023

together with prologue and epilogue register constraints compliant to conventions.

Integrated this branch with reference to the sasha/workshop-all branch.

Copy link
Member

@superlopuh superlopuh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! There are a few changes from my branch that I was hoping to clean up before merging, could you please address the comments?

xdsl/dialects/riscv_func.py Outdated Show resolved Hide resolved
xdsl/dialects/riscv_func.py Outdated Show resolved Hide resolved
xdsl/transforms/lower_riscv_func.py Outdated Show resolved Hide resolved
xdsl/dialects/riscv.py Outdated Show resolved Hide resolved
xdsl/dialects/riscv.py Outdated Show resolved Hide resolved
@georgebisbas georgebisbas added the dialects Changes on the dialects label May 10, 2023
@superlopuh superlopuh force-pushed the sasha/riscv/riscv-ssa-syscall branch 2 times, most recently from 07524c3 to 876f15a Compare May 13, 2023 10:45
@eymay eymay force-pushed the sasha/riscv/riscv-ssa-syscall branch from 26f3cc4 to 51b2390 Compare May 15, 2023 16:30
Copy link
Member

@superlopuh superlopuh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, code mostly looks good to me, could you please remove the remaining TODOs?

xdsl/xdsl_opt_main.py Outdated Show resolved Hide resolved
xdsl/transforms/lower_riscv_func.py Outdated Show resolved Hide resolved
xdsl/dialects/riscv_func.py Outdated Show resolved Hide resolved
@superlopuh superlopuh deleted the branch xdslproject:main May 17, 2023 10:07
@superlopuh superlopuh closed this May 17, 2023
@superlopuh
Copy link
Member

GitHub automatically deleted the target branch of this PR, and clsoed the PR instead of retargeting it to main. Sorry about that.

@superlopuh superlopuh reopened this May 17, 2023
@superlopuh superlopuh changed the base branch from sasha/riscv/riscv-ssa-syscall to main May 17, 2023 10:35
@eymay eymay force-pushed the sasha/riscv/riscv-ssa-syscall branch from 2ae064f to 7185a6f Compare May 17, 2023 19:42
Copy link
Member

@superlopuh superlopuh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please rebase again?

xdsl/dialects/riscv_func.py Outdated Show resolved Hide resolved
xdsl/dialects/riscv.py Outdated Show resolved Hide resolved
xdsl/dialects/riscv_func.py Outdated Show resolved Hide resolved
xdsl/transforms/lower_riscv_func.py Show resolved Hide resolved
xdsl/dialects/riscv_func.py Show resolved Hide resolved
@eymay eymay force-pushed the sasha/riscv/riscv-ssa-syscall branch from 7185a6f to b8ba98e Compare May 18, 2023 13:56
Copy link
Collaborator

@nazavode nazavode left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks really nice, thanks! Left just one question in review.

if func_op is not None:
assert isinstance(func_op, riscv_func.FuncOp)
if func_op.func_name.data == "main":
# Main does not return, call exit syscall instead
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably I'm missing something here but why main doesn't return?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where would it return to? My understanding is that main is kind of just the entry point to the .text section, and not a "real" function

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

main always returns as a regular function, what happens later depends on the platform. On bare metal it's usually a super simple wrapper (crt0) that takes care of the return value but since we already have syscalls in the mix we are assuming a full fledged OS (e.g.: on linux-gnu is _libc_start_main that also does some flavor of exit syscall). I would say that the compiler has zero knowledge of who's going to invoke main (not really sure it's always true tho...).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...it's a much bigger topic tho, maybe this PR is not the right place to figure it out :) Approving as it is because it's really nice overall.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah no I'd love your input, we don't need to merge it as-is. It seems that we could simplify this PR by removing the syscall special case, if I understand you correctly. At the least, some lever higher than riscv-func could be made to deal with this, maybe the llvm to riscv lowering.

Copy link
Collaborator

@compor compor May 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the truth is somewhere in the middle and that seems to be acknowledged in the C standard at least:
A return statement with a integer compatible value implies a call to exit.
If there is a plain return the termination status to the host environment is undefined which is the same as declaring void main().

More frustrating details here: https://en.cppreference.com/w/c/language/main_function.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems to be at a slightly higher level of abstraction to me, I think that's something that should be handled at the llvm level, unless I'm missing something

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No objection there.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the discussion, removed special handling of main function

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the changes, looks super neat!

@superlopuh
Copy link
Member

LGTM, @AntonLydike, WDYT?

Copy link
Collaborator

@AntonLydike AntonLydike left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's very nice to see work continue in this direction! Although I want to re-iterate, that I feel that we are "just winging" API/ABI here. I don't think that's a very good direction to take.

Furthermore, I think we need some unit tests on the verifiers here!

name = "riscv_func.call"
args: Annotated[VarOperand, riscv.RegisterType]
func_name: OpAttr[StringAttr]
result: Annotated[OptOpResult, riscv.RegisterType]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty sure that we want to have VarResult here instead. It's common to return values in multiple registers to prevent values spilling to the stack (e.g. when returning a 64 bit value, or a struct)

"""RISC-V function return operation"""

name = "riscv_func.return"
value: Annotated[OptOperand, riscv.RegisterType]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should also be VarOperand

"""RISC-V function definition operation"""

name = "riscv_func.func"
args: Annotated[VarOperand, riscv.RegisterType]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does the function definition take arguments here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah that's a good point, they should not be here indeed

args: Annotated[VarOperand, riscv.RegisterType]
func_name: OpAttr[StringAttr]
func_body: SingleBlockRegion

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel this is missing a function_type style annotation? @superlopuh what's your opinion on that?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still not exactly sure when we need it and when we don't. I guess it doesn't hurt, and should help with printing/parsing more cleanly

xdsl/dialects/riscv_func.py Outdated Show resolved Hide resolved
xdsl/dialects/riscv_func.py Show resolved Hide resolved
xdsl/dialects/riscv_func.py Outdated Show resolved Hide resolved
xdsl/transforms/lower_riscv_func.py Outdated Show resolved Hide resolved
xdsl/transforms/lower_riscv_func.py Outdated Show resolved Hide resolved
Copy link
Collaborator

@JosseVanDelm JosseVanDelm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @eymay ! This looks really cool!
But maybe we should make issues for the cases that are not covered yet:

  • (register spilling)
  • non-main functions

xdsl/dialects/riscv_func.py Outdated Show resolved Hide resolved
xdsl/transforms/lower_riscv_func.py Outdated Show resolved Hide resolved
@superlopuh
Copy link
Member

Would be nice to have this soon, I'm happy to address remaining comments and merge in the next couple of days

@superlopuh
Copy link
Member

@AntonLydike I addressed your comments

adutilleul added a commit that referenced this pull request Jun 1, 2023
The current register allocator for the RISC-V dialect exclusively
utilizes j-registers for unallocated values. However, @compor and I
propose an improvement over the existing allocator by introducing a
naive strategy that leverages the available real RISC-V registers for
each block. In case the real registers are exhausted, the allocator
gracefully falls back to j-registers.

This enhancement brings forth several important questions that need to
be addressed at this stage:

- Determining the Set of Available Registers: The choice of available
registers depends on the ABI and the adopted calling convention. So, we
probably want to determine a target for now and see how it involves
other topics (like function handling see
#929).

- Efficiency Requirements for Future Work: We might need to establish
the desired level of efficiency for the register allocator (linear scan,
...) and the relevant use cases.

Moreover, this improvement is contingent on the merging of the LabelOp
into the main branch. For further details regarding the LabelOp merge,
please refer to the following pull request
#994.

---------

Co-authored-by: Chris Vasiladiotis <cvassiladiotis@gmail.com>
Copy link
Collaborator

@AntonLydike AntonLydike left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@@ -58,18 +58,18 @@ class CallOp(IRDLOperation):
name = "riscv_func.call"
args: Annotated[VarOperand, riscv.RegisterType]
func_name: OpAttr[StringAttr]
result: Annotated[OptOpResult, riscv.RegisterType]
ress: Annotated[VarOpResult, riscv.RegisterType]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: should this be results or res? ress looks a bit weird?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

results is reserved, res to me implies singular, and ress is weird, alternative suggestions welcome

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be honest results already works, I expect people will use that, we can always rename it later

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure!

@superlopuh superlopuh merged commit 4343a8f into xdslproject:main Jun 1, 2023
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dialects Changes on the dialects
Projects
Development

Successfully merging this pull request may close these issues.

None yet

7 participants