Commit 20abce83 authored by Tom Zhao's avatar Tom Zhao
Browse files

xz1919: finished intel isa support and refactored code

parent ac4bd6e3
......@@ -44,7 +44,7 @@ for folder in ${VALID_EXAMPLES[@]}; do
./compile -i $file 2> "${EXECUTABLE_FILE_NAME}.log.txt"
mv "${FILE_NAME}.s" "${EXECUTABLE_FILE_NAME}.s"
gcc "${EXECUTABLE_FILE_NAME}.s" -o "${EXECUTABLE_FILE_NAME}"
./"${EXECUTABLE_FILE_NAME}" > "${EXECUTABLE_OUTPUT_FILE}"
timeout 3 ./"${EXECUTABLE_FILE_NAME}" > "${EXECUTABLE_OUTPUT_FILE}"
# Generate the result from reference compiler
cat <(echo "N" | $REF_COMPILE $file -x) | awk '/===========================================================/ {x=!x; if(x) next} x==1 {print}' > temp
# Use the result generated by our compiler
......
......@@ -52,7 +52,6 @@ public class Compiler {
File sourceFile = new File(args[0]);
File file = new PreCompiler(sourceFile).preCompile();
// System.out.println(file.getName());
// try-with-resources so that fis can be closed properly even when error occurs
try (FileInputStream fis = new FileInputStream(file)) {
// Input stream of the file
......
......@@ -32,6 +32,10 @@ public abstract class InstructionGenerator<T extends Instruction> implements Nod
protected LabelInstruction currBreakJumpToLabel;
protected LabelInstruction currContinueJumpToLabel;
/* used when a break/jump occure in a loop statment, accumulated on entering scope */
protected int breakSectionStackSize;
protected int continueSectionStackSize;
public InstructionGenerator() {
instructions = new ArrayList<>();
currSymbolTable = null;
......@@ -40,5 +44,7 @@ public abstract class InstructionGenerator<T extends Instruction> implements Nod
currBreakJumpToLabel = null;
currContinueJumpToLabel = null;
currForLoopSymbolTable = null;
breakSectionStackSize = 0;
continueSectionStackSize = 0;
}
}
......@@ -30,7 +30,6 @@ import frontend.node.expr.*;
import frontend.node.expr.BinopNode.Binop;
import frontend.node.expr.UnopNode.Unop;
import frontend.node.stat.*;
import frontend.node.stat.JumpNode.JumpContext;
import frontend.node.stat.JumpNode.JumpType;
import frontend.node.stat.SwitchNode.CaseStat;
import frontend.type.Type;
......@@ -42,12 +41,10 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import utils.NodeVisitor;
import utils.backend.LabelGenerator;
import utils.backend.register.arm.ARMConcreteRegister;
import utils.backend.register.arm.ARMConcreteRegisterAllocator;
import utils.backend.register.Register;
import utils.frontend.symbolTable.SymbolTable;
public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction> {
......@@ -71,9 +68,6 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
/* call getLabel() on msgLabelGenerator to get label in the format of "msg_0, msg_1, msg_2, ..."*/
protected final LabelGenerator<Label> msgLabelGenerator;
/* used when a break/jump occure in a loop statment, accumulated on entering scope */
private int sectionStackSize;
/* used for mapping type with its print routine function */
private final Map<Type, RoutineInstruction> typeRoutineMap = Map.of(
INT_BASIC_TYPE, PRINT_INT,
......@@ -82,9 +76,6 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
STRING_BASIC_TYPE, PRINT_STRING,
CHAR_ARRAY_TYPE, PRINT_STRING
);
/* recording the jump-to label for branching statement, i.e. break, continue */
private Label currBreakJumpToLabel;
private Label currContinueJumpToLabel;
public ARMInstructionGenerator() {
super();
......@@ -677,7 +668,8 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
/* accumulate function stack size, in case this scope is a function scope and contain return */
funcStackSize += stackSize;
sectionStackSize += stackSize;
breakSectionStackSize += stackSize;
continueSectionStackSize += stackSize;
/* 2 visit statements
* set currentSymbolTable here, eliminate all other set symbol table in other statNode */
......@@ -689,7 +681,8 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
/* decrease function stack size, as from this point stack is freed by the scope, not by return */
funcStackSize -= stackSize;
sectionStackSize -= stackSize;
breakSectionStackSize -= stackSize;
continueSectionStackSize -= stackSize;
/* 3 restore stack */
incStack(stackSize);
......@@ -716,22 +709,25 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
Label nextLabel = branchLabelGenerator.getLabel().asArmLabel();
/* restore the last jump-to label after visiting the while-loop body */
Label lastBreakJumpToLabel = currBreakJumpToLabel;
Label lastContinueJumpToLabel = currContinueJumpToLabel;
Label lastBreakJumpToLabel = currBreakJumpToLabel == null ? null : currBreakJumpToLabel.asArmLabel();
Label lastContinueJumpToLabel = currContinueJumpToLabel == null ? null : currContinueJumpToLabel.asArmLabel();
currBreakJumpToLabel = nextLabel;
currContinueJumpToLabel = testLabel;
instructions.add(startLabel);
/* record how much stack parent loop used */
int prevLoopSize = sectionStackSize;
sectionStackSize = 0;
int prevBreakLoopSize = breakSectionStackSize;
int prevContinueLoopSize = continueSectionStackSize;
breakSectionStackSize = 0;
continueSectionStackSize = 0;
/* 3 loop body */
visit(node.getBody());
/* restore parent loop stack size */
sectionStackSize = prevLoopSize;
breakSectionStackSize = prevBreakLoopSize;
continueSectionStackSize = prevContinueLoopSize;
currBreakJumpToLabel = lastBreakJumpToLabel;
currContinueJumpToLabel = lastContinueJumpToLabel;
......@@ -863,30 +859,31 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
Label incrementLabel = branchLabelGenerator.getLabel().asArmLabel();
/* restore the last jump-to label after visiting the for-loop body */
Label lastBreakJumpToLabel = currBreakJumpToLabel;
Label lastContinueJumpToLabel = currContinueJumpToLabel;
Label lastBreakJumpToLabel = currBreakJumpToLabel == null ? null : currBreakJumpToLabel.asArmLabel();
Label lastContinueJumpToLabel = currContinueJumpToLabel == null ? null : currContinueJumpToLabel.asArmLabel();
currBreakJumpToLabel = nextLabel;
currContinueJumpToLabel = incrementLabel;
instructions.add(new B(NULL, condLabel.getName()));
instructions.add(bodyLabel);
currForLoopSymbolTable = node.getBody().getScope();
/* record now much stack loop body have occupied */
int prevLoopSize = sectionStackSize;
sectionStackSize = 0;
int prevBreakLoopSize = breakSectionStackSize;
int prevContinueLoopSize = continueSectionStackSize;
breakSectionStackSize = 0;
continueSectionStackSize = 0;
visit(node.getBody());
/* restore parent loop stack size */
sectionStackSize = prevLoopSize;
breakSectionStackSize = prevBreakLoopSize;
continueSectionStackSize = prevContinueLoopSize;
/* here we also need to append the for-loop increment at the end */
instructions.add(incrementLabel);
visit(node.getIncrement());
// todo: is here the intended behavior
currBreakJumpToLabel = lastBreakJumpToLabel;
currContinueJumpToLabel = lastContinueJumpToLabel;
......@@ -914,13 +911,12 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
@Override
public Void visitJumpNode(JumpNode node) {
List<Instruction> addStack = new ArrayList<>();
/* this snippet is to deal with for-loop stack difference */
incStack(sectionStackSize);
if (node.getJumpType().equals(JumpType.BREAK)) {
/* this snippet is to deal with for-loop stack difference */
incStack(breakSectionStackSize);
instructions.add(new B(NULL, currBreakJumpToLabel.getName()));
} else if (node.getJumpType().equals(JumpType.CONTINUE)) {
incStack(continueSectionStackSize);
instructions.add(new B(NULL, currContinueJumpToLabel.getName()));
}
......@@ -946,34 +942,28 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
Label afterLabel = branchLabelGenerator.getLabel().asArmLabel();
/* restore the jump-to label after visiting the switch cases and default */
Label lastBreakJumpToLabel = currBreakJumpToLabel;
Label lastBreakJumpToLabel = currBreakJumpToLabel == null ? null : currBreakJumpToLabel.asArmLabel();
currBreakJumpToLabel = afterLabel;
instructions.add(new B(NULL, defaultLabel.getName()));
for (int i = 0; i < cLabels.size(); i++) {
instructions.add(cLabels.get(i));
/* record now much stack switch body have occupied
* */
int prevLoopSize = sectionStackSize;
sectionStackSize = 0;
/* record now much stack switch body have occupied */
int prevLoopSize = breakSectionStackSize;
breakSectionStackSize = 0;
visit(node.getCases().get(i).getBody());
/* restore parent switch stack size */
sectionStackSize = prevLoopSize;
breakSectionStackSize = prevLoopSize;
}
int prevLoopSize = sectionStackSize;
sectionStackSize = 0;
int prevLoopSize = breakSectionStackSize;
breakSectionStackSize = 0;
instructions.add(defaultLabel);
visit(node.getDefault());
sectionStackSize = prevLoopSize;
breakSectionStackSize = prevLoopSize;
currBreakJumpToLabel = lastBreakJumpToLabel;
instructions.add(afterLabel);
......
package backend.intel;
import backend.Instruction;
import backend.InstructionGenerator;
import backend.arm.instructions.B;
import backend.arm.instructions.addressing.Operand2;
import backend.intel.instructions.*;
import backend.intel.instructions.Mov.IntelMovType;
import backend.intel.instructions.address.IntelAddress;
......@@ -86,15 +83,7 @@ public class IntelInstructionGenerator extends InstructionGenerator<IntelInstruc
* Level 0: set by funcNode
* Level 1: function top level
* Level 2+: not function top level */
int funcLevel;
/* stack size used by scopes in a loop/switch statement, excluding init/increment statement size in for loop
* BREAK and CONTINUE are responsible for adding rbp back by sectionStackSize amount */
int sectionStackSize;
/* stack of label, BREAK and CONTINUE should jump to top of these stack records */
private Stack<Label> breakJumpToLabelStack;
private Stack<Label> continueJumpToLabelStack;
private int funcLevel;
public IntelInstructionGenerator() {
branchLabelGenerator = new LabelGenerator<>(".L", Label.class);
......@@ -104,9 +93,8 @@ public class IntelInstructionGenerator extends InstructionGenerator<IntelInstruc
biDataSection = new LinkedHashMap<>();
currParamListSize = 0;
funcLevel = 0;
sectionStackSize = 0;
breakJumpToLabelStack = new Stack<>();
continueJumpToLabelStack = new Stack<>();
breakSectionStackSize = 0;
continueSectionStackSize = 0;
}
@Override
......@@ -253,10 +241,6 @@ public class IntelInstructionGenerator extends InstructionGenerator<IntelInstruc
int paramNum = params.size();
/* assign rbp as rsp, so that new parameters added will not overwrite variables */
// todo: 1 mov should be consistent with moved in parameter size,
// 2 should move to stack below rsp, prevent overwrite variable in using by main body
System.out.println("in function call");
for (int i = paramNum - 1; i >= 0; i--) {
ExprNode expr = params.get(i);
visit(expr);
......@@ -288,15 +272,6 @@ public class IntelInstructionGenerator extends InstructionGenerator<IntelInstruc
int identTypeSize = node.getType().getSize();
/* put pointer that point to ident's value in stack to next available register */
System.out.println("ident " + node.getName() + " has:");
System.out.println("offset " + currSymbolTable.getStackOffset(node.getName(), node.getSymbol()));
System.out.println("paramList size " + currParamListSize);
System.out.println("ident size " + identTypeSize);
System.out.print("ident type ");
node.getType().showType();
System.out.println();
System.out.println();
int offset;
if (funcLevel == 1) {
offset = currSymbolTable.getStackOffset(node.getName(), node.getSymbol())
......@@ -459,8 +434,6 @@ public class IntelInstructionGenerator extends InstructionGenerator<IntelInstruc
visit(node.getRhs());
int identTypeSize = node.getRhs().getType().getSize();
/* TODO: add intel move type here */
int offset;
if (funcLevel == 1) {
offset = node.getScope().lookup(node.getIdentifier()).getStackOffset() - currParamListSize;
......@@ -644,7 +617,6 @@ public class IntelInstructionGenerator extends InstructionGenerator<IntelInstruc
@Override
public Void visitReturnNode(ReturnNode node) {
System.out.println("return with rsp + " + funcStackSize);
visit(node.getExpr());
IntelInstructionSize intelSize = intToIntelSize.get(node.getExpr().getType().getSize());
instructions.add(new Mov(intelRegAllocator.curr().withSize(intelSize), rax.withSize(intelSize)));
......@@ -661,8 +633,6 @@ public class IntelInstructionGenerator extends InstructionGenerator<IntelInstruc
public Void visitScopeNode(ScopeNode node) {
List<StatNode> list = node.getBody();
System.out.println("funcLevel = " + funcLevel);
/* 1 leave space for variables in stack
* special treat for three case:
* for-loop init and increment
......@@ -685,7 +655,8 @@ public class IntelInstructionGenerator extends InstructionGenerator<IntelInstruc
decStack(stackSize);
/* record loop size have increased */
sectionStackSize += stackSize;
breakSectionStackSize += stackSize;
continueSectionStackSize += stackSize;
/* 2 visit statements
* set currentSymbolTable here, eliminate all other set symbol table in other statNode */
......@@ -697,7 +668,8 @@ public class IntelInstructionGenerator extends InstructionGenerator<IntelInstruc
/* 3 restore stack */
incStack(stackSize);
sectionStackSize -= stackSize;
breakSectionStackSize -= stackSize;
continueSectionStackSize -= stackSize;
if (funcLevel == -1) {
/* not in function, no operation */
......@@ -735,9 +707,19 @@ public class IntelInstructionGenerator extends InstructionGenerator<IntelInstruc
instructions.add(startLabel);
/* record how much stack parent loop used */
int prevBreakLoopSize = breakSectionStackSize;
int prevContinueLoopSize = continueSectionStackSize;
breakSectionStackSize = 0;
continueSectionStackSize = 0;
/* 3 loop body */
visit(node.getBody());
/* restore parent loop stack size */
breakSectionStackSize = prevBreakLoopSize;
continueSectionStackSize = prevContinueLoopSize;
currBreakJumpToLabel = lastBreakJumpToLabel;
currContinueJumpToLabel = lastContinueJumpToLabel;
......@@ -760,11 +742,12 @@ public class IntelInstructionGenerator extends InstructionGenerator<IntelInstruc
return null;
}
@Override
@Override
public Void visitForNode(ForNode node) {
/* 1 translate the initiator of the for-loop */
currSymbolTable = node.getIncrement().getScope();
int stackSize = currSymbolTable.getSize();
int stackSize = currSymbolTable.getParentSymbolTable() == null
? 0 : currSymbolTable.getParentSymbolTable().getSize();
decStack(stackSize);
visit(node.getInit());
......@@ -776,8 +759,10 @@ public class IntelInstructionGenerator extends InstructionGenerator<IntelInstruc
Label incrementLabel = branchLabelGenerator.getLabel().asIntelLabel();
/* restore the last jump-to label after visiting the for-loop body */
breakJumpToLabelStack.push(nextLabel);
continueJumpToLabelStack.push(incrementLabel);
Label lastBreakJumpToLabel = currBreakJumpToLabel == null ? null : currBreakJumpToLabel.asIntelLabel();
Label lastContinueJumpToLabel = currContinueJumpToLabel == null ? null : currContinueJumpToLabel.asIntelLabel();
currBreakJumpToLabel = nextLabel;
currContinueJumpToLabel = incrementLabel;
instructions.add(new Jmp(condLabel.getName()));
......@@ -785,20 +770,23 @@ public class IntelInstructionGenerator extends InstructionGenerator<IntelInstruc
currForLoopSymbolTable = node.getBody().getScope();
/* record now much stack loop body have occupied */
int prevLoopSize = sectionStackSize;
sectionStackSize = 0;
int prevBreakLoopSize = breakSectionStackSize;
int prevContinueLoopSize = continueSectionStackSize;
breakSectionStackSize = 0;
continueSectionStackSize = 0;
visit(node.getBody());
/* restore parent loop stack size */
sectionStackSize = prevLoopSize;
breakSectionStackSize = prevBreakLoopSize;
continueSectionStackSize = prevContinueLoopSize;
/* here we also need to append the for-loop increment at the end */
instructions.add(incrementLabel);
visit(node.getIncrement());
breakJumpToLabelStack.pop();
continueJumpToLabelStack.pop();
currBreakJumpToLabel = lastBreakJumpToLabel;
currContinueJumpToLabel = lastContinueJumpToLabel;
/* 3 add label for condition checking */
instructions.add(condLabel);
......@@ -809,7 +797,8 @@ public class IntelInstructionGenerator extends InstructionGenerator<IntelInstruc
currSymbolTable = currSymbolTable.getParentSymbolTable();
IntelConcreteRegister oneReg = intelRegAllocator.allocate();
instructions.add(new Mov(new IntelAddress(1), oneReg));
instructions.add(new Cmp(intelRegAllocator.curr().withSize(IntelInstructionSize.B), oneReg.withSize(IntelInstructionSize.B)));
instructions.add(new Cmp(intelRegAllocator.last().withSize(IntelInstructionSize.B), oneReg.withSize(IntelInstructionSize.B)));
intelRegAllocator.free();
intelRegAllocator.free();
/* 4 conditional branch jump to the start of loop */
instructions.add(new Jmp(E, bodyLabel.getName()));
......@@ -826,14 +815,13 @@ public class IntelInstructionGenerator extends InstructionGenerator<IntelInstruc
@Override
public Void visitJumpNode(JumpNode node) {
List<Instruction> addStack = new ArrayList<>();
/* this snippet is to deal with for-loop stack difference
* don't add stack only when it is a break in switch */
incStack(sectionStackSize);
if (node.getJumpType().equals(JumpNode.JumpType.BREAK)) {
incStack(breakSectionStackSize);
instructions.add(new Jmp(currBreakJumpToLabel.getName()));
} else if (node.getJumpType().equals(JumpNode.JumpType.CONTINUE)) {
/* this snippet is to deal with for-loop stack difference
* don't add stack only when it is a break in switch */
incStack(continueSectionStackSize);
instructions.add(new Jmp(currContinueJumpToLabel.getName()));
}
return null;
......@@ -859,7 +847,7 @@ public class IntelInstructionGenerator extends InstructionGenerator<IntelInstruc
Label afterLabel = branchLabelGenerator.getLabel().asIntelLabel();
/* restore the jump-to label after visiting the switch cases and default */
Label lastBreakJumpToLabel = currBreakJumpToLabel.asIntelLabel();
Label lastBreakJumpToLabel = currBreakJumpToLabel == null ? null : currBreakJumpToLabel.asIntelLabel();
currBreakJumpToLabel = afterLabel;
instructions.add(new Jmp(defaultLabel.getName()));
......@@ -867,25 +855,21 @@ public class IntelInstructionGenerator extends InstructionGenerator<IntelInstruc
for (int i = 0; i < cLabels.size(); i++) {
instructions.add(cLabels.get(i).asIntelLabel());
/* record now much stack switch body have occupied
* */
int prevLoopSize = sectionStackSize;
sectionStackSize = 0;
/* record now much stack switch body have occupied */
int prevLoopSize = breakSectionStackSize;
breakSectionStackSize = 0;
visit(node.getCases().get(i).getBody());
/* restore parent switch stack size */
sectionStackSize = prevLoopSize;
breakSectionStackSize = prevLoopSize;
}
int prevLoopSize = sectionStackSize;
sectionStackSize = 0;
int prevLoopSize = breakSectionStackSize;
breakSectionStackSize = 0;
instructions.add(defaultLabel);
visit(node.getDefault());
sectionStackSize = prevLoopSize;
breakSectionStackSize = prevLoopSize;
currBreakJumpToLabel = lastBreakJumpToLabel;
......@@ -899,7 +883,6 @@ public class IntelInstructionGenerator extends InstructionGenerator<IntelInstruc
/* cannot call get stack size on function body, as that will return 0
* public field used here, so that on visit return statement, return can add stack back */
funcStackSize = node.getFunctionBody().minStackRequired();
System.out.println("in function " + node.getFunctionName());
/* 1 add function label,
* PUSH {lr}
......@@ -924,9 +907,6 @@ public class IntelInstructionGenerator extends InstructionGenerator<IntelInstruc
visit(node.getFunctionBody());
currParamListSize = 0;
/* function always add pop and ltorg at the end of function body */
// instructions.add(new Pop(rbp));
return null;
}
......@@ -949,16 +929,16 @@ public class IntelInstructionGenerator extends InstructionGenerator<IntelInstruc
instructions.add(new Push(Collections.singletonList(rbp)));
instructions.add(new Mov(rsp, rbp));
int rspOffset = Math.max(16, node.getBody().minStackRequired());
System.out.println("#################rsp offset: " + node.getBody().minStackRequired());
instructions.add(new Sub(rspOffset, IntelInstructionSize.Q, rsp));
/* 4 main body */
visit(node.getBody());
instructions.add(new Add(rspOffset, IntelInstructionSize.Q, rsp));
/* 5 set return value and return */
instructions.add(new Mov(new IntelAddress(0), rax.withSize(IntelInstructionSize.L)));
// instructions.add(new Pop(rbp)); // delete by sx119: otherwise cannot pass functionSimple
instructions.add(new Leave());
instructions.add(new CFIEndProc());
instructions.add(new Ret());
......
......@@ -16,6 +16,7 @@ import backend.intel.instructions.Not;
import backend.intel.instructions.Set;
import backend.intel.instructions.Set.IntelSetType;
import backend.intel.instructions.address.IntelAddress;
import frontend.node.expr.ArrayElemNode;
import frontend.node.expr.ArrayNode;
import frontend.node.expr.BinopNode.Binop;
import frontend.node.expr.IdentNode;
......@@ -60,8 +61,13 @@ public abstract class IntelArithmeticLogic extends ArithmeticLogic implements In
int len = 0;
if (op.equals(Unop.LEN)) {
IdentNode id = (IdentNode) expr;
len = ((ArrayNode) (id.getSymbol().getExprNode())).getLength();
if (expr instanceof IdentNode) {
IdentNode id = (IdentNode) expr;
len = ((ArrayNode) (id.getSymbol().getExprNode())).getLength();
} else {
ArrayElemNode elem = (ArrayElemNode) expr;
len = ((ArrayNode) elem.getArray()).getLength();
}
}
Map<Unop, List<Instruction>> m = Map.of(
......
......@@ -143,7 +143,7 @@ public class SemanticChecker extends WACCParserBaseVisitor<Node> {
currSymbolTable = currSymbolTable.getParentSymbolTable();
if (semanticError) {
System.out.println("error found");
System.out.println("semantic errors found in the program!");
System.exit(SEMANTIC_ERROR_CODE);
}
......@@ -554,7 +554,6 @@ public class SemanticChecker extends WACCParserBaseVisitor<Node> {
_init.setAvoidSubStack();
ScopeNode _increment = increment instanceof ScopeNode ? (ScopeNode) increment : new ScopeNode(increment);
_increment.setAvoidSubStack();
// StatNode _body = body instanceof ScopeNode ? body : new ScopeNode(body);
StatNode forNode = new ForNode(_init, cond, _increment, _body);
......
......@@ -87,8 +87,4 @@ public class ScopeNode extends StatNode {
}
return scope.getSize();
}
// public int getMaxAccumulativeDepth() {
// return maxAccumulativeDepth;
// }
}
......@@ -433,19 +433,19 @@ public class ConstantPropagation implements NodeVisitor<Node> {
@Override
public Node visitStructElemNode(StructElemNode node) {
// todo: support constant propagation on struct, same difficulty as array, pair
/* Not yet supporting this type of constant propagation */
return node;
}
@Override
public Node visitStructNode(StructNode node) {
// todo: support constant propagation on struct, same difficulty as array, pair
/* Not yet supporting this type of constant propagation */
return node;
}
@Override
public Node visitStructDeclareNode(StructDeclareNode node) {
// todo: support constant propagation on struct, same difficulty as array, pair
/* Not yet supporting this type of constant propagation */
return node;
}
......