コード例 #1
0
        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 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);
コード例 #3
0
ファイル: ElseSyntax.cs プロジェクト: btbaggin/SmallerLang
        public override LLVMSharp.LLVMValueRef Emit(EmittingContext pContext)
        {
            pContext.EmitDebugLocation(this);

            If?.Emit(pContext);
            Body?.Emit(pContext);
            return(default);
コード例 #4
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();
            }
        }
コード例 #5
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);
        }
コード例 #6
0
ファイル: ForSyntax.cs プロジェクト: btbaggin/SmallerLang
        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);
コード例 #7
0
ファイル: MethodSyntax.cs プロジェクト: btbaggin/SmallerLang
        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);
コード例 #8
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);
        }
コード例 #9
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, ""));
        }
コード例 #10
0
        public override LLVMValueRef Emit(EmittingContext pContext)
        {
            pContext.EmitDebugLocation(this);

            ulong v = bool.Parse(Value) ? 1ul : 0ul;

            return(LLVM.ConstInt(LLVM.Int1Type(), v, EmittingContext.False));
        }
コード例 #11
0
        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);
コード例 #12
0
        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);
        }
コード例 #13
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"));
        }
コード例 #14
0
        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);
コード例 #15
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);
        }
コード例 #16
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));
        }
コード例 #17
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));
        }
コード例 #18
0
 public override LLVMValueRef Emit(EmittingContext pContext)
 {
     pContext.EmitDebugLocation(this);
     return(EmitOperator(Left.Emit(pContext), Operator, Right.Emit(pContext), pContext));
 }
コード例 #19
0
ファイル: CastSyntax.cs プロジェクト: btbaggin/SmallerLang
        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);
        }
コード例 #20
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();
            }
        }
コード例 #21
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);
        }
コード例 #22
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);
        }
コード例 #23
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");
            }
        }