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); NamespaceSyntax ns = null; IdentifierSyntax access = Identifier; if (Identifier.SyntaxType == SyntaxType.Namespace) { ns = (NamespaceSyntax)Identifier; access = Value; } //Check if this is a "static" method if (!pContext.Cache.IsTypeDefined(ns, access.Value) || Value.SyntaxType == SyntaxType.MethodCall) { LLVMValueRef value; if (Identifier.SyntaxType == SyntaxType.Namespace) { value = Value.Emit(pContext); //Terminal nodes are fully emitted in their child most node if (IsTerminalNode(Value)) { value = AccessStack <MemberAccess> .BuildGetElementPtr(pContext, value); } } else { LLVMValueRef identifier = Identifier.Emit(pContext); //For every method call we need to stop and allocate a new variable //This is because our method call is going to return a value, but we need a pointer. //To solve this we allocate a temporary variable, store the value, and continue if (Identifier.SyntaxType == SyntaxType.MethodCall) { var tempVar = pContext.AllocateVariable("memberaccess_temp", Identifier.Type); LLVM.BuildStore(pContext.Builder, identifier, tempVar); identifier = tempVar; pContext.AccessStack.Clear(); } //Store the index we pushed at. //We will later pop only if that index still exists //This allows things like MethodCalls to wipe the stack (because the arguments aren't in the same stack) while still properly popping values var index = pContext.AccessStack.Push(new MemberAccess(identifier, Identifier.Type)); value = Value.Emit(pContext); //Terminal nodes are fully emitted in their child most node if (IsTerminalNode(Value)) { value = AccessStack <MemberAccess> .BuildGetElementPtr(pContext, value); } pContext.AccessStack.PopFrom(index); } return(value); } else { //Only this way while fields are allow to be accessed if (access.Type.IsEnum) { int i = 0; if (access.SyntaxType == SyntaxType.MemberAccess) { i = access.Type.GetEnumValue(((MemberAccessSyntax)access).Value.Value); } else { i = access.Type.GetEnumValue(Value.Value); } return(pContext.GetInt(i)); } throw new NotSupportedException("Only static fields on Enums are supported"); } }