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(); }
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(); }
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()); }
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."); } }
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); }
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(); }
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(); }
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(); }
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()); }
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(); }
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(); }
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(); }
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(); }
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(); }
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(); }
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(); }
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(); }
private static void CompileNothing(FunctionCompiler compiler, FunctionalNode noopNode) { }