public override LLVMValueRef Emit(EmittingContext pContext) { System.Diagnostics.Debug.Assert(_definition.MangledName != null); pContext.EmitDebugLocation(this); LLVMValueRef[] arguments = null; int start = 0; //If we are calling an instance method, we need to add the "self" parameter if (pContext.AccessStack.Count > 0) { arguments = new LLVMValueRef[Arguments.Count + 1]; //"consume" the entire access stack to get the object we are calling the method on arguments[0] = AccessStack <MemberAccess> .BuildGetElementPtr(pContext, null); pContext.AccessStack.Clear(); start = 1; } else { arguments = new LLVMValueRef[Arguments.Count]; } for (int i = 0; i < Arguments.Count; i++) { arguments[start + i] = Arguments[i].Emit(pContext); //Load the location of any pointer calculations //The exceptions to this are structs (arrays are structs) since we pass those as a pointer if (!Arguments[i].Type.IsStruct && !Arguments[i].Type.IsArray) { Utils.LlvmHelper.LoadIfPointer(ref arguments[start + i], pContext); } //For external methods passing strings, we only grab the char pointer if (_definition.External && Arguments[i].Type == SmallTypeCache.String) { if (!Utils.LlvmHelper.IsPointer(arguments[start + i])) { var tempVar = pContext.AllocateVariable(Value + "_temp", Arguments[i].Type); LLVM.BuildStore(pContext.Builder, arguments[start + i], tempVar); arguments[start + i] = tempVar; } arguments[start + i] = LLVM.BuildInBoundsGEP(pContext.Builder, arguments[start + i], new LLVMValueRef[] { pContext.GetInt(0), pContext.GetInt(1) }, "char_pointer"); Utils.LlvmHelper.LoadIfPointer(ref arguments[start + i], pContext); } //Implicitly cast any derived types if (_definition.ArgumentTypes[i] != Arguments[i].Type) { var type = SmallTypeCache.GetLLVMType(_definition.ArgumentTypes[i], pContext); Utils.LlvmHelper.MakePointer(arguments[start + i], ref type); arguments[start + i] = LLVM.BuildBitCast(pContext.Builder, arguments[start + i], type, ""); } } return(LLVM.BuildCall(pContext.Builder, pContext.GetMethod(_definition.MangledName), arguments, "")); }
public override LLVMValueRef Emit(EmittingContext pContext) { pContext.EmitDebugLocation(this); var val = Value.Emit(pContext); if (FromType == Type) { return(val); } LLVMTypeRef type = SmallTypeCache.GetLLVMType(Type, pContext); LLVMValueRef ret; if (!string.IsNullOrEmpty(_method.MangledName)) { //User defined cast, call the method if (_method.ArgumentTypes[0] != Value.Type) { var t = SmallTypeCache.GetLLVMType(_method.ArgumentTypes[0], pContext); Utils.LlvmHelper.MakePointer(val, ref t); val = LLVM.BuildBitCast(pContext.Builder, val, t, ""); } Utils.LlvmHelper.LoadIfPointer(ref val, pContext); ret = LLVM.BuildCall(pContext.Builder, pContext.GetMethod(_method.MangledName), new LLVMValueRef[] { val }, "user_cast"); } else { //Built in conversions Utils.LlvmHelper.LoadIfPointer(ref val, pContext); var fromIsFloat = Utils.TypeHelper.IsFloat(FromType); //Implicit cast to boolean, compare value to default if (Type == SmallTypeCache.Boolean) { var cmp = SmallTypeCache.GetLLVMDefault(FromType, pContext); if (fromIsFloat) { ret = LLVM.BuildFCmp(pContext.Builder, LLVMRealPredicate.LLVMRealONE, val, cmp, ""); } else { ret = LLVM.BuildICmp(pContext.Builder, LLVMIntPredicate.LLVMIntNE, val, cmp, ""); } } else if (Utils.TypeHelper.IsInt(FromType) && Utils.TypeHelper.IsFloat(Type)) { //Int -> Float ret = LLVM.BuildSIToFP(pContext.Builder, val, type, ""); } else if (fromIsFloat && Utils.TypeHelper.IsInt(Type)) { //Float -> Int ret = LLVM.BuildFPToSI(pContext.Builder, val, type, ""); } else if (Utils.TypeHelper.IsFloat(FromType) && Utils.TypeHelper.IsFloat(Type)) { //Float -> Double //Double -> Float ret = LLVM.BuildFPCast(pContext.Builder, val, type, ""); } else if (Type == SmallTypeCache.Char) { //Int -> Char ret = LLVM.BuildIntCast(pContext.Builder, val, SmallTypeCache.GetLLVMType(Type, pContext), ""); } else if (FromType == SmallTypeCache.Char) { //Char -> Int ret = LLVM.BuildIntCast(pContext.Builder, val, SmallTypeCache.GetLLVMType(FromType, pContext), ""); } else { //Trait cast, it should have been validated that it's already the proper type, just bitcast Utils.LlvmHelper.MakePointer(val, ref type); ret = LLVM.BuildBitCast(pContext.Builder, val, type, ""); } } return(ret); }