public void GenerateAssign(Register source, CodeGen codeGen, ILinkingInfo fixer) { switch (Kind) { case ResultKind.Value: GenerateAssignValue(source, codeGen); return; case ResultKind.Pointer: GenerateAssignPointer(source, codeGen); return; case ResultKind.Pointer2: GenerateAssignPointer2(source, codeGen); return; case ResultKind.Pointer3: GenerateAssignPointer3(source, codeGen); return; case ResultKind.Offset: GenerateAssignOffset(source, codeGen, fixer); return; default: throw new NotImplementedException($"{nameof(ExpressionResult)}: {nameof(GenerateAssign)} has not implemented kind: {Kind}"); } }
public void GenerateMoveTo(Register target, CodeGen codeGen, ILinkingInfo fixer) { switch (Kind) { case ResultKind.Value: GenerateMoveToValue(target, codeGen); return; case ResultKind.Pointer: GenerateMoveToPointer(target, codeGen); return; case ResultKind.Pointer2: GenerateMoveToPointer2(target, codeGen); return; case ResultKind.Pointer3: GenerateMoveToPointer3(target, codeGen); return; case ResultKind.Offset: GenerateMoveToOffset(target, codeGen, fixer); return; default: throw new NotImplementedException($"{nameof(ExpressionResult)}: {nameof(GenerateMoveTo)} has not implemented kind: {Kind}"); } }
public void Store(ExpressionResult expressionResult, CodeGen codeGen, ILinkingInfo linkingInfo) { if (!IsRegister) { var tempRegister = IsIntegerType ? (Register)TempIntRegister : TempFloatRegister; expressionResult.GenerateMoveTo(tempRegister, expressionResult.ValueType, codeGen, linkingInfo); if (IsIntegerType) { codeGen.MovToDereferenced(Register64.RSP, tempRegister, StackOffset, Segment.SS); } else { codeGen.MovqToDereferenced(Register64.RSP, tempRegister, StackOffset, Segment.SS); } } else { expressionResult.GenerateMoveTo( expressionResult.ValueType.MakeRegisterWithCorrectSize(Register), expressionResult.ValueType, codeGen, linkingInfo ); } }
public static void InsertCode(this CodeGen codeGen, ILinkingInfo myFixer, long position, Action <CodeGen> insertAction) { var insertCode = new CodeGen(); insertAction(insertCode); myFixer.Insert(position, insertCode.GetBufferSpan().Length); codeGen.Insert(insertCode.GetBufferSpan(), position); }
public Compiler(ICompilerStore nodeCompilers, IFactory <ILinkingInfo> linkingInfoFactory, IEnumerable <FunctionImport> imports, IEnumerable <FunctionDeclaration> declarations) { _nodeCompilers = nodeCompilers ?? throw new ArgumentNullException(nameof(nodeCompilers)); _linkingInfoFactory = linkingInfoFactory ?? throw new ArgumentNullException(nameof(linkingInfoFactory)); _imports = imports ?? throw new ArgumentNullException(nameof(imports)); _declarations = declarations ?? throw new ArgumentNullException(nameof(declarations)); LinkingInfo = _linkingInfoFactory.Create(); }
private static ExpressionResult CastIntToFloat( Type sourceType, Type targetType, Register targetRegister, ExpressionResult source, CodeGen codeGen, ILinkingInfo linkingInfo ) { var sourceTypeSize = sourceType.SizeOf(); var tempSource = Register.IntRegisterFromSize(sourceTypeSize, 0); source.GenerateMoveTo(tempSource, Constants.LongType, codeGen, linkingInfo); if (targetType == Constants.FloatType) { switch (sourceTypeSize) { case 8: codeGen.CvtSi2Ss(targetRegister.AsFloat(), tempSource.AsR64()); break; case 4: codeGen.CvtSi2Ss(targetRegister.AsFloat(), tempSource.AsR32()); break; default: ThrowBadCast(sourceType, targetType); break; } } if (targetType == Constants.DoubleType) { switch (sourceTypeSize) { case 8: codeGen.CvtSi2Sd(targetRegister.AsFloat(), tempSource.AsR64()); break; case 4: codeGen.CvtSi2Sd(targetRegister.AsFloat(), tempSource.AsR32()); break; default: ThrowBadCast(sourceType, targetType); break; } } else { ThrowBadCast(sourceType, targetType); } return(new ExpressionResult(targetType, targetRegister)); }
public static void InsertCode( this CodeGen codeGen, ILinkingInfo myFixer, long position, ReadOnlySpan <byte> data, ILinkingInfo otherFixer = null ) { myFixer.Insert(position, data.Length); otherFixer?.CopyTo(myFixer, position); codeGen.Insert(data, position); }
private static ExpressionResult CastFloatToInt( Type sourceType, Type targetType, Register targetRegister, ExpressionResult source, CodeGen codeGen, ILinkingInfo linkingInfo ) { source.GenerateMoveTo(XmmRegister.XMM0, sourceType, codeGen, linkingInfo); if (sourceType == Constants.FloatType) { switch (targetType.SizeOf()) { case 8: codeGen.CvtSs2Si(targetRegister.AsR64(), XmmRegister.XMM0); break; case 4: codeGen.CvtSs2Si(targetRegister.AsR32(), XmmRegister.XMM0); break; default: ThrowBadCast(sourceType, targetType); break; } } if (sourceType == Constants.DoubleType) { switch (targetType.SizeOf()) { case 8: codeGen.CvtSd2Si(targetRegister.AsR64(), XmmRegister.XMM0); break; case 4: codeGen.CvtSd2Si(targetRegister.AsR32(), XmmRegister.XMM0); break; default: ThrowBadCast(sourceType, targetType); break; } } else { ThrowBadCast(sourceType, targetType); } return(new ExpressionResult(targetType, targetRegister)); }
private void GenerateMoveToOffset(Register register, CodeGen codeGen, ILinkingInfo fixer) { if (!register.FloatingPoint) { // mov target, [12345678] codeGen.MovFromDereferenced4(register, Constants.DummyOffsetInt); } else { // movq target, [12345678] codeGen.MovqFromDereferenced4(register.AsFloat(), Constants.DummyOffsetInt); } OffsetFixup(fixer, codeGen); }
private void GenerateAssignOffset(Register register, CodeGen codeGen, ILinkingInfo fixer) { if (!register.FloatingPoint) { // mov [12345678], register codeGen.MovToDereferenced4(Constants.DummyOffsetInt, register); } else { // movq [12345678], register codeGen.MovqToDereferenced4(Constants.DummyOffsetInt, register.AsFloat()); } OffsetFixup(fixer, codeGen); }
private static bool CompileIntegerDivision(CodeGen codeGen, ILinkingInfo linkingInfo, Type type, Register leftReg, ExpressionResult rightExpr) { var rightReg = type.OtherVolatileIntRegister(leftReg, Register64.RAX, Register64.RDX); rightExpr.GenerateMoveTo(rightReg, type, codeGen, linkingInfo); if (!leftReg.IsSameRegister(Register64.RAX)) { codeGen.Mov(Register64.RAX, leftReg.AsR64()); } var typeIsByte = type.SizeOf() == 1; var typeIsSigned = type.IsSignedInteger(); if (typeIsByte) { if (typeIsSigned) { codeGen.Movsx(Register64.RAX, Register8.AL); } else { codeGen.Movzx(Register64.RAX, Register8.AL); } } else { codeGen.Xor(Register64.RDX, Register64.RDX); if (typeIsSigned) { codeGen.Test(Register64.RAX, Register64.RAX); codeGen.Jns(CodeGenExtensions.InstructionLength(gen => gen.Not(Register64.RDX))); codeGen.Not(Register64.RDX); } } if (type.IsSignedInteger()) { codeGen.Idiv(rightReg); } else { codeGen.Div(rightReg); } return(typeIsByte); }
//todo: bug: rework this redundant shit private void GenerateUpgradeToOffset(Register target, CodeGen codeGen, ILinkingInfo fixer, bool signed) { if (!target.FloatingPoint && ValueType.IsIntegerRegisterType()) { var bitize = Math.Min(target.BitSize, ValueType.SizeOf() * 8); if (bitize == 32) { if (signed) { codeGen.MovsxdFromDereferenced4(target.AsR64(), Offset, Segment); } else { codeGen.MovFromDereferenced4(target, Offset, Segment); } } else { if (signed) { codeGen.MovsxFromDereferenced4(target, ValueType.SizeOf() == 1, Offset); } else { codeGen.MovzxFromDereferenced4(target, ValueType.SizeOf() == 1, Offset); } } } else if (target.FloatingPoint && Value.FloatingPoint) { codeGen.CvtSs2SdFromDereferenced4(target, Offset, Segment); } else { throw new NotImplementedException(); } OffsetFixup(fixer, codeGen); }
public void DereferenceFromRegister( CodeGen codeGen, Register source, ILinkingInfo fixer, GenericBrotherAction brotherAction, GenericToDrefAction drefAction, GenericToDref2Action dref2Action, GenericToDref3Action dref3Action, GenericToDref4Action dref4Action ) { switch (Kind) { case ResultKind.Value: DereferenceFromRegister(brotherAction, source); return; case ResultKind.Pointer: DereferenceFromRegister(drefAction, source); return; case ResultKind.Pointer2: DereferenceFromRegister(dref2Action, source); return; case ResultKind.Pointer3: DereferenceFromRegister(dref3Action, source); return; case ResultKind.Offset: DereferenceFromRegister(codeGen, source, dref4Action, fixer); return; default: throw new NotImplementedException($"{nameof(ExpressionResult)}: {nameof(GenerateMoveTo)} has not implemented kind: {Kind}"); } }
public static void TestTo(this ExpressionResult source, Register other, CodeGen codeGen, ILinkingInfo fixer) { source.DereferenceFromRegister( codeGen, other, fixer, codeGen.Test, codeGen.TestToDereferenced, codeGen.TestToDereferenced2, codeGen.TestToDereferenced3, codeGen.TestToDereferenced4 ); }
public static void ImulTo(this ExpressionResult source, Register target, CodeGen codeGen, ILinkingInfo fixer) { if (target.BitSize == 8) { throw new ArgumentException($"{nameof(ImulTo)} does not work with 8 bit types"); } source.DereferenceToRegister( target, codeGen, fixer, codeGen.Imul, codeGen.ImulFromDereferenced, codeGen.ImulFromDereferenced2, codeGen.ImulFromDereferenced3, codeGen.ImulFromDereferenced4 ); }
public static void AddTo(this ExpressionResult source, Register target, CodeGen codeGen, ILinkingInfo fixer) { source.DereferenceToRegister( target, codeGen, fixer, codeGen.Add, codeGen.AddFromDereferenced, codeGen.AddFromDereferenced2, codeGen.AddFromDereferenced3, codeGen.AddFromDereferenced4 ); }
private void DereferenceFromRegister(CodeGen codeGen, Register source, GenericToDref4Action action, ILinkingInfo fixer) { action(Offset, source); OffsetFixup(fixer, codeGen); }
public void GenerateMoveTo(Register target, Type targetType, CodeGen codeGen, ILinkingInfo fixer, bool isExplicitCast = false) { if (!isExplicitCast && !targetType.CanAssignImplicitly(ValueType)) { throw new TypeMismatchException(targetType.ToString(), ValueType.ToString()); } if (!target.FloatingPoint && target.BitSize / 8 != targetType.SizeOf()) { throw new ArgumentException($"Value of type {targetType} can not be moved to register {target}"); } if (targetType == ValueType) { GenerateMoveTo(target, codeGen, fixer); return; } if (targetType.SizeOf() < ValueType.SizeOf()) { throw new ArgumentException($"Cannot narrow type from {ValueType} to {targetType} without a cast", nameof(targetType)); } var signed = targetType.IsSignedInteger(); switch (Kind) { case ResultKind.Value: GenerateUpgradeToValue(target, codeGen, signed); return; case ResultKind.Pointer: GenerateUpgradeToPointer(target, codeGen, signed); return; case ResultKind.Pointer2: GenerateUpgradeToPointer2(target, codeGen, signed); return; case ResultKind.Pointer3: GenerateUpgradeToPointer3(target, codeGen, signed); return; case ResultKind.Offset: GenerateUpgradeToOffset(target, codeGen, fixer, signed); return; default: throw new NotImplementedException($"{nameof(ExpressionResult)}: {nameof(GenerateMoveTo)} has not implemented kind: {Kind}"); } }
private void DereferenceToRegister(Register target, CodeGen codeGen, GenericFromDref4Action action, ILinkingInfo fixer) { action(target, Offset); OffsetFixup(fixer, codeGen); }
public static void SubsdTo(this ExpressionResult source, Register target, CodeGen codeGen, ILinkingInfo fixer) { source.DereferenceToRegister( target, codeGen, fixer, (targetRegister, sourceRegister) => codeGen.Subsd(targetRegister.AsFloat(), sourceRegister.AsFloat()), codeGen.SubsdFromDereferenced, codeGen.SubsdFromDereferenced2, codeGen.SubsdFromDereferenced3, codeGen.SubsdFromDereferenced4 ); }