bool Board::isDangerQueen(const Move & move) const { const Field & ffrom = getField(move.from_); if ( ffrom.type() != Figure::TypeQueen ) return false; if ( move.capture_ ) return true; Figure::Color color = color_; Figure::Color ocolor = Figure::otherColor(color); int oki_pos = kingPos(ocolor); int dist = g_distanceCounter->getDistance(oki_pos, move.to_); if ( dist > 2 ) return false; BitMask mask_all = fmgr().mask(Figure::ColorBlack) | fmgr().mask(Figure::ColorWhite); BitMask oki_caps = g_movesTable->caps(Figure::TypeKing, oki_pos); BitMask q_caps = g_movesTable->caps(Figure::TypeQueen, move.to_); BitMask attacked_mask = (oki_caps & q_caps) & ~mask_all; BitMask ki_moves = oki_caps & ~(mask_all | attacked_mask); int movesN = pop_count(ki_moves); return attacked_mask && movesN <= 3; }
bool Board::isKnightForkAfter(const Move & move) const { const Field & fto = getField(move.to_); if ( fto.type() != Figure::TypeKnight ) return false; const BitMask & kn_caps = g_movesTable->caps(Figure::TypeKnight, move.to_); BitMask op_mask = fmgr().rook_mask(color_) | fmgr().queen_mask(color_); op_mask &= kn_caps; return op_mask != 0 && !one_bit_set(op_mask); }
bool Board::isDoublePawnAttack(const Move & move) const { const Field & fto = getField(move.to_); if ( fto.type() != Figure::TypePawn ) return false; Figure::Color ocolor = Figure::otherColor(color_); const BitMask & pw_caps = g_movesTable->pawnCaps_o(ocolor, move.to_); BitMask op_mask = fmgr().knight_mask(color_) | fmgr().bishop_mask(color_) | fmgr().rook_mask(color_) | fmgr().queen_mask(color_); op_mask &= pw_caps; return op_mask != 0 && !one_bit_set(op_mask); }
bool Board::isBishopAttack(const Move & move) const { const Field & fto = getField(move.to_); if ( fto.type() != Figure::TypeBishop ) return false; Figure::Color color = color_; Figure::Color ocolor = Figure::otherColor(color); const BitMask & bi_caps = g_movesTable->caps(Figure::TypeBishop, move.to_); BitMask op_mask = fmgr().rook_mask(color) | fmgr().queen_mask(color); if ( !(op_mask & bi_caps) ) return false; BitMask all_mask = fmgr().mask(Figure::ColorWhite) | fmgr().mask(Figure::ColorBlack); all_mask ^= op_mask; BitMask inv_mask_all = ~all_mask; op_mask &= bi_caps; const BitMask & oki_mask = fmgr().king_mask(color_); int oki_pos = _lsb64(oki_mask); int attackedN = 0; for ( ; op_mask;) { int p = clear_lsb(op_mask); if ( is_something_between(move.to_, p, inv_mask_all) ) continue; // 2 attacked figures found if ( ++attackedN > 1 ) return true; // may be it's pinned BitMask mask_from = g_betweenMasks->from(move.to_, p); mask_from &= oki_mask; if ( !mask_from ) continue; if ( is_nothing_between(move.to_, oki_pos, inv_mask_all) ) return true; } return false; }
bool Board::isKnightFork(const Move & move) const { const Field & ffrom = getField(move.from_); if ( ffrom.type() != Figure::TypeKnight ) return false; if ( move.capture_ ) return false; Figure::Color color = color_; Figure::Color ocolor = Figure::otherColor(color); const BitMask & kn_caps = g_movesTable->caps(Figure::TypeKnight, move.to_); BitMask op_mask = fmgr().rook_mask(ocolor) | fmgr().queen_mask(ocolor); op_mask &= kn_caps; return op_mask != 0 && !one_bit_set(op_mask); }
/* * index-info-- * Retrieves catalog information on an index on a given relation. * * The index relation is opened on the first invocation. The current * retrieves the next index relation within the catalog that has not * already been retrieved by a previous call. The index catalog * is closed when no more indices for 'relid' can be found. * * 'first' is 1 if this is the first call * * Returns true if successful and false otherwise. Index info is returned * via the transient data structure 'info'. * */ bool index_info(Query *root, bool first, int relid, IdxInfoRetval *info) { register i; HeapTuple indexTuple, amopTuple; IndexTupleForm index; Relation indexRelation; uint16 amstrategy; Oid relam; Oid indrelid; static Relation relation = (Relation) NULL; static HeapScanDesc scan = (HeapScanDesc) NULL; static ScanKeyData indexKey; /* find the oid of the indexed relation */ indrelid = getrelid(relid, root->rtable); memset(info, 0, sizeof(IdxInfoRetval)); /* * the maximum number of elements in each of the following arrays is * 8. We allocate one more for a terminating 0 to indicate the end * of the array. */ info->indexkeys = (int *)palloc(sizeof(int)*9); memset(info->indexkeys, 0, sizeof(int)*9); info->orderOprs = (Oid *)palloc(sizeof(Oid)*9); memset(info->orderOprs, 0, sizeof(Oid)*9); info->classlist = (Oid *)palloc(sizeof(Oid)*9); memset(info->classlist, 0, sizeof(Oid)*9); /* Find an index on the given relation */ if (first) { if (RelationIsValid(relation)) heap_close(relation); if (HeapScanIsValid(scan)) heap_endscan(scan); ScanKeyEntryInitialize(&indexKey, 0, Anum_pg_index_indrelid, F_OIDEQ, ObjectIdGetDatum(indrelid)); relation = heap_openr(IndexRelationName); scan = heap_beginscan(relation, 0, NowTimeQual, 1, &indexKey); } if (!HeapScanIsValid(scan)) elog(WARN, "index_info: scan not started"); indexTuple = heap_getnext(scan, 0, (Buffer *) NULL); if (!HeapTupleIsValid(indexTuple)) { heap_endscan(scan); heap_close(relation); scan = (HeapScanDesc) NULL; relation = (Relation) NULL; return(0); } /* Extract info from the index tuple */ index = (IndexTupleForm)GETSTRUCT(indexTuple); info->relid = index->indexrelid; /* index relation */ for (i = 0; i < 8; i++) info->indexkeys[i] = index->indkey[i]; for (i = 0; i < 8; i++) info->classlist[i] = index->indclass[i]; info->indproc = index->indproc; /* functional index ?? */ /* partial index ?? */ if (VARSIZE(&index->indpred) != 0) { /* * The memory allocated here for the predicate (in lispReadString) * only needs to stay around until it's used in find_index_paths, * which is all within a command, so the automatic pfree at end * of transaction should be ok. */ char *predString; predString = fmgr(F_TEXTOUT, &index->indpred); info->indpred = (Node*)stringToNode(predString); pfree(predString); } /* Extract info from the relation descriptor for the index */ indexRelation = index_open(index->indexrelid); #ifdef notdef /* XXX should iterate through strategies -- but how? use #1 for now */ amstrategy = indexRelation->rd_am->amstrategies; #endif /* notdef */ amstrategy = 1; relam = indexRelation->rd_rel->relam; info->relam = relam; info->pages = indexRelation->rd_rel->relpages; info->tuples = indexRelation->rd_rel->reltuples; heap_close(indexRelation); /* * Find the index ordering keys * * Must use indclass to know when to stop looking since with * functional indices there could be several keys (args) for * one opclass. -mer 27 Sept 1991 */ for (i = 0; i < 8 && index->indclass[i]; ++i) { amopTuple = SearchSysCacheTuple(AMOPSTRATEGY, ObjectIdGetDatum(relam), ObjectIdGetDatum(index->indclass[i]), UInt16GetDatum(amstrategy), 0); if (!HeapTupleIsValid(amopTuple)) elog(WARN, "index_info: no amop %d %d %d", relam, index->indclass[i], amstrategy); info->orderOprs[i] = ((Form_pg_amop)GETSTRUCT(amopTuple))->amopopr; } return(TRUE); }
void NasmInsnRunner::TestInsn(yasm::Insn* insn, std::size_t golden_len, const unsigned char* golden, const llvm::StringRef& ew_msg) { // // Turn the instruction into bytes // BytecodeContainer container(0); ::testing::StrictMock<MockDiagnosticString> mock_consumer; llvm::IntrusiveRefCntPtr<DiagnosticIDs> diagids(new DiagnosticIDs); DiagnosticsEngine diags(diagids, &mock_consumer, false); FileSystemOptions opts; FileManager fmgr(opts); SourceManager smgr(diags, fmgr); diags.setSourceManager(&smgr); if (!ew_msg.empty()) { EXPECT_CALL(mock_consumer, DiagString(ew_msg)) .Times(1); } else { // expect no diagnostic calls EXPECT_CALL(mock_consumer, DiagString(::testing::_)) .Times(0); } insn->Append(container, SourceLocation(), diags); container.Finalize(diags); if (diags.hasErrorOccurred()) return; container.bytecodes_front().CalcLen(AddSpanTest, diags); ASSERT_EQ(golden_len, container.bytecodes_front().getTotalLen()); if (diags.hasErrorOccurred()) return; container.UpdateOffsets(diags); if (diags.hasErrorOccurred()) return; llvm::SmallString<64> outbytes; llvm::raw_svector_ostream outstream(outbytes); RawOutput outputter(outstream, *m_arch, diags); container.bytecodes_front().Output(outputter); outstream.flush(); // // Compare the result against the golden result // if (golden_len != outbytes.size()) goto bad; for (std::size_t i=0; i<golden_len; ++i) { if ((int)(golden[i] & 0xff) != (int)(outbytes[i] & 0xff)) goto bad; } return; bad: std::string golden_str, outbytes_str; llvm::raw_string_ostream golden_ss(golden_str), outbytes_ss(outbytes_str); for (std::size_t i=0; i<golden_len; ++i) golden_ss << llvm::format("%02x ", (int)(golden[i] & 0xff)); golden_ss.flush(); for (std::size_t i=0; i<outbytes.size(); ++i) outbytes_ss << llvm::format("%02x ", (int)(outbytes[i] & 0xff)); outbytes_ss.flush(); ASSERT_EQ(golden_str, outbytes_str); }
void NasmInsnRunner::ParseAndTestLine(const char* filename, const llvm::StringRef& line, int linenum) { SCOPED_TRACE(llvm::format("%s:%d", filename, linenum)); llvm::StringRef insn_in, golden_in; llvm::tie(insn_in, golden_in) = line.split(';'); insn_in = strip(insn_in); golden_in = strip(golden_in); // Handle bits directive if (golden_in.empty() && insn_in.startswith("[bits ")) { int bits = atoi(insn_in.substr(6, 2).str().c_str()); if (bits == 64) m_arch->setMachine("amd64"); else m_arch->setMachine("x86"); m_arch->setVar("mode_bits", bits); return; } if (insn_in.empty() || golden_in.empty()) return; // skip lines that don't have both text and a comment // // parse the golden result // llvm::SmallVector<unsigned char, 64> golden; llvm::StringRef golden_errwarn; for (;;) { // strip whitespace golden_in = strip(golden_in); if (golden_in.empty() || !isxdigit(golden_in[0])) break; unsigned int byte_val = 0x100; llvm::StringRef byte_str; llvm::tie(byte_str, golden_in) = golden_in.split(' '); if (byte_str.size() == 2) // assume hex byte_val = (fromhexdigit(byte_str[0]) << 4) | fromhexdigit(byte_str[1]); else if (byte_str.size() == 3) // assume octal byte_val = (fromoctdigit(byte_str[0]) << 6) | (fromoctdigit(byte_str[1]) << 3) | fromoctdigit(byte_str[2]); ASSERT_LE(byte_val, 0xffU) << "invalid golden value"; golden.push_back(byte_val); } // interpret string in [] as error/warning if (!golden_in.empty() && golden_in[0] == '[') llvm::tie(golden_errwarn, golden_in) = golden_in.substr(1).split(']'); // // parse the instruction // ::testing::StrictMock<MockDiagnosticString> mock_consumer; llvm::IntrusiveRefCntPtr<DiagnosticIDs> diagids(new DiagnosticIDs); DiagnosticsEngine diags(diagids, &mock_consumer, false); FileSystemOptions opts; FileManager fmgr(opts); SourceManager smgr(diags, fmgr); diags.setSourceManager(&smgr); // instruction name is the first thing on the line llvm::StringRef insn_name; llvm::tie(insn_name, insn_in) = insn_in.split(' '); Arch::InsnPrefix insnprefix = m_arch->ParseCheckInsnPrefix(insn_name, SourceLocation(), diags); ASSERT_TRUE(insnprefix.isType(Arch::InsnPrefix::INSN)); std::auto_ptr<Insn> insn = m_arch->CreateInsn(insnprefix.getInsn()); ASSERT_TRUE(insn.get() != 0) << "unrecognized instruction '" << insn_name.str() << "'"; // parse insn arguments unsigned int wsize = m_arch_module->getWordSize(); // strip whitespace from arguments insn_in = strip(insn_in); while (!insn_in.empty()) { llvm::StringRef arg_str; llvm::tie(arg_str, insn_in) = insn_in.split(','); // strip whitespace from arg arg_str = strip(arg_str); unsigned int size = 0; bool strict = false; for (;;) { int next; int nsize = 0; // operand overrides (size and strict) if (arg_str.startswith("byte ")) { nsize = 8; next = 5; } else if (arg_str.startswith("hword ")) { nsize = wsize/2; next = 6; } else if (arg_str.startswith("word ")) { nsize = wsize; next = 5; } else if (arg_str.startswith("dword ")) { nsize = wsize*2; next = 6; } else if (arg_str.startswith("qword ")) { nsize = wsize*4; next = 6; } else if (arg_str.startswith("tword ")) { nsize = 80; next = 6; } else if (arg_str.startswith("dqword ")) { nsize = wsize*8; next = 7; } else if (arg_str.startswith("oword ")) { nsize = wsize*8; next = 6; } else if (arg_str.startswith("yword ")) { nsize = 256; next = 6; } else if (arg_str.startswith("strict ")) { strict = true; next = 7; } else break; if (size == 0) size = nsize; arg_str = arg_str.substr(next); } if (arg_str[0] == '[') { // Very simple int/reg expression parser. Does not handle parens or // order of operations; simply builds expr from left to right. // This means r8*4+r9 will have a different result than r9+r8*4! // Also only handles binary operators * and +. llvm::StringRef estr = arg_str.slice(1, arg_str.find(']')+1); std::auto_ptr<Expr> e(new Expr); char pendingop = '\0'; std::size_t tokstart = 0; for (std::size_t pos = 0; pos < estr.size(); ++pos) { if (estr[pos] == '*' || estr[pos] == '+' || estr[pos] == ']') { // figure out this token llvm::StringRef tok = strip(estr.slice(tokstart, pos)); if (isdigit(estr[tokstart])) e->Append(strtoint(tok)); else { Arch::RegTmod regtmod = m_arch->ParseCheckRegTmod(tok, SourceLocation(), diags); ASSERT_TRUE(regtmod.isType(Arch::RegTmod::REG)) << "cannot handle label '" << tok.str() << "'"; e->Append(*regtmod.getReg()); } // append pending operator if (pendingop == '*') e->AppendOp(Op::MUL, 2); else if (pendingop == '+') e->AppendOp(Op::ADD, 2); // store new operator pendingop = estr[pos]; tokstart = pos+1; } } Operand operand(m_arch->CreateEffAddr(e)); operand.setSize(size); operand.setStrict(strict); insn->AddOperand(operand); continue; } // TODO: split by space to allow target modifiers // Test for registers Arch::RegTmod regtmod = m_arch->ParseCheckRegTmod(arg_str, SourceLocation(), diags); if (const Register* reg = regtmod.getReg()) { Operand operand(reg); operand.setSize(size); operand.setStrict(strict); insn->AddOperand(operand); continue; } else if (const SegmentRegister* segreg = regtmod.getSegReg()) { Operand operand(segreg); operand.setSize(size); operand.setStrict(strict); insn->AddOperand(operand); continue; } else if (regtmod.getTargetMod()) { FAIL() << "cannot handle target modifier"; } else if (regtmod.getRegGroup()) { FAIL() << "cannot handle register group"; } // Can't handle labels ASSERT_TRUE(isdigit(arg_str[0]) || arg_str[0] == '-') << "cannot handle label '" << arg_str.str() << "'"; // Convert to integer expression Operand intop(Expr::Ptr(new Expr(strtoint(arg_str)))); intop.setSize(size); intop.setStrict(strict); insn->AddOperand(intop); } TestInsn(insn.get(), golden.size(), golden.data(), golden_errwarn); }