CodeGenerator实现
This commit is contained in:
@ -27,12 +27,32 @@ namespace ARMeilleure.CodeGen.Loong64
|
|||||||
return (GetIntCalleeSavedRegisters() ^ RegistersMask) & ~ReservedRegsMask;
|
return (GetIntCalleeSavedRegisters() ^ RegistersMask) & ~ReservedRegsMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int GetFpCallerSavedRegisters()
|
||||||
|
{
|
||||||
|
return GetFpCalleeSavedRegisters() ^ RegistersMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetVecCallerSavedRegisters()
|
||||||
|
{
|
||||||
|
return GetVecCalleeSavedRegisters() ^ RegistersMask;
|
||||||
|
}
|
||||||
|
|
||||||
public static int GetIntCalleeSavedRegisters()
|
public static int GetIntCalleeSavedRegisters()
|
||||||
{
|
{
|
||||||
// 被调用者保存的寄存器 (需要保存/恢复)
|
// 被调用者保存的寄存器 (需要保存/恢复)
|
||||||
return unchecked((int)0xff000000);
|
return unchecked((int)0xff000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int GetFpCalleeSavedRegisters()
|
||||||
|
{
|
||||||
|
return unchecked((int)0xff000000); // f24 to f31
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetVecCalleeSavedRegisters()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
public static int GetArgumentsOnRegsCount()
|
public static int GetArgumentsOnRegsCount()
|
||||||
{
|
{
|
||||||
return 8;
|
return 8;
|
||||||
|
|||||||
@ -0,0 +1,29 @@
|
|||||||
|
using ARMeilleure.CodeGen.Linking;
|
||||||
|
using ARMeilleure.CodeGen.RegisterAllocators;
|
||||||
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
|
using Microsoft.IO;
|
||||||
|
using Ryujinx.Common.Memory;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace ARMeilleure.CodeGen.Loong64
|
||||||
|
{
|
||||||
|
class CodeGenContext
|
||||||
|
{
|
||||||
|
private readonly RecyclableMemoryStream _stream;
|
||||||
|
|
||||||
|
public AllocationResult AllocResult { get; }
|
||||||
|
|
||||||
|
public Assembler Assembler { get; }
|
||||||
|
|
||||||
|
public CodeGenContext(AllocationResult allocResult)
|
||||||
|
{
|
||||||
|
_stream = MemoryStreamManager.Shared.GetStream();
|
||||||
|
|
||||||
|
AllocResult = allocResult;
|
||||||
|
|
||||||
|
Assembler = new Assembler(_stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
153
src/ARMeilleure/CodeGen/Loong64/CodeGenerator.cs
Normal file
153
src/ARMeilleure/CodeGen/Loong64/CodeGenerator.cs
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
using ARMeilleure.CodeGen.Linking;
|
||||||
|
using ARMeilleure.CodeGen.Optimizations;
|
||||||
|
using ARMeilleure.CodeGen.RegisterAllocators;
|
||||||
|
using ARMeilleure.CodeGen.Unwinding;
|
||||||
|
using ARMeilleure.Common;
|
||||||
|
using ARMeilleure.Diagnostics;
|
||||||
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
|
using ARMeilleure.Translation;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Numerics;
|
||||||
|
using static ARMeilleure.IntermediateRepresentation.Operand;
|
||||||
|
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||||
|
|
||||||
|
namespace ARMeilleure.CodeGen.Loong64
|
||||||
|
{
|
||||||
|
static class CodeGenerator
|
||||||
|
{
|
||||||
|
private const int RegistersCount = 32;
|
||||||
|
|
||||||
|
private static readonly Action<CodeGenContext, Operation>[] _instTable;
|
||||||
|
|
||||||
|
static CodeGenerator()
|
||||||
|
{
|
||||||
|
_instTable = new Action<CodeGenContext, Operation>[EnumUtils.GetCount(typeof(Instruction))];
|
||||||
|
|
||||||
|
#pragma warning disable IDE0055 // Disable formatting
|
||||||
|
Add(Instruction.Add, GenerateAdd);
|
||||||
|
#pragma warning restore IDE0055
|
||||||
|
|
||||||
|
static void Add(Instruction inst, Action<CodeGenContext, Operation> func)
|
||||||
|
{
|
||||||
|
_instTable[(int)inst] = func;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CompiledFunction Generate(CompilerContext cctx)
|
||||||
|
{
|
||||||
|
ControlFlowGraph cfg = cctx.Cfg;
|
||||||
|
|
||||||
|
Logger.StartPass(PassName.Optimization);
|
||||||
|
|
||||||
|
if (cctx.Options.HasFlag(CompilerOptions.Optimize))
|
||||||
|
{
|
||||||
|
if (cctx.Options.HasFlag(CompilerOptions.SsaForm))
|
||||||
|
{
|
||||||
|
Optimizer.RunPass(cfg); // SSA 优化
|
||||||
|
}
|
||||||
|
BlockPlacement.RunPass(cfg); // 基本块重排序
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.EndPass(PassName.Optimization, cfg);
|
||||||
|
|
||||||
|
Logger.StartPass(PassName.PreAllocation);
|
||||||
|
|
||||||
|
PreAllocator.RunPass(cctx, out int maxCallArgs);
|
||||||
|
|
||||||
|
Logger.EndPass(PassName.PreAllocation, cfg);
|
||||||
|
|
||||||
|
Logger.StartPass(PassName.RegisterAllocation);
|
||||||
|
|
||||||
|
StackAllocator stackAlloc = new();
|
||||||
|
|
||||||
|
if (cctx.Options.HasFlag(CompilerOptions.SsaForm))
|
||||||
|
{
|
||||||
|
Ssa.Deconstruct(cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
IRegisterAllocator regAlloc;
|
||||||
|
|
||||||
|
if (cctx.Options.HasFlag(CompilerOptions.Lsra))
|
||||||
|
{
|
||||||
|
regAlloc = new LinearScanAllocator(); // 快速分配
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
regAlloc = new HybridAllocator(); // 高质量分配
|
||||||
|
}
|
||||||
|
|
||||||
|
RegisterMasks regMasks = new(
|
||||||
|
CallingConvention.GetIntAvailableRegisters(),
|
||||||
|
CallingConvention.GetVecAvailableRegisters(),
|
||||||
|
CallingConvention.GetIntCallerSavedRegisters(),
|
||||||
|
CallingConvention.GetVecCallerSavedRegisters(),
|
||||||
|
CallingConvention.GetIntCalleeSavedRegisters(),
|
||||||
|
CallingConvention.GetVecCalleeSavedRegisters(),
|
||||||
|
RegistersCount);
|
||||||
|
|
||||||
|
AllocationResult allocResult = regAlloc.RunPass(cfg, stackAlloc, regMasks);
|
||||||
|
|
||||||
|
Logger.EndPass(PassName.RegisterAllocation, cfg);
|
||||||
|
|
||||||
|
Logger.StartPass(PassName.CodeGeneration);
|
||||||
|
|
||||||
|
bool relocatable = (cctx.Options & CompilerOptions.Relocatable) != 0;
|
||||||
|
|
||||||
|
CodeGenContext context = new(allocResult, maxCallArgs, relocatable);
|
||||||
|
|
||||||
|
UnwindInfo unwindInfo = WritePrologue(context);
|
||||||
|
|
||||||
|
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
|
||||||
|
{
|
||||||
|
context.EnterBlock(block);
|
||||||
|
|
||||||
|
for (Operation node = block.Operations.First; node != default; node = node.ListNext)
|
||||||
|
{
|
||||||
|
GenerateOperation(context, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (block.SuccessorsCount == 0)
|
||||||
|
{
|
||||||
|
// The only blocks which can have 0 successors are exit blocks.
|
||||||
|
Operation last = block.Operations.Last;
|
||||||
|
|
||||||
|
Debug.Assert(last.Instruction is Instruction.Tailcall or
|
||||||
|
Instruction.Return);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BasicBlock succ = block.GetSuccessor(0);
|
||||||
|
|
||||||
|
if (succ != block.ListNext)
|
||||||
|
{
|
||||||
|
context.JumpTo(succ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(byte[] code, RelocInfo relocInfo) = context.Assembler.GetCode();
|
||||||
|
|
||||||
|
Logger.EndPass(PassName.CodeGeneration);
|
||||||
|
|
||||||
|
return new CompiledFunction(code, unwindInfo, relocInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateAdd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
Operand dest = operation.Destination;
|
||||||
|
Operand src1 = operation.GetSource(0);
|
||||||
|
Operand src2 = operation.GetSource(1);
|
||||||
|
|
||||||
|
if (dest.Type.IsInteger())
|
||||||
|
{
|
||||||
|
context.Assembler.Add(dest, src1, src2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// todo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/ARMeilleure/CodeGen/Loong64/PreAllocator.cs
Normal file
18
src/ARMeilleure/CodeGen/Loong64/PreAllocator.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
|
using ARMeilleure.Translation;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||||
|
using static ARMeilleure.IntermediateRepresentation.Operation.Factory;
|
||||||
|
|
||||||
|
namespace ARMeilleure.CodeGen.Loong64
|
||||||
|
{
|
||||||
|
static class PreAllocator
|
||||||
|
{
|
||||||
|
public static void RunPass(CompilerContext cctx, out int maxCallArgs)
|
||||||
|
{
|
||||||
|
maxCallArgs = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user