private static void LdElemA(EmitFuncObj _) { var index = _.Stack.Pop(); var array = _.Stack.Pop(); var idx = _.Builder.Element(array, new[] { index }); _.Stack.Push(idx); }
private static void Call(EmitFuncObj _) { var method = (MethodInfo)_.Argument; var args = method.GetParameters().Select(x => _.Stack.Pop()).Reverse().ToArray(); var result = _.Builder.Call(EmitFunction(_.Context, _.Module, method), args); if (result.Type.StructuralEquals(Type.GetVoid(_.Context)) == false) _.Stack.Push(result); }
private static void LdVar(EmitFuncObj _, Value[] values, int index) { _.Stack.Push(_.Builder.Load(values[index])); }
private static void StVar(EmitFuncObj _, Value[] values, int index) { _.Builder.Store(_.Stack.Pop(), values[index]); }
private static Function EmitFunction(Module module, MethodBase method) { var methodInfo = method as MethodInfo; var methodConstructor = method as ConstructorInfo; var declaringType = method.DeclaringType; if (methodInfo == null && methodConstructor == null) throw new CudaSharpException("Unknown MethodBase type " + method.GetType().FullName); if (declaringType == null) throw new CudaSharpException("Could not find the declaring type of " + method.Name.StripNameToValidPtx()); var parameters = method.GetParameters().Select(p => p.ParameterType); if (methodConstructor != null) parameters = new[] { declaringType.MakeByRefType() }.Concat(parameters); if (methodInfo != null && methodInfo.IsStatic == false) { if (declaringType.IsValueType == false) throw new CudaSharpException("Cannot compile object instance methods (did you forget to mark the method as static?)"); parameters = new[] { declaringType.MakeByRefType() }.Concat(parameters); } var llvmParameters = parameters.Select(t => ConvertType(module, t)).ToArray(); var funcType = new FunctionType(ConvertType(module, methodInfo == null ? typeof(void) : methodInfo.ReturnType), llvmParameters); var intrinsic = method.GetCustomAttribute<Gpu.BuiltinAttribute>(); if (intrinsic != null) { var name = intrinsic.Intrinsic; var preExisting = module.GetFunction(name); if (preExisting != null) return preExisting; return module.CreateFunction(name, funcType); } var function = module.CreateFunction(methodConstructor == null ? method.Name.StripNameToValidPtx() : declaringType.Name.StripNameToValidPtx() + "_ctor", funcType); var block = new Block("entry", module.Context, function); var writer = new InstructionBuilder(module.Context, block); var opcodes = method.Disassemble().ToList(); FindBranchTargets(opcodes, module.Context, function); var body = method.GetMethodBody(); var efo = new EmitFuncObj(module, function, body, writer, null, new Stack<Value>(), body == null ? null : new Value[body.LocalVariables.Count], new Value[llvmParameters.Length]); PrintHeader(efo); foreach (var opcode in opcodes) { if (EmitFunctions.ContainsKey(opcode.Opcode) == false) throw new CudaSharpException("Unsupported CIL instruction " + opcode.Opcode); var func = EmitFunctions[opcode.Opcode]; efo.Argument = opcode.Parameter; func(efo); } return function; }
private static void Br(EmitFuncObj _) { _.Builder.GoTo((Block)_.Argument); _.Builder = null; }
private static void StVar(EmitFuncObj _, Value[] values, int index) { var pop = _.Stack.Pop(); if (values[index] == null) values[index] = _.Builder.StackAlloc(pop.Type); _.Builder.Store(pop, values[index]); }
private static void CleUn(EmitFuncObj _) { FlipTopTwoStack(_); _.Stack.Push(_.Builder.Compare(IntegerComparison.UnsignedLessEqual, _.Stack.Pop(), _.Stack.Pop())); }
private static void Cle(EmitFuncObj _) { _.Stack.Push(_.Builder.Compare(IntegerComparison.SignedLessEqual, _.Stack.Pop(), _.Stack.Pop())); }
private static void LdVar(EmitFuncObj _, Value[] values, int index, bool isParameter) { if (values[index] == null) { if (!isParameter) throw new Exception("Uninitialized variable at index " + index); var arg = _.Function[index]; values[index] = _.Builder.StackAlloc(_.Function[index].Type); _.Builder.Store(arg, values[index]); _.Stack.Push(arg); } else { var load = _.Builder.Load(values[index]); _.Stack.Push(load); } }
private static void CltUn(EmitFuncObj _) { _.Stack.Push(_.Builder.Compare(IntegerComparison.UnsignedLess, _.Stack.Pop(), _.Stack.Pop())); }
private static void CgeUn(EmitFuncObj _) { _.Stack.Push(_.Builder.Compare(IntegerComparison.UnsignedGreaterEqual, _.Stack.Pop(), _.Stack.Pop())); }
private static void Cgt(EmitFuncObj _) { _.Stack.Push(_.Builder.Compare(IntegerComparison.SignedGreater, _.Stack.Pop(), _.Stack.Pop())); }
private static void Ceq(EmitFuncObj _) { FlipTopTwoStack(_); _.Stack.Push(_.Builder.Compare(IntegerComparison.Equal, PopNoBool(_), PopNoBool(_))); }
private static void ConvertNum(EmitFuncObj _, Type target, bool integerSignedness) { //var value = _.Stack.Pop(); //var valueType = value.Type; //if (valueType is IntegerType && target is FloatType) //{ // value = _.Builder. //} }
private static void Cge(EmitFuncObj _) { FlipTopTwoStack(_); _.Stack.Push(_.Builder.Compare(IntegerComparison.SignedGreaterEqual, _.Stack.Pop(), _.Stack.Pop())); }
private static void PrintHeader(EmitFuncObj _) { for (var index = 0; index < _.Parameters.Length; index++) { _.Parameters[index] = _.Builder.StackAlloc(_.Function[index].Type); _.Builder.Store(_.Function[index], _.Parameters[index]); } for (var index = 0; index < _.Locals.Length; index++) _.Locals[index] = _.Builder.StackAlloc(ConvertType(_.Module, _.CilMethod.LocalVariables[index].LocalType)); }
private static Value PopNoBool(EmitFuncObj _) { var popped = _.Stack.Pop(); if (popped.Type.StructuralEquals(IntegerType.Get(_.Context, 1))) popped = _.Builder.ZeroExtend(popped, IntegerType.GetInt32(_.Context)); return popped; }
private static void Ldfld(EmitFuncObj _) { var obj = _.Stack.Pop(); if (obj.Type is PointerType) _.Stack.Push(_.Builder.Load(ElementPointer(_, obj, FieldIndex((FieldInfo)_.Argument)))); else _.Stack.Push(_.Builder.Extract(obj, FieldIndex((FieldInfo)_.Argument))); }
private static void Nop(EmitFuncObj _) { var block = (Block)_.Argument; if (block == null) return; if (_.Builder != null) _.Builder.GoTo(block); _.Builder = new InstructionBuilder(_.Context, block); }
private static Value ElementPointer(EmitFuncObj _, Value pointer, int index) { var zeroConstant = IntegerType.GetInt32(_.Context).Constant(0, false); var indexConstant = IntegerType.GetInt32(_.Context).Constant((ulong)index, false); return _.Builder.Element(pointer, new Value[] { zeroConstant, indexConstant }); // guarenteed to be pointer type }
private static void BrCond(EmitFuncObj _, bool isTrue) { var tuple = (Tuple<Block, Block>)_.Argument; var cont = tuple.Item1; var target = tuple.Item2; _.Builder.If(_.Stack.Pop(), isTrue ? target : cont, isTrue ? cont : target); _.Builder = new InstructionBuilder(_.Context, cont); }
private static void NewobjPreConstructor(EmitFuncObj _) { var stackalloca = _.Builder.StackAlloc(ConvertType(_.Module, ((ConstructorInfo)_.Argument).DeclaringType)); var altstack = new Stack<Value>(); var paramLength = ((MethodBase)_.Argument).GetParameters().Length; for (var i = 0; i < paramLength; i++) altstack.Push(_.Stack.Pop()); _.Stack.Push(stackalloca); for (var i = 0; i < paramLength; i++) _.Stack.Push(altstack.Pop()); }
private static void LdVarA(EmitFuncObj _, Value[] values, int index) { _.Stack.Push(values[index]); }
private static void Call(EmitFuncObj _) { var method = (MethodBase)_.Argument; var count = method.GetParameters().Length; if (method is ConstructorInfo || method.IsStatic == false) count++; var args = Enumerable.Range(0, count).Select(x => _.Stack.Pop()).Reverse().ToArray(); var result = _.Builder.Call(EmitFunction(_.Module, method), args); if (result.Type.StructuralEquals(Type.GetVoid(_.Context)) == false) _.Stack.Push(result); else if (method is ConstructorInfo) _.Stack.Push(_.Builder.Load(args[0])); }
private static void StElem(EmitFuncObj _) { var value = _.Stack.Pop(); var index = _.Stack.Pop(); var array = _.Stack.Pop(); var idx = _.Builder.Element(array, new[] { index }); _.Builder.Store(value, idx); }
private static void FlipTopTwoStack(EmitFuncObj _) { var top = _.Stack.Pop(); var bottom = _.Stack.Pop(); _.Stack.Push(top); _.Stack.Push(bottom); }
private static void ConvertNum(EmitFuncObj _, Type target, bool integerSignedness) { var value = _.Stack.Pop(); var valueType = value.Type; if (valueType is IntegerType && target is FloatType) { if (integerSignedness) value = _.Builder.SignedIntToFloat(value, target); else value = _.Builder.UnsignedIntToFloat(value, target); } else if (valueType is FloatType && target is IntegerType) { if (integerSignedness) value = _.Builder.FloatToSignedInt(value, target); else value = _.Builder.FloatToUnsignedInt(value, target); } else if (valueType is IntegerType && target is IntegerType) { var valueInt = (IntegerType) valueType; var targetInt = (IntegerType) target; if (valueInt.Width > targetInt.Width) value = _.Builder.Trunc(value, target); else if (integerSignedness) value = _.Builder.SignExtend(value, target); else value = _.Builder.ZeroExtend(value, target); } else { throw new CudaSharpException(string.Format("Cannot convert {0} to {1}", valueType, target)); } _.Stack.Push(value); }
private static Function EmitFunction(Context context, Module module, MethodInfo method) { var funcType = new FunctionType(ConvertType(context, method.ReturnType), AnalyzeArguments(context, method.GetParameters())); var intrinsic = method.GetCustomAttribute<Gpu.BuiltinAttribute>(); if (intrinsic != null) { var name = intrinsic.Intrinsic; var preExisting = module.GetFunction(name); if (preExisting != null) return preExisting; return module.CreateFunction(name, funcType); } var function = module.CreateFunction(method.Name, funcType); var block = new Block("entry", context, function); var writer = new InstructionBuilder(context, block); var opcodes = method.Decompile().ToList(); FindBranchTargets(opcodes, context, function); var body = method.GetMethodBody(); var efo = new EmitFuncObj(context, module, function, writer, null, new Stack<Value>(), body == null ? null : new Value[body.LocalVariables.Count], new Value[method.GetParameters().Length]); foreach (var opcode in opcodes) { if (EmitFunctions.ContainsKey(opcode.Opcode) == false) throw new Exception("Unsupported CIL instruction " + opcode.Opcode); var func = EmitFunctions[opcode.Opcode]; efo.Argument = opcode.Parameter; func(efo); } return function; }