source: icGREP/icgrep-devel/icgrep/kernels/source_kernel.cpp @ 6034

Last change on this file since 6034 was 6025, checked in by nmedfort, 17 months ago

bug fix for mmap kernel to prevent it from copying the entire file

File size: 22.6 KB
Line 
1/*
2 *  Copyright (c) 2018 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 */
5#include "source_kernel.h"
6#include <kernels/kernel_builder.h>
7#include <kernels/streamset.h>
8#include <llvm/IR/Module.h>
9#include <sys/stat.h>
10#include <fcntl.h>
11#include <toolchain/toolchain.h>
12
13using namespace llvm;
14
15extern "C" uint64_t file_size(const uint32_t fd) {
16    struct stat st;
17    if (LLVM_UNLIKELY(fstat(fd, &st) != 0)) {
18        st.st_size = 0;
19    }
20    return st.st_size;
21}
22
23namespace kernel {
24
25/// MMAP SOURCE KERNEL
26
27Function * MMapSourceKernel::linkFileSizeMethod(const std::unique_ptr<kernel::KernelBuilder> & b) {
28    return b->LinkFunction("file_size", &file_size);
29}
30
31void MMapSourceKernel::generateInitializeMethod(Function * const fileSizeMethod, const unsigned codeUnitWidth, const std::unique_ptr<KernelBuilder> & b) {
32
33    BasicBlock * const emptyFile = b->CreateBasicBlock("emptyFile");
34    BasicBlock * const nonEmptyFile = b->CreateBasicBlock("NonEmptyFile");
35    BasicBlock * const exit = b->CreateBasicBlock("Exit");
36    IntegerType * const sizeTy = b->getSizeTy();
37
38    ConstantInt * const PAGE_SIZE = b->getSize(getpagesize());
39    ConstantInt * const ZERO = b->getSize(0);
40
41
42    Value * const fd = b->getScalarField("fileDescriptor");
43    assert (fileSizeMethod);
44    Value * fileSize = b->CreateZExtOrTrunc(b->CreateCall(fileSizeMethod, fd), sizeTy);
45    b->CreateLikelyCondBr(b->CreateIsNotNull(fileSize), nonEmptyFile, emptyFile);
46
47    b->SetInsertPoint(nonEmptyFile);
48    PointerType * const codeUnitPtrTy = b->getIntNTy(codeUnitWidth)->getPointerTo();
49    Value * const fileBuffer = b->CreatePointerCast(b->CreateFileSourceMMap(fd, fileSize), codeUnitPtrTy);
50    b->setScalarField("buffer", fileBuffer);
51    b->setBaseAddress("sourceBuffer", fileBuffer);
52    b->CreateMAdvise(fileBuffer, fileSize, CBuilder::ADVICE_WILLNEED);
53    if (LLVM_UNLIKELY(codeUnitWidth > 8)) {
54        fileSize = b->CreateUDiv(fileSize, b->getSize(codeUnitWidth / 8));
55    }
56    b->setBufferedSize("sourceBuffer", fileSize);
57    b->setScalarField("fileSize", fileSize);
58    b->setProducedItemCount("sourceBuffer", ZERO);
59    b->setCapacity("sourceBuffer", fileSize);
60    b->CreateBr(exit);
61
62    b->SetInsertPoint(emptyFile);
63    Value * const emptyFilePtr = b->CreatePointerCast(b->CreateAnonymousMMap(PAGE_SIZE), codeUnitPtrTy);
64    b->setScalarField("buffer", emptyFilePtr);
65    b->setBaseAddress("sourceBuffer", emptyFilePtr);
66    b->setScalarField("fileSize", ZERO);
67    b->setBufferedSize("sourceBuffer", PAGE_SIZE);
68    b->setCapacity("sourceBuffer", PAGE_SIZE);
69    b->setTerminationSignal();
70    b->CreateBr(exit);
71
72    b->SetInsertPoint(exit);
73}
74
75
76void MMapSourceKernel::generateDoSegmentMethod(const unsigned codeUnitWidth, const std::unique_ptr<KernelBuilder> & b) {
77
78    BasicBlock * const dropPages = b->CreateBasicBlock("dropPages");
79    BasicBlock * const checkRemaining = b->CreateBasicBlock("checkRemaining");
80    BasicBlock * const setTermination = b->CreateBasicBlock("setTermination");
81    BasicBlock * const exit = b->CreateBasicBlock("mmapSourceExit");
82
83    Constant * const PAGE_SIZE = b->getSize(getpagesize());
84    Constant * const BLOCK_WIDTH = b->getSize(b->getBitBlockWidth());
85    Constant * const CODE_UNIT_BYTES = b->getSize(codeUnitWidth / 8);
86
87    Value * const fileItems = b->getScalarField("fileSize");
88    Value * const consumedItems = b->getConsumedItemCount("sourceBuffer");
89    Value * const consumedBytes = b->CreateMul(consumedItems, CODE_UNIT_BYTES);
90    Value * const consumedPageOffset = b->CreateAnd(consumedBytes, ConstantExpr::getNeg(PAGE_SIZE));
91    Value * const consumedBuffer = b->getRawOutputPointer("sourceBuffer", consumedPageOffset);
92    Value * const readableBuffer = b->getScalarField("buffer");
93    Value * const unnecessaryBytes = b->CreatePtrDiff(consumedBuffer, readableBuffer);
94
95    // avoid calling madvise unless an actual page table change could occur
96    b->CreateLikelyCondBr(b->CreateIsNotNull(unnecessaryBytes), dropPages, checkRemaining);
97
98    b->SetInsertPoint(dropPages);
99    // instruct the OS that it can safely drop any fully consumed pages
100    b->CreateMAdvise(readableBuffer, unnecessaryBytes, CBuilder::ADVICE_DONTNEED);
101    b->setScalarField("buffer", b->CreateGEP(readableBuffer, unnecessaryBytes));
102    b->CreateBr(checkRemaining);
103
104    // determine whether or not we've exhausted the file buffer
105    b->SetInsertPoint(checkRemaining);
106    Value * const producedItems = b->getProducedItemCount("sourceBuffer");
107    Value * const nextProducedItems = b->CreateAdd(producedItems, PAGE_SIZE);
108    Value * const lastPage = b->CreateICmpULE(fileItems, nextProducedItems);
109    b->CreateUnlikelyCondBr(lastPage, setTermination, exit);
110
111    // If this is the last page, create a temporary buffer of up to two pages size, copy the unconsumed data
112    // and zero any bytes that are not used.
113    b->SetInsertPoint(setTermination);
114    Value * const consumedOffset = b->CreateAnd(consumedItems, ConstantExpr::getNeg(BLOCK_WIDTH));
115    Value * const readStart = b->getRawOutputPointer("sourceBuffer", consumedOffset);
116    Value * const readEnd = b->getRawOutputPointer("sourceBuffer", fileItems);
117    Value * const unconsumedBytes = b->CreateTrunc(b->CreatePtrDiff(readEnd, readStart), b->getSizeTy());
118    Value * const bufferSize = b->CreateRoundUp(b->CreateAdd(unconsumedBytes, BLOCK_WIDTH), PAGE_SIZE);
119    Value * const buffer = b->CreateAlignedMalloc(bufferSize, b->getCacheAlignment());
120    b->CreateMemCpy(buffer, readStart, unconsumedBytes, 1);
121    b->CreateMemZero(b->CreateGEP(buffer, unconsumedBytes), b->CreateSub(bufferSize, unconsumedBytes), 1);
122    // get the difference between our base and from position then compute an offsetted temporary buffer address
123    Value * const base = b->getBaseAddress("sourceBuffer");
124    Value * const diff = b->CreatePtrDiff(b->CreatePointerCast(base, readStart->getType()), readStart);
125    Value * const offsettedBuffer = b->CreateGEP(buffer, diff);
126    b->CreateConsumerWait();
127    // Unmap the file buffer and set the temporary buffer as the new source buffer
128    Value * const fileSize = b->CreateMul(fileItems, CODE_UNIT_BYTES);
129    b->CreateMUnmap(base, fileSize);
130    PointerType * const codeUnitPtrTy = b->getIntNTy(codeUnitWidth)->getPointerTo();
131    b->setScalarField("buffer", b->CreatePointerCast(buffer, codeUnitPtrTy));
132    b->setBaseAddress("sourceBuffer", b->CreatePointerCast(offsettedBuffer, codeUnitPtrTy));
133    b->setTerminationSignal();
134    BasicBlock * const terminationExit = b->GetInsertBlock();
135    b->CreateBr(exit);
136
137    // finally, set the "produced" count to reflect current position in the file
138    b->SetInsertPoint(exit);
139    PHINode * const newProducedItems = b->CreatePHI(b->getSizeTy(), 2);
140    newProducedItems->addIncoming(nextProducedItems, checkRemaining);
141    newProducedItems->addIncoming(fileItems, terminationExit);
142    b->setProducedItemCount("sourceBuffer", newProducedItems);
143}
144
145void MMapSourceKernel::freeBuffer(const std::unique_ptr<KernelBuilder> & b) {
146    b->CreateFree(b->getScalarField("buffer"));
147}
148
149/// READ SOURCE KERNEL
150
151void ReadSourceKernel::generateInitializeMethod(const unsigned codeUnitWidth, const unsigned stride, const std::unique_ptr<KernelBuilder> & b) {
152    const unsigned pageSize = getpagesize();
153    const auto bufferSize = std::max(pageSize * 8, codegen::SegmentSize * stride  * 4);
154    ConstantInt * const bufferItems = b->getSize(bufferSize);
155    const auto codeUnitSize = codeUnitWidth / 8;
156    ConstantInt * const bufferBytes = b->getSize(bufferSize * codeUnitSize);
157    PointerType * const codeUnitPtrTy = b->getIntNTy(codeUnitWidth)->getPointerTo();
158    Value * const buffer = b->CreatePointerCast(b->CreateCacheAlignedMalloc(bufferBytes), codeUnitPtrTy);
159    b->setBaseAddress("sourceBuffer", buffer);
160    b->setScalarField("buffer", buffer);
161    b->setCapacity("sourceBuffer", bufferItems);
162}
163
164void ReadSourceKernel::generateDoSegmentMethod(const unsigned codeUnitWidth, const unsigned stride, const std::unique_ptr<KernelBuilder> & b) {
165
166    const unsigned pageSize = getpagesize();
167    ConstantInt * const itemsToRead = b->getSize(std::max(pageSize, codegen::SegmentSize * stride * 2));
168    ConstantInt * const codeUnitBytes = b->getSize(codeUnitWidth / 8);
169    ConstantInt * const itemsPerSegment = b->getSize(codegen::SegmentSize * stride);
170
171    BasicBlock * const entry = b->GetInsertBlock();
172    BasicBlock * const checkData = b->CreateBasicBlock("CheckData");
173    BasicBlock * const moveData = b->CreateBasicBlock("MoveData");
174    BasicBlock * const prepareBuffer = b->CreateBasicBlock("PrepareBuffer");
175    BasicBlock * const readData = b->CreateBasicBlock("ReadData");
176    BasicBlock * const setTermination = b->CreateBasicBlock("SetTermination");
177    BasicBlock * const readExit = b->CreateBasicBlock("ReadExit");
178
179    // Do we have enough unread data to support one segment?
180    Value * const produced = b->getProducedItemCount("sourceBuffer");
181    Value * const buffered = b->getBufferedSize("sourceBuffer");
182    Value * const itemsPending = b->CreateAdd(produced, itemsPerSegment);
183
184    b->CreateLikelyCondBr(b->CreateICmpULT(itemsPending, buffered), readExit, checkData);
185
186    // Can we append to our existing buffer without impacting any subsequent kernel?
187    b->SetInsertPoint(checkData);
188    Value * const capacity = b->getCapacity("sourceBuffer");
189    Value * const readEnd = b->getRawOutputPointer("sourceBuffer", b->CreateAdd(buffered, itemsToRead));
190    Value * const baseBuffer = b->getScalarField("buffer");
191    Value * const bufferLimit = b->CreateGEP(baseBuffer, capacity);
192    b->CreateLikelyCondBr(b->CreateICmpULE(readEnd, bufferLimit), readData, moveData);
193
194    // First wait on any consumers to finish processing then check how much data has been consumed.
195    b->SetInsertPoint(moveData);
196    b->CreateConsumerWait();
197
198    // Then determine how much data has been consumed and how much needs to be copied back, noting
199    // that our "unproduced" data must be block aligned.
200    BasicBlock * const copyBack = b->CreateBasicBlock("CopyBack");
201    BasicBlock * const expandAndCopyBack = b->CreateBasicBlock("ExpandAndCopyBack");
202
203    const auto blockSize = b->getBitBlockWidth() / 8;
204    Constant * const blockSizeAlignmentMask = ConstantExpr::getNeg(b->getSize(blockSize));
205    Value * const consumed = b->getConsumedItemCount("sourceBuffer");
206    Value * const offset = b->CreateAnd(consumed, blockSizeAlignmentMask);
207    Value * const unreadData = b->getRawOutputPointer("sourceBuffer", offset);
208    Value * const remainingItems = b->CreateSub(buffered, offset);
209    Value * const remainingBytes = b->CreateMul(remainingItems, codeUnitBytes);
210
211    // Have we consumed enough data that we can safely copy back the unconsumed data without needing a temporary buffer?
212    Value * const canCopy = b->CreateICmpULT(b->CreateGEP(baseBuffer, remainingItems), b->getRawOutputPointer("sourceBuffer", offset));
213    b->CreateLikelyCondBr(canCopy, copyBack, expandAndCopyBack);
214
215    // If so, just copy the data ...
216    b->SetInsertPoint(copyBack);
217    b->CreateMemCpy(baseBuffer, unreadData, remainingBytes, blockSize);
218    b->CreateBr(prepareBuffer);
219
220    // Otherwise, allocate a buffer with twice the capacity and copy the unconsumed data back into it
221    b->SetInsertPoint(expandAndCopyBack);
222    Value * const expandedCapacity = b->CreateShl(capacity, 1);
223    Value * const expandedBytes = b->CreateMul(expandedCapacity, codeUnitBytes);
224    Value * const expandedBuffer = b->CreatePointerCast(b->CreateCacheAlignedMalloc(expandedBytes), unreadData->getType());
225    b->CreateMemCpy(expandedBuffer, unreadData, remainingBytes, blockSize);
226    b->setScalarField("buffer", expandedBuffer);
227    b->setCapacity("sourceBuffer", expandedCapacity);
228    b->CreateFree(baseBuffer);
229    b->CreateBr(prepareBuffer);
230
231    b->SetInsertPoint(prepareBuffer);
232    PHINode * newBaseBuffer = b->CreatePHI(baseBuffer->getType(), 2);
233    newBaseBuffer->addIncoming(baseBuffer, copyBack);
234    newBaseBuffer->addIncoming(expandedBuffer, expandAndCopyBack);
235    b->setBaseAddress("sourceBuffer", b->CreateGEP(newBaseBuffer, b->CreateNeg(offset)));
236    b->CreateBr(readData);
237
238    // Regardless of whether we're simply appending data or had to allocate a new buffer, read a new page
239    // of data into the input source buffer. If we fail to read a full page ...
240    b->SetInsertPoint(readData);
241    Value * const sourceBuffer = b->getRawOutputPointer("sourceBuffer", buffered);
242    Value * const fd = b->getScalarField("fileDescriptor");
243    Constant * const bytesToRead = ConstantExpr::getMul(itemsToRead, codeUnitBytes);
244    Value * const bytesRead = b->CreateReadCall(fd, sourceBuffer, bytesToRead);
245    Value * const itemsRead = b->CreateUDiv(bytesRead, codeUnitBytes);
246    Value * const itemsBuffered = b->CreateAdd(buffered, itemsRead);
247    b->setBufferedSize("sourceBuffer", itemsBuffered);
248    b->CreateUnlikelyCondBr(b->CreateICmpULT(itemsBuffered, itemsPending), setTermination, readExit);
249
250    // ... set the termination signal.
251    b->SetInsertPoint(setTermination);
252    Value * const bytesToZero = b->CreateMul(b->CreateSub(itemsPending, itemsBuffered), codeUnitBytes);
253    b->CreateMemZero(b->getRawOutputPointer("sourceBuffer", itemsBuffered), bytesToZero);
254    b->setTerminationSignal();
255    b->CreateBr(readExit);
256
257    readExit->moveAfter(setTermination);
258    b->SetInsertPoint(readExit);
259    PHINode * const itemsProduced = b->CreatePHI(itemsPending->getType(), 3);
260    itemsProduced->addIncoming(itemsPending, entry);
261    itemsProduced->addIncoming(itemsPending, readData);
262    itemsProduced->addIncoming(itemsBuffered, setTermination);
263    b->setProducedItemCount("sourceBuffer", itemsProduced);
264}
265
266void ReadSourceKernel::freeBuffer(const std::unique_ptr<KernelBuilder> & b) {
267    b->CreateFree(b->getScalarField("buffer"));
268}
269
270/// Hybrid MMap/Read source kernel
271
272void FDSourceKernel::linkExternalMethods(const std::unique_ptr<kernel::KernelBuilder> & b) {
273    mFileSizeFunction = MMapSourceKernel::linkFileSizeMethod(b);
274}
275
276void FDSourceKernel::generateFinalizeMethod(const std::unique_ptr<KernelBuilder> & b) {
277    BasicBlock * finalizeRead = b->CreateBasicBlock("finalizeRead");
278    BasicBlock * finalizeMMap = b->CreateBasicBlock("finalizeMMap");
279    BasicBlock * finalizeDone = b->CreateBasicBlock("finalizeDone");
280    b->CreateCondBr(b->CreateTrunc(b->getScalarField("useMMap"), b->getInt1Ty()), finalizeMMap, finalizeRead);
281    b->SetInsertPoint(finalizeMMap);
282    MMapSourceKernel::freeBuffer(b);
283    b->CreateBr(finalizeDone);
284    b->SetInsertPoint(finalizeRead);
285    ReadSourceKernel::freeBuffer(b);
286    b->CreateBr(finalizeDone);
287    b->SetInsertPoint(finalizeDone);
288}
289
290void FDSourceKernel::generateInitializeMethod(const std::unique_ptr<KernelBuilder> & b) {
291    BasicBlock * initializeRead = b->CreateBasicBlock("initializeRead");
292    BasicBlock * tryMMap = b->CreateBasicBlock("tryMMap");
293    BasicBlock * initializeMMap = b->CreateBasicBlock("initializeMMap");
294    BasicBlock * initializeDone = b->CreateBasicBlock("initializeDone");
295
296    // The source will use MMapSource or readSoure kernel logic depending on the useMMap
297    // parameter, possibly overridden.
298    Value * useMMap = b->CreateTrunc(b->getScalarField("useMMap"), b->getInt1Ty());
299    // if the fileDescriptor is 0, the file is stdin, use readSource kernel logic.
300    Value * fd = b->getScalarField("fileDescriptor");
301    useMMap = b->CreateAnd(useMMap, b->CreateICmpNE(fd, b->getInt32(STDIN_FILENO)));
302    b->CreateCondBr(useMMap, tryMMap, initializeRead);
303
304    b->SetInsertPoint(tryMMap);
305    // If the fileSize is 0, we may have a virtual file such as /proc/cpuinfo
306    Value * fileSize = b->CreateZExtOrTrunc(b->CreateCall(mFileSizeFunction, fd), b->getSizeTy());
307    useMMap = b->CreateICmpNE(fileSize, b->getSize(0));
308    b->CreateCondBr(useMMap, initializeMMap, initializeRead);
309    b->SetInsertPoint(initializeMMap);
310    MMapSourceKernel::generateInitializeMethod(mFileSizeFunction, mCodeUnitWidth, b);
311    b->CreateBr(initializeDone);
312
313    b->SetInsertPoint(initializeRead);
314    // Ensure that readSource logic is used throughout.
315    b->setScalarField("useMMap", b->getInt8(0));
316    ReadSourceKernel::generateInitializeMethod(mCodeUnitWidth, getStride(), b);
317    b->CreateBr(initializeDone);
318    b->SetInsertPoint(initializeDone);
319}
320
321void FDSourceKernel::generateDoSegmentMethod(const std::unique_ptr<KernelBuilder> & b) {
322    BasicBlock * DoSegmentRead = b->CreateBasicBlock("DoSegmentRead");
323    BasicBlock * DoSegmentMMap = b->CreateBasicBlock("DoSegmentMMap");
324    BasicBlock * DoSegmentDone = b->CreateBasicBlock("DoSegmentDone");
325    b->CreateCondBr(b->CreateTrunc(b->getScalarField("useMMap"), b->getInt1Ty()), DoSegmentMMap, DoSegmentRead);
326    b->SetInsertPoint(DoSegmentMMap);
327    MMapSourceKernel::generateDoSegmentMethod(mCodeUnitWidth, b);
328    b->CreateBr(DoSegmentDone);
329    b->SetInsertPoint(DoSegmentRead);
330    ReadSourceKernel::generateDoSegmentMethod(mCodeUnitWidth, getStride(), b);
331    b->CreateBr(DoSegmentDone);
332    b->SetInsertPoint(DoSegmentDone);
333}
334
335/// MEMORY SOURCE KERNEL
336
337void MemorySourceKernel::generateInitializeMethod(const std::unique_ptr<KernelBuilder> & b) {
338    Value * const fileSource = b->getScalarField("fileSource");
339    b->setBaseAddress("sourceBuffer", fileSource);
340    Value * const fileSize = b->getScalarField("fileSize");
341    b->setBufferedSize("sourceBuffer", fileSize);
342    b->setCapacity("sourceBuffer", fileSize);
343    if (mStreamSetCount > 1) {
344        b->setProducedItemCount("sourceBuffer", fileSize);
345        b->setTerminationSignal();
346    }
347}
348
349void MemorySourceKernel::generateDoSegmentMethod(const std::unique_ptr<KernelBuilder> & b) {
350    if (mStreamSetCount == 1) {
351        Constant * const PAGE_SIZE = b->getSize(getStride());
352        Constant * const BLOCK_WIDTH = b->getSize(b->getBitBlockWidth());
353
354        BasicBlock * const entry = b->GetInsertBlock();
355        BasicBlock * const createTemporary = b->CreateBasicBlock("createTemporary");
356        BasicBlock * const exit = b->CreateBasicBlock("exit");
357
358        Value * const fileItems = b->getScalarField("fileSize");
359        Value * const producedItems = b->getProducedItemCount("sourceBuffer");
360        Value * const nextProducedItems = b->CreateAdd(producedItems, PAGE_SIZE);
361        Value * const lastPage = b->CreateICmpULE(fileItems, nextProducedItems);
362        b->CreateUnlikelyCondBr(lastPage, createTemporary, exit);
363
364        b->SetInsertPoint(createTemporary);
365        Value * const consumedItems = b->getConsumedItemCount("sourceBuffer");
366        Value * const consumedOffset = b->CreateAnd(consumedItems, ConstantExpr::getNeg(BLOCK_WIDTH));
367        Value * const readStart = b->getRawOutputPointer("sourceBuffer", consumedOffset);
368        Value * const readEnd = b->getRawOutputPointer("sourceBuffer", fileItems);
369        Value * const unconsumedBytes = b->CreateTrunc(b->CreatePtrDiff(readEnd, readStart), b->getSizeTy());
370        Value * const bufferSize = b->CreateRoundUp(b->CreateAdd(unconsumedBytes, BLOCK_WIDTH), PAGE_SIZE);
371        Value * const buffer = b->CreateAlignedMalloc(bufferSize, b->getCacheAlignment());
372        b->CreateMemCpy(buffer, readStart, unconsumedBytes, 1);
373        b->CreateMemZero(b->CreateGEP(buffer, unconsumedBytes), b->CreateSub(bufferSize, unconsumedBytes), 1);
374
375        // get the difference between our base and from position then compute an offsetted temporary buffer address
376        Value * const base = b->getBaseAddress("sourceBuffer");
377        Value * const diff = b->CreatePtrDiff(b->CreatePointerCast(base, readStart->getType()), readStart);
378        Value * const offsettedBuffer = b->CreateGEP(buffer, diff);
379        b->CreateConsumerWait();
380
381        // set the temporary buffer as the new source buffer
382        PointerType * const codeUnitPtrTy = b->getIntNTy(mCodeUnitWidth)->getPointerTo();
383        b->setScalarField("buffer", b->CreatePointerCast(buffer, codeUnitPtrTy));
384        b->setBaseAddress("sourceBuffer", b->CreatePointerCast(offsettedBuffer, codeUnitPtrTy));
385        b->setTerminationSignal();
386        BasicBlock * const terminationExit = b->GetInsertBlock();
387        b->CreateBr(exit);
388
389        b->SetInsertPoint(exit);
390        PHINode * const newProducedItems = b->CreatePHI(b->getSizeTy(), 2);
391        newProducedItems->addIncoming(nextProducedItems, entry);
392        newProducedItems->addIncoming(fileItems, terminationExit);
393        b->setProducedItemCount("sourceBuffer", newProducedItems);
394    }
395}
396
397void MemorySourceKernel::generateFinalizeMethod(const std::unique_ptr<KernelBuilder> & b) {
398    if (mStreamSetCount == 1) {
399        b->CreateFree(b->getScalarField("buffer"));
400    }
401}
402
403MMapSourceKernel::MMapSourceKernel(const std::unique_ptr<kernel::KernelBuilder> & b, const unsigned codeUnitWidth)
404: SegmentOrientedKernel("mmap_source@" + std::to_string(codeUnitWidth)
405, {}
406, {Binding{b->getStreamSetTy(1, codeUnitWidth), "sourceBuffer"}}
407, {Binding{b->getInt32Ty(), "fileDescriptor"}}
408, {Binding{b->getSizeTy(), "fileSize"}}
409, {Binding{b->getIntNTy(codeUnitWidth)->getPointerTo(), "buffer"}})
410, mCodeUnitWidth(codeUnitWidth)
411, mFileSizeFunction(nullptr) {
412    addAttribute(MustExplicitlyTerminate());
413    setStride(getpagesize());
414}
415
416ReadSourceKernel::ReadSourceKernel(const std::unique_ptr<kernel::KernelBuilder> & b, const unsigned codeUnitWidth)
417: SegmentOrientedKernel("read_source" + std::to_string(codegen::SegmentSize) + "@" + std::to_string(codeUnitWidth)
418, {}
419, {Binding{b->getStreamSetTy(1, codeUnitWidth), "sourceBuffer"}}
420, {Binding{b->getInt32Ty(), "fileDescriptor"}}
421, {}
422, {Binding{b->getIntNTy(codeUnitWidth)->getPointerTo(), "buffer"}})
423, mCodeUnitWidth(codeUnitWidth) {
424    addAttribute(MustExplicitlyTerminate());
425    setStride(getpagesize());
426}
427
428
429FDSourceKernel::FDSourceKernel(const std::unique_ptr<kernel::KernelBuilder> & b, const unsigned codeUnitWidth)
430: SegmentOrientedKernel("FD_source@" + std::to_string(codeUnitWidth)
431, {}
432// output stream
433, {Binding{b->getStreamSetTy(1, codeUnitWidth), "sourceBuffer"}}
434// input scalar
435, {Binding{b->getInt8Ty(), "useMMap"}, Binding{b->getInt32Ty(), "fileDescriptor"}}
436, {}
437// internal scalar
438, {Binding{b->getIntNTy(codeUnitWidth)->getPointerTo(), "buffer"}, Binding{b->getSizeTy(), "fileSize"}})
439, mCodeUnitWidth(codeUnitWidth)
440, mFileSizeFunction(nullptr) {
441    addAttribute(MustExplicitlyTerminate());
442    setStride(getpagesize());
443}
444
445MemorySourceKernel::MemorySourceKernel(const std::unique_ptr<kernel::KernelBuilder> & b, const unsigned streamSetCount, const unsigned codeUnitWidth)
446: SegmentOrientedKernel("memory_source@" + std::to_string(streamSetCount) + ":" + std::to_string(codeUnitWidth),
447{},
448// output stream
449{Binding{b->getStreamSetTy(streamSetCount, codeUnitWidth), "sourceBuffer"}},
450// input scalar
451{Binding{b->getIntNTy(codeUnitWidth)->getPointerTo(), "fileSource"}, Binding{b->getSizeTy(), "fileSize"}},
452{},
453// internal scalar
454{Binding{b->getIntNTy(codeUnitWidth)->getPointerTo(), "buffer"}})
455, mStreamSetCount(streamSetCount)
456, mCodeUnitWidth(codeUnitWidth) {
457    addAttribute(MustExplicitlyTerminate());
458    setStride(getpagesize());
459}
460
461}
Note: See TracBrowser for help on using the repository browser.