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 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 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 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 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(); }