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

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

New doSegment partial progress

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