source: icGREP/icgrep-devel/icgrep/kernels/interface.cpp @ 5257

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

finalSegment kernel methods initial check-in

File size: 7.2 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
6#include "interface.h"
7#include <llvm/IR/Module.h>
8#include <llvm/IR/Type.h>
9#include <llvm/IR/Value.h>
10#include <llvm/Support/raw_ostream.h>
11
12using namespace llvm;
13using namespace parabix;
14
15void KernelInterface::addKernelDeclarations(Module * client) {
16    Module * saveModule = iBuilder->getModule();
17    auto savePoint = iBuilder->saveIP();
18    iBuilder->setModule(client);
19    if (mKernelStateType == nullptr) {
20        throw std::runtime_error("Kernel interface " + mKernelName + " not yet finalized.");
21    }
22    Type * selfType = PointerType::getUnqual(mKernelStateType);
23
24    // Create the accumulator get function prototypes
25    for (auto binding : mScalarOutputs) {
26        FunctionType * accumFnType = FunctionType::get(binding.type, {selfType}, false);
27        std::string fnName = mKernelName + accumulator_infix + binding.name;
28        Function * accumFn = Function::Create(accumFnType, GlobalValue::ExternalLinkage, fnName, client);
29        accumFn->setCallingConv(CallingConv::C);
30        accumFn->setDoesNotThrow();
31        Value * self = &*(accumFn->arg_begin());
32        self->setName("self");       
33    }
34
35    // Create the initialization function prototype
36    std::vector<Type *> initParameters = {selfType};
37    for (auto binding : mScalarInputs) {
38        initParameters.push_back(binding.type);
39    }
40    FunctionType * initFunctionType = FunctionType::get(iBuilder->getVoidTy(), initParameters, false);
41    std::string initFnName = mKernelName + init_suffix;
42    Function * initFn = Function::Create(initFunctionType, GlobalValue::ExternalLinkage, initFnName, client);
43    initFn->setCallingConv(CallingConv::C);
44    initFn->setDoesNotThrow();
45    Function::arg_iterator initArgs = initFn->arg_begin();
46    Value * initArg = &*(initArgs++);
47    initArg->setName("self");
48    for (auto binding : mScalarInputs) {
49        initArg = &*(initArgs++);
50        initArg->setName(binding.name);
51    }
52
53    // Create the doBlock and finalBlock function prototypes
54   
55    std::vector<Type *> doBlockParameters = {selfType};
56    std::vector<Type *> finalBlockParameters = {selfType, iBuilder->getSizeTy()};
57    FunctionType * doBlockFunctionType = FunctionType::get(iBuilder->getVoidTy(), doBlockParameters, false);
58    std::string doBlockName = mKernelName + doBlock_suffix;
59    Function * doBlockFn = Function::Create(doBlockFunctionType, GlobalValue::ExternalLinkage, doBlockName, client);
60    doBlockFn->setCallingConv(CallingConv::C);
61    doBlockFn->setDoesNotThrow();
62    doBlockFn->setDoesNotCapture(1);
63   
64    FunctionType * finalBlockType = FunctionType::get(iBuilder->getVoidTy(), finalBlockParameters, false);
65    std::string finalBlockName = mKernelName + finalBlock_suffix;
66    Function * finalBlockFn = Function::Create(finalBlockType, GlobalValue::ExternalLinkage, finalBlockName, client);
67    finalBlockFn->setCallingConv(CallingConv::C);
68    finalBlockFn->setDoesNotThrow();
69    finalBlockFn->setDoesNotCapture(1);
70   
71    Function::arg_iterator doBlockArgs = doBlockFn->arg_begin();
72    Function::arg_iterator finalBlockArgs = finalBlockFn->arg_begin();
73    Value * doBlockArg = &*(doBlockArgs++);
74    doBlockArg->setName("self");
75    Value * finalBlockArg = &*(finalBlockArgs++);
76    finalBlockArg->setName("self");
77    finalBlockArg = &*(finalBlockArgs++);
78    finalBlockArg->setName("remainingBytes");
79
80    // Create the doSegment function prototype.
81    std::vector<Type *> doSegmentParameters = {selfType, iBuilder->getSizeTy()};
82    FunctionType * doSegmentFunctionType = FunctionType::get(iBuilder->getVoidTy(), doSegmentParameters, false);
83    std::string doSegmentName = mKernelName + doSegment_suffix;
84    Function * doSegmentFn = Function::Create(doSegmentFunctionType, GlobalValue::ExternalLinkage, doSegmentName, client);
85    doSegmentFn->setCallingConv(CallingConv::C);
86    doSegmentFn->setDoesNotThrow();
87    Function::arg_iterator args = doSegmentFn->arg_begin();
88    Value * arg = &*(args++);
89    arg->setName("self");
90    arg = &*(args++);
91    arg->setName("blockCnt");
92    doSegmentFn->setDoesNotCapture(1); // for self parameter only.
93    //
94    // Create the finalSegment function prototype.
95    std::vector<Type *> finalSegmentParameters = {selfType, iBuilder->getSizeTy()};
96    FunctionType * finalSegmentFunctionType = FunctionType::get(iBuilder->getVoidTy(), finalSegmentParameters, false);
97    std::string finalSegmentName = mKernelName + finalSegment_suffix;
98    Function * finalSegmentFn = Function::Create(finalSegmentFunctionType, GlobalValue::ExternalLinkage, finalSegmentName, client);
99    finalSegmentFn->setCallingConv(CallingConv::C);
100    finalSegmentFn->setDoesNotThrow();
101    Function::arg_iterator finalSegmentArgs = finalSegmentFn->arg_begin();
102    Value * finalSegmentArg = &*(finalSegmentArgs++);
103    finalSegmentArg->setName("self");
104    finalSegmentArg = &*(finalSegmentArgs++);
105    finalSegmentArg->setName("blockCnt");
106    finalSegmentFn->setDoesNotCapture(1); // for self parameter only.
107    iBuilder->setModule(saveModule);
108    iBuilder->restoreIP(savePoint);
109}
110
111void KernelInterface::setInitialArguments(std::vector<Value *> args) {
112    mInitialArguments = args;
113}
114
115Value * KernelInterface::createDoBlockCall(Value * self) const {
116    Module * m = iBuilder->getModule();
117    std::string doBlockName = mKernelName + doBlock_suffix;
118    Function * doBlockMethod = m->getFunction(doBlockName);
119    if (!doBlockMethod) {
120        throw std::runtime_error("Cannot find " + doBlockName);
121    }
122    std::vector<Value *> args = {self};
123    return iBuilder->CreateCall(doBlockMethod, args);
124}
125
126Value * KernelInterface::createFinalBlockCall(Value * self, Value * remainingBytes) const {
127    Module * m = iBuilder->getModule();
128    std::string finalBlockName = mKernelName + finalBlock_suffix;
129    Function * finalBlockMethod = m->getFunction(finalBlockName);
130    if (!finalBlockMethod) {
131        throw std::runtime_error("Cannot find " + finalBlockName);
132    }
133    std::vector<Value *> args = {self, remainingBytes};
134    return iBuilder->CreateCall(finalBlockMethod, args);
135}
136
137
138Value * KernelInterface::createDoSegmentCall(Value * self, Value * blksToDo) const {
139    Module * m = iBuilder->getModule();
140    std::string fnName = mKernelName + doSegment_suffix;
141    Function * method = m->getFunction(fnName);
142    if (!method) {
143        throw std::runtime_error("Cannot find " + fnName);
144    }
145    return iBuilder->CreateCall(method, {self, blksToDo});
146}
147
148Value * KernelInterface::createFinalSegmentCall(Value * self, Value * blksToDo) const {
149    Module * m = iBuilder->getModule();
150    std::string fnName = mKernelName + finalSegment_suffix;
151    Function * method = m->getFunction(fnName);
152    if (!method) {
153        throw std::runtime_error("Cannot find " + fnName);
154    }
155    return iBuilder->CreateCall(method, {self, blksToDo});
156}
157
158Value * KernelInterface::createGetAccumulatorCall(Value * self, std::string accumName) const {
159    Module * m = iBuilder->getModule();
160    std::string fnName = mKernelName + accumulator_infix + accumName;
161    Function * accumMethod = m->getFunction(fnName);
162    if (!accumMethod) {
163        throw std::runtime_error("Cannot find " + fnName);
164    }
165    return iBuilder->CreateCall(accumMethod, {self});
166}
167
168
Note: See TracBrowser for help on using the repository browser.