void ODSItemState :: ResetState ( ) { ResetValue(); ResetList(); }
CObjectEntry& CObjectEntry::operator=(CObjectEntry& other) { if(this != &other) { *((CObjectEntryBase*)this) = *((CObjectEntryBase*)&other); m_uSubIndex = other.m_uSubIndex; m_DataType = other.m_DataType; m_AccessType = other.m_AccessType; m_oPDOMapping = other.m_oPDOMapping; m_strLowLimit = other.m_strLowLimit; m_strHighLimit = other.m_strHighLimit; m_strDefault = other.m_strDefault; m_strObjFlags = other.m_strObjFlags; m_ValueStringFormat = other.m_ValueStringFormat; //TODO:CHHE091209Can be serialised as soon as DtmEpos and DtmEsam also use this OBD classes //m_Denotation = other.m_Denotation; //m_UniqueId = other.m_UniqueId; ResetValue(); if(other.m_dValueSize > 0) { m_pValue = (BYTE*)malloc(other.m_dValueSize); m_dValueSize = other.m_dValueSize; memcpy(m_pValue, other.m_pValue, other.m_dValueSize); } } return *this; }
ExecReturnCodes OPSynCase :: Execute ( ) { int32 indx0 = 0; ExecReturnCodes rc = ERC_undefined; BEGINSEQ if ( CheckCO() ) ERROR if ( (block_type == CB_CaseBlock) ) { if ( !source ) OQLSERR(99) if ( ExecuteParameter(0) != ERC_success ) ERROR if ( *source->GetValue() != *Parmlist()->GetAt(0)->GetValue() ) LEAVESEQ indx0 = 1; } if ( (rc = ExecuteStatements(indx0)) == ERC_undefined ) // no statements in case rc = ERC_success; RegisterLastValue(); RECOVER ResetValue(); rc = ERC_terminate; ENDSEQ return(rc); }
ExecReturnCodes OPSynWhile :: Execute ( ) { ExecReturnCodes rc = ERC_undefined; BEGINSEQ if ( CheckCO() ) ERROR while ( (rc = ExecuteSource()) == ERC_success ) { if ( !source->GetValue()->IsTrue() ) LEAVESEQ switch ( rc = ExecuteStatement(0) ) { case ERC_terminate : ERROR case ERC_null : case ERC_success : break; case ERC_undefined : // no statements case ERC_continue : rc = ERC_success; break; case ERC_break : rc = ERC_success; default : LEAVESEQ } } RECOVER ResetValue(); rc = ERC_terminate; ENDSEQ if ( rc != ERC_terminate ) RegisterLastValue(); return(rc); }
BOOL CObjectEntry::SetValue(BYTE* pValue, DWORD dValueSize) { BOOL oResult(FALSE); ResetValue(); if(InitValue(dValueSize)) { memcpy(m_pValue, pValue, dValueSize); oResult = TRUE; } return oResult; }
BOOL CObjectEntry::InitValue(DWORD dSize) { BOOL oResult(FALSE); ResetValue(); if(dSize > 0) { m_dValueSize = dSize; m_pValue = (BYTE*)malloc(m_dValueSize); memset(m_pValue, 0, m_dValueSize); oResult = TRUE; } return oResult; }
TEST_F(PropertiesTest, GetString) { // Try to use a default value that's too long => set fails { ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); std::string maxLengthString = std::string(PROPERTY_VALUE_MAX-1, 'a'); std::string oneLongerString = std::string(PROPERTY_VALUE_MAX, 'a'); // Expect that the value is truncated since it's too long (by 1) int len = property_get(PROPERTY_TEST_KEY, mValue, oneLongerString.c_str()); EXPECT_EQ(PROPERTY_VALUE_MAX-1, len); EXPECT_STREQ(maxLengthString.c_str(), mValue); ResetValue(); } }
BOOL CObjectEntry::Reset() { BOOL oResult(TRUE); CObjectEntryBase::Reset(); m_AccessType = AT_READ_ONLY; m_DataType = ODT_UNKNOWN; m_ValueStringFormat = OVF_HEX; m_oPDOMapping = 0; m_strDefault = _T(""); m_strHighLimit = _T(""); m_strLowLimit = _T(""); m_strObjFlags = _T("0"); m_uSubIndex = 0; if(!ResetValue()) oResult = FALSE; return oResult; }
BOOL CObjectEntry::SetValue(CStdString strValue) { CMmcDataConversion conversion; BOOL oResult(FALSE); //Reset ResetValue(); //SetValue switch(m_DataType) { case ODT_BOOLEAN: { if(InitValue(sizeof(WORD))) { if(strValue.CompareNoCase("TRUE") == 0) { *((WORD*)m_pValue) = TRUE; oResult = TRUE; } else { *((WORD*)m_pValue) = FALSE; oResult = TRUE; } } };break; case ODT_INT8: { if(InitValue(sizeof(char))) { oResult = conversion.CharStr2Char(strValue, ((char*)m_pValue), FALSE); } };break; case ODT_INT16: { if(InitValue(sizeof(short))) { oResult = conversion.ShortStr2Short(strValue, ((short*)m_pValue), FALSE); } };break; case ODT_INT32: { if(InitValue(sizeof(long))) { oResult = conversion.LongStr2Long(strValue, ((long*)m_pValue), FALSE); } };break; case ODT_INT64: { if(InitValue(sizeof(__int64))) { oResult = conversion.Int64Str2Int64(strValue, ((__int64*)m_pValue), FALSE); } };break; case ODT_UINT8: { if(InitValue(sizeof(BYTE))) { oResult = conversion.ByteStr2Byte(strValue, ((BYTE*)m_pValue), FALSE); } };break; case ODT_UINT16: { if(InitValue(sizeof(WORD))) { oResult = conversion.WordStr2Word(strValue, ((WORD*)m_pValue)); } };break; case ODT_UINT32: { if(InitValue(sizeof(DWORD))) { oResult = conversion.DWordStr2DWord(strValue, ((DWORD*)m_pValue), FALSE); } };break; case ODT_UINT64: { if(InitValue(sizeof(unsigned __int64))) { oResult = conversion.UInt64Str2UInt64(strValue, ((unsigned __int64*)m_pValue), FALSE); } };break; case ODT_FLOAT: { if(InitValue(sizeof(float))) { oResult = conversion.FloatStr2Float(strValue, ((float*)m_pValue), FALSE); } };break; case ODT_STRING: { if(InitValue(strlen(strValue))*sizeof(TCHAR)) { for(DWORD d=0;d<m_dValueSize;d++) { *((TCHAR*)m_pValue+d) = strValue.GetAt(d); } oResult = TRUE; } };break; } return oResult; }
CObjectEntry::~CObjectEntry() { ResetValue(); }
TEST_F(PropertiesTest, SetString) { // Null key -> unsuccessful set { // Null key -> fails EXPECT_GT(0, property_set(/*key*/NULL, PROPERTY_TEST_VALUE_DEFAULT)); } // Null value -> returns default value { // Null value -> OK , and it clears the value EXPECT_OK(property_set(PROPERTY_TEST_KEY, /*value*/NULL)); ResetValue(); // Since the value is null, default value will be returned size_t len = property_get(PROPERTY_TEST_KEY, mValue, PROPERTY_TEST_VALUE_DEFAULT); EXPECT_EQ(strlen(PROPERTY_TEST_VALUE_DEFAULT), len); EXPECT_STREQ(PROPERTY_TEST_VALUE_DEFAULT, mValue); } // Trivial case => get returns what was set { size_t len = SetAndGetProperty("hello_world"); EXPECT_EQ(strlen("hello_world"), len) << "hello_world key"; EXPECT_STREQ("hello_world", mValue); ResetValue(); } // Set to empty string => get returns default always { const char* EMPTY_STRING_DEFAULT = "EMPTY_STRING"; size_t len = SetAndGetProperty("", EMPTY_STRING_DEFAULT); EXPECT_EQ(strlen(EMPTY_STRING_DEFAULT), len) << "empty key"; EXPECT_STREQ(EMPTY_STRING_DEFAULT, mValue); ResetValue(); } // Set to max length => get returns what was set { std::string maxLengthString = std::string(PROPERTY_VALUE_MAX-1, 'a'); int len = SetAndGetProperty(maxLengthString.c_str()); EXPECT_EQ(PROPERTY_VALUE_MAX-1, len) << "max length key"; EXPECT_STREQ(maxLengthString.c_str(), mValue); ResetValue(); } // Set to max length + 1 => set fails { const char* VALID_TEST_VALUE = "VALID_VALUE"; ASSERT_OK(property_set(PROPERTY_TEST_KEY, VALID_TEST_VALUE)); std::string oneLongerString = std::string(PROPERTY_VALUE_MAX, 'a'); // Expect that the value set fails since it's too long EXPECT_GT(0, property_set(PROPERTY_TEST_KEY, oneLongerString.c_str())); size_t len = property_get(PROPERTY_TEST_KEY, mValue, PROPERTY_TEST_VALUE_DEFAULT); EXPECT_EQ(strlen(VALID_TEST_VALUE), len) << "set should've failed"; EXPECT_STREQ(VALID_TEST_VALUE, mValue); ResetValue(); } }
TEST_F(PropertiesTest, GetString) { // Try to use a default value that's too long => get truncates the value { ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); std::string maxLengthString = std::string(PROPERTY_VALUE_MAX - 1, 'a'); std::string oneLongerString = std::string(PROPERTY_VALUE_MAX, 'a'); // Expect that the value is truncated since it's too long (by 1) int len = property_get(PROPERTY_TEST_KEY, mValue, oneLongerString.c_str()); EXPECT_EQ(PROPERTY_VALUE_MAX - 1, len); EXPECT_STREQ(maxLengthString.c_str(), mValue); ResetValue(); } // Try to use a default value that's the max length => get succeeds { ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); std::string maxLengthString = std::string(PROPERTY_VALUE_MAX - 1, 'b'); // Expect that the value matches maxLengthString int len = property_get(PROPERTY_TEST_KEY, mValue, maxLengthString.c_str()); EXPECT_EQ(PROPERTY_VALUE_MAX - 1, len); EXPECT_STREQ(maxLengthString.c_str(), mValue); ResetValue(); } // Try to use a default value of length one => get succeeds { ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); std::string oneCharString = std::string(1, 'c'); // Expect that the value matches oneCharString int len = property_get(PROPERTY_TEST_KEY, mValue, oneCharString.c_str()); EXPECT_EQ(1, len); EXPECT_STREQ(oneCharString.c_str(), mValue); ResetValue(); } // Try to use a default value of length zero => get succeeds { ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); std::string zeroCharString = std::string(0, 'd'); // Expect that the value matches oneCharString int len = property_get(PROPERTY_TEST_KEY, mValue, zeroCharString.c_str()); EXPECT_EQ(0, len); EXPECT_STREQ(zeroCharString.c_str(), mValue); ResetValue(); } // Try to use a NULL default value => get returns 0 { ASSERT_OK(property_set(PROPERTY_TEST_KEY, "")); // Expect a return value of 0 int len = property_get(PROPERTY_TEST_KEY, mValue, NULL); EXPECT_EQ(0, len); ResetValue(); } }
Bool OptimizeLoop(Var * proc, InstrBlock * header, InstrBlock * end) /* 1. Find loop (starting with inner loops) - Every jump to label preceding the jump (backjump) forms a label - In nested labels, we encounter the backjump first <code1> l1@ <code2> l2@ <code3> if.. l2@ <code4> if.. l3@ <code5> 2. Select variable to put to register - Most used variable should be used - Some variables are already moved to index register (this is considered use too) 3. Compute cost of moving the variable to register */ { Instr * i, initial, ti, * last_mod; Var * top_var, * reg, * top_reg, * orig_result; UInt16 r, regi, changed; UInt32 var_size; Int32 q, top_q, n; Bool init, top_init; InstrBlock * blk, * last_mod_blk; InstrBlock * blk_exit; Bool var_modified; Bool verbose; Rule * rule; UInt8 color; blk_exit = end->next; G_VERBOSE = verbose = Verbose(proc); VarResetUse(); InstrVarUse(header, blk_exit); InstrVarLoopDependent(header, end); // When processing, we assign var to register for(regi = 0; regi < CPU->REG_CNT; regi++) CPU->REG[regi]->var = NULL; while(top_var = FindMostUsedVar()) { // if (Verbose(proc)) { // Print("Most user var: "); PrintVar(top_var); PrintEOL(); // } top_var->read = top_var->write = 0; var_size = VarByteSize(top_var); //====== Select the best register for the given variable // let %A,%A => index -3 // use of register instead of variable -1 // spill +3 top_q = 0; top_reg = NULL; top_init = false; for(regi = 0; regi < CPU->REG_CNT; regi++) { reg = CPU->REG[regi]; if (FlagOn(reg->submode, SUBMODE_IN|SUBMODE_OUT)) continue; // exclude input/output registers if (reg->type->range.max == 1) continue; // exclude flag registers if (var_size != VarByteSize(reg)) continue; // exclude registers with different byte size if (reg->var != NULL) continue; if (InstrRule2(INSTR_LET, reg, top_var, NULL)) { // if (StrEqual(reg->name, "x") && StrEqual(top_var->name, "i")) { // Print(" "); // } q = UsageQuotient(header, end, top_var, reg, &init); if (q < top_q) { top_q = q; top_reg = reg; top_init = init; } } } if (top_reg == NULL) continue; reg = top_reg; if (Verbose(proc)) { color = PrintColor(OPTIMIZE_COLOR); PrintFmt("*** Loop %d..%d\n", header->seq_no, end->seq_no); Print("Var: "); PrintVarVal(top_var); PrintEOL(); Print("Register: "); PrintVarName(top_reg); PrintEOL(); PrintFmt("Quotient: %d\n", top_q); PrintColor(color); } //TODO: If there is Let reg = var and var is not top_var, we need to spill store //=== Replace the use of registers // PrintProc(proc); ResetValues(); initial.op = INSTR_LET; initial.result = top_reg; initial.arg1 = top_var; initial.arg2 = NULL; var_modified = false; // Generate instruction initializing the register used to replace the variable // before the start of the loop. // We only do this, if the variable is not initialized inside the loop. // if (FlagOn(top_var->flags, VarUninitialized) && !top_init) { // top_init = true; // } if (top_init) { LoopInsertPrologue(proc, header, INSTR_LET, top_reg, top_var, NULL); VarSetSrcInstr(top_reg, &initial); } r = 0; last_mod = NULL; for(blk = header; blk != blk_exit; blk = blk->next) { if (verbose) PrintBlockHeader(blk); for(i = blk->first, n=0; i != NULL; i = i->next) { retry: n++; if (i->op == INSTR_LINE) { if (verbose) { PrintInstrLine(n); EmitInstrInline(i); PrintEOL(); } continue; } // Delete unnecessary assignment if (i->op == INSTR_LET) { if (!InVar(i->arg1) && !OutVar(i->result) && VarContains(i->result, i->arg1)) { del: if (verbose) { PrintInstrLine(n); EmitInstrInline(i); } del2: if (verbose) { PrintDelete(); } i = InstrDelete(blk, i); if (i == NULL) break; goto retry; //continue; } } // Load the register with variable if necessary if (InstrReadsVar(i, top_var)) { if (!VarContains(top_reg, top_var)) { if (!(i->op == INSTR_LET && i->result == top_reg && i->arg1 == top_var)) { InstrInsertRule(blk, i, INSTR_LET, top_reg, top_var, NULL); } } } if (i->op == INSTR_LET && (i->result == top_var && i->arg1 == top_reg)) { r++; goto del; } if (InstrSpill(i, top_var)) { InstrInsertRule(blk, i, INSTR_LET, top_var, top_reg, NULL); } if (verbose) { PrintInstrLine(n); EmitInstrInline(i); } orig_result = i->result; memcpy(&ti, i, sizeof(Instr)); changed = VarTestReplace(&ti.result, top_var, reg); r += changed; changed += VarTestReplace(&ti.arg1, top_var, reg); changed += VarTestReplace(&ti.arg2, top_var, reg); // If the instruction used variable, that contains same value as replaced register, use the register instead if (ti.arg1 != reg && VarContains(ti.arg1, reg)) { changed += VarTestReplace(&ti.result, ti.arg1, reg); changed += VarTestReplace(&ti.arg2, ti.arg1, reg); changed += VarTestReplace(&ti.arg1, ti.arg1, reg); } if (changed > 0) { if (i->op == INSTR_LET && ti.result == ti.arg1) { goto del2; } rule = InstrRule(&ti); if (rule != NULL && (i->rule->cycles >= rule->cycles)) { InstrReplaceVar(i, top_var, top_reg); if (i->arg1 != reg && VarContains(i->arg1, reg)) { VarTestReplace(&i->result, i->arg1, reg); VarTestReplace(&i->arg2, i->arg1, reg); VarTestReplace(&i->arg1, i->arg1, reg); } i->rule = rule; CheckInstr(i); PrintChange(i); } } if (verbose) PrintEOL(); ResetValue(i->result); if (orig_result == top_var) { // if (!InstrIsSelfReferencing(i)) { VarSetSrcInstr(i->result, &initial); // } else { // VarSetSrcInstr(i->result, NULL); // } last_mod = i; last_mod_blk = blk; } else { VarSetSrcInstr(i->result, i); } } } // Value of register is not known at the end of loop, but it is not initialized at the beginning of the loop // We must load it before first use. if (!top_init && last_mod) { InstrInsertRule(last_mod_blk, last_mod->next, INSTR_LET, top_var, top_reg, NULL); } // If we replaced some destination by the register, store the register to destination if (r > 0) { // There may be exit label as part of the loop // We need to spill after it if (!VarIsConst(top_var)) { if (blk_exit == NULL || blk_exit->callers != NULL || blk_exit->from != end) { blk_exit = InstrBlockAlloc(); blk_exit->to = end->to; blk_exit->next = end->to; end->next = blk_exit; end->to = blk_exit; } InstrInsertRule(blk_exit, blk_exit->first, INSTR_LET, top_var, top_reg, NULL); } // InstrInsert(blk_exit, blk_exit->first, INSTR_LET, top_var, top_reg, NULL); } if (FlagOn(top_var->flags, VarLoopDependent)) { reg->flags |= VarLoopDependent; } return true; } return false; }
Int32 UsageQuotient(InstrBlock * header, InstrBlock * end, Var * top_var, Var * reg, Bool * p_init) /* Purpose: Compute savings achieved by replacing variable top_var by register reg. The bigger the value, the more suitable the register is 0 means no gain, <0 means using the register would lead to less optimal code than if not used Arguments: header first block of the loop end last block of the loop (it is still part of the loop) top_var variable we want to put in a register reg register to use for the variable >p_init set to true, if we need to init the register with the variable value before the loop */{ Var * prev_var; Int32 q; UInt16 cycles; UInt16 changed; InstrBlock * blk, * blk_exit; Instr * i, ti; UInt32 n; Bool first_init, mod_reg; UInt16 reg_use; // number of times, the value in the register has been used since last loaded Rule * rule; Instr initial; blk_exit = end->next; // At the beginning, the quotient is 0. ResetValues(); initial.op = INSTR_LET; initial.result = reg; initial.arg1 = top_var; initial.arg2 = NULL; VarSetSrcInstr(reg, &initial); q = 0; // We expect, we will initialize the register with the variable value before entering the loop. // This operation is not added to quotient, as it should not affect the speed significantly. *p_init = true; prev_var = NULL; // previous variable contained in the register // this variable must be loaded, when instruction using the register is encountered // (if it is not top_var) reg_use = 0; first_init = true; // Compute usage quotient for(blk = header; blk != blk_exit; blk = blk->next) { for(i = blk->first, n = 0; i != NULL; i = i->next, n++) { if (i->op == INSTR_LINE) continue; // Call to subroutine destroys all registers, there will be spill if (i->op == INSTR_CALL) { q = 1; goto done; } // If there is jump except last instruction if (IS_INSTR_JUMP(i->op) && (i != blk->last || blk != end)) { // *p_init = false; } mod_reg = VarModifiesVar(i->result, reg); if (i->op == INSTR_LET) { // If this is let instruction that initializes a variable to value it already contains, // we will be able to remove it completely. if (!InVar(i->arg1) && !OutVar(i->result) && VarContains(i->result, i->arg1)) { if (mod_reg) first_init = false; ASSERT(i->rule->cycles > 0); q -= i->rule->cycles; continue; } } // Instruction uses the register if (InstrReadsVar(i, reg)) { reg_use++; // Instruction uses the register and the register has not been initialized yet. // This means, that the register is initialized before the loop and we cannot optimize the loop this way. // TODO: Maybe spill to temporary variable is enough?) if (first_init) { q = 1; goto done; } } // Instruction uses top_var and the register does not currently contain the top_var value, // we need to load the value to register first. if (InstrReadsVar(i, top_var)) { if (!VarContains(reg, top_var)) { if (!(i->op == INSTR_LET && i->result == reg && i->arg1 == top_var) && LetCycles(reg, top_var, &cycles)) { q += cycles; } reg_use = 0; // We may not had to add the load, but we still can not remove this instruction, so do not // continue the processing in a normal way, as it would leed to removing the instruction. goto next; } } // If we assign the register back to variable, we may remove this instruction if (i->op == INSTR_LET && (i->result == top_var && i->arg1 == reg)) { q -= i->rule->cycles; continue; } else { // If current instruction uses the register, and it is // we need to save the register and load some other. if (InstrUsesVar(i, reg) && !VarContains(reg, top_var)) { if (prev_var != NULL && LetCycles(reg, top_var, &cycles)) { q += cycles; } } } // If the instruction stores the result to the variable, we will want to change it to store the result in the top_reg. // If the register is currently used for some different purpose, we must spill it. if (i->result == top_var && !VarContains(reg, top_var)) { if (i->next_use[0] != NULL && LetCycles(top_var, reg, &cycles)) { q += cycles; // TODO: we should use some temporary variable here } //TODO: In this case, we will need to load the register later, when it is used //We should handle the situation. // Will it be necessary to spill? // We use the variable (array) that is stored to register } else if (InstrSpill(i, top_var) && LetCycles(top_var, reg, &cycles)) { q += cycles; } memcpy(&ti, i, sizeof(Instr)); changed = InstrTestReplaceVar(&ti, top_var, reg); // If the instruction was changed (it used top_var and it has been replaced to top_reg), // test, whether we are able to compile it (some register/adress mode combinations must not be available) if (changed > 0) { if (ti.op == INSTR_LET && ti.result == ti.arg1) { q -= i->rule->cycles; continue; } rule = InstrRule(&ti); if (rule == NULL) { if (top_var->mode != INSTR_INT) { q = 1; // do not use this register, as invalid code would get generated goto done; } else { } } else { ASSERT(rule->cycles > 0); if (i->rule->cycles >= rule->cycles) { q -= i->rule->cycles; // we remove the current instruction q += rule->cycles; // and add new instruction } } } // Instruction modifies the register. // We may need to store the value of the register in case it has been modified. if (mod_reg) { *p_init = false; first_init = false; reg_use = 0; } next: if (i->result != NULL) { ResetValue(i->result); if (i->result == top_var) { if (!InstrIsSelfReferencing(i)) { VarSetSrcInstr(reg, &initial); } else { VarSetSrcInstr(reg, &initial); // VarSetSrcInstr(reg, NULL); } } else { VarSetSrcInstr(i->result, i); } } } // instr } // blk // Value of register is not known at the end of loop, but it is not initialized at the beginning of the loop // We must load it before first use. if (!*p_init) { if (LetCycles(reg, top_var, &cycles)) { q += cycles; } } done: return q; }
extern "C" int DLL_EXPORT PushCollapsedLog(CLogInfo data) { ResetValue(data); CollapsedLogStore.push_back(data); return 0; }
extern "C" int DLL_EXPORT SaveLogStoreInfo(CLogInfo data) { ResetValue(data); LogStore.push_back(data); return 0; }