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

Last change on this file since 5589 was 5449, checked in by cameron, 2 years ago

FileSink? uses MultiBlockKernel?

File size: 5.0 KB
Line 
1/*
2 *  Copyright (c) 2016 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 */
5#include "stdout_kernel.h"
6#include <llvm/IR/Module.h>
7#include <kernels/kernel_builder.h>
8#include <kernels/streamset.h>
9
10namespace llvm { class Type; }
11
12using namespace llvm;
13using namespace parabix;
14
15namespace kernel {
16
17// Rather than using doBlock logic to write one block at a time, this custom
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.
21void StdOutKernel::generateMultiBlockLogic(const std::unique_ptr<KernelBuilder> & iBuilder) {
22    PointerType * i8PtrTy = iBuilder->getInt8PtrTy();
23    Constant * itemBytes = iBuilder->getSize(mCodeUnitWidth / 8);
24   
25    Function::arg_iterator args = mCurrentMethod->arg_begin();
26    /* self = */ args++;
27    Value * itemsToDo = &*(args++);
28    Value * codeUnitBuffer = &*(args++);
29
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);
33}
34
35StdOutKernel::StdOutKernel(const std::unique_ptr<kernel::KernelBuilder> & iBuilder, unsigned codeUnitWidth)
36: MultiBlockKernel("stdout", {Binding{iBuilder->getStreamSetTy(1, codeUnitWidth), "codeUnitBuffer"}}, {}, {}, {}, {})
37, mCodeUnitWidth(codeUnitWidth) {
38    setNoTerminateAttribute(true);
39}
40
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");
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());
50    iBuilder->setScalarField("tmpFileName", tmpFileNamePtr);
51    iBuilder->CreateMemCpy(tmpFileNamePtr, fileName, fileNameLength, 1);
52#ifdef BACKUP_OLDFILE
53    iBuilder->CreateMemCpy(iBuilder->CreateGEP(tmpFileNamePtr, fileNameLength), iBuilder->GetString(".saved"), suffixPlusNullLength, 1);
54    iBuilder->CreateRenameCall(fileName, tmpFileNamePtr);
55#else
56    iBuilder->CreateUnlinkCall(fileName);
57#endif
58    iBuilder->CreateMemCpy(iBuilder->CreateGEP(tmpFileNamePtr, fileNameLength), iBuilder->GetString("XXXXXX"), suffixPlusNullLength, 1);
59    Value * fileDes = iBuilder->CreateMkstempCall(tmpFileNamePtr);
60    iBuilder->setScalarField("fileDes", fileDes);
61    Value * failure = iBuilder->CreateICmpEQ(fileDes, iBuilder->getInt32(-1));
62    iBuilder->CreateCondBr(failure, setTerminationOnFailure, fileSinkInitExit);
63    iBuilder->SetInsertPoint(setTerminationOnFailure);
64    iBuilder->setTerminationSignal();
65    iBuilder->CreateBr(fileSinkInitExit);
66    iBuilder->SetInsertPoint(fileSinkInitExit);
67}
68
69void FileSink::generateMultiBlockLogic(const std::unique_ptr<KernelBuilder> & iBuilder) {
70    BasicBlock * closeFile = iBuilder->CreateBasicBlock("closeFile");
71    BasicBlock * fileOutExit = iBuilder->CreateBasicBlock("fileOutExit");
72   
73    PointerType * i8PtrTy = iBuilder->getInt8PtrTy();
74    Constant * itemBytes = iBuilder->getSize(mCodeUnitWidth / 8);
75    Value * fileDes = iBuilder->getScalarField("fileDes");
76
77    Function::arg_iterator args = mCurrentMethod->arg_begin();
78    /* self = */ args++;
79    Value * itemsToDo = &*(args++);
80    Value * codeUnitBuffer = &*(args++);
81   
82    Value * bytesToDo = mCodeUnitWidth == 8 ? itemsToDo : iBuilder->CreateMul(itemsToDo, itemBytes);
83    Value * bytePtr = iBuilder->CreatePointerCast(codeUnitBuffer, i8PtrTy);
84   
85    iBuilder->CreateWriteCall(fileDes, bytePtr, bytesToDo);
86    iBuilder->CreateCondBr(iBuilder->CreateICmpULT(itemsToDo, iBuilder->getSize(iBuilder->getBitBlockWidth())), closeFile, fileOutExit);
87   
88    iBuilder->SetInsertPoint(closeFile);
89    iBuilder->CreateCloseCall(fileDes);
90    Value * newFileNamePtr = iBuilder->getScalarField("fileName");
91    Value * tmpFileNamePtr = iBuilder->getScalarField("tmpFileName");
92    iBuilder->CreateRenameCall(tmpFileNamePtr, newFileNamePtr);
93    iBuilder->CreateFree(tmpFileNamePtr);
94   
95    iBuilder->CreateBr(fileOutExit);
96   
97    iBuilder->SetInsertPoint(fileOutExit);
98}
99
100FileSink::FileSink(const std::unique_ptr<kernel::KernelBuilder> & iBuilder, unsigned codeUnitWidth)
101: MultiBlockKernel("filesink", {Binding{iBuilder->getStreamSetTy(1, codeUnitWidth), "codeUnitBuffer"}}, {},
102                {Binding{iBuilder->getInt8PtrTy(), "fileName"}}, {}, {Binding{iBuilder->getInt8PtrTy(), "tmpFileName"}, Binding{iBuilder->getInt32Ty(), "fileDes"}})
103, mCodeUnitWidth(codeUnitWidth) {
104}
105
106}
107
108
109
110
Note: See TracBrowser for help on using the repository browser.