示例#1
0
        private static void BuildStringConcatFunction(Module stringModule, CommonExternalFunctions externalFunctions)
        {
            LLVMValueRef      stringConcatFunction = stringModule.AddFunction(StringConcatName, CommonModuleSignatures[StringConcatName]);
            LLVMBasicBlockRef entryBlock           = stringConcatFunction.AppendBasicBlock("entry");
            var builder = new IRBuilder();

            builder.PositionBuilderAtEnd(entryBlock);

            LLVMValueRef slice0                    = stringConcatFunction.GetParam(0u),
                         slice1                    = stringConcatFunction.GetParam(1u),
                         sliceSize0                = builder.CreateExtractValue(slice0, 1u, "sliceSize0"),
                         sliceSize1                = builder.CreateExtractValue(slice1, 1u, "sliceSize1"),
                         concatSize                = builder.CreateAdd(sliceSize0, sliceSize1, "concatSize"),
                         concatAllocationPtr       = builder.CreateArrayMalloc(LLVMTypeRef.Int8Type(), concatSize, "concatAllocationPtr"),
                         concatAllocationOffsetPtr = builder.CreateGEP(concatAllocationPtr, new LLVMValueRef[] { sliceSize0 }, "concatAllocationOffsetPtr"),
                         stringPtr                 = stringConcatFunction.GetParam(2u),
                         stringAllocationPtrPtr    = builder.CreateStructGEP(stringPtr, 0u, "stringAllocationPtrPtr"),
                         stringSizePtr             = builder.CreateStructGEP(stringPtr, 1u, "stringSizePtr");

            builder.CreateCall(_copySliceToPointerFunction, new LLVMValueRef[] { slice0, concatAllocationPtr }, string.Empty);
            builder.CreateCall(_copySliceToPointerFunction, new LLVMValueRef[] { slice1, concatAllocationOffsetPtr }, string.Empty);
            builder.CreateStore(concatAllocationPtr, stringAllocationPtrPtr);
            builder.CreateStore(concatSize, stringSizePtr);
            builder.CreateRetVoid();
        }
示例#2
0
        private static void BuildOpenFileHandleFunction(Module fileModule, CommonExternalFunctions externalFunctions)
        {
            LLVMValueRef      openFileHandleFunction = fileModule.AddFunction(OpenFileHandleName, CommonModuleSignatures[OpenFileHandleName]);
            LLVMBasicBlockRef entryBlock             = openFileHandleFunction.AppendBasicBlock("entry");
            var builder = new IRBuilder();

            builder.PositionBuilderAtEnd(entryBlock);

            LLVMValueRef pathSliceRef            = openFileHandleFunction.GetParam(0u),
                         nullTerminatedStringPtr = builder.CreateCall(_createNullTerminatedStringFromSliceFunction, new LLVMValueRef[] { pathSliceRef }, "nullTerminatedStringtPtr"),
                         readWriteAccess         = (0xC0000000u).AsLLVMValue(),
                         noShareMode             = 0u.AsLLVMValue(),
                         openAlways                        = (0x4u).AsLLVMValue(),
                         fileAttributeNormal               = (0x80u).AsLLVMValue(),
                         fileHandleOptionPtr               = openFileHandleFunction.GetParam(1u),
                         fileHandleIsSomePtr               = builder.CreateStructGEP(fileHandleOptionPtr, 0u, "fileHandleIsSomePtr"),
                         fileHandleInnerValuePtr           = builder.CreateStructGEP(fileHandleOptionPtr, 1u, "fileHandleInnerValuePtr"),
                         fileHandleInnerValueFileHandlePtr = builder.CreateStructGEP(fileHandleInnerValuePtr, 0u, "fileHandleInnerValueFileHandlePtr"),
                         fileHandle                        = builder.CreateCall(
                externalFunctions.CreateFileAFunction,
                new LLVMValueRef[] { nullTerminatedStringPtr, readWriteAccess, noShareMode, LLVMExtensions.NullVoidPointer, openAlways, fileAttributeNormal, LLVMExtensions.NullVoidPointer },
                "fileHandle");

            builder.CreateFree(nullTerminatedStringPtr);
            builder.CreateStore(true.AsLLVMValue(), fileHandleIsSomePtr);
            builder.CreateStore(fileHandle, fileHandleInnerValueFileHandlePtr);
            builder.CreateRetVoid();
        }
示例#3
0
        private static void BuildStringFromSliceFunction(Module stringModule, CommonExternalFunctions externalFunctions)
        {
            LLVMValueRef      stringFromSliceFunction = stringModule.AddFunction(StringFromSliceName, CommonModuleSignatures[StringFromSliceName]);
            LLVMBasicBlockRef entryBlock = stringFromSliceFunction.AppendBasicBlock("entry");
            var builder = new IRBuilder();

            builder.PositionBuilderAtEnd(entryBlock);

            LLVMValueRef stringSliceReference   = stringFromSliceFunction.GetParam(0u),
                         stringPtr              = stringFromSliceFunction.GetParam(1u),
                         stringAllocationPtrPtr = builder.CreateStructGEP(stringPtr, 0u, "stringAllocationPtrPtr"),
                         stringSizePtr          = builder.CreateStructGEP(stringPtr, 1u, "stringSizePtr");

            LLVMValueRef sliceAllocationPtr = builder.CreateExtractValue(stringSliceReference, 0u, "sliceAllocationPtr");
            LLVMValueRef sliceSize          = builder.CreateExtractValue(stringSliceReference, 1u, "sliceSize");

            // Get a pointer to a heap allocation big enough for the string
            LLVMValueRef allocationPtr = builder.CreateArrayMalloc(LLVMTypeRef.Int8Type(), sliceSize, "allocationPtr");

            builder.CreateStore(allocationPtr, stringAllocationPtrPtr);

            // Copy the data from the string slice to the heap allocation
            LLVMValueRef sizeExtend = builder.CreateSExt(sliceSize, LLVMTypeRef.Int64Type(), "sizeExtend");

            builder.CreateCall(externalFunctions.CopyMemoryFunction, new LLVMValueRef[] { allocationPtr, sliceAllocationPtr, sizeExtend }, string.Empty);

            // Copy actual size into string handle
            builder.CreateStore(sliceSize, stringSizePtr);

            builder.CreateRetVoid();
        }
        public FunctionCompiler(Module module, string functionName, Dictionary <VariableReference, ValueSource> variableValues)
        {
            Module          = module;
            _variableValues = variableValues;

            LLVMTypeRef functionType = LLVMSharp.LLVM.FunctionType(LLVMSharp.LLVM.VoidType(), new LLVMTypeRef[] { }, false);

            _topLevelFunction = Module.AddFunction(functionName, functionType);
            LLVMBasicBlockRef entryBlock = _topLevelFunction.AppendBasicBlock("entry");

            _builder = new IRBuilder();
            _builder.PositionBuilderAtEnd(entryBlock);

            _commonExternalFunctions = new CommonExternalFunctions(module);
            InitializeLocalAllocations();
        }
示例#5
0
        private static void BuildCopySliceToPointerFunction(Module stringModule, CommonExternalFunctions externalFunctions)
        {
            _copySliceToPointerFunction = stringModule.AddFunction(CopySliceToPointerName, CommonModuleSignatures[CopySliceToPointerName]);
            LLVMBasicBlockRef entryBlock = _copySliceToPointerFunction.AppendBasicBlock("entry");
            var builder = new IRBuilder();

            builder.PositionBuilderAtEnd(entryBlock);

            LLVMValueRef slice          = _copySliceToPointerFunction.GetParam(0u),
                         sourcePtr      = builder.CreateExtractValue(slice, 0u, "sourcePtr"),
                         size           = builder.CreateExtractValue(slice, 1u, "size"),
                         sizeExtend     = builder.CreateSExt(size, LLVMTypeRef.Int64Type(), "sizeExtend"),
                         destinationPtr = _copySliceToPointerFunction.GetParam(1u);

            builder.CreateCall(externalFunctions.CopyMemoryFunction, new LLVMValueRef[] { destinationPtr, sourcePtr, sizeExtend }, string.Empty);
            builder.CreateRetVoid();
        }
示例#6
0
        private static void BuildDropFileHandleFunction(Module fileModule, CommonExternalFunctions externalFunctions)
        {
            LLVMValueRef      dropFileHandleFunction = fileModule.AddFunction(DropFileHandleName, CommonModuleSignatures[DropFileHandleName]);
            LLVMBasicBlockRef entryBlock             = dropFileHandleFunction.AppendBasicBlock("entry");
            var builder = new IRBuilder();

            builder.PositionBuilderAtEnd(entryBlock);

            LLVMValueRef fileHandleStructPtr = dropFileHandleFunction.GetParam(0u),
                         fileHandlePtr       = builder.CreateStructGEP(fileHandleStructPtr, 0u, "fileHandlePtr"),
                         fileHandle          = builder.CreateLoad(fileHandlePtr, "fileHandle");

            builder.CreateCall(
                externalFunctions.CloseHandleFunction,
                new LLVMValueRef[] { fileHandle },
                "closeHandleResult");
            builder.CreateRetVoid();
        }
示例#7
0
        private static void CreateFileModule(Module fileModule)
        {
            CommonExternalFunctions externalFunctions = new CommonExternalFunctions(fileModule);

            CommonModuleSignatures[OpenFileHandleName] = LLVMSharp.LLVM.FunctionType(
                LLVMSharp.LLVM.VoidType(),
                new LLVMTypeRef[]
            {
                LLVMExtensions.StringSliceReferenceType,
                LLVMTypeRef.PointerType(LLVMExtensions.FileHandleType.CreateLLVMOptionType(), 0),
            },
                false);
            BuildOpenFileHandleFunction(fileModule, externalFunctions);

            CommonModuleSignatures[ReadLineFromFileHandleName] = LLVMSharp.LLVM.FunctionType(
                LLVMSharp.LLVM.VoidType(),
                new LLVMTypeRef[]
            {
                LLVMTypeRef.PointerType(LLVMExtensions.FileHandleType, 0),
                LLVMTypeRef.PointerType(LLVMExtensions.StringType.CreateLLVMOptionType(), 0),
            },
                false);
            BuildReadLineFromFileHandleFunction(fileModule, externalFunctions);

            CommonModuleSignatures[WriteStringToFileHandleName] = LLVMSharp.LLVM.FunctionType(
                LLVMSharp.LLVM.VoidType(),
                new LLVMTypeRef[]
            {
                LLVMTypeRef.PointerType(LLVMExtensions.FileHandleType, 0),
                LLVMExtensions.StringSliceReferenceType,
            },
                false);
            BuildWriteStringToFileHandleFunction(fileModule, externalFunctions);

            CommonModuleSignatures[DropFileHandleName] = LLVMSharp.LLVM.FunctionType(
                LLVMSharp.LLVM.VoidType(),
                new LLVMTypeRef[]
            {
                LLVMTypeRef.PointerType(LLVMExtensions.FileHandleType, 0),
            },
                false);
            BuildDropFileHandleFunction(fileModule, externalFunctions);
        }
示例#8
0
        private static void BuildOutputStringSliceFunction(Module stringModule, CommonExternalFunctions externalFunctions)
        {
            LLVMValueRef      outputStringSliceFunction = stringModule.AddFunction(OutputStringSliceName, CommonModuleSignatures[OutputStringSliceName]);
            LLVMBasicBlockRef entryBlock = outputStringSliceFunction.AppendBasicBlock("entry");
            var builder = new IRBuilder();

            builder.PositionBuilderAtEnd(entryBlock);

            LLVMValueRef stringSlice = outputStringSliceFunction.GetParam(0u);

            builder.CreateCall(
                externalFunctions.OutputStringFunction,
                new LLVMValueRef[]
            {
                builder.CreateExtractValue(stringSlice, 0u, "stringBufferPtr"),
                builder.CreateExtractValue(stringSlice, 1u, "stringSize")
            },
                string.Empty);
            builder.CreateRetVoid();
        }
示例#9
0
        private static void BuildStringAppendFunction(Module stringModule, CommonExternalFunctions externalFunctions)
        {
            _stringAppendFunction = stringModule.AddFunction(StringAppendName, CommonModuleSignatures[StringAppendName]);
            LLVMBasicBlockRef entryBlock = _stringAppendFunction.AppendBasicBlock("entry");
            var builder = new IRBuilder();

            builder.PositionBuilderAtEnd(entryBlock);

            LLVMValueRef stringPtr      = _stringAppendFunction.GetParam(0u),
                         sliceReference = _stringAppendFunction.GetParam(1u);

            // for now, always create a new allocation, rather than trying to use existing one
            // compute the new allocation size and allocate it
            LLVMValueRef stringAllocationPtrPtr = builder.CreateStructGEP(stringPtr, 0u, "stringAllocationPtrPtr"),
                         stringSizePtr          = builder.CreateStructGEP(stringPtr, 1u, "stringSizePtr"),
                         stringAllocationPtr    = builder.CreateLoad(stringAllocationPtrPtr, "stringAllocationPtr"),
                         stringSize             = builder.CreateLoad(stringSizePtr, "stringSize"),
                         sliceSize        = builder.CreateExtractValue(sliceReference, 1u, "sliceSize"),
                         appendedSize     = builder.CreateAdd(stringSize, sliceSize, "appendedSize"),
                         newAllocationPtr = builder.CreateArrayMalloc(LLVMTypeRef.Int8Type(), appendedSize, "newAllocationPtr");

            // copy from old allocation to new allocation
            LLVMValueRef stringSlice = builder.CreateCall(_stringFromSliceRetFunction, new LLVMValueRef[] { stringPtr }, "stringSlice");

            builder.CreateCall(_copySliceToPointerFunction, new LLVMValueRef[] { stringSlice, newAllocationPtr }, string.Empty);

            // copy from slice to offset in new allocation
            LLVMValueRef newAllocationOffsetPtr = builder.CreateGEP(newAllocationPtr, new LLVMValueRef[] { stringSize }, "newAllocationOffsetPtr");

            builder.CreateCall(_copySliceToPointerFunction, new LLVMValueRef[] { sliceReference, newAllocationOffsetPtr }, string.Empty);

            // free old allocation and update string fields
            builder.CreateFree(stringAllocationPtr);
            builder.CreateStore(newAllocationPtr, stringAllocationPtrPtr);
            builder.CreateStore(appendedSize, stringSizePtr);

            builder.CreateRetVoid();
        }
示例#10
0
        private static void BuildWriteStringToFileHandleFunction(Module fileModule, CommonExternalFunctions externalFunctions)
        {
            LLVMValueRef      writeStringToFileHandleFunction = fileModule.AddFunction(WriteStringToFileHandleName, CommonModuleSignatures[WriteStringToFileHandleName]);
            LLVMBasicBlockRef entryBlock = writeStringToFileHandleFunction.AppendBasicBlock("entry");
            var builder = new IRBuilder();

            builder.PositionBuilderAtEnd(entryBlock);

            LLVMValueRef fileHandleStructPtr      = writeStringToFileHandleFunction.GetParam(0u),
                         fileHandlePtr            = builder.CreateStructGEP(fileHandleStructPtr, 0u, "fileHandlePtr"),
                         fileHandle               = builder.CreateLoad(fileHandlePtr, "fileHandle"),
                         stringSlice              = writeStringToFileHandleFunction.GetParam(1u),
                         stringSliceAllocationPtr = builder.CreateExtractValue(stringSlice, 0u, "stringSliceAllocationPtr"),
                         stringSliceLength        = builder.CreateExtractValue(stringSlice, 1u, "stringSliceLength"),
                         bytesWrittenPtr          = builder.CreateAlloca(LLVMTypeRef.Int32Type(), "bytesWrittenPtr");

            builder.CreateCall(
                externalFunctions.WriteFileFunction,
                new LLVMValueRef[] { fileHandle, stringSliceAllocationPtr, stringSliceLength, bytesWrittenPtr, LLVMExtensions.NullVoidPointer },
                "writeFileResult");

            builder.CreateRetVoid();
        }
示例#11
0
        private static void CreateStringModule(Module stringModule)
        {
            var externalFunctions = new CommonExternalFunctions(stringModule);

            CommonModuleSignatures[CopySliceToPointerName] = LLVMSharp.LLVM.FunctionType(
                LLVMSharp.LLVM.VoidType(),
                new LLVMTypeRef[] { LLVMExtensions.StringSliceReferenceType, LLVMTypeRef.PointerType(LLVMTypeRef.Int8Type(), 0) },
                false);
            BuildCopySliceToPointerFunction(stringModule, externalFunctions);

            CommonModuleSignatures[CreateEmptyStringName] = LLVMSharp.LLVM.FunctionType(
                LLVMSharp.LLVM.VoidType(),
                new LLVMTypeRef[] { LLVMTypeRef.PointerType(LLVMExtensions.StringType, 0) },
                false);
            BuildCreateEmptyStringFunction(stringModule);

            CommonModuleSignatures[CreateNullTerminatedStringFromSliceName] = LLVMSharp.LLVM.FunctionType(
                LLVMExtensions.BytePointerType,
                new LLVMTypeRef[] { LLVMExtensions.StringSliceReferenceType },
                false);
            BuildCreateNullTerminatedStringFromSlice(stringModule);

            CommonModuleSignatures[DropStringName] = LLVMSharp.LLVM.FunctionType(
                LLVMSharp.LLVM.VoidType(),
                new LLVMTypeRef[] { LLVMTypeRef.PointerType(LLVMExtensions.StringType, 0) },
                false);
            BuildDropStringFunction(stringModule);

            CommonModuleSignatures[OutputStringSliceName] = LLVMSharp.LLVM.FunctionType(
                LLVMSharp.LLVM.VoidType(),
                new LLVMTypeRef[] { LLVMExtensions.StringSliceReferenceType },
                false);
            BuildOutputStringSliceFunction(stringModule, externalFunctions);

            CommonModuleSignatures[StringFromSliceName] = LLVMSharp.LLVM.FunctionType(
                LLVMSharp.LLVM.VoidType(),
                new LLVMTypeRef[] { LLVMExtensions.StringSliceReferenceType, LLVMTypeRef.PointerType(LLVMExtensions.StringType, 0) },
                false);
            BuildStringFromSliceFunction(stringModule, externalFunctions);

            CommonModuleSignatures[StringToSliceRetName] = LLVMSharp.LLVM.FunctionType(
                LLVMExtensions.StringSliceReferenceType,
                new LLVMTypeRef[] { LLVMTypeRef.PointerType(LLVMExtensions.StringType, 0), },
                false);
            BuildStringToSliceRetFunction(stringModule);

            CommonModuleSignatures[StringToSliceName] = LLVMSharp.LLVM.FunctionType(
                LLVMSharp.LLVM.VoidType(),
                new LLVMTypeRef[] { LLVMTypeRef.PointerType(LLVMExtensions.StringType, 0), LLVMTypeRef.PointerType(LLVMExtensions.StringSliceReferenceType, 0) },
                false);
            BuildStringToSliceFunction(stringModule);

            CommonModuleSignatures[StringAppendName] = LLVMSharp.LLVM.FunctionType(
                LLVMSharp.LLVM.VoidType(),
                new LLVMTypeRef[] { LLVMTypeRef.PointerType(LLVMExtensions.StringType, 0), LLVMExtensions.StringSliceReferenceType },
                false);
            BuildStringAppendFunction(stringModule, externalFunctions);

            CommonModuleSignatures[StringConcatName] = LLVMSharp.LLVM.FunctionType(
                LLVMSharp.LLVM.VoidType(),
                new LLVMTypeRef[] { LLVMExtensions.StringSliceReferenceType, LLVMExtensions.StringSliceReferenceType, LLVMTypeRef.PointerType(LLVMExtensions.StringType, 0) },
                false);
            BuildStringConcatFunction(stringModule, externalFunctions);

            stringModule.VerifyAndThrowIfInvalid();
        }
示例#12
0
        private static void BuildReadLineFromFileHandleFunction(Module fileModule, CommonExternalFunctions externalFunctions)
        {
            LLVMValueRef      readLineFromFileHandleFunction = fileModule.AddFunction(ReadLineFromFileHandleName, CommonModuleSignatures[ReadLineFromFileHandleName]);
            LLVMBasicBlockRef entryBlock = readLineFromFileHandleFunction.AppendBasicBlock("entry");
            var builder = new IRBuilder();

            builder.PositionBuilderAtEnd(entryBlock);

            LLVMBasicBlockRef loopStartBlock      = readLineFromFileHandleFunction.AppendBasicBlock("loopStart"),
                              handleByteBlock     = readLineFromFileHandleFunction.AppendBasicBlock("handleByte"),
                              byteIsCRBlock       = readLineFromFileHandleFunction.AppendBasicBlock("byteIsCR"),
                              byteIsNotCRBlock    = readLineFromFileHandleFunction.AppendBasicBlock("byteIsNotCR"),
                              notNewLineBlock     = readLineFromFileHandleFunction.AppendBasicBlock("notNewLine"),
                              appendCRBlock       = readLineFromFileHandleFunction.AppendBasicBlock("appendCR"),
                              appendByteBlock     = readLineFromFileHandleFunction.AppendBasicBlock("appendByte"),
                              loopEndBlock        = readLineFromFileHandleFunction.AppendBasicBlock("loopEnd"),
                              nonEmptyStringBlock = readLineFromFileHandleFunction.AppendBasicBlock("nonEmptyString"),
                              emptyStringBlock    = readLineFromFileHandleFunction.AppendBasicBlock("emptyString");

            LLVMValueRef fileHandlePtr     = readLineFromFileHandleFunction.GetParam(0u),
                         stringPtr         = builder.CreateAlloca(LLVMExtensions.StringType, "stringPtr"),
                         carriageReturnPtr = builder.CreateAlloca(LLVMTypeRef.Int8Type(), "carriageReturnPtr"),
                         carriageReturn    = ((byte)0xD).AsLLVMValue(),
                         byteReadPtr       = builder.CreateAlloca(LLVMTypeRef.Int8Type(), "byteReadPtr"),
                         bytesReadPtr      = builder.CreateAlloca(LLVMTypeRef.Int32Type(), "bytesReadPtr"),
                         nonEmptyStringPtr = builder.CreateAlloca(LLVMTypeRef.Int1Type(), "nonEmptyStringPtr"),
                         seenCRPtr         = builder.CreateAlloca(LLVMTypeRef.Int1Type(), "seenCRPtr");

            builder.CreateStore(carriageReturn, carriageReturnPtr);
            builder.CreateStore(false.AsLLVMValue(), seenCRPtr);
            builder.CreateStore(false.AsLLVMValue(), nonEmptyStringPtr);
            builder.CreateCall(_createEmptyStringFunction, new LLVMValueRef[] { stringPtr }, string.Empty);
            builder.CreateBr(loopStartBlock);

            builder.PositionBuilderAtEnd(loopStartBlock);
            LLVMValueRef hFilePtr       = builder.CreateStructGEP(fileHandlePtr, 0u, "hFilePtr"),
                         hFile          = builder.CreateLoad(hFilePtr, "hFile");
            LLVMValueRef readFileResult = builder.CreateCall(
                externalFunctions.ReadFileFunction,
                new LLVMValueRef[] { hFile, byteReadPtr, 1.AsLLVMValue(), bytesReadPtr, LLVMExtensions.NullVoidPointer },
                "readFileResult"),
                         readFileResultBool = builder.CreateICmp(LLVMIntPredicate.LLVMIntNE, readFileResult, 0.AsLLVMValue(), "readFileResultBool"),
                         bytesRead          = builder.CreateLoad(bytesReadPtr, "bytesRead"),
                         zeroBytesRead      = builder.CreateICmp(LLVMIntPredicate.LLVMIntEQ, bytesRead, 0.AsLLVMValue(), "zeroBytesRead"),
                         eof = builder.CreateAnd(readFileResultBool, zeroBytesRead, "eof");

            builder.CreateCondBr(eof, loopEndBlock, handleByteBlock);

            builder.PositionBuilderAtEnd(handleByteBlock);
            LLVMValueRef byteRead     = builder.CreateLoad(byteReadPtr, "byteRead"),
                         byteReadIsCR = builder.CreateICmp(LLVMIntPredicate.LLVMIntEQ, byteRead, carriageReturn, "byteReadIsCR");

            builder.CreateCondBr(byteReadIsCR, byteIsCRBlock, byteIsNotCRBlock);

            builder.PositionBuilderAtEnd(byteIsCRBlock);
            builder.CreateStore(true.AsLLVMValue(), seenCRPtr);
            builder.CreateBr(loopStartBlock);

            builder.PositionBuilderAtEnd(byteIsNotCRBlock);
            LLVMValueRef byteIsLF = builder.CreateICmp(LLVMIntPredicate.LLVMIntEQ, byteRead, ((byte)0xA).AsLLVMValue(), "byteIsLF"),
                         seenCR   = builder.CreateLoad(seenCRPtr, "seenCR"),
                         newLine  = builder.CreateAnd(byteIsLF, seenCR, "newLine");

            builder.CreateCondBr(newLine, loopEndBlock, notNewLineBlock);

            builder.PositionBuilderAtEnd(notNewLineBlock);
            builder.CreateCondBr(seenCR, appendCRBlock, appendByteBlock);

            builder.PositionBuilderAtEnd(appendCRBlock);
            LLVMValueRef crSlice = builder.BuildStringSliceReferenceValue(carriageReturnPtr, 1.AsLLVMValue());

            builder.CreateCall(_stringAppendFunction, new LLVMValueRef[] { stringPtr, crSlice }, string.Empty);
            builder.CreateBr(appendByteBlock);

            builder.PositionBuilderAtEnd(appendByteBlock);
            LLVMValueRef byteSlice = builder.BuildStringSliceReferenceValue(byteReadPtr, 1.AsLLVMValue());

            builder.CreateCall(_stringAppendFunction, new LLVMValueRef[] { stringPtr, byteSlice }, string.Empty);
            builder.CreateStore(true.AsLLVMValue(), nonEmptyStringPtr);
            builder.CreateStore(false.AsLLVMValue(), seenCRPtr);
            builder.CreateBr(loopStartBlock);

            builder.PositionBuilderAtEnd(loopEndBlock);
            LLVMValueRef optionStringPtr       = readLineFromFileHandleFunction.GetParam(1u),
                         optionStringIsSomePtr = builder.CreateStructGEP(optionStringPtr, 0u, "optionStringIsSomePtr"),
                         nonEmptyString        = builder.CreateLoad(nonEmptyStringPtr, "nonEmptyString");

            builder.CreateCondBr(nonEmptyString, nonEmptyStringBlock, emptyStringBlock);

            builder.PositionBuilderAtEnd(nonEmptyStringBlock);
            builder.CreateStore(true.AsLLVMValue(), optionStringIsSomePtr);
            LLVMValueRef optionStringInnerValuePtr = builder.CreateStructGEP(optionStringPtr, 1u, "optionStringInnerValuePtr"),
                         stringValue = builder.CreateLoad(stringPtr, "string");

            builder.CreateStore(stringValue, optionStringInnerValuePtr);
            builder.CreateRetVoid();

            builder.PositionBuilderAtEnd(emptyStringBlock);
            builder.CreateStore(false.AsLLVMValue(), optionStringIsSomePtr);
            builder.CreateCall(_dropStringFunction, new LLVMValueRef[] { stringPtr }, string.Empty);
            builder.CreateRetVoid();
        }