$search
00001 /* 00002 Aseba - an event-based framework for distributed robot control 00003 Copyright (C) 2007--2012: 00004 Stephane Magnenat <stephane at magnenat dot net> 00005 (http://stephane.magnenat.net) 00006 and other contributors, see authors.txt for details 00007 00008 This program is free software: you can redistribute it and/or modify 00009 it under the terms of the GNU Lesser General Public License as published 00010 by the Free Software Foundation, version 3 of the License. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU Lesser General Public License for more details. 00016 00017 You should have received a copy of the GNU Lesser General Public License 00018 along with this program. If not, see <http://www.gnu.org/licenses/>. 00019 */ 00020 00021 #include "compiler.h" 00022 #include "../common/consts.h" 00023 #include <cassert> 00024 #include <iostream> 00025 00026 namespace Aseba 00027 { 00030 00032 bool Compiler::verifyStackCalls(PreLinkBytecode& preLinkBytecode) 00033 { 00034 // check stack for events 00035 for (PreLinkBytecode::EventsBytecode::iterator it = preLinkBytecode.events.begin(); it != preLinkBytecode.events.end(); ++it) 00036 { 00037 if (it->second.maxStackDepth > targetDescription->stackSize) 00038 return false; 00039 00040 const BytecodeVector& bytecode = it->second; 00041 for (size_t pc = 0; pc < bytecode.size();) 00042 { 00043 switch (bytecode[pc] >> 12) 00044 { 00045 case ASEBA_BYTECODE_SUB_CALL: 00046 { 00047 unsigned id = bytecode[pc] & 0x0fff; 00048 PreLinkBytecode::SubroutinesBytecode::iterator destIt = preLinkBytecode.subroutines.find(id); 00049 assert(destIt != preLinkBytecode.subroutines.end()); 00050 destIt->second.callDepth = 1; 00051 pc += 1; 00052 } 00053 break; 00054 00055 case ASEBA_BYTECODE_LARGE_IMMEDIATE: 00056 case ASEBA_BYTECODE_LOAD_INDIRECT: 00057 case ASEBA_BYTECODE_STORE_INDIRECT: 00058 case ASEBA_BYTECODE_CONDITIONAL_BRANCH: 00059 pc += 2; 00060 break; 00061 00062 case ASEBA_BYTECODE_EMIT: 00063 pc += 3; 00064 break; 00065 00066 default: 00067 pc += 1; 00068 break; 00069 } 00070 } 00071 } 00072 00073 // check stack for subroutines 00074 bool wasActivity; 00075 do 00076 { 00077 wasActivity = false; 00078 for (PreLinkBytecode::SubroutinesBytecode::iterator it = preLinkBytecode.subroutines.begin(); it != preLinkBytecode.subroutines.end(); ++it) 00079 { 00080 unsigned myDepth = it->second.callDepth; 00081 if (myDepth + it->second.maxStackDepth > targetDescription->stackSize) 00082 { 00083 return false; 00084 } 00085 00086 const BytecodeVector& bytecode = it->second; 00087 for (size_t pc = 0; pc < bytecode.size();) 00088 { 00089 switch (bytecode[pc] >> 12) 00090 { 00091 case ASEBA_BYTECODE_SUB_CALL: 00092 { 00093 unsigned id = bytecode[pc] & 0x0fff; 00094 PreLinkBytecode::SubroutinesBytecode::iterator destIt = preLinkBytecode.subroutines.find(id); 00095 assert(destIt != preLinkBytecode.subroutines.end()); 00096 if (myDepth + 1 > destIt->second.callDepth) 00097 { 00098 wasActivity = true; 00099 destIt->second.callDepth = myDepth + 1; 00100 } 00101 pc += 1; 00102 } 00103 break; 00104 00105 case ASEBA_BYTECODE_LARGE_IMMEDIATE: 00106 case ASEBA_BYTECODE_LOAD_INDIRECT: 00107 case ASEBA_BYTECODE_STORE_INDIRECT: 00108 case ASEBA_BYTECODE_CONDITIONAL_BRANCH: 00109 pc += 2; 00110 break; 00111 00112 case ASEBA_BYTECODE_EMIT: 00113 pc += 3; 00114 break; 00115 00116 default: 00117 pc += 1; 00118 break; 00119 } 00120 } 00121 } 00122 } 00123 while (wasActivity); 00124 00125 return true; 00126 } 00127 00130 } // Aseba 00131