コード例 #1
0
ファイル: baseline_jit.cpp プロジェクト: jmgc/pyston
void JitFragmentWriter::_emitPPCall(RewriterVar* result, void* func_addr, const RewriterVar::SmallVector& args,
                                    int num_slots, int slot_size) {
    assembler::Register r = allocReg(assembler::R11);

    if (args.size() > 6) { // only 6 args can get passed in registers.
        assert(args.size() <= 6 + JitCodeBlock::num_stack_args);
        for (int i = 6; i < args.size(); ++i) {
            assembler::Register reg = args[i]->getInReg(Location::any(), true);
            assembler->mov(reg, assembler::Indirect(assembler::RSP, sizeof(void*) * (i - 6)));
        }
        RewriterVar::SmallVector reg_args(args.begin(), args.begin() + 6);
        assert(reg_args.size() == 6);
        _setupCall(false, reg_args, RewriterVar::SmallVector());
    } else
        _setupCall(false, args, RewriterVar::SmallVector());

    if (failed)
        return;

    // make sure setupCall doesn't use R11
    assert(vars_by_location.count(assembler::R11) == 0);

    int pp_size = slot_size * num_slots;

    // make space for patchpoint
    uint8_t* pp_start = rewrite->getSlotStart() + assembler->bytesWritten();
    constexpr int call_size = 16;
    assembler->skipBytes(pp_size + call_size);
    uint8_t* pp_end = rewrite->getSlotStart() + assembler->bytesWritten();
    assert(assembler->hasFailed() || (pp_start + pp_size + call_size == pp_end));

    std::unique_ptr<ICSetupInfo> setup_info(
        ICSetupInfo::initialize(true, num_slots, slot_size, ICSetupInfo::Generic, NULL));

    // calculate available scratch space
    int pp_scratch_size = 0;
    int pp_scratch_location = rewrite->getScratchRspOffset() + rewrite->getScratchSize();
    for (int i = rewrite->getScratchSize() - 8; i >= 0; i -= 8) {
        Location l(Location::Scratch, i);
        if (vars_by_location.count(l))
            break;

        pp_scratch_size += 8;
        pp_scratch_location -= 8;
    }

    for (RewriterVar* arg : args) {
        arg->bumpUse();
    }

    assertConsistent();

    StackInfo stack_info(pp_scratch_size, pp_scratch_location);
    pp_infos.emplace_back(PPInfo{ func_addr, pp_start, pp_end, std::move(setup_info), stack_info });

    assert(vars_by_location.count(assembler::RAX) == 0);
    result->initializeInReg(assembler::RAX);
    assertConsistent();

    result->releaseIfNoUses();
}
コード例 #2
0
ファイル: tile.cpp プロジェクト: Xaymar/BlitzNext
int Tile::eval(int want)
{
	//save any hit registers
	int spill = hits;
	if (want_l)
		spill |= 1 << want_l;
	if (want_r)
		spill |= 1 << want_r;
	if (spill) {
		for (int n = 1; n <= NUM_REGS; ++n) {
			if (spill & (1 << n)) {
				if (regUsed[n])
					pushReg(n);
				else
					spill &= ~(1 << n);
			}
		}
	}

	//if tile needs an argFrame...
	if (argFrame) {
		codeFrags.push_back("-" + itoa(argFrame));
	}

	int got_l = 0, got_r = 0;
	if (want_l)
		want = want_l;

	std::string* as = &assem;

	if (!l) {
		got_l = allocReg(want);
	} else if (!r) {
		got_l = l->eval(want);
	} else {
		if (l->need >= NUM_REGS && r->need >= NUM_REGS) {
			got_r = r->eval(0);
			pushReg(got_r);
			freeReg(got_r);
			got_l = l->eval(want);
			got_r = allocReg(want_r);
			popReg(got_r);
		} else if (r->need > l->need) {
			got_r = r->eval(want_r);
			got_l = l->eval(want);
		} else {
			got_l = l->eval(want);
			got_r = r->eval(want_r);
			if (assem2.size())
				as = &assem2;
		}
		if (want_l == got_r || want_r == got_l) {
			swapRegs(got_l, got_r);
			int t = got_l;
			got_l = got_r;
			got_r = t;
		}
	}

	if (!want_l)
		want_l = got_l;
	else if (want_l != got_l)
		moveReg(want_l, got_l);

	if (!want_r)
		want_r = got_r;
	else if (want_r != got_r)
		moveReg(want_r, got_r);

	int i;
	while ((i = as->find("%l")) != std::string::npos)
		as->replace(i, 2, regs[want_l]);
	while ((i = as->find("%r")) != std::string::npos)
		as->replace(i, 2, regs[want_r]);

	codeFrags.push_back(*as);

	freeReg(got_r);
	if (want_l != got_l)
		moveReg(got_l, want_l);

	//cleanup argFrame
	if (argFrame) {
		//***** Not needed for STDCALL *****
		//		codeFrags.push_back( "+"+itoa(argFrame) );
	}

	//restore spilled regs
	if (spill) {
		for (int n = NUM_REGS; n >= 1; --n) {
			if (spill & (1 << n))
				popReg(n);
		}
	}
	return got_l;
}