Internals: Enable future JumpGo to non-end. No functional change intended.
This commit is contained in:
parent
ca77a93214
commit
546ccd56c4
|
|
@ -1508,6 +1508,7 @@ public:
|
|||
}
|
||||
bool brokeExists() const;
|
||||
bool brokeExistsAbove() const;
|
||||
bool brokeExistsBelow() const;
|
||||
|
||||
// CONSTRUCTORS
|
||||
virtual ~AstNode() {}
|
||||
|
|
|
|||
|
|
@ -746,6 +746,14 @@ AstNode* AstArraySel::baseFromp(AstNode* nodep) {
|
|||
return nodep;
|
||||
}
|
||||
|
||||
const char* AstJumpBlock::broken() const {
|
||||
BROKEN_RTN(!labelp()->brokeExistsBelow());
|
||||
return NULL;
|
||||
}
|
||||
void AstJumpBlock::cloneRelink() {
|
||||
if (m_labelp->clonep()) m_labelp = m_labelp->clonep();
|
||||
}
|
||||
|
||||
const char* AstScope::broken() const {
|
||||
BROKEN_RTN(m_aboveScopep && !m_aboveScopep->brokeExists());
|
||||
BROKEN_RTN(m_aboveCellp && !m_aboveCellp->brokeExists());
|
||||
|
|
@ -753,7 +761,6 @@ const char* AstScope::broken() const {
|
|||
BROKEN_RTN(m_modp && !m_modp->brokeExists());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void AstScope::cloneRelink() {
|
||||
if (m_aboveScopep && m_aboveScopep->clonep()) m_aboveScopep->clonep();
|
||||
if (m_aboveCellp && m_aboveCellp->clonep()) m_aboveCellp->clonep();
|
||||
|
|
@ -761,7 +768,6 @@ void AstScope::cloneRelink() {
|
|||
static_cast<AstNode*>(m_modp)->clonep();
|
||||
}
|
||||
}
|
||||
|
||||
string AstScope::nameDotless() const {
|
||||
string out = shortName();
|
||||
string::size_type pos;
|
||||
|
|
@ -780,7 +786,6 @@ string AstScopeName::scopePrettyNameFormatter(AstText* scopeTextp) const {
|
|||
if (out.substr(0, 1) == ".") out.replace(0, 1, "");
|
||||
return AstNode::prettyName(out);
|
||||
}
|
||||
|
||||
string AstScopeName::scopeNameFormatter(AstText* scopeTextp) const {
|
||||
string out;
|
||||
for (AstText* textp = scopeTextp; textp; textp = VN_CAST(textp->nextp(), Text)) {
|
||||
|
|
@ -1142,6 +1147,15 @@ void AstJumpGo::dump(std::ostream& str) const {
|
|||
str << "%Error:UNLINKED";
|
||||
}
|
||||
}
|
||||
void AstJumpLabel::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
str << " -> ";
|
||||
if (blockp()) {
|
||||
blockp()->dump(str);
|
||||
} else {
|
||||
str << "%Error:UNLINKED";
|
||||
}
|
||||
}
|
||||
void AstMemberSel::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
str << " -> ";
|
||||
|
|
|
|||
|
|
@ -4292,44 +4292,81 @@ public:
|
|||
void priorityPragma(bool flag) { m_priorityPragma = flag; }
|
||||
};
|
||||
|
||||
class AstJumpLabel : public AstNodeStmt {
|
||||
// Jump point declaration
|
||||
// Separate from AstJumpGo; as a declaration can't be deleted
|
||||
class AstJumpBlock : public AstNodeStmt {
|
||||
// Block of code including a JumpGo and JumpLabel
|
||||
// Parents: {statement list}
|
||||
// Children: {statement list, with JumpGo below}
|
||||
// Children: {statement list, with JumpGo and JumpLabel below}
|
||||
private:
|
||||
AstJumpLabel* m_labelp; // [After V3Jump] Pointer to declaration
|
||||
int m_labelNum; // Set by V3EmitCSyms to tell final V3Emit what to increment
|
||||
public:
|
||||
AstJumpLabel(FileLine* fl, AstNode* stmtsp)
|
||||
// After construction must call ->labelp to associate with appropriate label
|
||||
AstJumpBlock(FileLine* fl, AstNode* stmtsp)
|
||||
: ASTGEN_SUPER(fl)
|
||||
, m_labelNum(0) {
|
||||
addNOp1p(stmtsp);
|
||||
}
|
||||
virtual const char* broken() const;
|
||||
virtual void cloneRelink();
|
||||
ASTNODE_NODE_FUNCS(JumpBlock)
|
||||
virtual int instrCount() const { return 0; }
|
||||
ASTNODE_NODE_FUNCS(JumpLabel)
|
||||
virtual bool maybePointedTo() const { return true; }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(const AstNode* samep) const { return true; }
|
||||
// op1 = Statements
|
||||
AstNode* stmtsp() const { return op1p(); } // op1 = List of statements
|
||||
void addStmtsp(AstNode* nodep) { addNOp1p(nodep); }
|
||||
AstNode* endStmtsp() const { return op2p(); } // op1 = List of end-of-block
|
||||
void addEndStmtsp(AstNode* nodep) { addNOp2p(nodep); }
|
||||
int labelNum() const { return m_labelNum; }
|
||||
void labelNum(int flag) { m_labelNum = flag; }
|
||||
AstJumpLabel* labelp() const { return m_labelp; }
|
||||
void labelp(AstJumpLabel* labelp) { m_labelp = labelp; }
|
||||
};
|
||||
|
||||
class AstJumpLabel : public AstNodeStmt {
|
||||
// Jump point declaration
|
||||
// Parents: {statement list with JumpBlock above}
|
||||
// Children: none
|
||||
private:
|
||||
AstJumpBlock* m_blockp; // [After V3Jump] Pointer to declaration
|
||||
public:
|
||||
AstJumpLabel(FileLine* fl, AstJumpBlock* blockp)
|
||||
: ASTGEN_SUPER(fl)
|
||||
, m_blockp(blockp) {}
|
||||
ASTNODE_NODE_FUNCS(JumpLabel)
|
||||
virtual bool maybePointedTo() const { return true; }
|
||||
virtual const char* broken() const {
|
||||
BROKEN_RTN(!blockp()->brokeExistsAbove());
|
||||
BROKEN_RTN(blockp()->labelp() != this);
|
||||
return NULL;
|
||||
}
|
||||
virtual void cloneRelink() {
|
||||
if (m_blockp->clonep()) m_blockp = m_blockp->clonep();
|
||||
}
|
||||
virtual void dump(std::ostream& str) const;
|
||||
virtual int instrCount() const { return 0; }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(const AstNode* samep) const {
|
||||
return blockp() == static_cast<const AstJumpLabel*>(samep)->blockp();
|
||||
}
|
||||
AstJumpBlock* blockp() const { return m_blockp; }
|
||||
};
|
||||
|
||||
class AstJumpGo : public AstNodeStmt {
|
||||
// Jump point; branch up to the JumpLabel
|
||||
// Parents: {statement list}
|
||||
// Jump point; branch down to a JumpLabel
|
||||
// No support for backward jumps at present
|
||||
// Parents: {statement list with JumpBlock above}
|
||||
// Children: none
|
||||
private:
|
||||
AstJumpLabel* m_labelp; // [After V3Jump] Pointer to declaration
|
||||
public:
|
||||
AstJumpGo(FileLine* fl, AstJumpLabel* labelp)
|
||||
: ASTGEN_SUPER(fl) {
|
||||
m_labelp = labelp;
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(JumpGo)
|
||||
: ASTGEN_SUPER(fl)
|
||||
, m_labelp(labelp) {}
|
||||
ASTNODE_NODE_FUNCS(JumpGo);
|
||||
virtual const char* broken() const {
|
||||
BROKEN_RTN(!labelp()->brokeExistsAbove());
|
||||
BROKEN_RTN(!labelp()->brokeExistsBelow());
|
||||
return NULL;
|
||||
}
|
||||
virtual void cloneRelink() {
|
||||
|
|
@ -4339,7 +4376,6 @@ public:
|
|||
virtual int instrCount() const { return instrCountBranch(); }
|
||||
virtual V3Hash sameHash() const { return V3Hash(labelp()); }
|
||||
virtual bool same(const AstNode* samep) const {
|
||||
// Also same if identical tree structure all the way down, but hard to detect
|
||||
return labelp() == static_cast<const AstJumpGo*>(samep)->labelp();
|
||||
}
|
||||
virtual bool isGateOptimizable() const { return false; }
|
||||
|
|
|
|||
|
|
@ -131,6 +131,14 @@ public:
|
|||
if (!(iter->second & FLAG_LINKABLE)) return false;
|
||||
return true;
|
||||
}
|
||||
static bool okIfAbove(const AstNode* nodep) {
|
||||
// Must be linked to and below current node
|
||||
if (!okIfLinkedTo(nodep)) return false;
|
||||
NodeMap::iterator iter = s_nodes.find(nodep);
|
||||
if (iter == s_nodes.end()) return false;
|
||||
if ((iter->second & FLAG_UNDER_NOW)) return false;
|
||||
return true;
|
||||
}
|
||||
static bool okIfBelow(const AstNode* nodep) {
|
||||
// Must be linked to and below current node
|
||||
if (!okIfLinkedTo(nodep)) return false;
|
||||
|
|
@ -193,6 +201,10 @@ bool AstNode::brokeExistsAbove() const {
|
|||
// Called by node->broken() routines to do table lookup
|
||||
return BrokenTable::okIfBelow(this);
|
||||
}
|
||||
bool AstNode::brokeExistsBelow() const {
|
||||
// Called by node->broken() routines to do table lookup
|
||||
return BrokenTable::okIfAbove(this);
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
|
||||
|
|
|
|||
|
|
@ -2167,24 +2167,32 @@ private:
|
|||
}
|
||||
virtual void visit(AstJumpGo* nodep) VL_OVERRIDE {
|
||||
iterateChildren(nodep);
|
||||
m_hasJumpDelay = true;
|
||||
// Jump to label where label immediately follows label is not useful
|
||||
if (nodep->labelp() == VN_CAST(nodep->nextp(), JumpLabel)) {
|
||||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
// Keep the label, might be other jumps pointing to it, gets cleaned later
|
||||
return;
|
||||
}
|
||||
if (m_doExpensive) {
|
||||
// If last statement in a jump label we have JumpLabel(...., JumpGo)
|
||||
// Often caused by "return" in a Verilog function. The Go is pointless, remove.
|
||||
if (!nodep->nextp()) {
|
||||
if (AstJumpLabel* aboveLabelp = VN_CAST(nodep->abovep(), JumpLabel)) {
|
||||
if (aboveLabelp == nodep->labelp()) {
|
||||
UINFO(4, "JUMPGO => last remove " << nodep << endl);
|
||||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
return;
|
||||
if (AstJumpBlock* aboveBlockp = VN_CAST(nodep->abovep(), JumpBlock)) {
|
||||
if (aboveBlockp == nodep->labelp()->blockp()) {
|
||||
if (aboveBlockp->endStmtsp() == nodep->labelp()) {
|
||||
UINFO(4, "JUMPGO => last remove " << nodep << endl);
|
||||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
nodep->labelp()->user4(true);
|
||||
nodep->labelp()->blockp()->user4(true);
|
||||
}
|
||||
m_hasJumpDelay = true;
|
||||
}
|
||||
|
||||
virtual void visit(AstJumpLabel* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstJumpBlock* nodep) VL_OVERRIDE {
|
||||
// Because JumpLabels disable many optimizations,
|
||||
// remove JumpLabels that are not pointed to by any AstJumpGos
|
||||
// Note this assumes all AstJumpGos are underneath the given label; V3Broken asserts this
|
||||
|
|
@ -2199,6 +2207,7 @@ private:
|
|||
} else {
|
||||
nodep->unlinkFrBack();
|
||||
}
|
||||
nodep->labelp()->unlinkFrBack()->deleteTree();
|
||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -697,15 +697,18 @@ public:
|
|||
iterateAndNextNull(nodep->lhsp());
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstJumpGo* nodep) VL_OVERRIDE {
|
||||
puts("goto __Vlabel" + cvtToStr(nodep->labelp()->labelNum()) + ";\n");
|
||||
}
|
||||
virtual void visit(AstJumpLabel* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstJumpBlock* nodep) VL_OVERRIDE {
|
||||
nodep->labelNum(++m_labelNum);
|
||||
puts("{\n"); // Make it visually obvious label jumps outside these
|
||||
iterateAndNextNull(nodep->stmtsp());
|
||||
iterateAndNextNull(nodep->endStmtsp());
|
||||
puts("}\n");
|
||||
puts("__Vlabel" + cvtToStr(nodep->labelNum()) + ": ;\n");
|
||||
}
|
||||
virtual void visit(AstJumpGo* nodep) VL_OVERRIDE {
|
||||
puts("goto __Vlabel" + cvtToStr(nodep->labelp()->blockp()->labelNum()) + ";\n");
|
||||
}
|
||||
virtual void visit(AstJumpLabel* nodep) VL_OVERRIDE {
|
||||
puts("__Vlabel" + cvtToStr(nodep->blockp()->labelNum()) + ": ;\n");
|
||||
}
|
||||
virtual void visit(AstWhile* nodep) VL_OVERRIDE {
|
||||
iterateAndNextNull(nodep->precondsp());
|
||||
|
|
|
|||
|
|
@ -272,14 +272,17 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
if (nodep->filep()) iterateAndNextNull(nodep->filep());
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstJumpGo* nodep) VL_OVERRIDE {
|
||||
putbs("disable " + cvtToHex(nodep->labelp()) + ";\n");
|
||||
}
|
||||
virtual void visit(AstJumpLabel* nodep) VL_OVERRIDE {
|
||||
putbs("begin : " + cvtToHex(nodep) + "\n");
|
||||
virtual void visit(AstJumpBlock* nodep) VL_OVERRIDE {
|
||||
putbs("begin : label" + cvtToStr(nodep->labelNum()) + "\n");
|
||||
if (nodep->stmtsp()) iterateAndNextNull(nodep->stmtsp());
|
||||
puts("end\n");
|
||||
}
|
||||
virtual void visit(AstJumpGo* nodep) VL_OVERRIDE {
|
||||
putbs("disable label" + cvtToStr(nodep->labelp()->blockp()->labelNum()) + ";\n");
|
||||
}
|
||||
virtual void visit(AstJumpLabel* nodep) VL_OVERRIDE {
|
||||
putbs("// " + cvtToStr(nodep->blockp()) + ":\n");
|
||||
}
|
||||
virtual void visit(AstNodeReadWriteMem* nodep) VL_OVERRIDE {
|
||||
putfs(nodep, nodep->verilogKwd());
|
||||
putbs(" (");
|
||||
|
|
|
|||
|
|
@ -390,7 +390,7 @@ private:
|
|||
VL_DO_DANGLING(delete condLifep, condLifep);
|
||||
VL_DO_DANGLING(delete bodyLifep, bodyLifep);
|
||||
}
|
||||
virtual void visit(AstJumpLabel* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstJumpBlock* nodep) VL_OVERRIDE {
|
||||
// As with While's we can't predict if a JumpGo will kill us or not
|
||||
// It's worse though as an IF(..., JUMPGO) may change the control flow.
|
||||
// Just don't optimize blocks with labels; they're rare - so far.
|
||||
|
|
|
|||
|
|
@ -21,9 +21,11 @@
|
|||
// FOR -> WHILEs
|
||||
//
|
||||
// Add JumpLabel which branches to after statements within JumpLabel
|
||||
// RETURN -> JUMPLABEL(statements with RETURN changed to JUMPGO)
|
||||
// WHILE(... BREAK) -> JUMPLABEL(WHILE(... statements with BREAK changed to JUMPGO)
|
||||
// WHILE(... CONTINUE) -> WHILE(JUMPLABEL(... statements with CONTINUE changed to JUMPGO)
|
||||
// RETURN -> JUMPBLOCK(statements with RETURN changed to JUMPGO, ..., JUMPLABEL)
|
||||
// WHILE(... BREAK) -> JUMPBLOCK(WHILE(... statements with BREAK changed to JUMPGO),
|
||||
// ... JUMPLABEL)
|
||||
// WHILE(... CONTINUE) -> WHILE(JUMPBLOCK(... statements with CONTINUE changed to JUMPGO,
|
||||
// ... JUMPPABEL))
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
|
|
@ -90,7 +92,9 @@ private:
|
|||
if (VN_IS(underp, JumpLabel)) {
|
||||
return VN_CAST(underp, JumpLabel);
|
||||
} else { // Move underp stuff to be under a new label
|
||||
AstJumpLabel* labelp = new AstJumpLabel(nodep->fileline(), NULL);
|
||||
AstJumpBlock* blockp = new AstJumpBlock(nodep->fileline(), NULL);
|
||||
AstJumpLabel* labelp = new AstJumpLabel(nodep->fileline(), blockp);
|
||||
blockp->labelp(labelp);
|
||||
|
||||
AstNRelinker repHandle;
|
||||
if (under_and_next) {
|
||||
|
|
@ -98,14 +102,16 @@ private:
|
|||
} else {
|
||||
underp->unlinkFrBack(&repHandle);
|
||||
}
|
||||
repHandle.relink(labelp);
|
||||
repHandle.relink(blockp);
|
||||
|
||||
labelp->addStmtsp(underp);
|
||||
blockp->addStmtsp(underp);
|
||||
// Keep any AstVars under the function not under the new JumpLabel
|
||||
for (AstNode *nextp, *varp = underp; varp; varp = nextp) {
|
||||
nextp = varp->nextp();
|
||||
if (VN_IS(varp, Var)) labelp->addPrev(varp->unlinkFrBack());
|
||||
if (VN_IS(varp, Var)) blockp->addPrev(varp->unlinkFrBack());
|
||||
}
|
||||
// Label goes last
|
||||
blockp->addEndStmtsp(labelp);
|
||||
return labelp;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -818,6 +818,10 @@ private:
|
|||
|
||||
virtual void visit(AstComment*) VL_OVERRIDE {}
|
||||
|
||||
virtual void visit(AstJumpBlock* nodep) VL_OVERRIDE {
|
||||
if (jumpingOver(nodep)) return;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstJumpGo* nodep) VL_OVERRIDE {
|
||||
if (jumpingOver(nodep)) return;
|
||||
checkNodeInfo(nodep);
|
||||
|
|
@ -827,6 +831,8 @@ private:
|
|||
}
|
||||
}
|
||||
virtual void visit(AstJumpLabel* nodep) VL_OVERRIDE {
|
||||
// This only supports forward jumps. That's all we make at present,
|
||||
// AstJumpGo::broken uses brokeExistsBelow() to check this.
|
||||
if (jumpingOver(nodep)) return;
|
||||
checkNodeInfo(nodep);
|
||||
iterateChildren(nodep);
|
||||
|
|
|
|||
Loading…
Reference in New Issue