Beispiel #1
0
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;
}
Beispiel #2
0
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);
}
Beispiel #3
0
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);
}
Beispiel #4
0
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;
}
Beispiel #5
0
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);
}
Beispiel #6
0
/*    
 * 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);
}
Beispiel #7
0
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);
}
Beispiel #8
0
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);
}