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) { LLVMValueRef _main = Module.Emit(pContext); //Emit our function that the runtime will call. //This will just call the method marked with "@run" //The reason we do this is so we have a static method name we can call var main = pContext.EmitMethodHeader("_main", LLVMTypeRef.Int32Type(), new LLVMTypeRef[] { }); var mainB = main.AppendBasicBlock(""); LLVM.PositionBuilderAtEnd(pContext.Builder, mainB); LLVM.BuildCall(pContext.Builder, _main, new LLVMValueRef[] { }, ""); LLVM.BuildRet(pContext.Builder, pContext.GetInt(0)); pContext.ValidateMethod(main); return(default);
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) { 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); 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); 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"); } }
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 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")); }