-
Notifications
You must be signed in to change notification settings - Fork 4
Add conditional statements & expressions #8
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -83,6 +83,8 @@ Constructor.prototype.visit = function visit(ast) { | |
return this.visitUpdate(ast); | ||
else if (ast.type === 'SequenceExpression') | ||
return this.visitSequence(ast); | ||
else if (ast.type === 'IfStatement' || ast.type === 'ConditionalExpression') | ||
return this.visitConditional(ast); | ||
else | ||
assert(false, `Unknown AST node type: "${ast.type}"`); | ||
}; | ||
|
@@ -238,6 +240,39 @@ Constructor.prototype.visitSequence = function visitSequence(ast) { | |
return res; | ||
}; | ||
|
||
Constructor.prototype.visitConditional = function visitConditional(ast) { | ||
const test = this.visit(ast.test); | ||
|
||
let start = test.block; | ||
|
||
if (start.predecessors.length > 1) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice, fixing Xs in CFG ;) |
||
this.pipeline.addControl('jump'); | ||
start = this.pipeline.jumpFrom(start); | ||
} | ||
|
||
const branch = this.pipeline.addControl('if', [ test ]); | ||
|
||
const left = this.pipeline.jumpFrom(start); | ||
const consequent = this.visit(ast.consequent); | ||
this.pipeline.addControl('jump'); | ||
|
||
if (ast.alternate) { | ||
const right = this.pipeline.jumpFrom(start); | ||
const alternate = this.visit(ast.alternate); | ||
this.pipeline.addControl('jump'); | ||
|
||
this.pipeline.merge(left, right); | ||
|
||
if (ast.type === 'ConditionalExpression') { | ||
return this.pipeline.addControl('phi', [ consequent, alternate ]); | ||
} | ||
} else { | ||
this.pipeline.merge(left, start); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a bad idea, better create There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why? This allows to avoid a need to handle extra jumps. |
||
} | ||
|
||
return null; | ||
}; | ||
|
||
// | ||
// Routines | ||
// | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason to not move it closer to
branch
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well,
jump
needs to be inserted after thetest
instructions but before branch to handle X inif (ternary condition)
. Or I might be missing something.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can be right to the branch, that's fine. It is just a placement of instruction in a block, and it is way cleaner to place it closer to the branch that consumes it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I fail to see your idea on where it can be put. Can you please explain / show how the pipeline would look like for this test case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not suggesting to change anything significant, just suggesting to move the instruction to the
start
block. Right now, if you do a split at line 248 of the patch, this instruction will still be in a previous block:Here something along the lines will be generated:
While I think it is fine to have it in
b4
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So back to this after long time :) The problem I see is that in order to do a split, you need
this.pipeline.jumpFrom(start)
, so it depends onstart
, and in order to getstart
, you need to have already visitedtest
. I would love to move visitingtest
to this newly created block, but not sure how to split that dependency (this.currentBlock
doesn't seem to be as reliable replacement).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alternatively, I can split blocks unconditionally and thus drop dependency on
start
that we have inif (start.predecessors.length > 1) {
, but it would lead to extraneous blocks.