Ejemplo n.º 1
0
        [TestCase(X64Register.R14)] // Never allocated in this method without a requirement
        public void Register_requirement_is_respected(X64Register required)
        {
            var method = new LowMethod <X64Register>();

            method.Locals.Add(new LowLocal <X64Register>(SimpleType.Bool));
            method.Locals.Add(new LowLocal <X64Register>(SimpleType.Bool, required));
            method.Blocks.Add(new LowBlock
            {
                Instructions =
                {
                    new LowInstruction(LowOp.LoadInt, 0, 0, 0, 1), // Load 1 -> #0
                    new LowInstruction(LowOp.Move,    1, 0, 0, 0), // Move #0 -> #1
                    new LowInstruction(LowOp.Compare, 0, 1, 0, 0), // Compare #1, #0
                    new LowInstruction(LowOp.Return,  0, 0, 0, 0)  // Return #0
                },
                Predecessors = Array.Empty <int>(),
                Successors   = Array.Empty <int>()
            });

            var(rewritten, allocationMap) = X64RegisterAllocator.Allocate(method);

            AssertDump(rewritten, @"
LB_0:
    LoadInt 0 0 1 -> 0
    Move 0 0 0 -> 1
    Compare 1 0 0 -> 0
    Return 0 0 0 -> 0");

            Assert.That(allocationMap.Get(0).localIndex, Is.EqualTo(0));
            Assert.That(allocationMap.Get(1).localIndex, Is.EqualTo(1));

            Assert.That(allocationMap.Get(0).location.IsSet, Is.True);
            Assert.That(allocationMap.Get(1).location.IsSet, Is.True);
            Assert.That(allocationMap.Get(1).location.Register, Is.EqualTo(required));
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Emits a full-width pop instruction with the specified destination register.
        /// </summary>
        public void EmitPop(X64Register dest)
        {
            if (dest >= X64Register.Xmm0)
            {
                throw new InvalidOperationException("Pop on XMM register");
            }

            _disassemblyWriter?.WriteLine($"{Indent}pop {GetRegisterName(dest, 8)}");
            var(encodedReg, needB) = GetRegisterEncoding(dest);

            // The opcode is encoded exactly as push, except for the 0x8 bit
            if (needB)
            {
                _outputStream.WriteByte(0x41);
            }
            _outputStream.WriteByte((byte)(0x58 | encodedReg));
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Emits a full-width push instruction with the specified source register.
        /// </summary>
        public void EmitPush(X64Register src)
        {
            if (src >= X64Register.Xmm0)
            {
                throw new InvalidOperationException("Push on XMM register");
            }

            _disassemblyWriter?.WriteLine($"{Indent}push {GetRegisterName(src, 8)}");
            var(encodedReg, needB) = GetRegisterEncoding(src);

            if (needB)
            {
                // New registers need a REX.B prefix
                _outputStream.WriteByte(0x41);
            }
            _outputStream.WriteByte((byte)(0x50 | encodedReg));
        }