CodeGenerator实现

This commit is contained in:
2026-01-22 21:23:08 +08:00
parent caf0f58fb0
commit 100a9d3546
4 changed files with 220 additions and 0 deletions

View File

@ -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;

View File

@ -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);
}
}
}

View 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
}
}
}
}

View 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;
}
}
}