source: icGREP/icgrep-devel/icgrep/kernels/stdout_kernel.cpp @ 5699

Last change on this file since 5699 was 5606, checked in by cameron, 2 years ago

Allow different strides for FileSink? kernel

File size: 5.0 KB
RevLine 
[4988]1/*
2 *  Copyright (c) 2016 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 */
[5260]5#include "stdout_kernel.h"
6#include <llvm/IR/Module.h>
[5436]7#include <kernels/kernel_builder.h>
[5267]8#include <kernels/streamset.h>
[5436]9
[5267]10namespace llvm { class Type; }
[4988]11
[5260]12using namespace llvm;
[5303]13using namespace parabix;
[5260]14
[4988]15namespace kernel {
[5307]16
[5195]17// Rather than using doBlock logic to write one block at a time, this custom
[5303]18// doSegment method attempts to write the entire segment with a single write call.
19// However, if the segment spans two memory areas (e.g., because of wraparound),
20// then two write calls are made.
[5441]21void StdOutKernel::generateMultiBlockLogic(const std::unique_ptr<KernelBuilder> & iBuilder) {
[5286]22    PointerType * i8PtrTy = iBuilder->getInt8PtrTy();
[5307]23    Constant * itemBytes = iBuilder->getSize(mCodeUnitWidth / 8);
[5195]24   
[5441]25    Function::arg_iterator args = mCurrentMethod->arg_begin();
[5442]26    /* self = */ args++;
[5441]27    Value * itemsToDo = &*(args++);
28    Value * codeUnitBuffer = &*(args++);
[5307]29
[5441]30    Value * bytesToDo = mCodeUnitWidth == 8 ? itemsToDo : iBuilder->CreateMul(itemsToDo, itemBytes);
31    Value * bytePtr = iBuilder->CreatePointerCast(codeUnitBuffer, i8PtrTy);
32    iBuilder->CreateWriteCall(iBuilder->getInt32(1), bytePtr, bytesToDo);
[4988]33}
[5007]34
[5436]35StdOutKernel::StdOutKernel(const std::unique_ptr<kernel::KernelBuilder> & iBuilder, unsigned codeUnitWidth)
[5441]36: MultiBlockKernel("stdout", {Binding{iBuilder->getStreamSetTy(1, codeUnitWidth), "codeUnitBuffer"}}, {}, {}, {}, {})
[5267]37, mCodeUnitWidth(codeUnitWidth) {
38    setNoTerminateAttribute(true);
[4988]39}
[5267]40
[5440]41void FileSink::generateInitializeMethod(const std::unique_ptr<kernel::KernelBuilder> & iBuilder) {
42    BasicBlock * setTerminationOnFailure = iBuilder->CreateBasicBlock("setTerminationOnFailure");
43    BasicBlock * fileSinkInitExit = iBuilder->CreateBasicBlock("fileSinkInitExit");
44    Value * fileName = iBuilder->getScalarField("fileName");
[5415]45    Value * fileNameLength = iBuilder->CreateStrlenCall(fileName);
46    // Make a temporary file name template with the characters "XXXXXX" appended
47    // as required by mkstemp.
48    Constant * suffixPlusNullLength = iBuilder->getSize(7);
49    Value * tmpFileNamePtr = iBuilder->CreatePointerCast(iBuilder->CreateMalloc(iBuilder->CreateAdd(fileNameLength, suffixPlusNullLength)), iBuilder->getInt8PtrTy());
[5440]50    iBuilder->setScalarField("tmpFileName", tmpFileNamePtr);
[5415]51    iBuilder->CreateMemCpy(tmpFileNamePtr, fileName, fileNameLength, 1);
52#ifdef BACKUP_OLDFILE
[5440]53    iBuilder->CreateMemCpy(iBuilder->CreateGEP(tmpFileNamePtr, fileNameLength), iBuilder->GetString(".saved"), suffixPlusNullLength, 1);
[5415]54    iBuilder->CreateRenameCall(fileName, tmpFileNamePtr);
55#else
56    iBuilder->CreateUnlinkCall(fileName);
57#endif
[5440]58    iBuilder->CreateMemCpy(iBuilder->CreateGEP(tmpFileNamePtr, fileNameLength), iBuilder->GetString("XXXXXX"), suffixPlusNullLength, 1);
[5415]59    Value * fileDes = iBuilder->CreateMkstempCall(tmpFileNamePtr);
[5440]60    iBuilder->setScalarField("fileDes", fileDes);
[5415]61    Value * failure = iBuilder->CreateICmpEQ(fileDes, iBuilder->getInt32(-1));
[5280]62    iBuilder->CreateCondBr(failure, setTerminationOnFailure, fileSinkInitExit);
63    iBuilder->SetInsertPoint(setTerminationOnFailure);
[5440]64    iBuilder->setTerminationSignal();
[5280]65    iBuilder->CreateBr(fileSinkInitExit);
66    iBuilder->SetInsertPoint(fileSinkInitExit);
[5267]67}
[5280]68
[5449]69void FileSink::generateMultiBlockLogic(const std::unique_ptr<KernelBuilder> & iBuilder) {
[5440]70    BasicBlock * closeFile = iBuilder->CreateBasicBlock("closeFile");
71    BasicBlock * fileOutExit = iBuilder->CreateBasicBlock("fileOutExit");
[5449]72   
73    PointerType * i8PtrTy = iBuilder->getInt8PtrTy();
74    Constant * itemBytes = iBuilder->getSize(mCodeUnitWidth / 8);
75    Value * fileDes = iBuilder->getScalarField("fileDes");
[5307]76
[5449]77    Function::arg_iterator args = mCurrentMethod->arg_begin();
78    /* self = */ args++;
79    Value * itemsToDo = &*(args++);
80    Value * codeUnitBuffer = &*(args++);
[5280]81   
[5448]82    Value * bytesToDo = mCodeUnitWidth == 8 ? itemsToDo : iBuilder->CreateMul(itemsToDo, itemBytes);
[5449]83    Value * bytePtr = iBuilder->CreatePointerCast(codeUnitBuffer, i8PtrTy);
84   
[5448]85    iBuilder->CreateWriteCall(fileDes, bytePtr, bytesToDo);
[5606]86    iBuilder->CreateCondBr(iBuilder->CreateICmpULT(itemsToDo, iBuilder->getSize(getKernelStride())), closeFile, fileOutExit);
[5280]87   
88    iBuilder->SetInsertPoint(closeFile);
[5415]89    iBuilder->CreateCloseCall(fileDes);
[5440]90    Value * newFileNamePtr = iBuilder->getScalarField("fileName");
91    Value * tmpFileNamePtr = iBuilder->getScalarField("tmpFileName");
[5415]92    iBuilder->CreateRenameCall(tmpFileNamePtr, newFileNamePtr);
93    iBuilder->CreateFree(tmpFileNamePtr);
94   
[5280]95    iBuilder->CreateBr(fileOutExit);
[5449]96   
[5280]97    iBuilder->SetInsertPoint(fileOutExit);
98}
99
[5436]100FileSink::FileSink(const std::unique_ptr<kernel::KernelBuilder> & iBuilder, unsigned codeUnitWidth)
[5449]101: MultiBlockKernel("filesink", {Binding{iBuilder->getStreamSetTy(1, codeUnitWidth), "codeUnitBuffer"}}, {},
[5415]102                {Binding{iBuilder->getInt8PtrTy(), "fileName"}}, {}, {Binding{iBuilder->getInt8PtrTy(), "tmpFileName"}, Binding{iBuilder->getInt32Ty(), "fileDes"}})
[5280]103, mCodeUnitWidth(codeUnitWidth) {
104}
105
106}
107
108
109
[5307]110
Note: See TracBrowser for help on using the repository browser.