roadrunner  2.6.0
Fast simulator for SBML models
GetInitialValueCodeGenBase.h
1 /*
2  *
3  * Created on: Jul 29, 2013
4  * Author: andy
5  */
6 
7 #ifndef RRLLVM_GETINITIALVALUECODEGENBASE_H_
8 #define RRLLVM_GETINITIALVALUECODEGENBASE_H_
9 
10 #include "CodeGenBase.h"
11 #include "ModelGeneratorContext.h"
12 #include "SymbolForest.h"
13 #include "ASTNodeFactory.h"
14 #include "ModelDataIRBuilder.h"
15 #include "ModelInitialValueSymbolResolver.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 double (*GetInitialValueCodeGenBase_FunctionPtr)(LLVMModelData*, size_t);
26 
30  template <typename Derived, bool substanceUnits>
32  public CodeGenBase<GetInitialValueCodeGenBase_FunctionPtr>
33  {
34  public:
36  virtual ~GetInitialValueCodeGenBase();
37 
38  llvm::Value* codeGen();
39 
40  typedef GetInitialValueCodeGenBase_FunctionPtr FunctionPtr;
41 
42  };
43 
44  template <typename Derived, bool substanceUnits>
46  const ModelGeneratorContext& mgc) :
47  CodeGenBase<GetInitialValueCodeGenBase_FunctionPtr>(mgc)
48  {
49  }
50 
51  template <typename Derived, bool substanceUnits>
52  GetInitialValueCodeGenBase<Derived, substanceUnits>::~GetInitialValueCodeGenBase()
53  {
54  }
55 
56  template <typename Derived, bool substanceUnits>
57  llvm::Value* GetInitialValueCodeGenBase<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  };
64 
65  const char* argNames[] = {
66  "modelData", Derived::IndexArgName
67  };
68 
69  llvm::Value* args[] = { 0, 0 };
70 
71  llvm::BasicBlock* entry = this->codeGenHeader(Derived::FunctionName, llvm::Type::getDoubleTy(this->context),
72  argTypes, argNames, args);
73 
74  std::vector<std::string> ids = static_cast<Derived*>(this)->getIds();
75 
76  ModelInitialValueSymbolResolver resolver(args[0], this->modelGenContext);
77 
78  // default, return NaN
79  llvm::BasicBlock* def = llvm::BasicBlock::Create(this->context, "default", this->function);
80  this->builder.SetInsertPoint(def);
81 
82  this->builder.CreateRet(llvm::ConstantFP::get(this->context,
83  llvm::APFloat::getQNaN(llvm::APFloat::IEEEdouble())));
84 
85  // write the switch at the func entry point, the switch is also the
86  // entry block terminator
87  this->builder.SetInsertPoint(entry);
88 
89  llvm::SwitchInst* s = this->builder.CreateSwitch(args[1], def, static_cast<unsigned int>(ids.size()));
90 
91  for (int i = 0; i < ids.size(); ++i)
92  {
93  llvm::BasicBlock* block = llvm::BasicBlock::Create(this->context, ids[i] + "_block", this->function);
94  this->builder.SetInsertPoint(block);
95 
96  // the requested value
97  llvm::Value* value = resolver.loadSymbolValue(ids[i]);
98 
99  // need to check if we have an amount or concentration and check if we
100  // are asked for asked for an amount or concentration and convert accordingly
101  const libsbml::SBase* sbase = const_cast<libsbml::Model*>(model)->getElementBySId(ids[i]);
102  if (sbase && sbase->getTypeCode() == libsbml::SBML_SPECIES)
103  {
104  const libsbml::Species* species = static_cast<const libsbml::Species*>(sbase);
105  if (species->getHasOnlySubstanceUnits())
106  {
107  value->setName(ids[i] + "_amt");
108  // species is treated as an amount
109  if (!substanceUnits)
110  {
111  // convert to concentration
112  llvm::Value* comp = resolver.loadSymbolValue(species->getCompartment());
113  value = this->builder.CreateFDiv(value, comp, ids[i] + "_conc");
114  }
115  }
116  else
117  {
118  value->setName(ids[i] + "_conc");
119  // species is treated as a concentration
120  if (substanceUnits)
121  {
122  // convert to amount
123  llvm::Value* comp = resolver.loadSymbolValue(species->getCompartment());
124  value = this->builder.CreateFMul(value, comp, ids[i] + "_amt");
125  }
126  }
127  }
128  else
129  {
130  value->setName(ids[i] + "_value");
131  }
132  this->builder.CreateRet(value);
133  s->addCase(llvm::ConstantInt::get(llvm::Type::getInt32Ty(this->context), i), block);
134  }
135 
136  return this->verifyFunction();
137  }
138 
139 
140 } /* namespace rr */
141 
142 
143 
144 
145 #endif /* RRLLVM_GETINITIALVALUECODEGENBASE_H_ */
a convenience class to pull the vars out of a context, and store them as ivars.
Definition: CodeGenBase.h:54
Base class for getting the initial value of an element.
Definition: GetInitialValueCodeGenBase.h:33
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