Exemplo n.º 1
0
        public void ShouldMapAllConfigFields()
        {
            var console = new string[0];
            var config = new ApplicationConfiguration
            {
                IsInGroupMode = true,
                IsTimedMode = true,
                IsVerbodeMode = true
            };
            config.DefaultArguments.ExecuteAlias = "alias";
            config.DefaultArguments.MethodArguments = new[] { "config" };
            config.DefaultArguments.ConstructorArguments = new[] { "config" };

            builder = new InstructionBuilder(console, config);
            var instructions = builder.Build();

            Assert.That(instructions.ExecuteAlias.Alias, Is.EqualTo("alias"));
            Assert.That(instructions.Instructions.ContainsKey(InstructionType.DisplayHelp), Is.False);
            Assert.That(instructions.Instructions.ContainsKey(InstructionType.DisplayList), Is.False);
            Assert.That(instructions.Instructions[InstructionType.Constructor].Arguments, Is.EqualTo(new[] { "config" }));
            Assert.That(instructions.Instructions[InstructionType.Method].Arguments, Is.EqualTo(new[] { "config" }));
            Assert.That(instructions.Instructions[InstructionType.Group], Is.Not.Null);
            Assert.That(instructions.Instructions[InstructionType.Timed], Is.Not.Null);
            Assert.That(instructions.Instructions[InstructionType.Verbose], Is.Not.Null);
        }
Exemplo n.º 2
0
        private static Function EmitFunction(Module module, MethodBase method)
        {
            var methodInfo = method as MethodInfo;
            var methodConstructor = method as ConstructorInfo;
            var declaringType = method.DeclaringType;
            if (methodInfo == null && methodConstructor == null)
                throw new CudaSharpException("Unknown MethodBase type " + method.GetType().FullName);
            if (declaringType == null)
                throw new CudaSharpException("Could not find the declaring type of " + method.Name.StripNameToValidPtx());

            var parameters = method.GetParameters().Select(p => p.ParameterType);
            if (methodConstructor != null)
                parameters = new[] { declaringType.MakeByRefType() }.Concat(parameters);
            if (methodInfo != null && methodInfo.IsStatic == false)
            {
                if (declaringType.IsValueType == false)
                    throw new CudaSharpException("Cannot compile object instance methods (did you forget to mark the method as static?)");
                parameters = new[] { declaringType.MakeByRefType() }.Concat(parameters);
            }
            var llvmParameters =
                parameters.Select(t => ConvertType(module, t)).ToArray();
            var funcType = new FunctionType(ConvertType(module, methodInfo == null ? typeof(void) : methodInfo.ReturnType), llvmParameters);

            var intrinsic = method.GetCustomAttribute<Gpu.BuiltinAttribute>();
            if (intrinsic != null)
            {
                var name = intrinsic.Intrinsic;
                var preExisting = module.GetFunction(name);
                if (preExisting != null)
                    return preExisting;
                return module.CreateFunction(name, funcType);
            }

            var function = module.CreateFunction(methodConstructor == null ? method.Name.StripNameToValidPtx() : declaringType.Name.StripNameToValidPtx() + "_ctor", funcType);

            var block = new Block("entry", module.Context, function);
            var writer = new InstructionBuilder(module.Context, block);

            var opcodes = method.Disassemble().ToList();
            FindBranchTargets(opcodes, module.Context, function);

            var body = method.GetMethodBody();
            var efo = new EmitFuncObj(module, function, body, writer, null, new Stack<Value>(),
                body == null ? null : new Value[body.LocalVariables.Count], new Value[llvmParameters.Length]);

            PrintHeader(efo);
            foreach (var opcode in opcodes)
            {
                if (EmitFunctions.ContainsKey(opcode.Opcode) == false)
                    throw new CudaSharpException("Unsupported CIL instruction " + opcode.Opcode);
                var func = EmitFunctions[opcode.Opcode];
                efo.Argument = opcode.Parameter;
                func(efo);
            }

            return function;
        }
Exemplo n.º 3
0
        public void ShouldMapAllConsoleFields()
        {
            var console = new[] { "alias", "-m", "console", "-c", "console", "-v", "-t", "-g", "-h", "-l" };

            builder = new InstructionBuilder(console, new ApplicationConfiguration());
            var instructions = builder.Build();

            Assert.That(instructions.ExecuteAlias.Alias, Is.EqualTo("alias"));
            Assert.That(instructions.Instructions[InstructionType.DisplayHelp], Is.Not.Null);
            Assert.That(instructions.Instructions[InstructionType.DisplayList], Is.Not.Null);
            Assert.That(instructions.Instructions[InstructionType.Constructor].Arguments, Is.EqualTo(new[] { "console" }));
            Assert.That(instructions.Instructions[InstructionType.Method].Arguments, Is.EqualTo(new[] { "console" }));
            Assert.That(instructions.Instructions[InstructionType.Group], Is.Not.Null);
            Assert.That(instructions.Instructions[InstructionType.Timed], Is.Not.Null);
            Assert.That(instructions.Instructions[InstructionType.Verbose], Is.Not.Null);
        }
Exemplo n.º 4
0
        public override Value?Visit(VarInExpression varInExpression)
        {
            varInExpression.ValidateNotNull(nameof(varInExpression));
            using (NamedValues.EnterScope( ))
            {
                EmitBranchToNewBlock("VarInScope");
                foreach (var localVar in varInExpression.LocalVariables)
                {
                    Alloca alloca    = LookupVariable(localVar.Name);
                    Value  initValue = Context.CreateConstant(0.0);
                    if (localVar.Initializer != null)
                    {
                        initValue = localVar.Initializer.Accept(this) ?? throw new CodeGeneratorException(ExpectValidExpr);
                    }

                    InstructionBuilder.Store(initValue, alloca);
                }

                return(varInExpression.Body.Accept(this));
            }
        }
Exemplo n.º 5
0
        public override Value VisitUnaryOpExpression([NotNull] UnaryOpExpressionContext context)
        {
            var opKind = context.GetOperatorInfo(ParserStack.Parser);

            if (opKind == OperatorKind.None)
            {
                throw new ArgumentException($"invalid unary operator {context.Op}", nameof(context));
            }

            string calleeName = $"$unary{context.Op}";
            var    function   = GetFunction(calleeName);

            if (function == null)
            {
                throw new ArgumentException($"Unknown function reference {calleeName}", nameof(context));
            }

            var arg = context.Rhs.Accept(this);

            return(InstructionBuilder.Call(function, arg).RegisterName("calltmp"));
        }
Exemplo n.º 6
0
        public void Ps3p_GetTrampoline()
        {
            var arch = new PowerPcBe64Architecture("ppc-be-64");
            var m    = new InstructionBuilder(arch, Address.Ptr32(0x10030000));

            m.Lis(m.r11, 0x1006);
            m.Lwz(m.r11, 0x1234, m.r11);
            m.Mtctr(m.r11);
            m.Bctr();
            var host = mr.Stub <IRewriterHost>();

            host.Stub(h => h.GetImportedProcedure(
                          Arg <Address> .Matches(a => a.ToLinear() == 0x10061234),
                          Arg <Address> .Is.Anything)).Return(new ExternalProcedure("foo", null));
            mr.ReplayAll();

            ProcedureBase proc = arch.GetTrampolineDestination(m.Instructions, host);

            Assert.IsNotNull(proc);
            Assert.AreEqual("foo", proc.Name);
        }
Exemplo n.º 7
0
        public void Ps3p_GetTrampoline()
        {
            var arch = new PowerPcBe64Architecture(new ServiceContainer(), "ppc-be-64", new Dictionary <string, object>());
            var m    = new InstructionBuilder(arch, Address.Ptr32(0x10030000));

            m.Lis(m.r11, 0x1006);
            m.Lwz(m.r11, 0x1234, m.r11);
            m.Mtctr(m.r11);
            m.Bctr();
            var host = new Mock <IRewriterHost>();

            host.Setup(h => h.GetImportedProcedure(
                           It.IsNotNull <IProcessorArchitecture>(),
                           It.Is <Address>(a => a.ToLinear() == 0x10061234),
                           It.IsAny <Address>()))
            .Returns(new ExternalProcedure("foo", new FunctionType()));

            ProcedureBase proc = arch.GetTrampolineDestination(m.Instructions, host.Object);

            Assert.IsNotNull(proc);
            Assert.AreEqual("foo", proc.Name);
        }
Exemplo n.º 8
0
 /// <summary>
 /// Tells if a particular value is strictly dominated by another value,
 /// that is, if control cannot flow to the value unless it first flowed
 /// through the dominator value.
 /// </summary>
 /// <param name="value">
 /// An value that might be dominated by <paramref name="dominator"/>.
 /// </param>
 /// <param name="dominator">
 /// An value that might dominate <paramref name="value"/>.
 /// </param>
 /// <returns>
 /// <c>true</c> if <paramref name="value"/> is strictly dominated by
 /// <paramref name="dominator"/>; otherwise, <c>false</c>.
 /// </returns>
 public bool IsStrictlyDominatedBy(InstructionBuilder value, ValueTag dominator)
 {
     if (value is NamedInstructionBuilder)
     {
         return(IsStrictlyDominatedBy((NamedInstructionBuilder)value, dominator, value.Graph));
     }
     else
     {
         var block          = value.Block;
         var dominatorBlock = value.Graph.GetValueParent(dominator);
         if (block == dominatorBlock)
         {
             // Anonymous flow instructions are always strictly dominated by
             // named values in the same block.
             return(true);
         }
         else
         {
             return(IsStrictlyDominatedBy(block, dominatorBlock));
         }
     }
 }
Exemplo n.º 9
0
        public CodeGenerator(DynamicRuntimeState globalState, TargetMachine machine, string sourcePath, bool disableOptimization = false)
            : base(null)
        {
            globalState.ValidateNotNull(nameof(globalState));
            machine.ValidateNotNull(nameof(machine));
            if (globalState.LanguageLevel > LanguageLevel.MutableVariables)
            {
                throw new ArgumentException("Language features not supported by this generator", nameof(globalState));
            }

            RuntimeState         = globalState;
            Context              = new Context( );
            TargetMachine        = machine;
            DisableOptimizations = disableOptimization;
            InstructionBuilder   = new InstructionBuilder(Context);

            #region InitializeModuleAndPassManager
            Module = Context.CreateBitcodeModule(Path.GetFileName(sourcePath), SourceLanguage.C, sourcePath, "Kaleidoscope Compiler");
            Debug.Assert(Module.DICompileUnit != null, "Expected non null compile unit");
            Debug.Assert(Module.DICompileUnit.File != null, "Expected non-null file for compile unit");

            Module.TargetTriple = machine.Triple;
            Module.Layout       = TargetMachine.TargetData;
            DoubleType          = new DebugBasicType(Context.DoubleType, Module, "double", DiTypeKind.Float);

            FunctionPassManager = new FunctionPassManager(Module);
            FunctionPassManager.AddPromoteMemoryToRegisterPass( );

            if (!DisableOptimizations)
            {
                FunctionPassManager.AddInstructionCombiningPass( )
                .AddReassociatePass( )
                .AddGVNPass( )
                .AddCFGSimplificationPass( );
            }

            FunctionPassManager.Initialize( );
            #endregion
        }
Exemplo n.º 10
0
        private (Function Function, int JitHandle) DefineFunction(Function function, ExpressionContext body)
        {
            if (!function.IsDeclaration)
            {
                throw new ArgumentException($"Function {function.Name} cannot be redefined", nameof(function));
            }

            var basicBlock = function.AppendBasicBlock("entry");

            InstructionBuilder.PositionAtEnd(basicBlock);
            NamedValues.Clear( );
            foreach (var arg in function.Parameters)
            {
                NamedValues[arg.Name] = arg;
            }

            var funcReturn = body.Accept(this);

            if (funcReturn == null)
            {
                function.EraseFromParent( );
                return(null, default);
Exemplo n.º 11
0
        public override Value?Visit(FunctionCallExpression functionCall)
        {
            functionCall.ValidateNotNull(nameof(functionCall));
            string targetName = functionCall.FunctionPrototype.Name;

            IrFunction?function;

            if (RuntimeState.FunctionDeclarations.TryGetValue(targetName, out Prototype target))
            {
                function = GetOrDeclareFunction(target);
            }
            else if (!Module.TryGetFunction(targetName, out function))
            {
                throw new CodeGeneratorException($"Definition for function {targetName} not found");
            }

            var args = (from expr in functionCall.Arguments
                        select expr.Accept(this) ?? throw new CodeGeneratorException(ExpectValidExpr)
                        ).ToArray();

            return(InstructionBuilder.Call(function, args).RegisterName("calltmp"));
        }
Exemplo n.º 12
0
        public Value Generate(IAstNode ast, Action <CodeGeneratorException> codeGenerationErroHandler)
        {
            try
            {
                ast.Accept(this);

                if (AnonymousFunctions.Count > 0)
                {
                    var mainFunction = Module.AddFunction("main", Context.GetFunctionType(Context.VoidType));
                    var block        = mainFunction.AppendBasicBlock("entry");
                    var irBuilder    = new InstructionBuilder(block);
                    var printdFunc   = Module.AddFunction("printd", Context.GetFunctionType(Context.DoubleType, Context.DoubleType));
                    foreach (var anonFunc in AnonymousFunctions)
                    {
                        var value = irBuilder.Call(anonFunc);
                        irBuilder.Call(printdFunc, value);
                    }

                    irBuilder.Return( );

                    // Use always inline and Dead Code Elimination module passes to inline all of the
                    // anonymous functions. This effectively strips all the calls just generated for main()
                    // and inlines each of the anonymous functions directly into main, dropping the now
                    // unused original anonymous functions all while retaining all of the original source
                    // debug information locations.
                    var mpm = new ModulePassManager( )
                              .AddAlwaysInlinerPass( )
                              .AddGlobalDCEPass( );
                    mpm.Run(Module);
                    Module.DIBuilder.Finish( );
                }
            }
            catch (CodeGeneratorException ex) when(codeGenerationErroHandler != null)
            {
                codeGenerationErroHandler(ex);
            }

            return(null);
        }
Exemplo n.º 13
0
        private bool TryGetCallee(InstructionBuilder instruction, out IMethod callee)
        {
            var proto = instruction.Prototype;

            if (proto is CallPrototype)
            {
                var callProto = (CallPrototype)proto;
                if (callProto.Lookup == MethodLookup.Static)
                {
                    callee = callProto.Callee;
                    return(true);
                }
            }
            else if (proto is NewObjectPrototype)
            {
                var newObjproto = (NewObjectPrototype)proto;
                callee = newObjproto.Constructor;
                return(true);
            }

            callee = null;
            return(false);
        }
Exemplo n.º 14
0
        public override Value Visit(VarInExpression varInExpression)
        {
            EmitLocation(varInExpression);
            using (NamedValues.EnterScope( ))
            {
                EmitBranchToNewBlock("VarInScope");
                foreach (var localVar in varInExpression.LocalVariables)
                {
                    EmitLocation(localVar);
                    Alloca alloca    = LookupVariable(localVar.Name);
                    Value  initValue = Context.CreateConstant(0.0);
                    if (localVar.Initializer != null)
                    {
                        initValue = localVar.Initializer.Accept(this);
                    }

                    InstructionBuilder.Store(initValue, alloca);
                }

                EmitLocation(varInExpression);
                return(varInExpression.Body.Accept(this));
            }
        }
Exemplo n.º 15
0
 public EmitFuncObj(Module module, Function function, MethodBody cilMethod, InstructionBuilder instructionBuilder, object argument, Stack <Value> stack, Value[] locals, Value[] parameters)
 {
     Module     = module;
     Function   = function;
     CilMethod  = cilMethod;
     Builder    = instructionBuilder;
     Argument   = argument;
     Stack      = stack;
     Locals     = locals;
     Parameters = parameters;
 }
Exemplo n.º 16
0
        private static void CreateCopyFunctionBody(BitcodeModule module
                                                   , DataLayout layout
                                                   , Function copyFunc
                                                   , DIFile diFile
                                                   , ITypeRef foo
                                                   , DebugPointerType fooPtr
                                                   , DIType constFooType
                                                   )
        {
            var diBuilder = module.DIBuilder;

            copyFunc.Parameters[0].Name = "src";
            copyFunc.Parameters[1].Name = "pDst";

            // create block for the function body, only need one for this simple sample
            var blk = copyFunc.AppendBasicBlock("entry");

            // create instruction builder to build the body
            var instBuilder = new InstructionBuilder(blk);

            // create debug info locals for the arguments
            // NOTE: Debug parameter indices are 1 based!
            var paramSrc = diBuilder.CreateArgument(copyFunc.DISubProgram, "src", diFile, 11, constFooType, false, 0, 1);
            var paramDst = diBuilder.CreateArgument(copyFunc.DISubProgram, "pDst", diFile, 12, fooPtr.DIType, false, 0, 2);

            uint ptrAlign = layout.CallFrameAlignmentOf(fooPtr);

            // create Locals
            // NOTE: There's no debug location attached to these instructions.
            //       The debug info will come from the declare intrinsic below.
            var dstAddr = instBuilder.Alloca(fooPtr)
                          .RegisterName("pDst.addr")
                          .Alignment(ptrAlign);

            bool param0ByVal = copyFunc.Attributes[FunctionAttributeIndex.Parameter0].Contains(AttributeKind.ByVal);

            if (param0ByVal)
            {
                diBuilder.InsertDeclare(copyFunc.Parameters[0]
                                        , paramSrc
                                        , new DILocation(module.Context, 11, 43, copyFunc.DISubProgram)
                                        , blk
                                        );
            }

            instBuilder.Store(copyFunc.Parameters[1], dstAddr)
            .Alignment(ptrAlign);

            // insert declare pseudo instruction to attach debug info to the local declarations
            diBuilder.InsertDeclare(dstAddr, paramDst, new DILocation(module.Context, 12, 38, copyFunc.DISubProgram), blk);

            if (!param0ByVal)
            {
                // since the function's LLVM signature uses a pointer, which is copied locally
                // inform the debugger to treat it as the value by dereferencing the pointer
                diBuilder.InsertDeclare(copyFunc.Parameters[0]
                                        , paramSrc
                                        , diBuilder.CreateExpression(ExpressionOp.deref)
                                        , new DILocation(module.Context, 11, 43, copyFunc.DISubProgram)
                                        , blk
                                        );
            }

            var loadedDst = instBuilder.Load(dstAddr)
                            .Alignment(ptrAlign)
                            .SetDebugLocation(15, 6, copyFunc.DISubProgram);

            var dstPtr = instBuilder.BitCast(loadedDst, module.Context.Int8Type.CreatePointerType( ))
                         .SetDebugLocation(15, 13, copyFunc.DISubProgram);

            var srcPtr = instBuilder.BitCast(copyFunc.Parameters[0], module.Context.Int8Type.CreatePointerType( ))
                         .SetDebugLocation(15, 13, copyFunc.DISubProgram);

            uint pointerSize = layout.IntPtrType(module.Context).IntegerBitWidth;

            instBuilder.MemCpy(module
                               , dstPtr
                               , srcPtr
                               , module.Context.CreateConstant(pointerSize, layout.ByteSizeOf(foo), false)
                               , ( int )layout.AbiAlignmentOf(foo)
                               , false
                               ).SetDebugLocation(15, 13, copyFunc.DISubProgram);

            instBuilder.Return( )
            .SetDebugLocation(16, 1, copyFunc.DISubProgram);
        }
Exemplo n.º 17
0
        private static bool TrySimplify(InstructionBuilder instruction)
        {
            var proto = instruction.Prototype;

            if (proto is ConstrainedCallPrototype)
            {
                //
                //     constrained_call(f)(this_ref, args...)
                //
                // is equivalent to
                //
                //     call(impl(f), static)(this_ref, args...)  if this_ref == T ref* where T is a value type,
                //     call(f, virtual)(load(this_ref), args...) if this_ref == T any* ref*.

                var constrainedCallProto = (ConstrainedCallPrototype)proto;
                var thisArg     = constrainedCallProto.GetThisArgument(instruction.Instruction);
                var thisRefType = instruction.Graph.GetValueType(thisArg) as PointerType;
                if (thisRefType == null)
                {
                    return(false);
                }

                var thisValType = thisRefType.ElementType;
                if (thisValType is PointerType)
                {
                    instruction.Instruction = Instruction.CreateCall(
                        constrainedCallProto.Callee,
                        MethodLookup.Virtual,
                        instruction.InsertBefore(
                            Instruction.CreateLoad(thisValType, thisArg),
                            "this_value"),
                        constrainedCallProto.GetArgumentList(instruction.Instruction).ToArray());

                    TrySimplify(instruction);
                    return(true);
                }
                else if (!(thisValType is IGenericParameter))
                {
                    var realCallee = thisValType.GetImplementationOf(constrainedCallProto.Callee);
                    if (realCallee != null && realCallee.ParentType == thisValType)
                    {
                        instruction.Instruction = Instruction.CreateCall(
                            realCallee,
                            MethodLookup.Static,
                            constrainedCallProto.GetThisArgument(instruction.Instruction),
                            constrainedCallProto.GetArgumentList(instruction.Instruction).ToArray());

                        return(true);
                    }
                }
            }
            else if (proto is CallPrototype)
            {
                var callProto = (CallPrototype)proto;
                if (callProto.Callee.IsStatic)
                {
                    return(false);
                }

                var thisType = GetActualType(
                    callProto.GetThisArgument(instruction.Instruction),
                    instruction.Graph.ImmutableGraph) as PointerType;

                if (thisType == null)
                {
                    return(false);
                }

                var realCallee = thisType.ElementType.GetImplementationOf(callProto.Callee);
                if (realCallee == null || realCallee == callProto.Callee)
                {
                    return(false);
                }

                instruction.Instruction = Instruction.CreateCall(
                    realCallee,
                    realCallee.IsVirtual() ? MethodLookup.Virtual : MethodLookup.Static,
                    instruction.InsertBefore(
                        Instruction.CreateReinterpretCast(
                            realCallee.ParentType.MakePointerType(thisType.Kind),
                            callProto.GetThisArgument(instruction.Instruction))),
                    callProto.GetArgumentList(instruction.Instruction).ToArray());

                return(true);
            }
            return(false);
        }
Exemplo n.º 18
0
        /*
         * // Output for-loop as:
         * //   ...
         * //   start = startexpr
         * //   goto loop
         * // loop:
         * //   variable = phi [start, loopheader], [nextvariable, loopend]
         * //   ...
         * //   bodyexpr
         * //   ...
         * // loopend:
         * //   step = stepexpr
         * //   nextvariable = variable + step
         * //   endcond = endexpr
         * //   br endcond, loop, endloop
         * // outloop:
         */
        public override Value VisitForExpression([NotNull] ForExpressionContext context)
        {
            var    function  = InstructionBuilder.InsertBlock.ContainingFunction;
            string varName   = context.Initializer.Name;
            var    allocaVar = CreateEntryBlockAlloca(function, varName);

            // Emit the start code first, without 'variable' in scope.
            Value startVal = null;

            if (context.Initializer.Value != null)
            {
                startVal = context.Initializer.Value.Accept(this);
                if (startVal == null)
                {
                    return(null);
                }
            }
            else
            {
                startVal = Context.CreateConstant(0.0);
            }

            // store the value into allocated location
            InstructionBuilder.Store(startVal, allocaVar);

            // Make the new basic block for the loop header, inserting after current
            // block.
            var preHeaderBlock = InstructionBuilder.InsertBlock;
            var loopBlock      = Context.CreateBasicBlock("loop", function);

            // Insert an explicit fall through from the current block to the loopBlock.
            InstructionBuilder.Branch(loopBlock);

            // Start insertion in loopBlock.
            InstructionBuilder.PositionAtEnd(loopBlock);

            // Start the PHI node with an entry for Start.
            var variable = InstructionBuilder.PhiNode(Context.DoubleType)
                           .RegisterName(varName);

            variable.AddIncoming(startVal, preHeaderBlock);

            // Within the loop, the variable is defined equal to the PHI node.  If it
            // shadows an existing variable, we have to restore it, so save it now.
            NamedValues.TryGetValue(varName, out Alloca oldValue);
            NamedValues[varName] = allocaVar;

            // Emit the body of the loop.  This, like any other expr, can change the
            // current BB.  Note that we ignore the value computed by the body, but don't
            // allow an error.
            if (context.BodyExpression.Accept(this) == null)
            {
                return(null);
            }

            Value stepValue = Context.CreateConstant(1.0);

            // DEBUG: How does ANTLR represent optional context (Null or IsEmpty == true)
            if (context.StepExpression != null)
            {
                stepValue = context.StepExpression.Accept(this);
                if (stepValue == null)
                {
                    return(null);
                }
            }

            // Compute the end condition.
            Value endCondition = context.EndExpression.Accept(this);

            if (endCondition == null)
            {
                return(null);
            }

            var curVar = InstructionBuilder.Load(allocaVar)
                         .RegisterName(varName);
            var nextVar = InstructionBuilder.FAdd(curVar, stepValue)
                          .RegisterName("nextvar");

            InstructionBuilder.Store(nextVar, allocaVar);

            // Convert condition to a bool by comparing non-equal to 0.0.
            endCondition = InstructionBuilder.Compare(RealPredicate.OrderedAndNotEqual, endCondition, Context.CreateConstant(1.0))
                           .RegisterName("loopcond");

            // Create the "after loop" block and insert it.
            var loopEndBlock = InstructionBuilder.InsertBlock;
            var afterBlock   = Context.CreateBasicBlock("afterloop", function);

            // Insert the conditional branch into the end of LoopEndBB.
            InstructionBuilder.Branch(endCondition, loopBlock, afterBlock);
            InstructionBuilder.PositionAtEnd(afterBlock);

            // Add a new entry to the PHI node for the backedge.
            variable.AddIncoming(nextVar, loopEndBlock);

            // Restore the unshadowed variable.
            if (oldValue != null)
            {
                NamedValues[varName] = oldValue;
            }
            else
            {
                NamedValues.Remove(varName);
            }

            // for expr always returns 0.0 for consistency, there is no 'void'
            return(Context.DoubleType.GetNullValue( ));
        }
Exemplo n.º 19
0
        public override Value?Visit(ForInExpression forInExpression)
        {
            forInExpression.ValidateNotNull(nameof(forInExpression));
            EmitLocation(forInExpression);
            var function = InstructionBuilder.InsertFunction;

            if (function is null)
            {
                throw new InternalCodeGeneratorException("ICE: Expected block attached to a function at this point");
            }

            string varName   = forInExpression.LoopVariable.Name;
            Alloca allocaVar = LookupVariable(varName);

            // Emit the start code first, without 'variable' in scope.
            Value?startVal;

            if (forInExpression.LoopVariable.Initializer != null)
            {
                startVal = forInExpression.LoopVariable.Initializer.Accept(this);
                if (startVal is null)
                {
                    return(null);
                }
            }
            else
            {
                startVal = Context.CreateConstant(0.0);
            }

            // store the value into allocated location
            InstructionBuilder.Store(startVal, allocaVar);

            // Make the new basic block for the loop header.
            var loopBlock = function.AppendBasicBlock("loop");

            // Insert an explicit fall through from the current block to the loopBlock.
            InstructionBuilder.Branch(loopBlock);

            // Start insertion in loopBlock.
            InstructionBuilder.PositionAtEnd(loopBlock);

            // Within the loop, the variable is defined equal to the PHI node.
            // So, push a new scope for it and any values the body might set
            using (NamedValues.EnterScope( ))
            {
                EmitBranchToNewBlock("ForInScope");

                // Emit the body of the loop.  This, like any other expression, can change the
                // current BB.  Note that we ignore the value computed by the body, but don't
                // allow an error.
                if (forInExpression.Body.Accept(this) == null)
                {
                    return(null);
                }

                Value?stepValue = forInExpression.Step.Accept(this);
                if (stepValue == null)
                {
                    return(null);
                }

                // Compute the end condition.
                Value?endCondition = forInExpression.Condition.Accept(this);
                if (endCondition == null)
                {
                    return(null);
                }

                // since the Alloca is created as a non-opaque pointer it is OK to just use the
                // ElementType. If full opaque pointer support was used, then the Lookup map
                // would need to include the type of the value allocated.
                var curVar = InstructionBuilder.Load(allocaVar.ElementType, allocaVar)
                             .RegisterName(varName);
                var nextVar = InstructionBuilder.FAdd(curVar, stepValue)
                              .RegisterName("nextvar");
                InstructionBuilder.Store(nextVar, allocaVar);

                // Convert condition to a bool by comparing non-equal to 0.0.
                endCondition = InstructionBuilder.Compare(RealPredicate.OrderedAndNotEqual, endCondition, Context.CreateConstant(0.0))
                               .RegisterName("loopcond");

                // Create the "after loop" block and insert it.
                var afterBlock = function.AppendBasicBlock("afterloop");

                // Insert the conditional branch into the end of LoopEndBB.
                InstructionBuilder.Branch(endCondition, loopBlock, afterBlock);
                InstructionBuilder.PositionAtEnd(afterBlock);

                // for expression always returns 0.0 for consistency, there is no 'void'
                return(Context.DoubleType.GetNullValue( ));
            }
        }
Exemplo n.º 20
0
 public EmitFuncObj(Module module, Function function, MethodBody cilMethod, InstructionBuilder instructionBuilder, object argument, Stack<Value> stack, Value[] locals, Value[] parameters)
 {
     Module = module;
     Function = function;
     CilMethod = cilMethod;
     Builder = instructionBuilder;
     Argument = argument;
     Stack = stack;
     Locals = locals;
     Parameters = parameters;
 }
Exemplo n.º 21
0
        public override Value?Visit(ConditionalExpression conditionalExpression)
        {
            conditionalExpression.ValidateNotNull(nameof(conditionalExpression));
            var result = LookupVariable(conditionalExpression.ResultVariable.Name);

            EmitLocation(conditionalExpression);
            var condition = conditionalExpression.Condition.Accept(this);

            if (condition == null)
            {
                return(null);
            }

            EmitLocation(conditionalExpression);

            var condBool = InstructionBuilder.Compare(RealPredicate.OrderedAndNotEqual, condition, Context.CreateConstant(0.0))
                           .RegisterName("ifcond");

            var function = InstructionBuilder.InsertFunction;

            if (function is null)
            {
                throw new InternalCodeGeneratorException("ICE: expected block that is attached to a function at this point");
            }

            var thenBlock     = function.AppendBasicBlock("then");
            var elseBlock     = function.AppendBasicBlock("else");
            var continueBlock = function.AppendBasicBlock("ifcont");

            InstructionBuilder.Branch(condBool, thenBlock, elseBlock);

            // generate then block instructions
            InstructionBuilder.PositionAtEnd(thenBlock);

            // InstructionBuilder.InserBlock after this point is !null
            Debug.Assert(InstructionBuilder.InsertBlock != null, "expected non-null InsertBlock");
            var thenValue = conditionalExpression.ThenExpression.Accept(this);

            if (thenValue == null)
            {
                return(null);
            }

            InstructionBuilder.Store(thenValue, result);
            InstructionBuilder.Branch(continueBlock);

            // generate else block
            InstructionBuilder.PositionAtEnd(elseBlock);
            var elseValue = conditionalExpression.ElseExpression.Accept(this);

            if (elseValue == null)
            {
                return(null);
            }

            InstructionBuilder.Store(elseValue, result);
            InstructionBuilder.Branch(continueBlock);

            // generate continue block
            InstructionBuilder.PositionAtEnd(continueBlock);

            // since the Alloca is created as a non-opaque pointer it is OK to just use the
            // ElementType. If full opaque pointer support was used, then the Lookup map
            // would need to include the type of the value allocated.
            return(InstructionBuilder.Load(result.ElementType, result)
                   .RegisterName("ifresult"));
        }
Exemplo n.º 22
0
 public static Value FloatExtend(this InstructionBuilder builder, Value value, LLVM.Type type, string name = "")
 {
     return((Value)ValueConstructor.Invoke(new object[] { LLVMBuildFPExt(builder, value, type, name) }));
 }
Exemplo n.º 23
0
 public EmitFuncObj(Context context, Module module, Function function, InstructionBuilder instructionBuilder, object argument, Stack<Value> stack, Value[] locals, Value[] parameters)
 {
     Context = context;
     Module = module;
     Function = function;
     Builder = instructionBuilder;
     Argument = argument;
     Stack = stack;
     Locals = locals;
     Parameters = parameters;
 }
Exemplo n.º 24
0
        public override Value?Visit(FunctionDefinition definition)
        {
            definition.ValidateNotNull(nameof(definition));
            var function = GetOrDeclareFunction(definition.Signature);

            if (!function.IsDeclaration)
            {
                throw new CodeGeneratorException($"Function {function.Name} cannot be redefined in the same module");
            }

            Debug.Assert(function.DISubProgram != null, "Expected function with non-null DISubProgram");
            LexicalBlocks.Push(function.DISubProgram);
            try
            {
                var entryBlock = function.AppendBasicBlock("entry");
                InstructionBuilder.PositionAtEnd(entryBlock);

                // Unset the location for the prologue emission (leading instructions with no
                // location in a function are considered part of the prologue and the debugger
                // will run past them when breaking on a function)
                EmitLocation(null);

                using (NamedValues.EnterScope( ))
                {
                    foreach (var param in definition.Signature.Parameters)
                    {
                        var argSlot = InstructionBuilder.Alloca(function.Context.DoubleType)
                                      .RegisterName(param.Name);
                        AddDebugInfoForAlloca(argSlot, function, param);
                        InstructionBuilder.Store(function.Parameters[param.Index], argSlot);
                        NamedValues[param.Name] = argSlot;
                    }

                    foreach (LocalVariableDeclaration local in definition.LocalVariables)
                    {
                        var localSlot = InstructionBuilder.Alloca(function.Context.DoubleType)
                                        .RegisterName(local.Name);
                        AddDebugInfoForAlloca(localSlot, function, local);
                        NamedValues[local.Name] = localSlot;
                    }

                    EmitBranchToNewBlock("body");

                    var funcReturn = definition.Body.Accept(this) ?? throw new CodeGeneratorException(ExpectValidFunc);
                    InstructionBuilder.Return(funcReturn);
                    Module.DIBuilder.Finish(function.DISubProgram);
                    function.Verify( );

                    FunctionPassManager.Run(function);

                    if (definition.IsAnonymous)
                    {
                        function.AddAttribute(FunctionAttributeIndex.Function, AttributeKind.AlwaysInline)
                        .Linkage(Linkage.Private);

                        AnonymousFunctions.Add(function);
                    }

                    return(function);
                }
            }
            catch (CodeGeneratorException)
            {
                function.EraseFromParent( );
                throw;
            }
        }
Exemplo n.º 25
0
 public static Value SignedIntToFloat(this InstructionBuilder builder, Value value, LLVM.Type type, string name = "")
 {
     return((Value)ValueConstructor.Invoke(new object[] { LLVMBuildSIToFP(builder, value, type, name) }));
 }
Exemplo n.º 26
0
        public override Value Visit(ForInExpression forInExpression)
        {
            var    function = InstructionBuilder.InsertBlock.ContainingFunction;
            string varName  = forInExpression.LoopVariable.Name;

            // Emit the start code first, without 'variable' in scope.
            Value startVal;

            if (forInExpression.LoopVariable.Initializer != null)
            {
                startVal = forInExpression.LoopVariable.Initializer.Accept(this);
                if (startVal == null)
                {
                    return(null);
                }
            }
            else
            {
                startVal = Context.CreateConstant(0.0);
            }

            // Make the new basic block for the loop header, inserting after current
            // block.
            var preHeaderBlock = InstructionBuilder.InsertBlock;
            var loopBlock      = function.AppendBasicBlock("loop");

            // Insert an explicit fall through from the current block to the loopBlock.
            InstructionBuilder.Branch(loopBlock);

            // Start insertion in loopBlock.
            InstructionBuilder.PositionAtEnd(loopBlock);

            // Start the PHI node with an entry for Start.
            var variable = InstructionBuilder.PhiNode(Context.DoubleType)
                           .RegisterName(varName);

            variable.AddIncoming(startVal, preHeaderBlock);

            // Within the loop, the variable is defined equal to the PHI node.
            // So, push a new scope for it and any values the body might set
            using (NamedValues.EnterScope( ))
            {
                NamedValues[varName] = variable;

                // Emit the body of the loop.  This, like any other expression, can change the
                // current BB.  Note that we ignore the value computed by the body, but don't
                // allow an error.
                if (forInExpression.Body.Accept(this) == null)
                {
                    return(null);
                }

                Value stepValue = forInExpression.Step.Accept(this);
                if (stepValue == null)
                {
                    return(null);
                }

                var nextVar = InstructionBuilder.FAdd(variable, stepValue)
                              .RegisterName("nextvar");

                // Compute the end condition.
                Value endCondition = forInExpression.Condition.Accept(this);
                if (endCondition == null)
                {
                    return(null);
                }

                // Convert condition to a bool by comparing non-equal to 0.0.
                endCondition = InstructionBuilder.Compare(RealPredicate.OrderedAndNotEqual, endCondition, Context.CreateConstant(0.0))
                               .RegisterName("loopcond");

                // capture loop end result block for loop variable PHI node
                var loopEndBlock = InstructionBuilder.InsertBlock;

                // Create the "after loop" block and insert it.
                var afterBlock = function.AppendBasicBlock("afterloop");

                // Insert the conditional branch into the end of LoopEndBB.
                InstructionBuilder.Branch(endCondition, loopBlock, afterBlock);
                InstructionBuilder.PositionAtEnd(afterBlock);

                // Add a new entry to the PHI node for the back-edge.
                variable.AddIncoming(nextVar, loopEndBlock);

                // for expression always returns 0.0 for consistency, there is no 'void'
                return(Context.DoubleType.GetNullValue( ));
            }
        }
Exemplo n.º 27
0
        private Function DefineFunction(Function function, ExpressionContext body)
        {
            if (!function.IsDeclaration)
            {
                throw new ArgumentException($"Function {function.Name} cannot be redefined", nameof(function));
            }

            var proto      = FunctionPrototypes[function.Name];
            var basicBlock = function.AppendBasicBlock("entry");

            InstructionBuilder.PositionAtEnd(basicBlock);

            var diFile = Module.DICompileUnit.File;
            var scope  = Module.DICompileUnit;

            LexicalBlocks.Push(function.DISubProgram);

            // Unset the location for the prologue emission (leading instructions with no
            // location in a function are considered part of the prologue and the debugger
            // will run past them when breaking on a function)
            EmitLocation(null);

            NamedValues.Clear( );
            foreach (var arg in function.Parameters)
            {
                uint line = ( uint )proto.Parameters[( int )(arg.Index)].Span.StartLine;
                uint col  = ( uint )proto.Parameters[( int )(arg.Index)].Span.StartColumn;

                var             argSlot  = CreateEntryBlockAlloca(function, arg.Name);
                DILocalVariable debugVar = Module.DIBuilder.CreateArgument(function.DISubProgram
                                                                           , arg.Name
                                                                           , diFile
                                                                           , line
                                                                           , DoubleType
                                                                           , true
                                                                           , DebugInfoFlags.None
                                                                           , checked (( ushort )(arg.Index + 1)) // Debug index starts at 1!
                                                                           );
                Module.DIBuilder.InsertDeclare(argSlot
                                               , debugVar
                                               , new DILocation(Context, line, col, function.DISubProgram)
                                               , InstructionBuilder.InsertBlock
                                               );

                InstructionBuilder.Store(arg, argSlot);
                NamedValues[arg.Name] = argSlot;
            }

            var funcReturn = body.Accept(this);

            if (funcReturn == null)
            {
                function.EraseFromParent( );
                LexicalBlocks.Pop( );
                return(null);
            }

            InstructionBuilder.Return(funcReturn);
            LexicalBlocks.Pop( );
            Module.DIBuilder.Finish(function.DISubProgram);
            function.Verify( );
            Trace.TraceInformation(function.ToString( ));

            return(function);
        }
Exemplo n.º 28
0
        public override Value VisitBinaryOpExpression([NotNull] BinaryOpExpressionContext context)
        {
            EmitLocation(context);
            var lhs = context.Lhs.Accept(this);
            var rhs = context.Rhs.Accept(this);

            if (lhs == null || rhs == null)
            {
                return(null);
            }

            switch (context.Op)
            {
            case '<':
            {
                var tmp = InstructionBuilder.Compare(RealPredicate.UnorderedOrLessThan, lhs, rhs)
                          .RegisterName("cmptmp");
                return(InstructionBuilder.UIToFPCast(tmp, InstructionBuilder.Context.DoubleType)
                       .RegisterName("booltmp"));
            }

            case '^':
            {
                var pow = GetOrDeclareFunction(new Prototype("llvm.pow.f64", "value", "power"));
                return(InstructionBuilder.Call(pow, lhs, rhs)
                       .RegisterName("powtmp"));
            }

            case '+':
                return(InstructionBuilder.FAdd(lhs, rhs).RegisterName("addtmp"));

            case '-':
                return(InstructionBuilder.FSub(lhs, rhs).RegisterName("subtmp"));

            case '*':
                return(InstructionBuilder.FMul(lhs, rhs).RegisterName("multmp"));

            case '/':
                return(InstructionBuilder.FDiv(lhs, rhs).RegisterName("divtmp"));

            default:
            {
                // User defined op?
                var opKind = context.GetOperatorInfo(ParserStack.Parser);
                if (opKind != OperatorKind.InfixLeftAssociative && opKind != OperatorKind.InfixRightAssociative)
                {
                    throw new ArgumentException($"Invalid binary operator {context.Op}", nameof(context));
                }

                string calleeName = $"$binary{context.Op}";
                var    function   = GetFunction(calleeName);
                if (function == null)
                {
                    throw new ArgumentException($"Unknown function reference {calleeName}", nameof(context));
                }

                var args = context.Args.Select(a => a.Accept(this)).ToList( );
                return(InstructionBuilder.Call(function, args).RegisterName("calltmp"));
            }
            }
        }
Exemplo n.º 29
0
 public abstract void Lower(InstructionBuilder builder);
Exemplo n.º 30
0
            public override Matcher Build()
            {
                _entries.Sort((x, y) =>
                {
                    var comparison = x.Order.CompareTo(y.Order);
                    if (comparison != 0)
                    {
                        return(comparison);
                    }

                    comparison = y.Precedence.CompareTo(x.Precedence);
                    if (comparison != 0)
                    {
                        return(comparison);
                    }

                    return(x.Pattern.TemplateText.CompareTo(y.Pattern.TemplateText));
                });

                var roots = new List <OrderNode>();

                for (var i = 0; i < _entries.Count; i++)
                {
                    var entry = _entries[i];

                    var parent = (SequenceNode)GetOrCreateRootNode(roots, entry.Order);

                    for (var depth = 0; depth < entry.Pattern.Segments.Count; depth++)
                    {
                        var segment = entry.Pattern.Segments[depth];
                        if (segment.IsSimple && segment.Parts[0].IsLiteral)
                        {
                            var branch = parent.GetNode <BranchNode>() ?? parent.AddNode(new BranchNode(depth));

                            var index = branch.Literals.IndexOf(segment.Parts[0].Text);
                            if (index == -1)
                            {
                                branch.Literals.Add(segment.Parts[0].Text);
                                branch.AddNode(new SequenceNode(depth + 1));
                                index = branch.Children.Count - 1;
                            }

                            parent = (SequenceNode)branch.Children[index];
                        }
                        else if (segment.IsSimple && segment.Parts[0].IsParameter)
                        {
                            var parameter = parent.GetNode <ParameterNode>() ?? parent.AddNode(new ParameterNode(depth));
                            if (parameter.Children.Count == 0)
                            {
                                parameter.AddNode(new SequenceNode(depth + 1));
                            }

                            parent = (SequenceNode)parameter.Children[0];
                        }
                        else
                        {
                            throw new InvalidOperationException("Not implemented!");
                        }
                    }

                    parent.AddNode(new AcceptNode(entry.Endpoint));
                }

                var builder = new InstructionBuilder();

                for (var i = 0; i < roots.Count; i++)
                {
                    roots[i].Lower(builder);
                }

                var(instructions, endpoints, tables) = builder;
                return(new InstructionMatcher(instructions, endpoints, tables));
            }
Exemplo n.º 31
0
        private static Function EmitFunction(Context context, Module module, MethodInfo method)
        {
            var funcType = new FunctionType(ConvertType(context, method.ReturnType), AnalyzeArguments(context, method.GetParameters()));

            var intrinsic = method.GetCustomAttribute<Gpu.BuiltinAttribute>();
            if (intrinsic != null)
            {
                var name = intrinsic.Intrinsic;
                var preExisting = module.GetFunction(name);
                if (preExisting != null)
                    return preExisting;
                return module.CreateFunction(name, funcType);
            }

            var function = module.CreateFunction(method.Name, funcType);

            var block = new Block("entry", context, function);
            var writer = new InstructionBuilder(context, block);

            var opcodes = method.Decompile().ToList();
            FindBranchTargets(opcodes, context, function);

            var body = method.GetMethodBody();
            var efo = new EmitFuncObj(context, module, function, writer, null, new Stack<Value>(),
                body == null ? null : new Value[body.LocalVariables.Count], new Value[method.GetParameters().Length]);

            foreach (var opcode in opcodes)
            {
                if (EmitFunctions.ContainsKey(opcode.Opcode) == false)
                    throw new Exception("Unsupported CIL instruction " + opcode.Opcode);
                var func = EmitFunctions[opcode.Opcode];
                efo.Argument = opcode.Parameter;
                func(efo);
            }

            return function;
        }