void CR_ModuleEx::CreateFlowGraph64(CR_Addr64 entrance) { auto cf = Info64()->CodeFuncFromAddr(entrance); assert(cf); CR_Addr64Set leaders; leaders.insert(entrance); // insert jumpees auto& jumpees = cf->Jumpees(); leaders.insert(jumpees.begin(), jumpees.end()); // insert exits' next auto& exits = cf->Exits(); for (auto addr : exits) { auto op_code = Info64()->OpCodeFromAddr(addr); auto size = op_code->Codes().size(); auto next_addr = static_cast<CR_Addr64>(addr + size); leaders.insert(next_addr); } // insert jumpers' next auto& jumpers = cf->Jumpers(); for (auto addr : jumpers) { auto op_code = Info64()->OpCodeFromAddr(addr); auto size = op_code->Codes().size(); auto next_addr = static_cast<CR_Addr64>(addr + size); leaders.insert(next_addr); } // sort std::vector<CR_Addr64> vecLeaders(leaders.begin(), leaders.end()); std::sort(vecLeaders.begin(), vecLeaders.end()); // store leaders cf->Leaders() = std::move(leaders); const size_t size = vecLeaders.size() - 1; for (size_t i = 0; i < size; ++i) { // for every pair of two adjacent leaders auto addr1 = vecLeaders[i], addr2 = vecLeaders[i + 1]; // prepare a basic block CR_BasicBlock64 block; block.m_addr = addr1; CR_Addr64 next_addr = cr_invalid_addr64; for (auto addr = addr1; addr < addr2; ) { if (cf->Leaders().count(addr)) { // set label at each leader block.AddLeaderLabel(addr); } // op.code from addr auto op_code = Info64()->OpCodeFromAddr(addr); if (op_code == NULL) { break; } auto type = op_code->OpCodeType(); if (type == cr_OCT_JMP) { // jump auto oper = op_code->Operand(0); if (oper->GetOperandType() == cr_DF_IMM) { block.m_jump_to = oper->Value64(); // jump to } next_addr = cr_invalid_addr64; } else if (type == cr_OCT_RETURN) { next_addr = cr_invalid_addr64; } else if (type == cr_OCT_JCC || type == cr_OCT_LOOP) { // conditional jump or loop auto oper = op_code->Operand(0); if (oper->GetOperandType() == cr_DF_IMM) { block.m_jump_to = oper->Value64(); // jump to } block.m_cond_code = op_code->CondCode(); next_addr = static_cast<CR_Addr64>(addr + op_code->Codes().size()); } else { next_addr = static_cast<CR_Addr64>(addr + op_code->Codes().size()); } // add op.code block.m_stmts.emplace_back(*op_code); // go to next addr addr += static_cast<CR_Addr64>(op_code->Codes().size()); } // add label at last block.AddLeaderLabel(addr2); // set next addr block.m_next_addr = next_addr; // add block cf->BasicBlocks().emplace_back(block); } } // CR_ModuleEx::CreateFlowGraph64
/*! \param RecBufSw */ xbShort xbExpn::ProcessOperator( xbShort RecBufSw ) { xbExpNode * WorkNode; char Operator[6]; char t; if( GetStackDepth() < 3 ) return XB_PARSE_ERROR; WorkNode = (xbExpNode *) Pop(); if( WorkNode->Len > 5 ) return XB_PARSE_ERROR; memset( Operator, 0x00, 6 ); strncpy( Operator, WorkNode->NodeText, WorkNode->Len ); if( !WorkNode->InTree ) delete WorkNode; /* load up operand 1 */ WorkNode = (xbExpNode *) Pop(); if(( OpType1 = GetOperandType( WorkNode )) == 0 ) return XB_PARSE_ERROR; if( OpLen1 < WorkNode->DataLen+1 && WorkNode->Type != 'd' ) { if( OpLen1 > 0 ) free( Op1 ); if(( Op1 = (char *) malloc( WorkNode->DataLen+1 )) == NULL ) { return XB_NO_MEMORY; } OpLen1 = WorkNode->DataLen+1; } OpDataLen1 = WorkNode->DataLen; memset( Op1, 0x00, WorkNode->DataLen+1 ); if( WorkNode->Type == 'D' && WorkNode->dbf ) { /* database field */ WorkNode->dbf->GetField( WorkNode->FieldNo, Op1, RecBufSw ); t = WorkNode->dbf->GetFieldType( WorkNode->FieldNo ); if( t == 'N' || t == 'F' ) Opd1 = strtod( WorkNode->StringResult, 0 ); else if( t == 'D' ){ // date field xbDate d; Opd1 = d.JulianDays( WorkNode->StringResult ); } } else if( WorkNode->Type == 'C' ) /* constant */ memcpy( Op1, WorkNode->NodeText, WorkNode->DataLen ); else if( WorkNode->Type == 's' ) /* previous result */ memcpy( Op1, WorkNode->StringResult, WorkNode->DataLen+1 ); else if( WorkNode->Type == 'd' ) /* previous numeric result */ Opd1 = WorkNode->DoubResult; else if( WorkNode->Type == 'N' ) /* previous numeric result */ Opd1 = strtod( WorkNode->StringResult, 0 ); else if(WorkNode->Type == 'l') /* previous logical result 3/26/00 dtb */ Opd1 = WorkNode->IntResult; if( !WorkNode->InTree ) delete WorkNode; /* load up operand 2 */ WorkNode = (xbExpNode *) Pop(); if(( OpType2 = GetOperandType( WorkNode )) == 0 ) return XB_PARSE_ERROR; if( OpLen2 < WorkNode->DataLen+1 && WorkNode->Type != 'd' ) { if( OpLen2 > 0 ) free( Op2 ); if(( Op2 = (char *) malloc( WorkNode->DataLen+1 )) == NULL ) { return XB_NO_MEMORY; } OpLen2 = WorkNode->DataLen+1; } OpDataLen2 = WorkNode->DataLen; memset( Op2, 0x00, WorkNode->DataLen+1 ); if( WorkNode->Type == 'D' && WorkNode->dbf ) { /* database field */ WorkNode->dbf->GetField( WorkNode->FieldNo, Op2, RecBufSw ); t = WorkNode->dbf->GetFieldType( WorkNode->FieldNo ); if( t == 'N' || t == 'F' ) Opd2 = strtod( WorkNode->StringResult, 0 ); else if( t == 'D' ){ // date field xbDate d; Opd2 = d.JulianDays( WorkNode->StringResult ); } } else if( WorkNode->Type == 'C' ) /* constant */ memcpy( Op2, WorkNode->NodeText, WorkNode->DataLen ); else if( WorkNode->Type == 's' ) /* previous result */ memcpy( Op2, WorkNode->StringResult, WorkNode->DataLen+1 ); else if( WorkNode->Type == 'd' ) /* previous numeric result */ Opd2 = WorkNode->DoubResult; else if( WorkNode->Type == 'N' ) /* previous numeric result */ Opd2 = strtod( WorkNode->StringResult, 0 ); else if(WorkNode->Type == 'l') /* previous logical result 3/26/00 dtb*/ Opd2 = WorkNode->IntResult; if( !WorkNode->InTree ) delete WorkNode; if( !ValidOperation( Operator, OpType1, OpType2 )) return XB_PARSE_ERROR; if( OpType1 == 'N' || OpType1 == 'L' || OpType1 == 'D' ) /* numeric procesing */ return NumericOperation( Operator ); else /* must be character */ return AlphaOperation( Operator ); }