#light namespace Lost.JIT.AMD64 open System open System.Reflection open Lost.JIT.AMD64 type StackItem= { Size: int; IsInteger: bool; IsFloat: bool; IsSigned: bool; ContentType: Type; IsBox: bool; } module public CodeGen= let EAX = GeneralPurposeRegister.EAX let EBX = GeneralPurposeRegister.EBX let RIP = MemoryOperand(RipBased=true) let ADC dest source = AddWithCarry(dest, source) let ADD dest source = Add(dest, source) let AND dest source = And(dest, source) let CMP dest source = Compare(dest, source) let JMP dest = Jump(LabelOperand(Label = dest)) let LABEL label = Label(Name = label) let CALL dest = Call(dest) let RET() = Return() let RETP(value) = Return(value) let MOV dest source = Move(dest, source) let POP dest = Pop(dest) let PUSH source = Push(source) let GenerateSub(left, right)= match left, right with | left, right when left.IsInteger && right.IsInteger && right.Size == 4 && left.Size == 4 -> [POP RAX; POP RBX; SUB EBX EAX; PUSH RBX;] | left, right when left.IsInteger && right.IsInteger && right.Size == 8 && left.Size == 8 -> [POP RAX; POP RBX; SUB RBX, RAX; PUSH RBX;] | _ -> raise (NotSupportedException("invalid sizes")) let GenerateAdd(left, right)= match left, right with | left, right when left.IsInteger && right.IsInteger && right.Size == 4 && left.Size == 4 -> [POP RAX; POP RBX; ADD EBX EAX; PUSH RBX;] | left, right when left.IsInteger && right.IsInteger && right.Size == 8 && left.Size == 8 -> [POP RAX; POP RBX; ADD RBX, RAX; PUSH RBX;] | _ -> raise (NotSupportedException("invalid sizes")) let rec GenerateCodeRec(il, offset, func, nametable, localtable, stack)= let add = byte 0x58 let sub = byte 0x59 let div = byte 0x5B match il with | add :: ilxs -> match stack with | right :: left :: stackxs -> GenerateAdd(left, right) :: GenerateCodeRec(ilxs, offset + 1, func, nametable, localtable, stackxs) | _ -> raise (InvalidProgramException("invalid stack for add")) | sub :: ilxs -> match stack with | right :: left :: stackxs -> GenerateSub(left, right) :: GenerateCodeRec(ilxs, offset + 1, func, nametable, localtable, stackxs) | _ -> raise (InvalidProgramException("invalid stack for sub")) | div :: ilxs -> | right :: left :: stackxs -> GenerateAdd(left, right) :: GenerateCodeRec(ilxs, offset + 1, func, nametable, localtable, stackxs) | _ -> raise (InvalidProgramException("invalid stack for add")) let GenerateCode(func: System.Reflection.MethodInfo, nametable)= List.of_array(func.GetMethodBody().GetILAsByteArray()) GenerateCodeRec(il, 0, func, nametable, localtable, []) open CodeGen ADC EAX EBX ADC (EAX + 0) EAX ADC (EAX + RIP) EAX LABEL "start" JMP "start"