CodeGenerator实现
This commit is contained in:
@ -27,12 +27,32 @@ namespace ARMeilleure.CodeGen.Loong64
|
||||
return (GetIntCalleeSavedRegisters() ^ RegistersMask) & ~ReservedRegsMask;
|
||||
}
|
||||
|
||||
public static int GetFpCallerSavedRegisters()
|
||||
{
|
||||
return GetFpCalleeSavedRegisters() ^ RegistersMask;
|
||||
}
|
||||
|
||||
public static int GetVecCallerSavedRegisters()
|
||||
{
|
||||
return GetVecCalleeSavedRegisters() ^ RegistersMask;
|
||||
}
|
||||
|
||||
public static int GetIntCalleeSavedRegisters()
|
||||
{
|
||||
// 被调用者保存的寄存器 (需要保存/恢复)
|
||||
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()
|
||||
{
|
||||
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