Пример #1
0
        internal LLVMValueRef StartMethod(string pName, Syntax.MethodSyntax pNode)
        {
            var func = LLVM.GetNamedFunction(CurrentModule, pName);

            Debug.Assert(func.Pointer != IntPtr.Zero);
            Locals.AddScope();
            AddDebugScope(pNode.Span);

            //Emit body
            var body = LLVM.AppendBasicBlock(func, pName + "body");

            LLVM.PositionBuilderAtEnd(Builder, body);

            int start = 0;

            if (CurrentStruct != null)
            {
                start = 1;
                LLVMValueRef p = LLVM.GetParam(func, 0);
                LLVM.SetValueName(p, "self");
                Locals.DefineVariableInScope("self", LocalDefinition.CreateParameter(p, CurrentStruct));
                EmitDebugParameter("self", CurrentStruct, pNode.Span.Line, 0);
            }

            //Set parameter names and define in scope
            for (int i = 0; i < pNode.Parameters.Count; i++)
            {
                string       name = pNode.Parameters[i].Value;
                LLVMValueRef parm = LLVM.GetParam(func, (uint)(i + start));
                LLVM.SetValueName(parm, name);
                EmitDebugParameter(name, pNode.Parameters[i].Type, pNode.Span.Line, i + start);

                Debug.Assert(!Locals.IsVariableDefinedInScope(name), $"Parameter {name} already defined");
                Locals.DefineVariableInScope(name, LocalDefinition.CreateParameter(parm, pNode.Parameters[i].Type));
            }

            EmitFunctionDebugInfo(pNode, func);

            CurrentMethod = func;
            return(func);
        }
Пример #2
0
        public LLVMValueRef EmitMethodHeader(string pName, Syntax.MethodSyntax pMethod, out string pNewName)
        {
            //Get method return type
            LLVMTypeRef ret;

            if (pMethod.ReturnValues.Count == 0)
            {
                ret = LLVMTypeRef.VoidType();
            }
            else if (pMethod.ReturnValues.Count == 1)
            {
                ret = SmallTypeCache.GetLLVMType(pMethod.Type, this);
            }
            else
            {
                LLVMTypeRef[] types = new LLVMTypeRef[pMethod.ReturnValues.Count];
                for (int i = 0; i < types.Length; i++)
                {
                    types[i] = SmallTypeCache.GetLLVMType(pMethod.ReturnValues[i].Type, this);
                }
                ret = LLVM.StructType(types, false);
                Cache.SetLLVMType(pMethod.Type.Name, ret);
            }

            //If we are emitting a struct method we need to add "self" as a parameter
            SmallType[]   originalTypes = new SmallType[pMethod.Parameters.Count];
            LLVMTypeRef[] parmTypes     = null;
            int           start         = 0;

            if (CurrentStruct != null)
            {
                parmTypes    = new LLVMTypeRef[pMethod.Parameters.Count + 1];
                parmTypes[0] = LLVMTypeRef.PointerType(SmallTypeCache.GetLLVMType(CurrentStruct, this), 0);
                start        = 1;
            }
            else
            {
                parmTypes = new LLVMTypeRef[pMethod.Parameters.Count];
            }

            //Get parameter types
            for (int i = 0; i < pMethod.Parameters.Count; i++)
            {
                var parmType = pMethod.Parameters[i].Type;
                if (parmType.IsGenericParameter)
                {
                    originalTypes[i] = TypeMappings[parmType.Name];
                }
                else
                {
                    originalTypes[i] = parmType;
                }

                //For calling external methods with strings, we only want to pass the character array
                if (pMethod.External && parmType == SmallTypeCache.String)
                {
                    parmType = parmType.GetElementType();
                }

                parmTypes[start + i] = SmallTypeCache.GetLLVMType(parmType, this);
                if (pMethod.Parameters[i].Type.IsStruct || pMethod.Parameters[i].Type.IsArray)
                {
                    parmTypes[start + i] = LLVMTypeRef.PointerType(parmTypes[start + i], 0);
                }
            }

            var result = Cache.FindMethod(out MethodDefinition pDefinition, null, CurrentStruct, pName, originalTypes);

            Debug.Assert(result == Compiler.FindResult.Found);
            pNewName = pDefinition.MangledName;

            //Method header
            var func = LLVM.GetNamedFunction(CurrentModule, pNewName);

            if (func.Pointer == IntPtr.Zero)
            {
                func = LLVM.AddFunction(CurrentModule, pNewName, LLVM.FunctionType(ret, parmTypes, false));
                LLVM.SetLinkage(func, LLVMLinkage.LLVMExternalLinkage);
            }

            if (pMethod.External)
            {
                //Create attribute so we can find it later when executing
                var attribute = LLVM.CreateStringAttribute(_context, "external", 8, pMethod.Annotation.Value, (uint)pMethod.Annotation.Value.Length);
                LLVM.AddAttributeAtIndex(func, LLVMAttributeIndex.LLVMAttributeFunctionIndex, attribute);
            }

            return(func);
        }
Пример #3
0
 public static void MethodReturnPaths(Syntax.MethodSyntax pMethod, TextSpan pSpan)
 {
     _error.WriteError($"Not all code paths within {pMethod.Name} return a value", pSpan);
 }
Пример #4
0
 public static void MethodNoReturn(Syntax.MethodSyntax pMethod, TextSpan pSpan)
 {
     _error.WriteError($"Method {pMethod.Name} returns no values, a return keyword must not be followed by an expression", pSpan);
 }