/* st-sglobal_infer.cc: infer sglobal qualifiers for methods */ #include "AST.h" #include "compiler.h" #include "decls.h" #include "errors.h" static bool change; static Decl *currentMethod; static void markMethodSglobal() { if (!(currentMethod->modifiers() & Common::Sglobal)) { currentMethod->modifiers((Common::Modifiers)(currentMethod->modifiers() | Common::Sglobal)); change = true; } } // Set sglobal on a method if it assigns a single field or a single // array element (with exception of this.field in constructors) static bool inConstructor; void TreeNode::sglobalData() { foriter (p, allChildren(), ChildIter) (*p)->sglobalData(); } void TemplateDeclNode::sglobalData() { } // Class members void MethodSignatureNode::sglobalData() { // nothing to do } void FieldDeclNode::sglobalData() { } void StaticInitNode::sglobalData() { } void MethodDeclNode::sglobalData() { bool declaredSingle = (decl()->modifiers() & Sglobal) != 0; if (!declaredSingle) { currentMethod = decl(); inConstructor = false; TreeNode::sglobalData(); currentMethod = NULL; } } void ConstructorDeclNode::sglobalData() { bool declaredSingle = (decl()->modifiers() & Sglobal) != 0; if (!declaredSingle) { currentMethod = decl(); inConstructor = true; TreeNode::sglobalData(); currentMethod = NULL; } } void IncrDecrNode::sglobalData() { child(0)->sglobalDataAssign(); } void BinaryArithAssignNode::sglobalData() { child(0)->sglobalDataAssign(); } void ShiftAssignNode::sglobalData() { child(0)->sglobalDataAssign(); } void BitwiseAssignNode::sglobalData() { child(0)->sglobalDataAssign(); } void AssignNode::sglobalData() { child(0)->sglobalDataAssign(); } void StringConcatAssignNode::sglobalData() { child(0)->sglobalDataAssign(); } void MethodCallAssignNode::sglobalData() { method()->object()->sglobalDataAssign(); } void TreeNode::sglobalDataAssign() { undefined("sglobalDataAssign"); } void ObjectNode::sglobalDataAssign() { // Local variables don't count } void ArrayAccessNode::sglobalDataAssign() { if (array()->type()->elementType()->isSingle()) markMethodSglobal(); } void FieldAccessNode::sglobalDataAssign() { if (decl()->type()->isSingle()) markMethodSglobal(); } void ThisFieldAccessNode::sglobalDataAssign() { if (decl()->type()->isSingle() && ((decl()->modifiers() & Static) || !inConstructor)) markMethodSglobal(); } // Set sglobal on a method whenever it may call a method that is sglobal void TreeNode::sglobalCall() { foriter (p, allChildren(), ChildIter) (*p)->sglobalCall(); } void TemplateDeclNode::sglobalCall() { } // Class members void MethodSignatureNode::sglobalCall() { // nothing to do } void FieldDeclNode::sglobalCall() { } void StaticInitNode::sglobalCall() { } void MethodDeclNode::sglobalCall() { bool declaredSingle = (decl()->modifiers() & Sglobal) != 0; if (!declaredSingle) { currentMethod = decl(); TreeNode::sglobalCall(); currentMethod = NULL; } } void ConstructorDeclNode::sglobalCall() { bool declaredSingle = (decl()->modifiers() & Sglobal) != 0; if (!declaredSingle) { currentMethod = decl(); TreeNode::sglobalCall(); currentMethod = NULL; } } void MethodCallNode::sglobalCall() { if (isGlobalCall(decl())) markMethodSglobal(); } void MethodCallAssignNode::sglobalCall() { if (isGlobalCall(decl())) markMethodSglobal(); } void ThisConstructorCallNode::sglobalCall() { if (isGlobalCall(decl())) markMethodSglobal(); } void SuperConstructorCallNode::sglobalCall() { if (decl() && isGlobalCall(decl())) markMethodSglobal(); } void AllocateNode::sglobalCall() { if (isGlobalCall(decl())) markMethodSglobal(); } void sglobalInference(void) { foreach (f, llist, *allFiles) (*f)->sglobalData(); do { change = false; foreach (f, llist, *allFiles) (*f)->sglobalCall(); } while (change); }