Internals: Further performance improvement of AstNode type tests, #2138. No functional change intended.
Replace the virtual type() method on AstNode with a non-virtual, inlined accessor to a const member variable m_type. This means that in order to be able to use this for type testing, it needs to be initialized based on the final type of the node. This is achieved by passing the relevant AstType value back through the constructor call chain. Most of the boilerplate involved is auto generated by first feeding V3AstNodes.h through astgen to get V3AstNodes__gen.h, which is then included in V3Ast.h. No client code needs to be aware and there is no functional change intended. Eliminating the virtual function call to fetch the node type identifier results in measured compilation speed improvement of 5-10% as it eliminates up to 20% of all mispredicted branches from the execution.
This commit is contained in:
parent
eafed88a6e
commit
ef5250f0ca
2
Changes
2
Changes
|
|
@ -9,6 +9,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
|
|||
|
||||
** Add -match to lint_off to waive warnings. [Philipp Wagner]
|
||||
|
||||
*** Verilation speed improvements, #2133, #2138. [Geza Lore]
|
||||
|
||||
*** Support libgoogle-perftools-dev's libtcmalloc if available. #2137. [Geza Lore]
|
||||
|
||||
*** Support $readmem/$writemem with assoc arrarys. Closes #2100. [agrobman]
|
||||
|
|
|
|||
123
src/V3Ast.h
123
src/V3Ast.h
|
|
@ -1159,6 +1159,8 @@ class AstNode {
|
|||
|
||||
AstNode* m_headtailp; // When at begin/end of list, the opposite end of the list
|
||||
|
||||
const AstType m_type; // Node sub-type identifier
|
||||
|
||||
FileLine* m_fileline; // Where it was declared
|
||||
vluint64_t m_editCount; // When it was last edited
|
||||
static vluint64_t s_editCntGbl; // Global edit counter
|
||||
|
|
@ -1213,8 +1215,10 @@ public:
|
|||
|
||||
protected:
|
||||
// CONSTRUCTORS
|
||||
AstNode() { init(); }
|
||||
explicit AstNode(FileLine* fileline) {init(); m_fileline = fileline; }
|
||||
AstNode(AstType t)
|
||||
: m_type(t) { init(); }
|
||||
AstNode(AstType t, FileLine* fl)
|
||||
: m_type(t) { init(); m_fileline = fl; }
|
||||
virtual AstNode* clone() = 0; // Generally, cloneTree is what you want instead
|
||||
virtual void cloneRelink() {}
|
||||
void cloneRelinkTree();
|
||||
|
|
@ -1245,7 +1249,7 @@ protected:
|
|||
|
||||
public:
|
||||
// ACCESSORS
|
||||
virtual AstType type() const = 0;
|
||||
inline AstType type() const { return m_type; }
|
||||
const char* typeName() const { return type().ascii(); } // See also prettyTypeName
|
||||
AstNode* nextp() const { return m_nextp; }
|
||||
AstNode* backp() const { return m_backp; }
|
||||
|
|
@ -1570,8 +1574,8 @@ inline void AstNRelinker::relink(AstNode* newp) { newp->AstNode::relink(this); }
|
|||
class AstNodeMath : public AstNode {
|
||||
// Math -- anything that's part of an expression tree
|
||||
public:
|
||||
explicit AstNodeMath(FileLine* fl)
|
||||
: AstNode(fl) {}
|
||||
AstNodeMath(AstType t, FileLine* fl)
|
||||
: AstNode(t, fl) {}
|
||||
ASTNODE_BASE_FUNCS(NodeMath)
|
||||
// METHODS
|
||||
virtual bool hasDType() const { return true; }
|
||||
|
|
@ -1587,8 +1591,8 @@ public:
|
|||
class AstNodeTermop : public AstNodeMath {
|
||||
// Terminal operator -- a operator with no "inputs"
|
||||
public:
|
||||
explicit AstNodeTermop(FileLine* fl)
|
||||
: AstNodeMath(fl) {}
|
||||
AstNodeTermop(AstType t, FileLine* fl)
|
||||
: AstNodeMath(t, fl) {}
|
||||
ASTNODE_BASE_FUNCS(NodeTermop)
|
||||
// Know no children, and hot function, so skip iterator for speed
|
||||
// See checkTreeIter also that asserts no children
|
||||
|
|
@ -1599,8 +1603,8 @@ public:
|
|||
class AstNodeUniop : public AstNodeMath {
|
||||
// Unary math
|
||||
public:
|
||||
AstNodeUniop(FileLine* fl, AstNode* lhsp)
|
||||
: AstNodeMath(fl) {
|
||||
AstNodeUniop(AstType t, FileLine* fl, AstNode* lhsp)
|
||||
: AstNodeMath(t, fl) {
|
||||
dtypeFrom(lhsp);
|
||||
setOp1p(lhsp); }
|
||||
ASTNODE_BASE_FUNCS(NodeUniop)
|
||||
|
|
@ -1621,8 +1625,8 @@ public:
|
|||
class AstNodeBiop : public AstNodeMath {
|
||||
// Binary math
|
||||
public:
|
||||
AstNodeBiop(FileLine* fl, AstNode* lhs, AstNode* rhs)
|
||||
: AstNodeMath(fl) {
|
||||
AstNodeBiop(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs)
|
||||
: AstNodeMath(t, fl) {
|
||||
setOp1p(lhs); setOp2p(rhs); }
|
||||
ASTNODE_BASE_FUNCS(NodeBiop)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) = 0; // Clone single node, just get same type back.
|
||||
|
|
@ -1648,8 +1652,8 @@ public:
|
|||
class AstNodeTriop : public AstNodeMath {
|
||||
// Trinary math
|
||||
public:
|
||||
AstNodeTriop(FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths)
|
||||
: AstNodeMath(fl) {
|
||||
AstNodeTriop(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths)
|
||||
: AstNodeMath(t, fl) {
|
||||
setOp1p(lhs); setOp2p(rhs); setOp3p(ths); }
|
||||
ASTNODE_BASE_FUNCS(NodeTriop)
|
||||
AstNode* lhsp() const { return op1p(); }
|
||||
|
|
@ -1676,22 +1680,22 @@ public:
|
|||
class AstNodeBiCom : public AstNodeBiop {
|
||||
// Binary math with commutative properties
|
||||
public:
|
||||
AstNodeBiCom(FileLine* fl, AstNode* lhs, AstNode* rhs)
|
||||
: AstNodeBiop(fl, lhs, rhs) {}
|
||||
AstNodeBiCom(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs)
|
||||
: AstNodeBiop(t, fl, lhs, rhs) {}
|
||||
ASTNODE_BASE_FUNCS(NodeBiCom)
|
||||
};
|
||||
|
||||
class AstNodeBiComAsv : public AstNodeBiCom {
|
||||
// Binary math with commutative & associative properties
|
||||
public:
|
||||
AstNodeBiComAsv(FileLine* fl, AstNode* lhs, AstNode* rhs)
|
||||
: AstNodeBiCom(fl, lhs, rhs) {}
|
||||
AstNodeBiComAsv(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs)
|
||||
: AstNodeBiCom(t, fl, lhs, rhs) {}
|
||||
ASTNODE_BASE_FUNCS(NodeBiComAsv)
|
||||
};
|
||||
class AstNodeCond : public AstNodeTriop {
|
||||
public:
|
||||
AstNodeCond(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p)
|
||||
: AstNodeTriop(fl, condp, expr1p, expr2p) {
|
||||
AstNodeCond(AstType t, FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p)
|
||||
: AstNodeTriop(t, fl, condp, expr1p, expr2p) {
|
||||
if (expr1p) dtypeFrom(expr1p);
|
||||
else if (expr2p) dtypeFrom(expr2p);
|
||||
}
|
||||
|
|
@ -1717,8 +1721,8 @@ public:
|
|||
class AstNodePreSel : public AstNode {
|
||||
// Something that becomes an AstSel
|
||||
public:
|
||||
AstNodePreSel(FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths)
|
||||
: AstNode(fl) {
|
||||
AstNodePreSel(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths)
|
||||
: AstNode(t, fl) {
|
||||
setOp1p(lhs); setOp2p(rhs); setNOp3p(ths); }
|
||||
ASTNODE_BASE_FUNCS(NodePreSel)
|
||||
AstNode* lhsp() const { return op1p(); }
|
||||
|
|
@ -1739,8 +1743,8 @@ class AstNodeStmt : public AstNode {
|
|||
// Statement -- anything that's directly under a function
|
||||
bool m_statement; // Really a statement (e.g. not a function with return)
|
||||
public:
|
||||
explicit AstNodeStmt(FileLine* fl, bool statement = true)
|
||||
: AstNode(fl)
|
||||
AstNodeStmt(AstType t, FileLine* fl, bool statement = true)
|
||||
: AstNode(t, fl)
|
||||
, m_statement(statement) {}
|
||||
ASTNODE_BASE_FUNCS(NodeStmt)
|
||||
// METHODS
|
||||
|
|
@ -1752,8 +1756,8 @@ public:
|
|||
|
||||
class AstNodeAssign : public AstNodeStmt {
|
||||
public:
|
||||
AstNodeAssign(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
||||
: AstNodeStmt(fl) {
|
||||
AstNodeAssign(AstType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
||||
: AstNodeStmt(t, fl) {
|
||||
setOp1p(rhsp); setOp2p(lhsp);
|
||||
dtypeFrom(lhsp);
|
||||
}
|
||||
|
|
@ -1775,9 +1779,9 @@ public:
|
|||
|
||||
class AstNodeFor : public AstNodeStmt {
|
||||
public:
|
||||
AstNodeFor(FileLine* fileline, AstNode* initsp, AstNode* condp,
|
||||
AstNodeFor(AstType t, FileLine* fl, AstNode* initsp, AstNode* condp,
|
||||
AstNode* incsp, AstNode* bodysp)
|
||||
: AstNodeStmt(fileline) {
|
||||
: AstNodeStmt(t, fl) {
|
||||
addNOp1p(initsp); setOp2p(condp); addNOp3p(incsp); addNOp4p(bodysp);
|
||||
}
|
||||
ASTNODE_BASE_FUNCS(NodeFor)
|
||||
|
|
@ -1795,8 +1799,8 @@ class AstNodeIf : public AstNodeStmt {
|
|||
private:
|
||||
VBranchPred m_branchPred; // Branch prediction as taken/untaken?
|
||||
public:
|
||||
AstNodeIf(FileLine* fl, AstNode* condp, AstNode* ifsp, AstNode* elsesp)
|
||||
: AstNodeStmt(fl) {
|
||||
AstNodeIf(AstType t, FileLine* fl, AstNode* condp, AstNode* ifsp, AstNode* elsesp)
|
||||
: AstNodeStmt(t, fl) {
|
||||
setOp1p(condp); addNOp2p(ifsp); addNOp3p(elsesp);
|
||||
}
|
||||
ASTNODE_BASE_FUNCS(NodeIf)
|
||||
|
|
@ -1817,8 +1821,8 @@ public:
|
|||
|
||||
class AstNodeCase : public AstNodeStmt {
|
||||
public:
|
||||
AstNodeCase(FileLine* fl, AstNode* exprp, AstNode* casesp)
|
||||
: AstNodeStmt(fl) {
|
||||
AstNodeCase(AstType t, FileLine* fl, AstNode* exprp, AstNode* casesp)
|
||||
: AstNodeStmt(t, fl) {
|
||||
setOp1p(exprp); addNOp2p(casesp);
|
||||
}
|
||||
ASTNODE_BASE_FUNCS(NodeCase)
|
||||
|
|
@ -1833,7 +1837,8 @@ public:
|
|||
class AstNodeSenItem : public AstNode {
|
||||
// An AstSenItem or AstSenGate
|
||||
public:
|
||||
explicit AstNodeSenItem(FileLine* fl) : AstNode(fl) {}
|
||||
AstNodeSenItem(AstType t, FileLine* fl)
|
||||
: AstNode(t, fl) {}
|
||||
ASTNODE_BASE_FUNCS(NodeSenItem)
|
||||
virtual bool isClocked() const = 0;
|
||||
virtual bool isCombo() const = 0;
|
||||
|
|
@ -1854,14 +1859,14 @@ private:
|
|||
bool m_hierThis; // Hiername points to "this" function
|
||||
void init();
|
||||
public:
|
||||
AstNodeVarRef(FileLine* fl, const string& name, bool lvalue)
|
||||
: AstNodeMath(fl), m_lvalue(lvalue), m_varp(NULL), m_varScopep(NULL),
|
||||
m_packagep(NULL), m_name(name), m_hierThis(false) {
|
||||
AstNodeVarRef(AstType t, FileLine* fl, const string& name, bool lvalue)
|
||||
: AstNodeMath(t, fl), m_lvalue(lvalue), m_varp(NULL), m_varScopep(NULL)
|
||||
, m_packagep(NULL), m_name(name), m_hierThis(false) {
|
||||
init();
|
||||
}
|
||||
AstNodeVarRef(FileLine* fl, const string& name, AstVar* varp, bool lvalue)
|
||||
: AstNodeMath(fl), m_lvalue(lvalue), m_varp(varp), m_varScopep(NULL),
|
||||
m_packagep(NULL), m_name(name), m_hierThis(false) {
|
||||
AstNodeVarRef(AstType t, FileLine* fl, const string& name, AstVar* varp, bool lvalue)
|
||||
: AstNodeMath(t, fl), m_lvalue(lvalue), m_varp(varp), m_varScopep(NULL)
|
||||
, m_packagep(NULL), m_name(name), m_hierThis(false) {
|
||||
// May have varp==NULL
|
||||
init();
|
||||
}
|
||||
|
|
@ -1896,8 +1901,8 @@ private:
|
|||
string m_text;
|
||||
public:
|
||||
// Node that simply puts text into the output stream
|
||||
AstNodeText(FileLine* fileline, const string& textp)
|
||||
: AstNode(fileline) {
|
||||
AstNodeText(AstType t, FileLine* fl, const string& textp)
|
||||
: AstNode(t, fl) {
|
||||
m_text = textp; // Copy it
|
||||
}
|
||||
ASTNODE_BASE_FUNCS(NodeText)
|
||||
|
|
@ -1922,7 +1927,8 @@ private:
|
|||
static int s_uniqueNum; // Unique number assigned to each dtype during creation for IEEE matching
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit AstNodeDType(FileLine* fl) : AstNode(fl) {
|
||||
AstNodeDType(AstType t, FileLine* fl)
|
||||
: AstNode(t, fl) {
|
||||
m_width = 0; m_widthMin = 0; m_generic = false;
|
||||
}
|
||||
ASTNODE_BASE_FUNCS(NodeDType)
|
||||
|
|
@ -1982,8 +1988,8 @@ private:
|
|||
bool m_isFourstate;
|
||||
MemberNameMap m_members;
|
||||
public:
|
||||
AstNodeUOrStructDType(FileLine* fl, AstNumeric numericUnpack)
|
||||
: AstNodeDType(fl) {
|
||||
AstNodeUOrStructDType(AstType t, FileLine* fl, AstNumeric numericUnpack)
|
||||
: AstNodeDType(t, fl) {
|
||||
// AstNumeric::NOSIGN overloaded to indicate not packed
|
||||
m_packed = (numericUnpack != AstNumeric::NOSIGN);
|
||||
m_isFourstate = false; // V3Width computes
|
||||
|
|
@ -2033,7 +2039,8 @@ private:
|
|||
AstNodeDType* m_refDTypep; // Elements of this type (after widthing)
|
||||
AstNode* rangenp() const { return op2p(); } // op2 = Array(s) of variable
|
||||
public:
|
||||
explicit AstNodeArrayDType(FileLine* fl) : AstNodeDType(fl) {
|
||||
AstNodeArrayDType(AstType t, FileLine* fl)
|
||||
: AstNodeDType(t, fl) {
|
||||
m_refDTypep = NULL;
|
||||
}
|
||||
ASTNODE_BASE_FUNCS(NodeArrayDType)
|
||||
|
|
@ -2084,8 +2091,8 @@ public:
|
|||
class AstNodeSel : public AstNodeBiop {
|
||||
// Single bit range extraction, perhaps with non-constant selection or array selection
|
||||
public:
|
||||
AstNodeSel(FileLine* fl, AstNode* fromp, AstNode* bitp)
|
||||
: AstNodeBiop(fl, fromp, bitp) {}
|
||||
AstNodeSel(AstType t, FileLine* fl, AstNode* fromp, AstNode* bitp)
|
||||
: AstNodeBiop(t, fl, fromp, bitp) {}
|
||||
ASTNODE_BASE_FUNCS(NodeSel)
|
||||
AstNode* fromp() const { return op1p(); } // op1 = Extracting what (NULL=TBD during parsing)
|
||||
void fromp(AstNode* nodep) { setOp1p(nodep); }
|
||||
|
|
@ -2098,7 +2105,8 @@ public:
|
|||
class AstNodeStream : public AstNodeBiop {
|
||||
// Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp()
|
||||
public:
|
||||
AstNodeStream(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
AstNodeStream(AstType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
||||
: AstNodeBiop(t, fl, lhsp, rhsp) {
|
||||
if (lhsp->dtypep()) {
|
||||
dtypeSetLogicSized(lhsp->dtypep()->width(), AstNumeric::UNSIGNED);
|
||||
}
|
||||
|
|
@ -2124,8 +2132,8 @@ private:
|
|||
bool m_dpiTask:1; // DPI import task (vs. void function)
|
||||
bool m_pure:1; // DPI import pure
|
||||
public:
|
||||
AstNodeFTask(FileLine* fileline, const string& name, AstNode* stmtsp)
|
||||
: AstNode(fileline)
|
||||
AstNodeFTask(AstType t, FileLine* fl, const string& name, AstNode* stmtsp)
|
||||
: AstNode(t, fl)
|
||||
, m_name(name)
|
||||
, m_dpiOpenParent(0), m_taskPublic(false)
|
||||
, m_attrIsolateAssign(false), m_prototype(false)
|
||||
|
|
@ -2187,13 +2195,13 @@ private:
|
|||
string m_inlinedDots; // Dotted hierarchy flattened out
|
||||
AstPackage* m_packagep; // Package hierarchy
|
||||
public:
|
||||
AstNodeFTaskRef(FileLine* fl, bool statement, AstNode* namep, AstNode* pinsp)
|
||||
: AstNodeStmt(fl, statement)
|
||||
AstNodeFTaskRef(AstType t, FileLine* fl, bool statement, AstNode* namep, AstNode* pinsp)
|
||||
: AstNodeStmt(t, fl, statement)
|
||||
, m_taskp(NULL), m_packagep(NULL) {
|
||||
setOp1p(namep); addNOp2p(pinsp);
|
||||
}
|
||||
AstNodeFTaskRef(FileLine* fl, bool statement, const string& name, AstNode* pinsp)
|
||||
: AstNodeStmt(fl, statement)
|
||||
AstNodeFTaskRef(AstType t, FileLine* fl, bool statement, const string& name, AstNode* pinsp)
|
||||
: AstNodeStmt(t, fl, statement)
|
||||
, m_taskp(NULL), m_name(name), m_packagep(NULL) {
|
||||
addNOp2p(pinsp);
|
||||
}
|
||||
|
|
@ -2244,8 +2252,8 @@ private:
|
|||
int m_varNum; // Incrementing variable number
|
||||
int m_typeNum; // Incrementing implicit type number
|
||||
public:
|
||||
AstNodeModule(FileLine* fl, const string& name)
|
||||
: AstNode(fl)
|
||||
AstNodeModule(AstType t, FileLine* fl, const string& name)
|
||||
: AstNode(t, fl)
|
||||
, m_name(name), m_origName(name)
|
||||
, m_modPublic(false), m_modTrace(false), m_inLibrary(false), m_dead(false)
|
||||
, m_internal(false), m_recursive(false), m_recursiveClone(false)
|
||||
|
|
@ -2289,13 +2297,14 @@ public:
|
|||
class AstNodeRange : public AstNode {
|
||||
// A range, sized or unsized
|
||||
public:
|
||||
explicit AstNodeRange(FileLine* fl) : AstNode(fl) { }
|
||||
AstNodeRange(AstType t, FileLine* fl)
|
||||
: AstNode(t, fl) {}
|
||||
ASTNODE_BASE_FUNCS(NodeRange)
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
#include "V3AstNodes.h"
|
||||
#include "V3AstNodes__gen.h"
|
||||
|
||||
//######################################################################
|
||||
// Inline AstNVisitor METHODS
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ AstNodeBiop* AstEqWild::newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp) {
|
|||
}
|
||||
|
||||
AstExecGraph::AstExecGraph(FileLine* fileline)
|
||||
: AstNode(fileline) {
|
||||
: AstNode(AstType::atExecGraph, fileline) {
|
||||
m_depGraphp = new V3Graph;
|
||||
}
|
||||
AstExecGraph::~AstExecGraph() {
|
||||
|
|
|
|||
1111
src/V3AstNodes.h
1111
src/V3AstNodes.h
File diff suppressed because it is too large
Load Diff
36
src/astgen
36
src/astgen
|
|
@ -31,7 +31,7 @@ if (! GetOptions(
|
|||
read_types("$Opt_I[0]/V3Ast.h");
|
||||
read_types("$Opt_I[0]/V3AstNodes.h");
|
||||
foreach my $type (sort (keys %Classes)) {
|
||||
# Chekc all leafs are not AstNode* and non-leave are AstNode*
|
||||
# Check all leaves are not AstNode* and non-leaves are AstNode*
|
||||
my @children = children_of($type);
|
||||
if ($type =~ /^Node/) {
|
||||
@children || die "Error: Final AstNode subclasses must not be named AstNode*: Ast$type"
|
||||
|
|
@ -50,6 +50,7 @@ if ($opt_classes) {
|
|||
write_visitor("V3Ast__gen_visitor.h");
|
||||
write_impl("V3Ast__gen_impl.h");
|
||||
write_types("V3Ast__gen_types.h");
|
||||
write_header("V3AstNodes__gen.h");
|
||||
}
|
||||
foreach my $cpt (@Opt_Cpt) {
|
||||
Cpt::process(in_filename=>"$Opt_I[0]/${cpt}.cpp", out_filename=>"${cpt}__gen.cpp");
|
||||
|
|
@ -346,7 +347,7 @@ sub write_types {
|
|||
printf $fh " };\n";
|
||||
|
||||
printf $fh " const char* ascii() const {\n";
|
||||
printf $fh " const char* const names[_ENUM_END + 1] = {\n";
|
||||
printf $fh " static const char* const names[_ENUM_END + 1] = {\n";
|
||||
write_type_enum($fh, "Node", 0, {}, "concrete-ascii", 3);
|
||||
printf $fh " \"_ENUM_END\"\n";
|
||||
printf $fh " };\n";
|
||||
|
|
@ -355,6 +356,37 @@ sub write_types {
|
|||
$fh->close();
|
||||
}
|
||||
|
||||
sub write_header {
|
||||
my $fh = open_file(@_);
|
||||
|
||||
my $type = "None";
|
||||
my $base = "None";
|
||||
|
||||
my $ifile = "$Opt_I[0]/V3AstNodes.h";
|
||||
my $ifh = IO::File->new($ifile) or die "%Error: $! $ifile,";
|
||||
|
||||
while (defined (my $line = $ifh->getline())) {
|
||||
# Drop expanded macro definitions - but keep empty line so compiler
|
||||
# message locations are accurate
|
||||
$line =~ s/^\s*#(define|undef)\s+ASTGEN_.*$//;
|
||||
|
||||
# Track current node type and base class
|
||||
if ($line =~ /^\s*class\s*Ast(\S+)\s*:\s*(public)?\s*(AstNode\S*)/) {
|
||||
$type = $1;
|
||||
$base = $3;
|
||||
}
|
||||
|
||||
# Substitute macros
|
||||
$line =~ s/\bASTGEN_SUPER\s*\(/$base(AstType::at$type, /;
|
||||
|
||||
# Emit the line
|
||||
print $fh $line;
|
||||
}
|
||||
|
||||
$ifh->close();
|
||||
$fh->close();
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
|
||||
package Cpt;
|
||||
|
|
|
|||
Loading…
Reference in New Issue