Skip to content

Implement trans for the MIR Switch terminator #30337

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

Merged
merged 1 commit into from
Dec 16, 2015

Conversation

wesleywiser
Copy link
Member

Fixes #29574

@rust-highfive
Copy link
Contributor

r? @arielb1

(rust_highfive has picked a reviewer for you, use r? to override)

@wesleywiser
Copy link
Member Author

r? @nikomatsakis

Abc::C => 3,
Abc::D => 4,
Abc::B(_) => 2,
Abc::A(_) => 1,
Copy link
Member

Choose a reason for hiding this comment

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

You need at least a test for the _ => case.

@wesleywiser
Copy link
Member Author

@nagisa Fixed nit and added test case for _ =>. It looks like the default case is translated to all other variants pointing to the same block. (You can see the graphviz for foo2 here: https://gist.github.com/wesleywiser/698dbdd7945ec51a1e3c)

@dotdash I think I fixed this in my last commit. Does that look right to you?

@nagisa
Copy link
Member

nagisa commented Dec 12, 2015

@wesleywiser @dotdash regarding unreachable

DIVERGE_BLOCK is guaranteed to only contain the Diverge terminator (and no statements), which translates down straight to unreachable. That being said, @wesleywiser, I would remove the b834929

Re _=>, I see, its all good then.

EDIT: ah, right, it might be a Resume in case some llpersonality is set. but it is never set (yet?)


Thinking about that more, resume inside DIVERGE_BLOCK is an unpleasant hack to do, especially in cases like this. There’s some nice properties when you know DIVERGE_BLOCK is always an unreachable. resume is only relevant for function calls which have landing pads, and I believe translation for function calls should take care to generate necessary resume themselves, since they gonna have to generate necessary landingpad insns anyway. Any thoughts on it, @nikomatsakis?

@dotdash
Copy link
Contributor

dotdash commented Dec 13, 2015

@nagisa AIUI, the fact that the diverge block can contain an unreachable is the hack. The block is meant for unwinding/panicking, but we always translate it, even if there's no way to actually reach it , and only in that case we put the unreachable there. In a perfect world, we wouldn't even create the block in that case.

@nagisa
Copy link
Member

nagisa commented Dec 13, 2015

@dotdash but all you can really do in that block, really, is having a resume, since landing block itself will be dependent on the location where function was generated, no?

I’d rather have DIVERGE_BLOCK be unconditionally unreachable (and translated lazily, only if necessary/removed by CFG simplification), for cases like this (something to branch into after call to diverging function comes into mind as similar case) and a separate Resume terminator which is emitted by librustc_mir/build/scope.rs after all necessary cleanups.

@nikomatsakis
Copy link
Contributor

So, it seems to me that perhaps we should just remove DIVERGE_BLOCK altogether, and instead replicate the DIVERGE terminator at the end of every cleanup sequence. What @nagisa says is, I think, true -- that is, that there isn't much useful code there. I'm not sure I included it exactly, probably just by analogy to the "return" block. Certainly, one could also make the argument that RETURN is not needed. I think mainly I was thinking that it's often easier for analysis purposes if you have a fixed set of "postdominator" blocks, but that may not be really true.

@nikomatsakis
Copy link
Contributor

As far as having a special block for unreachable code, that seems fine, but it seems like something specific to trans, and not necessarily something that needs to be made manifest in the MIR.

unimplemented!()
mir::Terminator::Switch { ref discr, ref adt_def, ref targets } => {
let adt_ty = bcx.tcx().lookup_item_type(adt_def.did).ty;
let represented_ty = adt::represent_type(bcx.ccx(), adt_ty).clone();
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: I don't think you need to call clone() here, do you?

@wesleywiser
Copy link
Member Author

@nikomatsakis Fixed nits.

it might be nice to have just one such block (created lazilly), we could store it in the "MIR trans" state.

Do you want me to work on that in this PR?

@nagisa
Copy link
Member

nagisa commented Dec 14, 2015

You can leave it as it is currently, however, if you can add a FIXME of some sort to that effect.

@wesleywiser
Copy link
Member Author

Ok. Should I tidy the branch up too while I'm in there?

@nagisa
Copy link
Member

nagisa commented Dec 14, 2015

Sure!

@wesleywiser
Copy link
Member Author

I've squashed all my changes and rebased against master.

@nikomatsakis
Copy link
Contributor

@bors r+

nice!

@bors
Copy link
Collaborator

bors commented Dec 15, 2015

📌 Commit 2b15361 has been approved by nikomatsakis

bors added a commit that referenced this pull request Dec 16, 2015
@bors
Copy link
Collaborator

bors commented Dec 16, 2015

⌛ Testing commit 2b15361 with merge 073b0f9...

@bors bors merged commit 2b15361 into rust-lang:master Dec 16, 2015
@wesleywiser wesleywiser deleted the mir_switch branch December 20, 2015 06:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants