roadrunner  2.6.0
Fast simulator for SBML models
SetValueCodeGenBase.h
1 /*
2  *
3  * Created on: Sept 16, 2013
4  * Author: andy
5  */
6 
7 #ifndef RRLLVMSETVALUECODEGENBASE_H_
8 #define RRLLVMSETVALUECODEGENBASE_H_
9 
10 #include "CodeGenBase.h"
11 #include "ModelGeneratorContext.h"
12 #include "SymbolForest.h"
13 #include "ASTNodeFactory.h"
14 #include "ModelDataIRBuilder.h"
15 #include "ModelDataSymbolResolver.h"
16 #include "LLVMException.h"
17 #include "rrLogger.h"
18 #include <sbml/Model.h>
19 #include <Poco/Logger.h>
20 #include <vector>
21 
22 namespace rrllvm
23 {
24 
25  typedef bool (*SetValueCodeGenBase_FunctionPtr)(LLVMModelData*, int32_t, double);
26 
31  template <typename Derived, bool substanceUnits>
33  public CodeGenBase<SetValueCodeGenBase_FunctionPtr>
34  {
35  public:
37  virtual ~SetValueCodeGenBase();
38 
39  llvm::Value* codeGen();
40 
41  typedef SetValueCodeGenBase_FunctionPtr FunctionPtr;
42  };
43 
44  template <typename Derived, bool substanceUnits>
46  const ModelGeneratorContext& mgc) :
47  CodeGenBase<SetValueCodeGenBase_FunctionPtr>(mgc)
48  {
49  }
50 
51  template <typename Derived, bool substanceUnits>
52  SetValueCodeGenBase<Derived, substanceUnits>::~SetValueCodeGenBase()
53  {
54  }
55 
56  template <typename Derived, bool substanceUnits>
57  llvm::Value* SetValueCodeGenBase<Derived, substanceUnits>::codeGen()
58  {
59  // make the set init value function
60  llvm::Type* argTypes[] = {
61  llvm::PointerType::get(ModelDataIRBuilder::getStructType(this->module), 0),
62  llvm::Type::getInt32Ty(this->context),
63  llvm::Type::getDoubleTy(this->context)
64  };
65 
66  const char* argNames[] = {
67  "modelData", Derived::IndexArgName, "value"
68  };
69 
70  llvm::Value* args[] = { 0, 0, 0 };
71 
72  llvm::BasicBlock* entry = this->codeGenHeader(Derived::FunctionName, llvm::Type::getInt8Ty(this->context),
73  argTypes, argNames, args);
74 
75  StringIntVector ids = static_cast<Derived*>(this)->getIds();
76 
77  ModelDataLoadSymbolResolver loadResolver(args[0], this->modelGenContext);
78 
79  ModelDataStoreSymbolResolver storeResolver(args[0], this->model, this->modelSymbols,
80  this->dataSymbols, this->builder, loadResolver);
81 
82  // default, return false
83  llvm::BasicBlock* def = llvm::BasicBlock::Create(this->context, "default", this->function);
84  this->builder.SetInsertPoint(def);
85 
86  // false (0) retval
87  this->builder.CreateRet(llvm::ConstantInt::get(llvm::Type::getInt8Ty(this->context), 0));
88 
89  // write the switch at the func entry point, the switch is also the
90  // entry block terminator
91  this->builder.SetInsertPoint(entry);
92 
93  llvm::SwitchInst* s = this->builder.CreateSwitch(args[1], def, static_cast<unsigned int>(ids.size()));
94 
95  for (int i = 0; i < ids.size(); ++i)
96  {
97  llvm::BasicBlock* block = llvm::BasicBlock::Create(this->context, ids[i].first + "_block", this->function);
98  this->builder.SetInsertPoint(block);
99  loadResolver.flushCache();
100 
101  // the value we are attempting to store, make a copy in loop scope
102  // because we can modify the copy.
103  llvm::Value* value = args[2];
104 
105  // need to check if we have an amount or concentration and check if we
106  // are asked for asked for an amount or concentration and convert accordingly
107  const libsbml::SBase* sbase = const_cast<libsbml::Model*>(model)->getElementBySId(ids[i].first);
108  if (sbase && sbase->getTypeCode() == libsbml::SBML_SPECIES)
109  {
110  const libsbml::Species* species = static_cast<const libsbml::Species*>(sbase);
111  if (species->getHasOnlySubstanceUnits())
112  {
113  // species is treated as an amount
114  if (!substanceUnits)
115  {
116  // given a conc, convert to amount
117  llvm::Value* comp = loadResolver.loadSymbolValue(species->getCompartment());
118  value = this->builder.CreateFMul(value, comp, ids[i].first + "_amt");
119  }
120  }
121  else
122  {
123  // species is treated as a concentration
124  if (substanceUnits)
125  {
126  // given an amount, need to convert to conc
127  llvm::Value* comp = loadResolver.loadSymbolValue(species->getCompartment());
128  value = this->builder.CreateFDiv(value, comp, ids[i].first + "_value_conc");
129  }
130  }
131  }
132 
133  // load after we've figured the species bits out
134  storeResolver.storeSymbolValue(ids[i].first, value);
135 
136  // true retval
137  this->builder.CreateRet(llvm::ConstantInt::get(llvm::Type::getInt8Ty(this->context), 1));
138  s->addCase(llvm::ConstantInt::get(llvm::Type::getInt32Ty(this->context), ids[i].second), block);
139  }
140 
141  return this->verifyFunction();
142  }
143 
144 
145 } /* namespace rrllvm */
146 #endif /* RRLLVMSETVALUECODEGENBASE_H_ */
a convenience class to pull the vars out of a context, and store them as ivars.
Definition: CodeGenBase.h:54
static llvm::StructType * getStructType(llvm::Module *module)
get the ModelData struct type.
Definition: ModelDataIRBuilder.cpp:731
All LLVM code generating objects basically need at a minimum three things to operate:
Definition: ModelGeneratorContext.h:95
base class for setting values.
Definition: SetValueCodeGenBase.h:34