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); }
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); }
public static void MethodReturnPaths(Syntax.MethodSyntax pMethod, TextSpan pSpan) { _error.WriteError($"Not all code paths within {pMethod.Name} return a value", pSpan); }
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); }