コード例 #1
0
        private static void CompileStringFromSlice(FunctionCompiler compiler, FunctionalNode stringFromSliceNode)
        {
            VariableReference input  = stringFromSliceNode.InputTerminals[0].GetTrueVariable(),
                              output = stringFromSliceNode.OutputTerminals[1].GetTrueVariable();

            Action <FunctionCompiler> loadStringOutputAllocationReference = c => c.LoadLocalAllocationReference(output);

            // Get a pointer to a heap allocation big enough for the string
            compiler.LoadConstantOffsetFromPointer(loadStringOutputAllocationReference, 0);
            compiler.LoadStringSliceReferenceSizeReference(input);
            compiler._builder.EmitDerefInteger();
            compiler._builder.EmitAlloc_TEMP();
            compiler._builder.EmitStorePointer();

            // Copy the data from the string slice to the heap allocation
            compiler.LoadStringSliceReferencePointer(input);
            compiler._builder.EmitDerefPointer();
            compiler.LoadConstantOffsetFromPointer(loadStringOutputAllocationReference, 0);
            compiler._builder.EmitDerefPointer();
            compiler.LoadStringSliceReferenceSizeReference(input);
            compiler._builder.EmitDerefInteger();
            compiler._builder.EmitCopyBytes_TEMP();

            // Copy actual size into string handle
            compiler.LoadConstantOffsetFromPointer(loadStringOutputAllocationReference, TargetConstants.PointerSize);
            compiler.LoadStringSliceReferenceSizeReference(input);
            compiler._builder.EmitDerefInteger();
            compiler._builder.EmitStoreInteger();
        }
コード例 #2
0
        private static void CompileSelectReference(FunctionCompiler compiler, FunctionalNode selectReferenceNode)
        {
            LabelBuilder falseLabel             = compiler._builder.CreateLabel(),
                         endLabel               = compiler._builder.CreateLabel();
            VariableReference input1            = selectReferenceNode.InputTerminals.ElementAt(1).GetTrueVariable(),
                              input2            = selectReferenceNode.InputTerminals.ElementAt(2).GetTrueVariable(),
                              selector          = selectReferenceNode.InputTerminals.ElementAt(0).GetTrueVariable(),
                              selectedReference = selectReferenceNode.OutputTerminals.ElementAt(1).GetTrueVariable();

            compiler.LoadLocalAllocationReference(selectedReference);
            compiler.LoadValueAsReference(selector);
            compiler._builder.EmitDerefInteger();
            compiler._builder.EmitBranchIfFalse(falseLabel);

            // true
            compiler.LoadValueAsReference(input1);
            compiler._builder.EmitBranch(endLabel);

            // false
            compiler._builder.SetLabel(falseLabel);
            compiler.LoadValueAsReference(input2);

            // end
            compiler._builder.SetLabel(endLabel);
            compiler._builder.EmitStorePointer();
        }
コード例 #3
0
        private static void CompileAssign(FunctionCompiler compiler, FunctionalNode assignNode)
        {
            VariableReference assignee = assignNode.InputTerminals.ElementAt(0).GetTrueVariable(),
                              value    = assignNode.InputTerminals.ElementAt(1).GetTrueVariable();

            compiler.CopyValueToReferencedAddress(assignee, value, assignee.Type.GetReferentType());
        }
コード例 #4
0
        private static void CompileOutput(FunctionCompiler compiler, FunctionalNode outputNode)
        {
            VariableReference input        = outputNode.InputTerminals.ElementAt(0).GetTrueVariable();
            NIType            referentType = input.Type.GetReferentType();

            if (referentType.IsInt32())
            {
                compiler.LoadValueAsReference(input);
                compiler._builder.EmitDerefInteger();
                compiler._builder.EmitOutput_TEMP();
            }
            else if (referentType.IsString())
            {
                compiler.LoadValueAsReference(input);
                compiler._builder.EmitDerefPointer();
                compiler.LoadValueAsReference(input);
                compiler._builder.EmitLoadIntegerImmediate(TargetConstants.PointerSize);
                compiler._builder.EmitAdd();
                compiler._builder.EmitDerefInteger();
                compiler._builder.EmitOutputString_TEMP();
            }
            else if (referentType == DataTypes.StringSliceType)
            {
                compiler.LoadStringSliceReferencePointer(input);
                compiler._builder.EmitDerefPointer();
                compiler.LoadStringSliceReferenceSizeReference(input);
                compiler._builder.EmitDerefInteger();
                compiler._builder.EmitOutputString_TEMP();
            }
            else
            {
                throw new NotImplementedException($"Don't know how to display type {referentType} yet.");
            }
        }
コード例 #5
0
        private static void CompileSomeConstructor(FunctionCompiler compiler, FunctionalNode someConstructorNode)
        {
            VariableReference input  = someConstructorNode.InputTerminals.ElementAt(0).GetTrueVariable(),
                              output = someConstructorNode.OutputTerminals.ElementAt(0).GetTrueVariable();

            compiler.CopyValueToSomeValue(input, output);
        }
コード例 #6
0
        private static void CompileNoneConstructor(FunctionCompiler compiler, FunctionalNode noneConstructorNode)
        {
            VariableReference output = noneConstructorNode.OutputTerminals.ElementAt(0).GetTrueVariable();

            compiler.LoadLocalAllocationReference(output);
            compiler._builder.EmitLoadIntegerImmediate(0);
            compiler._builder.EmitStoreInteger();
        }
コード例 #7
0
        private static void CompileMutatingUnaryPrimitive(FunctionCompiler compiler, FunctionalNode primitiveNode, UnaryPrimitiveOps operation)
        {
            VariableReference input = primitiveNode.InputTerminals.ElementAt(0).GetTrueVariable();

            compiler.LoadValueAsReference(input);
            compiler.EmitUnaryOperationOnVariable(input, operation);
            compiler._builder.EmitStoreInteger();
        }
コード例 #8
0
        private static void CompilePureUnaryPrimitive(FunctionCompiler compiler, FunctionalNode primitiveNode, UnaryPrimitiveOps operation)
        {
            VariableReference input  = primitiveNode.InputTerminals.ElementAt(0).GetTrueVariable(),
                              output = primitiveNode.OutputTerminals.ElementAt(1).GetTrueVariable();

            compiler.LoadLocalAllocationReference(output);
            compiler.EmitUnaryOperationOnVariable(input, operation);
            compiler._builder.EmitStoreInteger();
        }
コード例 #9
0
        private static void CompileCreateCopy(FunctionCompiler compiler, FunctionalNode createCopyNode)
        {
            VariableReference copyFrom = createCopyNode.InputTerminals.ElementAt(0).GetTrueVariable(),
                              copyTo   = createCopyNode.OutputTerminals.ElementAt(1).GetTrueVariable();

            compiler.CopyValue(
                () => compiler.LoadValueAsReference(copyFrom),
                () => compiler.LoadLocalAllocationReference(copyTo),
                copyFrom.Type.GetReferentType());
        }
コード例 #10
0
        private static void CompileExchangeValues(FunctionCompiler compiler, FunctionalNode exchangeValuesNode)
        {
            VariableReference var1 = exchangeValuesNode.InputTerminals.ElementAt(0).GetTrueVariable(),
                              var2 = exchangeValuesNode.InputTerminals.ElementAt(1).GetTrueVariable();

            compiler.LoadValueAsReference(var1);
            compiler.LoadValueAsReference(var2);
            compiler._builder.EmitLoadIntegerImmediate(BytecodeInterpreterAllocator.GetTypeSize(var1.Type.GetReferentType()));
            compiler._builder.EmitExchangeBytes_TEMP();
        }
コード例 #11
0
        private static void CompileMutatingBinaryPrimitive(FunctionCompiler compiler, FunctionalNode primitiveNode, BinaryPrimitiveOps operation)
        {
            VariableReference input1 = primitiveNode.InputTerminals.ElementAt(0).GetTrueVariable(),
                              input2 = primitiveNode.InputTerminals.ElementAt(1).GetTrueVariable();

            compiler.LoadValueAsReference(input1);
            compiler._builder.EmitDuplicate();
            compiler._builder.EmitDerefInteger();
            compiler.LoadValueAsReference(input2);
            compiler._builder.EmitDerefInteger();
            compiler.EmitBinaryOperation(operation);
            compiler._builder.EmitStoreInteger();
        }
コード例 #12
0
        private static void CompileInspect(FunctionCompiler compiler, FunctionalNode inspectNode)
        {
            VariableReference input      = inspectNode.InputTerminals[0].GetTrueVariable();
            int typeSize                 = BytecodeInterpreterAllocator.GetTypeSize(input.Type.GetReferentType());
            StaticDataBuilder staticData = compiler._builder.DefineStaticData();

            staticData.Data       = new byte[typeSize];
            staticData.Identifier = StaticDataIdentifier.CreateFromNode(inspectNode);

            compiler.LoadValueAsReference(input);
            compiler._builder.EmitLoadStaticDataAddress(staticData);
            compiler._builder.EmitLoadIntegerImmediate(typeSize);
            compiler._builder.EmitCopyBytes_TEMP();
        }
コード例 #13
0
        private static void CompileComparison(FunctionCompiler compiler, FunctionalNode comparisonNode, Action <FunctionBuilder> emitOperation)
        {
            VariableReference input1 = comparisonNode.InputTerminals[0].GetTrueVariable(),
                              input2 = comparisonNode.InputTerminals[1].GetTrueVariable(),
                              output = comparisonNode.OutputTerminals[2].GetTrueVariable();

            compiler.LoadLocalAllocationReference(output);
            compiler.LoadValueAsReference(input1);
            compiler._builder.EmitDerefInteger();
            compiler.LoadValueAsReference(input2);
            compiler._builder.EmitDerefInteger();
            emitOperation(compiler._builder);
            compiler._builder.EmitStoreInteger();
        }
コード例 #14
0
        private static void CompileStringAppend(FunctionCompiler compiler, FunctionalNode stringAppendNode)
        {
            VariableReference stringInput = stringAppendNode.InputTerminals[0].GetTrueVariable(),
                              sliceInput  = stringAppendNode.InputTerminals[1].GetTrueVariable();

            Action <FunctionCompiler> loadStringInputReference = c => c.LoadValueAsReference(stringInput);

            // for now, always create a new allocation, rather than trying to use existing one
            // TODO: free the old allocation
            // compute and store the size first to use it later
            compiler.LoadConstantOffsetFromPointer(loadStringInputReference, TargetConstants.PointerSize);
            compiler._builder.EmitDerefInteger();
            compiler.LoadStringSliceReferenceSizeReference(sliceInput);
            compiler._builder.EmitDerefInteger();
            compiler._builder.EmitAdd();
            compiler._builder.EmitDuplicate();
            compiler._builder.EmitAlloc_TEMP();
            compiler._builder.EmitDuplicate();

            // copy from old allocation to new allocation, then overwrite old allocation pointer
            compiler.LoadConstantOffsetFromPointer(loadStringInputReference, 0);
            compiler._builder.EmitDerefPointer();
            compiler._builder.EmitSwap();
            compiler.LoadConstantOffsetFromPointer(loadStringInputReference, TargetConstants.PointerSize);
            compiler._builder.EmitDerefInteger();
            compiler._builder.EmitCopyBytes_TEMP();
            compiler.LoadConstantOffsetFromPointer(loadStringInputReference, 0);
            compiler._builder.EmitSwap();
            compiler._builder.EmitStorePointer();

            // copy from slice to offset in new allocation
            compiler.LoadStringSliceReferencePointer(sliceInput);
            compiler._builder.EmitDerefPointer();
            compiler.LoadConstantOffsetFromPointer(loadStringInputReference, 0);
            compiler._builder.EmitDerefPointer();
            compiler.LoadConstantOffsetFromPointer(loadStringInputReference, TargetConstants.PointerSize);
            compiler._builder.EmitDerefInteger();
            compiler._builder.EmitAdd();
            compiler.LoadStringSliceReferenceSizeReference(sliceInput);
            compiler._builder.EmitDerefInteger();
            compiler._builder.EmitCopyBytes_TEMP();

            // copy total size to string
            compiler.LoadConstantOffsetFromPointer(loadStringInputReference, TargetConstants.PointerSize);
            compiler._builder.EmitSwap();
            compiler._builder.EmitStoreInteger();
        }
コード例 #15
0
        private static void CompileStringToSlice(FunctionCompiler compiler, FunctionalNode stringToSliceNode)
        {
            VariableReference input  = stringToSliceNode.InputTerminals[0].GetTrueVariable(),
                              output = stringToSliceNode.OutputTerminals[0].GetTrueVariable();

            Action <FunctionCompiler> loadStringInputReference = c => c.LoadValueAsReference(input);

            compiler.LoadStringSliceReferencePointer(output);
            compiler.LoadConstantOffsetFromPointer(loadStringInputReference, 0);
            compiler._builder.EmitDerefPointer();
            compiler._builder.EmitStorePointer();

            compiler.LoadStringSliceReferenceSizeReference(output);
            compiler.LoadConstantOffsetFromPointer(loadStringInputReference, TargetConstants.PointerSize);
            compiler._builder.EmitDerefInteger();
            compiler._builder.EmitStoreInteger();
        }
コード例 #16
0
        private static void CompileStringConcat(FunctionCompiler compiler, FunctionalNode stringConcatNode)
        {
            VariableReference input1 = stringConcatNode.InputTerminals[0].GetTrueVariable(),
                              input2 = stringConcatNode.InputTerminals[1].GetTrueVariable(),
                              output = stringConcatNode.OutputTerminals[2].GetTrueVariable();

            Action <FunctionCompiler> loadStringOutputAllocationReference = c => c.LoadLocalAllocationReference(output);

            // compute and store the size first to use it later
            compiler.LoadConstantOffsetFromPointer(loadStringOutputAllocationReference, TargetConstants.PointerSize);
            compiler.LoadStringSliceReferenceSizeReference(input1);
            compiler._builder.EmitDerefInteger();
            compiler.LoadStringSliceReferenceSizeReference(input2);
            compiler._builder.EmitDerefInteger();
            compiler._builder.EmitAdd();
            compiler._builder.EmitStoreInteger();

            // allocate a new string with stored size
            compiler.LoadConstantOffsetFromPointer(loadStringOutputAllocationReference, 0);
            compiler.LoadConstantOffsetFromPointer(loadStringOutputAllocationReference, TargetConstants.PointerSize);
            compiler._builder.EmitDerefInteger();
            compiler._builder.EmitAlloc_TEMP();
            compiler._builder.EmitStorePointer();

            // copy data from both slices
            compiler.LoadStringSliceReferencePointer(input1);
            compiler._builder.EmitDerefPointer();
            compiler.LoadConstantOffsetFromPointer(loadStringOutputAllocationReference, 0);
            compiler._builder.EmitDerefPointer();
            compiler.LoadStringSliceReferenceSizeReference(input1);
            compiler._builder.EmitDerefInteger();
            compiler._builder.EmitCopyBytes_TEMP();

            compiler.LoadStringSliceReferencePointer(input2);
            compiler._builder.EmitDerefPointer();
            compiler.LoadConstantOffsetFromPointer(loadStringOutputAllocationReference, 0);
            compiler._builder.EmitDerefPointer();
            compiler.LoadStringSliceReferenceSizeReference(input1);
            compiler._builder.EmitDerefInteger();
            compiler._builder.EmitAdd();
            compiler.LoadStringSliceReferenceSizeReference(input2);
            compiler._builder.EmitDerefInteger();
            compiler._builder.EmitCopyBytes_TEMP();
        }
コード例 #17
0
        private static void CompileRange(FunctionCompiler compiler, FunctionalNode rangeNode)
        {
            VariableReference lowInput  = rangeNode.InputTerminals.ElementAt(0).GetTrueVariable(),
                              highInput = rangeNode.InputTerminals.ElementAt(1).GetTrueVariable(),
                              output    = rangeNode.OutputTerminals.ElementAt(0).GetTrueVariable();

            compiler.LoadLocalAllocationReference(output);
            compiler._builder.EmitDuplicate();
            compiler.LoadLocalAllocationReference(lowInput);
            compiler._builder.EmitDerefInteger();
            compiler._builder.EmitLoadIntegerImmediate(1);
            compiler._builder.EmitSubtract();
            compiler._builder.EmitStoreInteger();

            compiler._builder.EmitLoadIntegerImmediate(4);
            compiler._builder.EmitAdd();
            compiler.LoadLocalAllocationReference(highInput);
            compiler._builder.EmitDerefInteger();
            compiler._builder.EmitStoreInteger();
        }
コード例 #18
0
 private static void CompileNothing(FunctionCompiler compiler, FunctionalNode noopNode)
 {
 }