/** * Entry function which will process the assembled code and perform the required actions */ struct value_defn processAssembledCode(char * assembled, unsigned int currentPoint, unsigned int length) { struct value_defn empty; empty.type=NONE_TYPE; empty.dtype=SCALAR; unsigned int i, fnAddr; for (i=currentPoint; i<length;) { unsigned char command=getUChar(&assembled[i]); i+=sizeof(unsigned char); if (command == LET_TOKEN) i=handleLet(assembled, i, length, 0); if (command == LETNOALIAS_TOKEN) i=handleLet(assembled, i, length, 1); if (command == ARRAYSET_TOKEN) i=handleArraySet(assembled, i, length); if (command == STOP_TOKEN) return empty; if (command == IF_TOKEN) i=handleIf(assembled, i, length); if (command == IFELSE_TOKEN) i=handleIf(assembled, i, length); if (command == FOR_TOKEN) i=handleFor(assembled, i, length); if (command == GOTO_TOKEN) i=handleGoto(assembled, i, length); if (command == FNCALL_TOKEN || command == FNCALL_BY_VAR_TOKEN) { i=handleFnCall(assembled, i, &fnAddr, length, command == FNCALL_BY_VAR_TOKEN ? 1:0); fnLevel++; processAssembledCode(assembled, fnAddr, length); clearVariablesToLevel(fnLevel); fnLevel--; } if (command == NATIVE_TOKEN) i=handleNative(assembled, i, length, NULL); if (command == RETURN_TOKEN) return empty; if (command == RETURN_EXP_TOKEN) { return getExpressionValue(assembled, &i, length); } if (stopInterpreter) return empty; } return empty; }
/** * Entry function which will process the assembled code and perform the required actions */ void processAssembledCode(char * assembled, unsigned int length, unsigned short numberSymbols, int coreId, int numberActiveCores, int baseHostPid) { stopInterpreter=0; currentSymbolEntries=0; localCoreId=coreId; numActiveCores=numberActiveCores; symbolTable=initialiseSymbolTable(numberSymbols); hostCoresBasePid=baseHostPid; unsigned int i; for (i=0;i<length;) { unsigned short command=getUShort(&assembled[i]); i+=sizeof(unsigned short); if (command == LET_TOKEN) i=handleLet(assembled, i); if (command == ARRAYSET_TOKEN) i=handleArraySet(assembled, i); if (command == DIMARRAY_TOKEN) i=handleDimArray(assembled, i, 0); if (command == DIMSHAREDARRAY_TOKEN) i=handleDimArray(assembled, i, 1); if (command == PRINT_TOKEN) i=handlePrint(assembled, i); if (command == STOP_TOKEN) return; if (command == SYNC_TOKEN) i=handleSync(assembled, i); if (command == IF_TOKEN) i=handleIf(assembled, i); if (command == IFELSE_TOKEN) i=handleIf(assembled, i); if (command == FOR_TOKEN) i=handleFor(assembled, i); if (command == GOTO_TOKEN) i=handleGoto(assembled, i); if (command == INPUT_TOKEN) i=handleInput(assembled, i); if (command == INPUT_STRING_TOKEN) i=handleInputWithString(assembled, i); if (command == SEND_TOKEN) i=handleSend(assembled, i); if (command == RECV_TOKEN) i=handleRecv(assembled, i); if (command == RECVTOARRAY_TOKEN) i=handleRecvToArray(assembled, i); if (command == SENDRECV_TOKEN) i=handleSendRecv(assembled, i); if (command == SENDRECVARRAY_TOKEN) i=handleSendRecvArray(assembled, i); if (command == BCAST_TOKEN) i=handleBcast(assembled, i); if (command == REDUCTION_TOKEN) i=handleReduction(assembled, i); if (stopInterpreter) return; } }
static struct value_defn getExpressionValue(char * assembled, unsigned int * currentPoint, unsigned int length, int threadId) { #else static struct value_defn getExpressionValue(char * assembled, unsigned int * currentPoint, unsigned int length) { #endif struct value_defn value; unsigned char expressionId=getUChar(&assembled[*currentPoint]); *currentPoint+=sizeof(unsigned char); if (expressionId == INTEGER_TOKEN) { value.type=INT_TYPE; value.dtype=SCALAR; cpy(value.data, &assembled[*currentPoint], sizeof(int)); *currentPoint+=sizeof(int); } else if (expressionId == REAL_TOKEN) { value.type=REAL_TYPE; value.dtype=SCALAR; cpy(value.data, &assembled[*currentPoint], sizeof(float)); *currentPoint+=sizeof(float); } else if (expressionId == BOOLEAN_TOKEN) { value.type=BOOLEAN_TYPE; value.dtype=SCALAR; cpy(value.data, &assembled[*currentPoint], sizeof(int)); *currentPoint+=sizeof(int); } else if (expressionId == STRING_TOKEN) { value.type=STRING_TYPE; char * strPtr=assembled + *currentPoint; cpy(&value.data, &strPtr, sizeof(char*)); *currentPoint+=(slength(strPtr)+1); value.dtype=SCALAR; } else if (expressionId == NONE_TOKEN) { value.type=NONE_TYPE; value.dtype=SCALAR; } else if (expressionId ==FN_ADDR_TOKEN) { value.type=FN_ADDR_TYPE; value.dtype=SCALAR; cpy(value.data, &assembled[*currentPoint], sizeof(unsigned short)); *currentPoint+=sizeof(unsigned short); } else if (expressionId == LET_TOKEN) { #ifdef HOST_INTERPRETER *currentPoint=handleLet(assembled, *currentPoint, length, 0, threadId); value=getExpressionValue(assembled, currentPoint, length, threadId); #else *currentPoint=handleLet(assembled, *currentPoint, length, 0); value=getExpressionValue(assembled, currentPoint, length); #endif } else if (expressionId == ARRAY_TOKEN) { int i, j, repetitionMultiplier=1, numItems=getInt(&assembled[*currentPoint]), totalSize=numItems; *currentPoint+=sizeof(int); unsigned char hasRepetition=getUChar(&assembled[*currentPoint]), ndims=1; *currentPoint+=sizeof(unsigned char); if (hasRepetition) { #ifdef HOST_INTERPRETER struct value_defn repetitionV=getExpressionValue(assembled, currentPoint, length, threadId); #else struct value_defn repetitionV=getExpressionValue(assembled, currentPoint, length); #endif cpy(&repetitionMultiplier, repetitionV.data, sizeof(int)); totalSize*=repetitionMultiplier; } #ifdef HOST_INTERPRETER char * address=getHeapMemory(sizeof(unsigned char) + (sizeof(int)*(totalSize+1)), 0, threadId); #else char * address=getHeapMemory(sizeof(unsigned char) + (sizeof(int)*(totalSize+1)), 0, currentSymbolEntries, symbolTable); #endif cpy(value.data, &address, sizeof(char*)); ndims=ndims | (1 << 4); cpy(address, &ndims, sizeof(unsigned char)); address+=sizeof(unsigned char); cpy(address, &totalSize, sizeof(int)); unsigned int prevCP=*currentPoint; for (j=0; j<repetitionMultiplier; j++) { *currentPoint=prevCP; for (i=0; i<numItems; i++) { #ifdef HOST_INTERPRETER struct value_defn itemV=getExpressionValue(assembled, currentPoint, length, threadId); #else struct value_defn itemV=getExpressionValue(assembled, currentPoint, length); #endif cpy(address+((i+(j*numItems)+1) * sizeof(int)), itemV.data, sizeof(int)); value.type=itemV.type; } } value.dtype=ARRAY; } else if (expressionId == FNCALL_TOKEN || expressionId == FNCALL_BY_VAR_TOKEN) { #ifdef HOST_INTERPRETER unsigned int fnAddr; *currentPoint=handleFnCall(assembled, *currentPoint, &fnAddr, length, expressionId == FNCALL_BY_VAR_TOKEN ? 1:0, threadId); fnLevel[threadId]++; value=processAssembledCode(assembled, fnAddr, length, threadId); clearVariablesToLevel(fnLevel[threadId], threadId); fnLevel[threadId]--; #else unsigned int fnAddr; *currentPoint=handleFnCall(assembled, *currentPoint, &fnAddr, length, expressionId == FNCALL_BY_VAR_TOKEN ? 1:0); fnLevel++; value=processAssembledCode(assembled, fnAddr, length); clearVariablesToLevel(fnLevel); fnLevel--; #endif } else if (expressionId == NATIVE_TOKEN) { #ifdef HOST_INTERPRETER *currentPoint=handleNative(assembled, *currentPoint, length, &value, threadId); #else *currentPoint=handleNative(assembled, *currentPoint, length, &value); #endif } else if (expressionId == IDENTIFIER_TOKEN || expressionId == ARRAYACCESS_TOKEN) { unsigned short variable_id=getUShort(&assembled[*currentPoint]); *currentPoint+=sizeof(unsigned short); #ifdef HOST_INTERPRETER struct symbol_node* variableSymbol=getVariableSymbol(variable_id, fnLevel[threadId], threadId, 1); #else struct symbol_node* variableSymbol=getVariableSymbol(variable_id, fnLevel, 1); #endif if (expressionId == IDENTIFIER_TOKEN) { if (variableSymbol->value.dtype==SCALAR) { value=getVariableValue(variableSymbol, -1); } else if (variableSymbol->value.dtype==ARRAY) { value.dtype=ARRAY; value.type=variableSymbol->value.type; cpy(value.data, variableSymbol->value.data, sizeof(char*)); } } else if (expressionId == ARRAYACCESS_TOKEN) { #ifdef HOST_INTERPRETER int targetIndex=getArrayAccessorIndex(variableSymbol, assembled, currentPoint, length, threadId); #else int targetIndex=getArrayAccessorIndex(variableSymbol, assembled, currentPoint, length); #endif value=getVariableValue(variableSymbol, targetIndex); } } else if (expressionId == ADD_TOKEN || expressionId == SUB_TOKEN || expressionId == MUL_TOKEN || expressionId == DIV_TOKEN || expressionId == MOD_TOKEN || expressionId == POW_TOKEN) { #ifdef HOST_INTERPRETER value=computeExpressionResult(expressionId, assembled, currentPoint, length, threadId); #else value=computeExpressionResult(expressionId, assembled, currentPoint, length); #endif } else if (expressionId == EQ_TOKEN || expressionId == NEQ_TOKEN || expressionId == GT_TOKEN || expressionId == GEQ_TOKEN || expressionId == LT_TOKEN || expressionId == LEQ_TOKEN || expressionId == IS_TOKEN) { *currentPoint-=sizeof(unsigned char); #ifdef HOST_INTERPRETER int retVal=determine_logical_expression(assembled, currentPoint, length, threadId); #else int retVal=determine_logical_expression(assembled, currentPoint, length); #endif value.type=BOOLEAN_TYPE; value.dtype=SCALAR; cpy(value.data, &retVal, sizeof(int)); } return value; } /** * Computes the result of a simple mathematical expression, if one is a real and the other an integer * then raises to be a real */ #ifdef HOST_INTERPRETER static struct value_defn computeExpressionResult(unsigned char operator, char * assembled, unsigned int * currentPoint, unsigned int length, int threadId) { #else static struct value_defn computeExpressionResult(unsigned char operator, char * assembled, unsigned int * currentPoint, unsigned int length) { #endif struct value_defn value; #ifdef HOST_INTERPRETER struct value_defn v1=getExpressionValue(assembled, currentPoint, length, threadId); struct value_defn v2=getExpressionValue(assembled, currentPoint, length, threadId); #else struct value_defn v1=getExpressionValue(assembled, currentPoint, length); struct value_defn v2=getExpressionValue(assembled, currentPoint, length); #endif value.type=v1.type==INT_TYPE && v2.type==INT_TYPE ? INT_TYPE : v1.type==STRING_TYPE || v2.type==STRING_TYPE ? STRING_TYPE : REAL_TYPE; value.dtype=SCALAR; if (value.type==INT_TYPE) { int i, value1=getInt(v1.data), value2=getInt(v2.data), result; if (operator==ADD_TOKEN) result=value1+value2; if (operator==SUB_TOKEN) result=value1-value2; if (operator==MUL_TOKEN) result=value1*value2; if (operator==DIV_TOKEN) result=value1/value2; if (operator==MOD_TOKEN) result=value1%value2; if (operator==POW_TOKEN) { result=value2 == 0 ? 1 : value1; for (i=1; i<value2; i++) result=result*value1; } cpy(&value.data, &result, sizeof(int)); } else if (value.type==REAL_TYPE) { float value1=getFloat(v1.data); float value2=getFloat(v2.data); float result; if (v1.type==INT_TYPE) value1=(float) getInt(v1.data); if (v2.type==INT_TYPE) { value2=(float) getInt(v2.data); if (operator == POW_TOKEN) { int i; result=value2 == 0 ? 1 : value1; for (i=1; i<(int) value2; i++) result=result*value1; } } if (operator == ADD_TOKEN) result=value1+value2; if (operator == SUB_TOKEN) result=value1-value2; if (operator == MUL_TOKEN) result=value1*value2; if (operator == DIV_TOKEN) result=value1/value2; cpy(&value.data, &result, sizeof(float)); } else if (value.type==STRING_TYPE) { if (operator == ADD_TOKEN) { #ifdef HOST_INTERPRETER return performStringConcatenation(v1, v2, threadId); #else return performStringConcatenation(v1, v2, currentSymbolEntries, symbolTable); #endif } else { raiseError(ERR_ONLY_ADDITION_STR); } } return value; } /** * Retrieves the absolute array target index based upon the provided index expression(s) and dimensions of the array itself. Does some error checking * to ensure that the configured values do not exceed the size */ #ifdef HOST_INTERPRETER static int getArrayAccessorIndex(struct symbol_node* variableSymbol, char * assembled, unsigned int * currentPoint, unsigned int length, int threadId) { #else static int getArrayAccessorIndex(struct symbol_node* variableSymbol, char * assembled, unsigned int * currentPoint, unsigned int length) { #endif struct value_defn index; int i, j, runningWeight, spec_weight, num_weights, specificIndex=0, provIdx; unsigned int totSize=1; unsigned char num_dims=getUChar(&assembled[*currentPoint]), array_dims, needsExtension=0, allowedExtension; *currentPoint+=sizeof(unsigned char); char * arraymemory; cpy(&arraymemory, variableSymbol->value.data, sizeof(char*)); cpy(&array_dims, arraymemory, sizeof(unsigned char)); allowedExtension=(array_dims >> 4) & 1; array_dims=array_dims&0xF; arraymemory+=sizeof(unsigned char); if (num_dims > array_dims) raiseError(ERR_TOO_MANY_ARR_INDEX); for (i=0; i<num_dims; i++) { num_weights=array_dims-(i+1); runningWeight=1; for (j=num_weights; j<0; j--) { cpy(&spec_weight, &arraymemory[sizeof(int) * (array_dims-j)], sizeof(int)); runningWeight*=spec_weight; } #ifdef HOST_INTERPRETER index=getExpressionValue(assembled, currentPoint, length, threadId); #else index=getExpressionValue(assembled, currentPoint, length); #endif cpy(&spec_weight, &arraymemory[sizeof(int) * i], sizeof(int)); totSize*=spec_weight; provIdx=getInt(index.data); if (provIdx < 0) { raiseError(ERR_NEG_ARR_INDEX); } else if (provIdx >= spec_weight) { if (!allowedExtension) raiseError(ERR_ARR_INDEX_EXCEED_SIZE); spec_weight=provIdx+1; cpy(&arraymemory[sizeof(int) * i], &spec_weight, sizeof(int)); needsExtension=1; } specificIndex+=(runningWeight * provIdx); } if (needsExtension) { unsigned int newSize=1; for (i=0; i<num_dims; i++) { cpy(&spec_weight, &arraymemory[sizeof(int) * i], sizeof(int)); newSize*=spec_weight; } #ifdef HOST_INTERPRETER char * newmem=getHeapMemory((sizeof(int) * newSize) + (sizeof(int) * num_dims) + sizeof(unsigned char), 0, threadId); #else char * newmem=getHeapMemory((sizeof(int) * newSize) + (sizeof(int) * num_dims) + sizeof(unsigned char), 0, currentSymbolEntries, symbolTable); #endif arraymemory-=sizeof(unsigned char); cpy(newmem, arraymemory, (sizeof(int) * totSize) + (sizeof(int) * num_dims) + sizeof(unsigned char)); #ifdef HOST_INTERPRETER freeMemoryInHeap(arraymemory, threadId); #else freeMemoryInHeap(arraymemory); #endif cpy(variableSymbol->value.data, &newmem, sizeof(char*)); } return specificIndex; } /** * Retrieves the symbol entry of a variable based upon its id */ #ifdef HOST_INTERPRETER static struct symbol_node* getVariableSymbol(unsigned short id, unsigned char lvl, int threadId, int followAlias) { #else static struct symbol_node* getVariableSymbol(unsigned short id, unsigned char lvl, int followAlias) { #endif int i; #ifdef HOST_INTERPRETER for (i=0; i<=currentSymbolEntries[threadId]; i++) { if (symbolTable[threadId][i].id == id && symbolTable[threadId][i].state != UNALLOCATED && (symbolTable[threadId][i].level == 0 || symbolTable[threadId][i].level==lvl)) { if (followAlias && symbolTable[threadId][i].state == ALIAS) { return getVariableSymbol(symbolTable[threadId][i].alias, lvl-1, threadId, 1); } else { return &(symbolTable[threadId])[i]; } } #else for (i=0; i<=currentSymbolEntries; i++) { if (symbolTable[i].id == id && symbolTable[i].state != UNALLOCATED && (symbolTable[i].level == 0 || symbolTable[i].level==lvl)) { if (followAlias && symbolTable[i].state == ALIAS) { return getVariableSymbol(symbolTable[i].alias, lvl-1, 1); } else { return &symbolTable[i]; } } #endif } int zero=0; #ifdef HOST_INTERPRETER int newEntryLocation=getSymbolTableEntryId(threadId); symbolTable[threadId][newEntryLocation].id=id; symbolTable[threadId][newEntryLocation].state=ALLOCATED; symbolTable[threadId][newEntryLocation].level=lvl; symbolTable[threadId][newEntryLocation].value.type=INT_TYPE; cpy(symbolTable[threadId][newEntryLocation].value.data, &zero, sizeof(int)); return &symbolTable[threadId][newEntryLocation]; #else int newEntryLocation=getSymbolTableEntryId(); symbolTable[newEntryLocation].id=id; symbolTable[newEntryLocation].level=lvl; symbolTable[newEntryLocation].state=ALLOCATED; symbolTable[newEntryLocation].value.type=INT_TYPE; symbolTable[newEntryLocation].value.dtype=SCALAR; cpy(symbolTable[newEntryLocation].value.data, &zero, sizeof(int)); return &symbolTable[newEntryLocation]; #endif } #ifdef HOST_INTERPRETER static int getSymbolTableEntryId(int threadId) { #else static int getSymbolTableEntryId(void) { #endif int i; #ifdef HOST_INTERPRETER for (i=0; i<=currentSymbolEntries[threadId]; i++) { if (symbolTable[threadId][i].state == UNALLOCATED) return i; } return ++currentSymbolEntries[threadId]; #else for (i=0; i<=currentSymbolEntries; i++) { if (symbolTable[i].state == UNALLOCATED) return i; } return ++currentSymbolEntries; #endif } #ifdef HOST_INTERPRETER static void clearVariablesToLevel(unsigned char clearLevel, int threadId) { #else static void clearVariablesToLevel(unsigned char clearLevel) { #endif int i; char * smallestMemoryAddress=0, *ptr; #ifdef HOST_INTERPRETER for (i=0; i<=currentSymbolEntries[threadId]; i++) { if (symbolTable[threadId][i].level >= clearLevel && symbolTable[threadId][i].state != UNALLOCATED) { symbolTable[threadId][i].state=UNALLOCATED; if (symbolTable[threadId][i].value.dtype==SCALAR && symbolTable[threadId][i].value.type != STRING_TYPE) { cpy(&ptr, symbolTable[threadId][i].value.data, sizeof(int*)); if (ptr != 0 && (smallestMemoryAddress == 0 || smallestMemoryAddress > ptr)) smallestMemoryAddress=ptr; } } } #else for (i=0; i<=currentSymbolEntries; i++) { if (symbolTable[i].level >= clearLevel && symbolTable[i].state != UNALLOCATED) { symbolTable[i].state=UNALLOCATED; if (symbolTable[i].value.dtype==SCALAR && symbolTable[i].value.type != STRING_TYPE) { cpy(&ptr, symbolTable[i].value.data, sizeof(char*)); if (ptr != 0 && (smallestMemoryAddress == 0 || smallestMemoryAddress > ptr)) smallestMemoryAddress=ptr; } } } #endif if (smallestMemoryAddress != 0) clearFreedStackFrames(smallestMemoryAddress); } /** * Sets a variables value in memory as pointed to by symbol table */ void setVariableValue(struct symbol_node* variableSymbol, struct value_defn value, int index) { variableSymbol->value.type=value.type; if (value.type == STRING_TYPE) { cpy(&variableSymbol->value.data, &value.data, sizeof(char*)); } else { int currentAddress=getInt(variableSymbol->value.data); if (currentAddress == 0) { char * address=getStackMemory(sizeof(int) * index, 0); cpy(variableSymbol->value.data, &address, sizeof(char*)); cpy(address+((index+1) *4), value.data, sizeof(int)); } else { char * ptr; cpy(&ptr, variableSymbol->value.data, sizeof(char*)); if (variableSymbol->value.dtype == ARRAY) { unsigned char num_dims; cpy(&num_dims, ptr, sizeof(unsigned char)); num_dims=num_dims & 0xF; ptr+=((index+num_dims)*sizeof(int)) + sizeof(unsigned char); } else { ptr+=(index+1)*sizeof(int); } cpy(ptr, value.data, sizeof(int)); } } } /** * Retrieves a variable value from memory, which the symbol table points to */ struct value_defn getVariableValue(struct symbol_node* variableSymbol, int index) { struct value_defn val; val.type=variableSymbol->value.type; val.dtype=SCALAR; if (variableSymbol->value.type == STRING_TYPE) { cpy(&val.data, &variableSymbol->value.data, sizeof(int*)); } else { char * ptr; cpy(&ptr, variableSymbol->value.data, sizeof(char*)); if (variableSymbol->value.dtype == ARRAY) { unsigned char num_dims; cpy(&num_dims, ptr, sizeof(unsigned char)); num_dims=num_dims & 0xF; ptr+=((index+num_dims)*sizeof(int)) + sizeof(unsigned char); } else { ptr+=(index+1)*sizeof(int); } cpy(val.data, ptr, sizeof(char*)); } return val; } static unsigned char getUChar(void* data) { unsigned char v; cpy(&v, data, sizeof(unsigned char)); return v; } /** * Helper method to get an unsigned short from data (needed as casting to integer directly requires 4 byte alignment * which we do not want to enforce as it wastes memory.) */ static unsigned short getUShort(void* data) { unsigned short v; cpy(&v, data, sizeof(unsigned short)); return v; }