public override LLVMValueRef Emit(EmittingContext pContext) { pContext.EmitDebugLocation(this); var m = Type.GetConstructor(); //Used in a return or some other expression. //Not being used in an assignment if (Values.Count == 0) { //We return a value here because we need to pass the value on to the rest of the expression var variable = pContext.AllocateVariable("return_temp", Type); BuildCallToConstructor(m, variable, pContext); return(variable); } else { foreach (var v in Values) { v.DoNotLoad = true; var variable = v.Emit(pContext); if (v.Type != Type) { //Implicitly cast any derived types //This is the type itself so if you are doing Trait: t = new Concrete() where Concrete -> Trait var t = SmallTypeCache.GetLLVMType(Type, pContext); Utils.LlvmHelper.MakePointer(variable, ref t); variable = LLVM.BuildBitCast(pContext.Builder, variable, t, ""); } BuildCallToConstructor(m, variable, pContext); } //This isn't used in an expression so just calling the constructor on the value is enough return(default);
public override LLVMSharp.LLVMValueRef Emit(EmittingContext pContext) { pContext.EmitDebugLocation(this); //If condition var cond = Condition.Emit(pContext); var loop = LLVMSharp.LLVM.AppendBasicBlock(pContext.CurrentMethod, "while_loop"); var end = LLVMSharp.LLVM.AppendBasicBlock(pContext.CurrentMethod, "while_end"); pContext.BreakLocations.Push(end); //Jump to end or loop LLVMSharp.LLVM.BuildCondBr(pContext.Builder, cond, loop, end); //Loop LLVMSharp.LLVM.PositionBuilderAtEnd(pContext.Builder, loop); Body.Emit(pContext); pContext.BreakLocations.Pop(); if (!Utils.SyntaxHelper.LastStatementIsReturn(Body)) { //Jump back to start cond = Condition.Emit(pContext); LLVMSharp.LLVM.BuildCondBr(pContext.Builder, cond, loop, end); } //End LLVMSharp.LLVM.PositionBuilderAtEnd(pContext.Builder, end); return(default);
public override LLVMSharp.LLVMValueRef Emit(EmittingContext pContext) { pContext.EmitDebugLocation(this); If?.Emit(pContext); Body?.Emit(pContext); return(default);
public override LLVMSharp.LLVMValueRef Emit(EmittingContext pContext) { pContext.EmitDebugLocation(this); switch (NumberType) { case NumberTypes.Integer: return(pContext.GetInt(int.Parse(Value))); case NumberTypes.Long: return(pContext.GetLong(long.Parse(Value))); case NumberTypes.Short: return(pContext.GetShort(short.Parse(Value))); case NumberTypes.Float: return(pContext.GetFloat(float.Parse(Value))); case NumberTypes.Double: return(pContext.GetDouble(double.Parse(Value))); default: throw new NotSupportedException(); } }
public override LLVMValueRef Emit(EmittingContext pContext) { pContext.EmitDebugLocation(this); var variable = pContext.AllocateVariable("string_temp", this); var literal = EscapeString(); //Save length var length = pContext.GetArrayLength(variable); LLVM.BuildStore(pContext.Builder, pContext.GetInt(literal.Length), length); //Allocate space for our string LLVMValueRef dataArray; using (var b = new VariableDeclarationBuilder(pContext)) { var charArray = LLVMTypeRef.ArrayType(SmallTypeCache.GetLLVMType(SmallTypeCache.Char, pContext), (uint)(literal.Length + 1)); //Need to allocate 1 more space for the /0 dataArray = LLVM.BuildAlloca(b.Builder, charArray, ""); } //Store the string constant in the allocated array var data = pContext.GetString(literal); LLVM.BuildStore(pContext.Builder, data, dataArray); //Store the allocated array in the string variable var dataAccess = LLVM.BuildInBoundsGEP(pContext.Builder, dataArray, new LLVMValueRef[] { pContext.GetInt(0), pContext.GetInt(0) }, ""); var variableData = LLVM.BuildInBoundsGEP(pContext.Builder, variable, new LLVMValueRef[] { pContext.GetInt(0), pContext.GetInt(1) }, ""); LLVM.BuildStore(pContext.Builder, dataAccess, variableData); return(variable); }
public override LLVMValueRef Emit(EmittingContext pContext) { //Iterator should have been rewritten to normal for loop System.Diagnostics.Debug.Assert(Iterator == null); pContext.EmitDebugLocation(this); pContext.Locals.AddScope(); pContext.AddDebugScope(Span); foreach (var d in Initializer) { d.Emit(pContext); } //for condition var cond = Condition.Emit(pContext); LLVMValueRef cmp = SmallTypeCache.GetLLVMDefault(Condition.Type, pContext); LLVMValueRef condv; if (Utils.TypeHelper.IsFloat(Condition.Type)) { condv = LLVM.BuildFCmp(pContext.Builder, LLVMRealPredicate.LLVMRealONE, cond, cmp, "for_cond"); } else { condv = LLVM.BuildICmp(pContext.Builder, LLVMIntPredicate.LLVMIntNE, cond, cmp, "for_cond"); } var loop = LLVM.AppendBasicBlock(pContext.CurrentMethod, "for_body"); var end = LLVM.AppendBasicBlock(pContext.CurrentMethod, "for_end"); pContext.BreakLocations.Push(end); //Jump to end or loop LLVM.BuildCondBr(pContext.Builder, condv, loop, end); //Loop LLVM.PositionBuilderAtEnd(pContext.Builder, loop); Body.Emit(pContext); foreach (var f in Finalizer) { f.Emit(pContext); } pContext.BreakLocations.Pop(); //Jump back to start cond = Condition.Emit(pContext); condv = LLVM.BuildICmp(pContext.Builder, LLVMIntPredicate.LLVMIntNE, cond, cmp, "for_cond"); LLVM.BuildCondBr(pContext.Builder, condv, loop, end); //End LLVM.PositionBuilderAtEnd(pContext.Builder, end); pContext.RemoveDebugScope(); pContext.Locals.RemoveScope(); return(default);
public override LLVMValueRef Emit(EmittingContext pContext) { pContext.EmitDebugLocation(this); if (!External) { System.Diagnostics.Debug.Assert(!string.IsNullOrEmpty(_name), "Method name cannot be blank"); var func = pContext.StartMethod(_name, this); pContext.AddDeferredStatementExecution(); pContext.Locals.AddScope(); pContext.AddDebugScope(Span); //Method bodies are slightly special because we want all variables to be declared in their scope //Don't call Body.Emit because that starts a new scope and all our variables will be not declared for deferred statements foreach (var s in Body.Statements) { if (!s.Deferred) { s.Emit(pContext); } else { pContext.AddDeferredStatement(s); } } //Emit all deferred statements unless the return handled it for us var lastIsReturn = Utils.SyntaxHelper.LastStatementIsReturn(Body); if (!lastIsReturn) { foreach (var s in pContext.GetDeferredStatements()) { s.Emit(pContext); } //We want to dispose variables after deferred statements because //then variables referenced in deferred statements will still be valid BlockSyntax.BuildCallToDispose(pContext); if (ReturnValues.Count == 0) { LLVM.BuildRetVoid(pContext.Builder); } else { //Return statements have been validated. It probably returned in some other block earlier. //LLVM requires return statement so just return default LLVM.BuildRet(pContext.Builder, SmallTypeCache.GetLLVMDefault(Type, pContext)); } } //End method pContext.RemoveDeferredStatementExecution(); pContext.RemoveDebugScope(); pContext.Locals.RemoveScope(); pContext.FinishMethod(func); return(func); } return(default);
public override LLVMValueRef Emit(EmittingContext pContext) { pContext.EmitDebugLocation(this); var variable = pContext.AllocateVariable("tern_return", Left.Type); var cond = Condition.Emit(pContext); Utils.LlvmHelper.LoadIfPointer(ref cond, pContext); var trueBranch = LLVM.AppendBasicBlock(pContext.CurrentMethod, "tern_true"); LLVMBasicBlockRef falseBranch = LLVM.AppendBasicBlock(pContext.CurrentMethod, "tern_false"); var end = LLVM.AppendBasicBlock(pContext.CurrentMethod, "tern_end"); //Jump to true or false LLVM.BuildCondBr(pContext.Builder, cond, trueBranch, falseBranch); //Emit true value LLVM.PositionBuilderAtEnd(pContext.Builder, trueBranch); LLVM.BuildStore(pContext.Builder, Left.Emit(pContext), variable); //Jump to end LLVM.BuildBr(pContext.Builder, end); //Emit false value LLVM.PositionBuilderAtEnd(pContext.Builder, falseBranch); LLVM.BuildStore(pContext.Builder, Right.Emit(pContext), variable); //Jump to end LLVM.BuildBr(pContext.Builder, end); LLVM.PositionBuilderAtEnd(pContext.Builder, end); return(variable); }
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); ulong v = bool.Parse(Value) ? 1ul : 0ul; return(LLVM.ConstInt(LLVM.Int1Type(), v, EmittingContext.False)); }
public override LLVMValueRef Emit(EmittingContext pContext) { pContext.EmitDebugLocation(this); var cond = Condition.Emit(pContext); Utils.LlvmHelper.LoadIfPointer(ref cond, pContext); var endBlock = LLVM.AppendBasicBlock(pContext.CurrentMethod, "endswitch"); LLVMBasicBlockRef elseBlock; pContext.BreakLocations.Push(endBlock); var builder = LLVM.CreateBuilder(); //Default case has to be the last one if (Cases[Cases.Count - 1].IsDefault) { //Emit else into our else block var b = pContext.Builder; pContext.SetBuilder(builder); elseBlock = Cases[Cases.Count - 1].Emit(pContext); pContext.SetBuilder(b); } else { //No else, so this is just an empty block elseBlock = LLVM.AppendBasicBlock(pContext.CurrentMethod, "else"); } LLVM.PositionBuilderAtEnd(builder, elseBlock); var s = LLVM.BuildSwitch(pContext.Builder, cond, elseBlock, (uint)Cases.Count); for (int i = 0; i < Cases.Count; i++) { if (!Cases[i].IsDefault) { //Emit case and jump to end var c = Cases[i].Emit(pContext); LLVM.BuildBr(pContext.Builder, endBlock); foreach (var cs in Cases[i].Conditions) { LLVM.AddCase(s, cs.Emit(pContext), c); } } } LLVM.PositionBuilderAtEnd(pContext.Builder, endBlock); pContext.BreakLocations.Pop(); //Jump from our else block to the end LLVM.BuildBr(builder, endBlock); LLVM.DisposeBuilder(builder); return(default);
public override LLVMValueRef Emit(EmittingContext pContext) { pContext.EmitDebugLocation(this); //Most of the code for case is generated in SelectSyntax var b = LLVM.AppendBasicBlock(pContext.CurrentMethod, "case"); LLVM.PositionBuilderAtEnd(pContext.Builder, b); Body.Emit(pContext); return(b); }
public override LLVMValueRef Emit(EmittingContext pContext) { pContext.EmitDebugLocation(this); //We are in a member access, just push the index of this field onto the stack LLVMValueRef variable = Identifier.Emit(pContext); var index = Index.Emit(pContext); Utils.LlvmHelper.LoadIfPointer(ref index, pContext); var indexAccess = LLVM.BuildInBoundsGEP(pContext.Builder, variable, new LLVMValueRef[] { pContext.GetInt(0), pContext.GetInt(1) }, "arrayaccess"); var load = LLVM.BuildLoad(pContext.Builder, indexAccess, ""); return(LLVM.BuildInBoundsGEP(pContext.Builder, load, new LLVMValueRef[] { index }, "arrayaccess")); }
public override LLVMSharp.LLVMValueRef Emit(EmittingContext pContext) { pContext.EmitDebugLocation(this); var cond = Condition.Emit(pContext); Utils.LlvmHelper.LoadIfPointer(ref cond, pContext); var then = LLVMSharp.LLVM.AppendBasicBlock(pContext.CurrentMethod, "if_then"); LLVMSharp.LLVMBasicBlockRef elseB = default; if (Else != null) { elseB = LLVMSharp.LLVM.AppendBasicBlock(pContext.CurrentMethod, "if_else"); } var endB = LLVMSharp.LLVM.AppendBasicBlock(pContext.CurrentMethod, "if_end"); //Jump to if or else/end (depending on if we have an else block) LLVMSharp.LLVM.BuildCondBr(pContext.Builder, cond, then, Else != null ? elseB : endB); //Emit then value LLVMSharp.LLVM.PositionBuilderAtEnd(pContext.Builder, then); Body.Emit(pContext); if (!Utils.SyntaxHelper.LastStatementIsReturn(Body) && !Utils.SyntaxHelper.LastStatementIsBreak(Body)) { //Jump to end only if we didn't terminate in the body LLVMSharp.LLVM.BuildBr(pContext.Builder, endB); } //Emit else value if (Else != null) { LLVMSharp.LLVM.PositionBuilderAtEnd(pContext.Builder, elseB); Else.Emit(pContext); if (!Utils.SyntaxHelper.LastStatementIsReturn(Else)) { //Jump to end only if we didn't terminate in the body LLVMSharp.LLVM.BuildBr(pContext.Builder, endB); } } //Position builder at the end of the if statement //before we continue on to emitting other statements LLVMSharp.LLVM.PositionBuilderAtEnd(pContext.Builder, endB); return(default);
public override LLVMValueRef Emit(EmittingContext pContext) { pContext.EmitDebugLocation(this); var variable = pContext.AllocateVariable("array_temp", this); var size = Size.Emit(pContext); var length = pContext.GetArrayLength(variable); LLVM.BuildStore(pContext.Builder, size, length); var data = pContext.AllocateArrayLiteral(Type.GetElementType(), size); var variableData = LLVM.BuildInBoundsGEP(pContext.Builder, variable, new LLVMValueRef[] { pContext.GetInt(0), pContext.GetInt(1) }, ""); LLVM.BuildStore(pContext.Builder, data, variableData); return(variable); }
public override LLVMValueRef Emit(EmittingContext pContext) { pContext.EmitDebugLocation(this); //Emit deferred statements right before return foreach (var s in pContext.GetDeferredStatements()) { s.Emit(pContext); } //We want to dispose variables after deferred statements because //then variables referenced in deferred statements will still be valid BlockSyntax.BuildCallToDispose(pContext); if (Values.Count == 0) { return(LLVM.BuildRetVoid(pContext.Builder)); } LLVMValueRef v; if (Values.Count == 1) { v = Values[0].Emit(pContext); Utils.LlvmHelper.LoadIfPointer(ref v, pContext); } else { //Allocate our tuple and set each field v = LLVM.BuildAlloca(pContext.Builder, SmallTypeCache.GetLLVMType(Type, pContext), ""); for (int i = 0; i < Values.Count; i++) { var location = LLVM.BuildInBoundsGEP(pContext.Builder, v, new LLVMValueRef[] { pContext.GetInt(0), pContext.GetInt(i) }, ""); var value = Values[i].Emit(pContext); Utils.LlvmHelper.LoadIfPointer(ref value, pContext); LLVM.BuildStore(pContext.Builder, value, location); } v = LLVM.BuildLoad(pContext.Builder, v, ""); } return(LLVM.BuildRet(pContext.Builder, v)); }
public override LLVMSharp.LLVMValueRef Emit(EmittingContext pContext) { pContext.EmitDebugLocation(this); //We are in a member access, just push the index of this field onto the stack if (pContext.AccessStack.Count > 0) { var idx = pContext.AccessStack.Peek().Type.GetFieldIndex(Value); System.Diagnostics.Debug.Assert(idx != -1, "Unable to find field"); return(pContext.GetInt(idx)); } System.Diagnostics.Debug.Assert(pContext.Locals.IsVariableDefined(Value), "Variable " + Value + " not defined in scope"); var ld = pContext.Locals.GetVariable(Value); if (ld.IsParameter || Type.IsStruct || Type.IsArray || Type.IsTrait || DoNotLoad) { return(ld.Value); } return(LLVMSharp.LLVM.BuildLoad(pContext.Builder, ld.Value, Value)); }
public override LLVMValueRef Emit(EmittingContext pContext) { pContext.EmitDebugLocation(this); return(EmitOperator(Left.Emit(pContext), Operator, Right.Emit(pContext), pContext)); }
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); }
public override LLVMValueRef Emit(EmittingContext pContext) { pContext.EmitDebugLocation(this); LLVMValueRef value; switch (Operator) { case UnaryExpressionOperator.Not: value = Value.Emit(pContext); Utils.LlvmHelper.LoadIfPointer(ref value, pContext); return(LLVM.BuildNot(pContext.Builder, value, "")); case UnaryExpressionOperator.Negative: value = Value.Emit(pContext); Utils.LlvmHelper.LoadIfPointer(ref value, pContext); return(LLVM.BuildNeg(pContext.Builder, value, "")); case UnaryExpressionOperator.Length: var arr = Value.Emit(pContext); return(LLVM.BuildLoad(pContext.Builder, pContext.GetArrayLength(arr), "")); case UnaryExpressionOperator.PreIncrement: case UnaryExpressionOperator.PreDecrement: case UnaryExpressionOperator.PostIncrement: case UnaryExpressionOperator.PostDecrement: var variable = (IdentifierSyntax)Value; variable.DoNotLoad = true; LLVMValueRef v = variable.Emit(pContext); BinaryExpressionOperator op = BinaryExpressionOperator.Equals; switch (Operator) { case UnaryExpressionOperator.PostDecrement: case UnaryExpressionOperator.PreDecrement: op = BinaryExpressionOperator.Subtraction; break; case UnaryExpressionOperator.PostIncrement: case UnaryExpressionOperator.PreIncrement: op = BinaryExpressionOperator.Addition; break; } value = BinaryExpressionSyntax.EmitOperator(v, op, pContext.GetInt(1), pContext); //Post unary we want to return the original variable value if (Operator == UnaryExpressionOperator.PostIncrement || Operator == UnaryExpressionOperator.PostDecrement) { //Save the old value to a temp variable that we will return var temp = pContext.AllocateVariable("<temp_unary>", Value); LLVMValueRef tempValue = Utils.LlvmHelper.IsPointer(v) ? LLVM.BuildLoad(pContext.Builder, v, "") : v; LLVM.BuildStore(pContext.Builder, tempValue, temp); //Increment the variable Utils.LlvmHelper.LoadIfPointer(ref value, pContext); if (Value.SyntaxType == SyntaxType.Identifier || Value.SyntaxType == SyntaxType.MemberAccess) { LLVM.BuildStore(pContext.Builder, value, v); } return(temp); } //If it isn't a variable we cane save we need to return the addition if (Value.SyntaxType == SyntaxType.Identifier || Value.SyntaxType == SyntaxType.MemberAccess) { LLVM.BuildStore(pContext.Builder, value, v); } return(value); default: throw new NotSupportedException(); } }
public override LLVMValueRef Emit(EmittingContext pContext) { pContext.EmitDebugLocation(this); LLVMValueRef value; if (Variables.Count == 1) { var v = Variables[0]; v.DoNotLoad = true; //we want to make sure to emit the variable before the value //Value could change Variable ie incrementing an array index ie x[y] = y += 1 //Emit the field if it's a member access var variable = v.Emit(pContext); value = Value.Emit(pContext); if (Value.SyntaxType != SyntaxType.StructInitializer) { //Struct initializers take a pointer to the object so we don't need to store it if (Operator != AssignmentOperator.Equals) { value = BinaryExpressionSyntax.EmitOperator(variable, AssignmentToBinary(Operator), value, pContext); } //Load the value of the pointer Utils.LlvmHelper.LoadIfPointer(ref value, pContext); LLVM.BuildStore(pContext.Builder, value, variable); } } else { value = Value.Emit(pContext); if (Value.SyntaxType != SyntaxType.StructInitializer) { //Create our temp tuple value var t = SmallTypeCache.GetOrCreateTuple(Utils.SyntaxHelper.SelectNodeTypes(Variables)); var tuple = pContext.AllocateVariable("<temp_tuple>", t); Utils.LlvmHelper.LoadIfPointer(ref value, pContext); //If our value is not a tuple we need to allocate the tuple fields manually if (!Value.Type.IsTuple) { for (int i = 0; i < t.GetFieldCount(); i++) { var tv = LLVM.BuildInBoundsGEP(pContext.Builder, tuple, new LLVMValueRef[] { pContext.GetInt(0), pContext.GetInt(i) }, ""); LLVM.BuildStore(pContext.Builder, value, tv); //Certain things must be reallocated every time //otherwise value would just be pointing at the same memory location, causing assignments to affect multiple variables if (Utils.SyntaxHelper.MustReallocateOnDeclaration(Value)) { value = Value.Emit(pContext); Utils.LlvmHelper.LoadIfPointer(ref value, pContext); } } } else { //Load the value into our temp variable LLVM.BuildStore(pContext.Builder, value, tuple); } //Access each of the tuples fields, assigning them to our variables for (int i = 0; i < Variables.Count; i++) { var currentVar = Variables[i]; if (!Utils.SyntaxHelper.IsDiscard(currentVar)) { currentVar.DoNotLoad = true; var variable = currentVar.Emit(pContext); //Load tuple's field var indexAccess = LLVM.BuildInBoundsGEP(pContext.Builder, tuple, new LLVMValueRef[] { pContext.GetInt(0), pContext.GetInt(i) }, ""); indexAccess = LLVM.BuildLoad(pContext.Builder, indexAccess, ""); if (Operator != AssignmentOperator.Equals) { indexAccess = BinaryExpressionSyntax.EmitOperator(variable, AssignmentToBinary(Operator), indexAccess, pContext); } LLVM.BuildStore(pContext.Builder, indexAccess, variable); } } } } return(value); }
public override LLVMValueRef Emit(EmittingContext pContext) { pContext.EmitDebugLocation(this); foreach (var v in Variables) { //Do not allocate discards if (!Utils.SyntaxHelper.IsDiscard(v)) { System.Diagnostics.Debug.Assert(!pContext.Locals.IsVariableDefinedInScope(v.Value), "Variable " + v.Value + " already defined"); LLVMValueRef var = pContext.AllocateVariable(v.Value, v.Type); pContext.Locals.DefineVariableInScope(v.Value, LocalDefinition.Create(var, v.Type)); } } var value = Value.Emit(pContext); //We only don't need to assign if we call the constructor since that passes a pointer to the object if (Value.SyntaxType != SyntaxType.StructInitializer) { if (Variables.Count == 1) { //Need to load address of pointers Utils.LlvmHelper.LoadIfPointer(ref value, pContext); var v = pContext.Locals.GetVariable(Variables[0].Value); LLVM.BuildStore(pContext.Builder, value, v.Value); } else { //Create our temp tuple value var t = SmallTypeCache.GetOrCreateTuple(Utils.SyntaxHelper.SelectNodeTypes(Variables)); LLVMValueRef tuple = pContext.AllocateVariable("<temp_tuple>", t); Utils.LlvmHelper.LoadIfPointer(ref value, pContext); //If our value is not a tuple we need to allocate the tuple fields manually if (!Value.Type.IsTuple) { for (int i = 0; i < t.GetFieldCount(); i++) { var tv = LLVM.BuildInBoundsGEP(pContext.Builder, tuple, new LLVMValueRef[] { pContext.GetInt(0), pContext.GetInt(i) }, ""); LLVM.BuildStore(pContext.Builder, value, tv); //Certain things must be reallocated every time //otherwise value would just be pointing at the same memory location, causing assignments to affect multiple variables if (Utils.SyntaxHelper.MustReallocateOnDeclaration(Value)) { value = Value.Emit(pContext); Utils.LlvmHelper.LoadIfPointer(ref value, pContext); } } } else { //Load the value into our temp variable LLVM.BuildStore(pContext.Builder, value, tuple); } //Access each of the tuples fields, assigning them to our variables for (int i = 0; i < Variables.Count; i++) { if (!Utils.SyntaxHelper.IsDiscard(Variables[i])) { var indexAccess = LLVM.BuildInBoundsGEP(pContext.Builder, tuple, new LLVMValueRef[] { pContext.GetInt(0), pContext.GetInt(i) }, ""); indexAccess = LLVM.BuildLoad(pContext.Builder, indexAccess, ""); var variable = pContext.Locals.GetVariable(Variables[i].Value); LLVM.BuildStore(pContext.Builder, indexAccess, variable.Value); } } } } return(value); }
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"); } }