Exemplo n.º 1
0
        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, ""));
        }
Exemplo n.º 2
0
        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);
        }