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);
Пример #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);
        }
Пример #3
0
        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);
        }
Пример #4
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, ""));
        }
Пример #5
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);
        }
Пример #6
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();
            }
        }
Пример #7
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);
        }
Пример #8
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);
        }
Пример #9
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");
            }
        }