public void OutputCodeForDelegateCtorInit(LLVMBuilderRef builder, LLVMValueRef helperFunc, MethodDesc constructor, LLVMValueRef fatFunction) { StackEntry[] argValues = new StackEntry [constructor.Signature.Length + 1]; // for delegate this var shadowStack = helperFunc.GetParam(0); argValues[0] = new LoadExpressionEntry(StackValueKind.ObjRef, "this", shadowStack, GetWellKnownType(WellKnownType.Object)); for (var i = 0; i < constructor.Signature.Length; i++) { if (i == 1) { argValues[i + 1] = new ExpressionEntry(StackValueKind.Int32, "arg" + (i + 1), builder.BuildIntToPtr(fatFunction, LLVMTypeRef.CreatePointer(LLVMTypeRef.Int8, 0), "toPtr"), GetWellKnownType(WellKnownType.IntPtr)); } else { var argRef = LoadVarAddress(i + 1, LocalVarKind.Argument, out TypeDesc type); var ptrPtr = builder.BuildPointerCast(argRef, LLVMTypeRef.CreatePointer(LLVMTypeRef.CreatePointer(LLVMTypeRef.Int8, 0), 0), "ptrPtr"); var loadArg = builder.BuildLoad(ptrPtr, "arg" + (i + 1)); argValues[i + 1] = new ExpressionEntry(GetStackValueKind(constructor.Signature[i]), "arg" + i + 1, loadArg, constructor.Signature[i]); } } HandleCall(constructor, constructor.Signature, constructor, argValues, null); }
private void ImportReturn() { if (_method.Signature.ReturnType != GetWellKnownType(WellKnownType.Void)) { StackEntry retVal = _stack.Pop(); LLVMTypeRef valueType = GetLLVMTypeForTypeDesc(_method.Signature.ReturnType); ImportStoreHelper(retVal.LLVMValue, valueType, LLVM.GetNextParam(LLVM.GetFirstParam(_llvmFunction)), 0); } LLVM.BuildRetVoid(_builder); }
/// <summary> /// Generate a cast in case the stack type of source is not identical or compatible with destination type. /// </summary> /// <param name="destType">Type of destination</param> /// <param name="srcEntry">Source entry from stack</param> private void AppendCastIfNecessary(TypeDesc destType, StackEntry srcEntry) { ConstantEntry constant = srcEntry as ConstantEntry; if ((constant != null) && (constant.IsCastNecessary(destType)) || !destType.IsValueType || destType != srcEntry.Type) { throw new NotImplementedException(); /* * Append("("); * Append(GetSignatureTypeNameAndAddReference(destType)); * Append(")");*/ } }
private void ImportConvert(WellKnownType wellKnownType, bool checkOverflow, bool unsigned) { StackEntry value = _stack.Pop(); StackEntry convertedValue = value.Duplicate(); //conv.u for a pointer should change to a int8* if (wellKnownType == WellKnownType.UIntPtr) { if (value.Kind == StackValueKind.Int32) { convertedValue.LLVMValue = LLVM.BuildIntToPtr(_builder, value.LLVMValue, LLVM.PointerType(LLVM.Int8Type(), 0), "conv.u"); } } _stack.Push(convertedValue); }
private void ImportStoreField(int token, bool isStatic) { if (isStatic) { throw new NotImplementedException("static stfld"); } FieldDesc field = (FieldDesc)_methodIL.GetObject(token); StackEntry valueEntry = _stack.Pop(); StackEntry objectEntry = _stack.Pop(); var untypedObjectPointer = LLVM.BuildPointerCast(_builder, objectEntry.LLVMValue, LLVM.PointerType(LLVMTypeRef.Int8Type(), 0), "stfld"); var storeLocation = LLVM.BuildGEP(_builder, untypedObjectPointer, new LLVMValueRef[] { LLVM.ConstInt(LLVM.Int32Type(), (ulong)field.Offset.AsInt, LLVMMisc.False) }, "stfld"); var typedStoreLocation = LLVM.BuildPointerCast(_builder, storeLocation, LLVM.PointerType(GetLLVMTypeForTypeDesc(valueEntry.Type), 0), "stfld"); LLVM.BuildStore(_builder, valueEntry.LLVMValue, typedStoreLocation); }
private void ImportLoadIndirect(TypeDesc type) { StackEntry pointer = _stack.Pop(); LLVMTypeRef loadType = GetLLVMTypeForTypeDesc(type); LLVMTypeRef pointerType = LLVM.PointerType(loadType, 0); LLVMValueRef typedPointer; if (LLVM.GetTypeKind(LLVM.TypeOf(pointer.LLVMValue)) != LLVMTypeKind.LLVMPointerTypeKind) { typedPointer = LLVM.BuildIntToPtr(_builder, pointer.LLVMValue, pointerType, "ldindintptrcast"); } else { typedPointer = LLVM.BuildPointerCast(_builder, pointer.LLVMValue, pointerType, "ldindptrcast"); } LLVMValueRef load = LLVM.BuildLoad(_builder, typedPointer, "ldind"); PushExpression(GetStackValueKind(type), "ldlind", load, type); }
private void ImportBinaryOperation(ILOpcode opcode) { StackEntry op1 = _stack.Pop(); StackEntry op2 = _stack.Pop(); // StackValueKind is carefully ordered to make this work (assuming the IL is valid) StackValueKind kind; TypeDesc type; if (op1.Kind > op2.Kind) { kind = op1.Kind; type = op1.Type; } else { kind = op2.Kind; type = op2.Type; } // The one exception from the above rule if ((kind == StackValueKind.ByRef) && (opcode == ILOpcode.sub || opcode == ILOpcode.sub_ovf || opcode == ILOpcode.sub_ovf_un)) { kind = StackValueKind.NativeInt; type = null; } LLVMValueRef result; switch (opcode) { case ILOpcode.add: // TODO: converting these to ints should also happen for sub and some other operations LLVMValueRef left = op1.LLVMValue; LLVMValueRef right = op2.LLVMValue; if (kind == StackValueKind.NativeInt || kind == StackValueKind.ObjRef || kind == StackValueKind.ByRef) { if (LLVM.GetTypeKind(LLVM.TypeOf(left)) == LLVMTypeKind.LLVMPointerTypeKind) { left = LLVM.BuildPtrToInt(_builder, left, LLVM.Int32Type(), "lptrasint"); } if (LLVM.GetTypeKind(LLVM.TypeOf(right)) == LLVMTypeKind.LLVMPointerTypeKind) { right = LLVM.BuildPtrToInt(_builder, right, LLVM.Int32Type(), "rptrasint"); } } result = LLVM.BuildAdd(_builder, left, right, "add"); break; case ILOpcode.sub: result = LLVM.BuildSub(_builder, op1.LLVMValue, op2.LLVMValue, "sub"); break; case ILOpcode.mul: result = LLVM.BuildMul(_builder, op1.LLVMValue, op2.LLVMValue, "mul"); break; case ILOpcode.div: result = LLVM.BuildSDiv(_builder, op1.LLVMValue, op2.LLVMValue, "sdiv"); break; case ILOpcode.div_un: result = LLVM.BuildUDiv(_builder, op1.LLVMValue, op2.LLVMValue, "udiv"); break; case ILOpcode.rem: result = LLVM.BuildSRem(_builder, op1.LLVMValue, op2.LLVMValue, "srem"); break; case ILOpcode.rem_un: result = LLVM.BuildURem(_builder, op1.LLVMValue, op2.LLVMValue, "urem"); break; case ILOpcode.and: result = LLVM.BuildAnd(_builder, op1.LLVMValue, op2.LLVMValue, "and"); break; case ILOpcode.or: result = LLVM.BuildOr(_builder, op1.LLVMValue, op2.LLVMValue, "or"); break; case ILOpcode.xor: result = LLVM.BuildXor(_builder, op1.LLVMValue, op2.LLVMValue, "xor"); break; // TODO: Overflow checks case ILOpcode.add_ovf: case ILOpcode.add_ovf_un: result = LLVM.BuildAdd(_builder, op1.LLVMValue, op2.LLVMValue, "add"); break; case ILOpcode.sub_ovf: case ILOpcode.sub_ovf_un: result = LLVM.BuildSub(_builder, op1.LLVMValue, op2.LLVMValue, "sub"); break; case ILOpcode.mul_ovf: case ILOpcode.mul_ovf_un: result = LLVM.BuildMul(_builder, op1.LLVMValue, op2.LLVMValue, "mul"); break; default: throw new InvalidOperationException(); // Should be unreachable } PushExpression(kind, "", result, type); }
public static string Name(this StackEntry entry) { return((entry as ExpressionEntry)?.Name); }
private void ImportBinaryOperation(ILOpcode opcode) { StackEntry op1 = _stack.Pop(); StackEntry op2 = _stack.Pop(); // StackValueKind is carefully ordered to make this work (assuming the IL is valid) StackValueKind kind; TypeDesc type; if (op1.Kind > op2.Kind) { kind = op1.Kind; type = op1.Type; } else { kind = op2.Kind; type = op2.Type; } // The one exception from the above rule if ((kind == StackValueKind.ByRef) && (opcode == ILOpcode.sub || opcode == ILOpcode.sub_ovf || opcode == ILOpcode.sub_ovf_un)) { kind = StackValueKind.NativeInt; type = null; } LLVMValueRef result; switch (opcode) { case ILOpcode.add: result = LLVM.BuildAdd(_builder, op1.LLVMValue, op2.LLVMValue, "add"); break; case ILOpcode.sub: result = LLVM.BuildSub(_builder, op1.LLVMValue, op2.LLVMValue, "sub"); break; case ILOpcode.mul: result = LLVM.BuildMul(_builder, op1.LLVMValue, op2.LLVMValue, "mul"); break; case ILOpcode.div: result = LLVM.BuildSDiv(_builder, op1.LLVMValue, op2.LLVMValue, "sdiv"); break; case ILOpcode.div_un: result = LLVM.BuildUDiv(_builder, op1.LLVMValue, op2.LLVMValue, "udiv"); break; case ILOpcode.rem: result = LLVM.BuildSRem(_builder, op1.LLVMValue, op2.LLVMValue, "srem"); break; case ILOpcode.rem_un: result = LLVM.BuildURem(_builder, op1.LLVMValue, op2.LLVMValue, "urem"); break; case ILOpcode.and: result = LLVM.BuildAnd(_builder, op1.LLVMValue, op2.LLVMValue, "and"); break; case ILOpcode.or: result = LLVM.BuildOr(_builder, op1.LLVMValue, op2.LLVMValue, "or"); break; case ILOpcode.xor: result = LLVM.BuildXor(_builder, op1.LLVMValue, op2.LLVMValue, "xor"); break; // TODO: Overflow checks case ILOpcode.add_ovf: case ILOpcode.add_ovf_un: result = LLVM.BuildAdd(_builder, op1.LLVMValue, op2.LLVMValue, "add"); break; case ILOpcode.sub_ovf: case ILOpcode.sub_ovf_un: result = LLVM.BuildSub(_builder, op1.LLVMValue, op2.LLVMValue, "sub"); break; case ILOpcode.mul_ovf: case ILOpcode.mul_ovf_un: result = LLVM.BuildMul(_builder, op1.LLVMValue, op2.LLVMValue, "mul"); break; default: throw new InvalidOperationException(); // Should be unreachable } PushExpression(kind, "", result, type); }