Exemplo n.º 1
0
        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();
            }
        }
Exemplo n.º 2
0
        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);
        }
Exemplo n.º 3
0
        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);
Exemplo n.º 4
0
        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));
        }
Exemplo n.º 5
0
        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, ""));
        }
Exemplo n.º 6
0
        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);
        }
Exemplo n.º 7
0
        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();
            }
        }
Exemplo n.º 8
0
        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);
        }
Exemplo n.º 9
0
        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);
        }
Exemplo n.º 10
0
        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");
            }
        }
Exemplo n.º 11
0
        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));
        }
Exemplo n.º 12
0
        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"));
        }