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

Last change on this file since 6025 was 6025, checked in by nmedfort, 5 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.