llvm::Value* ModelDataLoadSymbolResolver::loadSymbolValue(
        const std::string& symbol,
        const llvm::ArrayRef<llvm::Value*>& args)
{
    ModelDataIRBuilder mdbuilder(modelData, modelDataSymbols,
            builder);

    /*************************************************************************/
    /* time */
    /*************************************************************************/
    if (symbol.compare(SBML_TIME_SYMBOL) == 0)
    {
        Value *timeEP = mdbuilder.createGEP(Time);
        Value *time = builder.CreateLoad(timeEP, SBML_TIME_SYMBOL);
        return time;
    }

    /*************************************************************************/
    /* Function */
    /*************************************************************************/
    {
        Value *funcVal =
            FunctionResolver(*this, model, builder).loadSymbolValue(symbol, args);
        if (funcVal)
        {
            return funcVal;
        }
    }

    /*************************************************************************/
    /* AssignmentRule */
    /*************************************************************************/
    {
        SymbolForest::ConstIterator i = modelSymbols.getAssigmentRules().find(
                symbol);
        if (i != modelSymbols.getAssigmentRules().end())
        {
            recursiveSymbolPush(symbol);
            Value* result = ASTNodeCodeGen(builder, *this).codeGen(i->second);
            recursiveSymbolPop();
            return result;
        }
    }

    /*************************************************************************/
    /* Species */
    /*************************************************************************/
    const Species *species = model->getSpecies(symbol);
    if (species)
    {
        Value *amt = 0;
        if (modelDataSymbols.isIndependentFloatingSpecies(symbol))
        {
            amt = mdbuilder.createFloatSpeciesAmtLoad(symbol, symbol + "_amt");
        }
        else if (modelDataSymbols.isIndependentBoundarySpecies(symbol))
        {
            amt = mdbuilder.createBoundSpeciesAmtLoad(symbol, symbol + "_amt");
        }
        else if(modelDataSymbols.hasRateRule(symbol))
        {
            amt = mdbuilder.createRateRuleValueLoad(symbol, symbol + "_amt");
        }
        else
        {
            string msg = string("the symbol ") + symbol + string(" appeared to "
                    "be a species, but it could not be found as an independent "
                    "species or rate rule");
            throw_llvm_exception(msg);
        }
        assert(amt);

        // now we have an amount, check to see if we need to convert to conc
        if (species->getHasOnlySubstanceUnits())
        {
            return amt;
        }
        else
        {
            // expect a concentration, need to convert amt to conc,
            // so we need to get the compartment its in, but these
            // can vary also...
            Value *comp = loadSymbolValue(species->getCompartment());
            return builder.CreateFDiv(amt, comp, symbol + "_conc");
        }
    }

    if (modelDataSymbols.isIndependentCompartment(symbol))
    {
        return mdbuilder.createCompLoad(symbol);
    }

    if (modelDataSymbols.isIndependentGlobalParameter(symbol))
    {
        return mdbuilder.createGlobalParamLoad(symbol);
    }

    if (modelDataSymbols.hasRateRule(symbol))
    {
        // species conc / amt has already been taken care of at this point
        return mdbuilder.createRateRuleValueLoad(symbol);
    }

    if (modelDataSymbols.isNamedSpeciesReference(symbol))
    {
        const LLVMModelDataSymbols::SpeciesReferenceInfo &info =
                modelDataSymbols.getNamedSpeciesReferenceInfo(symbol);

        Value *value = mdbuilder.createStoichiometryLoad(info.row, info.column, symbol);

        if (info.type == LLVMModelDataSymbols::MultiReactantProduct)
        {
            string msg = "mutable stochiometry for species which appear "
                    "multiple times in a single reaction is not currently "
                    "supported, species reference id: ";
            msg += symbol;
            throw_llvm_exception(msg);
        }

        if (info.type == LLVMModelDataSymbols::Reactant)
        {
            // its consumed in the reaction, so has a negative in the stoich
            // matrix
            Value *negOne = ConstantFP::get(builder.getContext(), APFloat(-1.0));
            negOne->setName("neg_one");
            value = builder.CreateFMul(negOne, value, "neg_" + symbol);
        }

        return value;
    }

    /*************************************************************************/
    /* Reaction Rate */
    /*************************************************************************/
    const Reaction* reaction = model->getReaction(symbol);
    if (reaction)
    {
        return loadReactionRate(reaction);
    }


    string msg = "the symbol \'";
    msg += symbol;
    msg += "\' is not physically stored in the ModelData structure, "
            "it either does not exists or is defined by an assigment rule (hence it "
            "is not a terminal symbol)";

    throw_llvm_exception(msg);
    return 0;
}
Esempio n. 2
0
int SSPParser::getNextToken(void *Val) {
  YYSTYPE *Value = static_cast<YYSTYPE*>(Val);

  StringRef    BufferData = Buf->getBuffer();
  const char  *Data       = BufferData.data();
  const char*  CurCh      = Data+CurPos;

  while (CurPos < BufferData.size()                         &&
         (*CurCh == '\t' || *CurCh == ' ' || *CurCh == '\r' ||
          *CurCh == '\n')) {
    CurPos++;
    CurCh         = Data+CurPos;
  }
  
  if (CurPos >= BufferData.size())
    return 0;                   // EOF

  if (*CurCh == '+') {
    CurPos++;
    return PLUS;
  } else if (*CurCh == '-') {
    CurPos++;
    return MINUS;
  } else if (*CurCh == '*') {
    CurPos++;
    return ASTERISK;
  } else if (*CurCh == '/') {
    CurPos++;
    return SLASH;
  } else if (*CurCh == '$') {
    CurPos++;
    return DOLLAR;
  } else if (*CurCh == '@') {
    CurPos++;
    return AT;
  } else if (IsAlpha(*CurCh)) {
    const char *Start  = CurCh;
    size_t      Length = 0;
    
    do {
      Length++;
      CurPos++;
      CurCh = Data+CurPos;

    } while (CurPos < BufferData.size() && (IsAlphaOrDigit(*CurCh) || *CurCh == '_'));

    StringRef *Str = new StringRef(Start, Length);

    // Check for keywords
    if (Str->compare("double")   == 0) {
      return DOUBLE;
    } else if (Str->compare("field")    == 0) {
      return FIELD;
    } else if (Str->compare("float")    == 0) {
      return FLOAT;
    } else if (Str->compare("grid")     == 0) {
      return GRID;
    } else if (Str->compare("in")       == 0) {
      return IN;
    } else if (Str->compare("inout")    == 0) {
      return INOUT;
    } else if (Str->compare("is")       == 0) {
      return IS;
    } else if (Str->compare("let")      == 0) {
      return LET;
    } else if (Str->compare("out")      == 0) {
      return OUT;
    } else if (Str->compare("param")    == 0) {
      return PARAM;
    } else if (Str->compare("program")  == 0) {
      return PROGRAM;
    }

    // Not a keyword
    InternedStrings.push_back(Str);
    Value->Ident        = Str;
    return IDENT;
  } else if (IsDigit(*CurCh)) {
    const char *Start   = CurCh;
    size_t      Length  = 0;
    bool        IsFloat = false;
      
    do {
      if (*CurCh == '.') IsFloat = true;
      
      Length++;
      CurPos++;
      CurCh = Data+CurPos;
      
    } while (CurPos < BufferData.size() && (IsDigit(*CurCh) || *CurCh == '.'));

    if (CurPos < BufferData.size() && (*CurCh == 'e' || *CurCh == 'E')) {
      // Start of an exponent

      IsFloat = true;
      
      CurPos++;
      CurCh = Data+CurPos;
      Length++;
      
      if (CurPos == BufferData.size() || (!IsDigit(*CurCh) && *CurCh != '-')) {
        SrcMgr.PrintMessage(SMLoc::getFromPointer(Data+CurPos),
                            SourceMgr::DK_Error, "Missing exponent");
        return 0;
      }

      if (*CurCh == '-') {
        Length++;
        CurPos++;
        CurCh = Data+CurPos;

        if (CurPos == BufferData.size() || !IsDigit(*CurCh)) {
          SrcMgr.PrintMessage(SMLoc::getFromPointer(Data+CurPos),
                              SourceMgr::DK_Error, "Missing exponent");
          return 0;
        }
      }

      do {
        Length++;
        CurPos++;
        CurCh = Data+CurPos;
      
      } while (CurPos < BufferData.size() && IsDigit(*CurCh));

    }
    
    StringRef Str = StringRef(Start, Length);

    if (IsFloat) {
      APFloat DoubleValue = APFloat(APFloat::IEEEdouble, Str);
      Value->DoubleConst  = DoubleValue.convertToDouble();
      return DOUBLECONST;
    } else {
      long    IntValue    = atol(Str.data());
      Value->IntConst     = IntValue;
      return INTCONST;
    }
  } else if (*CurCh == '=') {
    CurPos++;
    return EQUALS;
  } else if (*CurCh == '(') {
    CurPos++;
    return OPENPARENS;
  } else if (*CurCh == ')') {
    CurPos++;
    return CLOSEPARENS;
  } else if (*CurCh == '[') {
    CurPos++;
    return OPENBRACE;
  } else if (*CurCh == ']') {
    CurPos++;
    return CLOSEBRACE;
  } else if (*CurCh == ',') {
    CurPos++;
    return COMMA;
  } else if (*CurCh == ':') {
    CurPos++;
    return COLON;
  }

  CurPos++;
  // If we get here, then we have no idea how to lex this!
  printError("Unknown symbol");
  
  return 0;
}
llvm::Value* ModelDataStoreSymbolResolver::storeSymbolValue(
        const std::string& symbol, llvm::Value *value)
{
    assert(value);

    ModelDataIRBuilder mdbuilder(modelData, modelDataSymbols,
            builder);

    /*************************************************************************/
    /* AssignmentRule */
    /*************************************************************************/
    // can not store anything with an assigment rule, these are determined
    // by other independent elements.
    if (modelDataSymbols.hasAssignmentRule(symbol))
    {
        throw_llvm_exception("Attempt to store a value in symbol \""
                + symbol + "\" which is defined by an assignemnt rule");
    }


    /*************************************************************************/
    /* Species */
    /*************************************************************************/
    const Species *species = model->getSpecies(symbol);
    if (species)
    {
        Value *amt = 0;
        // only amounts are stored, convert to conc if required
        if (species->getHasOnlySubstanceUnits())
        {
            amt = value;
        }
        else
        {
            // have a conc, need to convert to amt
            Value *comp = resolver.loadSymbolValue(species->getCompartment());
            amt =  builder.CreateFMul(value, comp, symbol + "_amt");
        }

        assert(amt);

        // now look where we need to store it
        if (modelDataSymbols.isIndependentFloatingSpecies(symbol))
        {
            return mdbuilder.createFloatSpeciesAmtStore(symbol, amt);
        }
        else if (modelDataSymbols.isIndependentBoundarySpecies(symbol))
        {
            return mdbuilder.createBoundSpeciesAmtStore(symbol, amt);
        }
        else if(modelDataSymbols.hasRateRule(symbol))
        {
            return mdbuilder.createRateRuleValueStore(symbol, amt);
        }
        else
        {
            string msg = string("the symbol ") + symbol + string(" appeared to "
                    "be a species, but it could not be found as an independent "
                    "species or rate rule");
            throw_llvm_exception(msg);
            return 0;
        }
    }

    // at this point, we have already taken care of the species amount /
    // conc conversion, rest are just plain stores.

    if (modelDataSymbols.hasRateRule(symbol))
    {
        return mdbuilder.createRateRuleValueStore(symbol, value);
    }

    else if (modelDataSymbols.isIndependentCompartment(symbol))
    {
        return mdbuilder.createCompStore(symbol, value);
    }

    else if (modelDataSymbols.isIndependentGlobalParameter(symbol))
    {
        return mdbuilder.createGlobalParamStore(symbol, value);
    }

    else if (modelDataSymbols.isNamedSpeciesReference(symbol))
    {
        const LLVMModelDataSymbols::SpeciesReferenceInfo &info =
                modelDataSymbols.getNamedSpeciesReferenceInfo(symbol);

        if (info.type == LLVMModelDataSymbols::MultiReactantProduct)
        {
            string msg = "mutable stochiometry for species which appear "
                    "multiple times in a single reaction is not currently "
                    "supported, species reference id: ";
            msg += symbol;
            throw_llvm_exception(msg);
        }

        if (info.type == LLVMModelDataSymbols::Reactant)
        {
            // its consumed in the reaction, so has a negative in the stoich
            // matrix
            Value *negOne = ConstantFP::get(builder.getContext(), APFloat(-1.0));
            negOne->setName("neg_one");
            value = builder.CreateFMul(negOne, value, "neg_" + symbol);
        }

        return mdbuilder.createStoichiometryStore(info.row, info.column, value);
    }

    string msg = "The symbol \'";
    msg += symbol;
    msg += "\' is not physically stored in the ModelData structure, "
            "it either does not exists or is defined by an assigment rule (hence it "
            "is not a terminal symbol)";

    throw_llvm_exception(msg);
    return 0;
}
llvm::Value* Unop::Codegen(WasmFunction* fct, llvm::IRBuilder<>& builder) {
  bool is_intrinsic = false;
  OPERATION op = operation_->GetOperation();

  switch (op) {
    case CLZ_OPER:
    case CTZ_OPER:
    case POPCNT_OPER:
    case SQRT_OPER:
    case ABS_OPER:
    case CEIL_OPER:
    case FLOOR_OPER:
    case NEAREST_OPER:
      is_intrinsic = true;
      break;
    case TRUNC_OPER: {
        // Use the intrinsic value if we have the same type.
        //   Basically this is used for f32.trunc or f64.trunc...
        ConversionOperation* conversion = dynamic_cast<ConversionOperation*>(operation_);
        assert(conversion != nullptr);
        is_intrinsic = (conversion->GetSrc() == conversion->GetDest());
        break;
    }
    default:
      break;
  }

  if (is_intrinsic == true) {
    WasmModule* wasm_module = fct->GetModule();
    ETYPE type = operation_->GetType();
    llvm::Intrinsic::ID intrinsic;

    bool extra_true_arg = false;

    switch (op) {
      case CLZ_OPER:
        intrinsic = llvm::Intrinsic::ctlz;
        // We need to pass true as second argument to produce defined result for zero.
        extra_true_arg = true;
        break;
      case CTZ_OPER:
        intrinsic = llvm::Intrinsic::cttz;
        // We need to pass true as second argument to produce defined result for zero.
        extra_true_arg = true;
        break;
      case POPCNT_OPER:
        intrinsic = llvm::Intrinsic::ctpop;
        break;
      case SQRT_OPER:
        intrinsic = llvm::Intrinsic::sqrt;
        break;
      case ABS_OPER:
        intrinsic = llvm::Intrinsic::fabs;
        break;
      case CEIL_OPER:
        intrinsic = llvm::Intrinsic::ceil;
        break;
      case FLOOR_OPER:
        intrinsic = llvm::Intrinsic::floor;
        break;
      case TRUNC_OPER:
        intrinsic = llvm::Intrinsic::trunc;
        break;
      case NEAREST_OPER:
        intrinsic = llvm::Intrinsic::nearbyint;
        break;
      default:
        assert(0);
        return nullptr;
    }

    llvm::Function* intrinsic_fct = wasm_module->GetOrCreateIntrinsic(intrinsic, type);
    assert(intrinsic_fct != nullptr);

    std::vector<Value*> arg;
    arg.push_back(only_->Codegen(fct, builder));

    if (extra_true_arg) {
      llvm::Value* val_true = llvm::ConstantInt::get(llvm::getGlobalContext(), APInt(1, 0, false));
      arg.push_back(val_true);
    }

    return builder.CreateCall(intrinsic_fct, arg, "calltmp");
  } else {
    llvm::Value* rv = only_->Codegen(fct, builder);
    ETYPE type = operation_->GetType();

    switch (op) {
      case NEG_OPER: {
        llvm::Value* lv;
        if (type == FLOAT_32) {
          lv = llvm::ConstantFP::get(llvm::getGlobalContext(), APFloat(0.0f));
        } else {
          lv = llvm::ConstantFP::get(llvm::getGlobalContext(), APFloat(0.0));
        }
        return builder.CreateFSub(lv, rv, "subtmp");
      }

      case REINTERPRET_OPER:
        return builder.CreateBitCast(rv, ConvertType(type), DumpOperation(op));

      case EXTEND_OPER:
      case TRUNC_OPER:
      case PROMOTE_OPER:
      case DEMOTE_OPER:
      case CONVERT_OPER:
      case WRAP_OPER: {
        ConversionOperation* conversion = dynamic_cast<ConversionOperation*>(operation_);
        assert(conversion != nullptr);
        return HandleTypeCasts(rv, ConvertType(conversion->GetSrc()), ConvertType(type), operation_->GetSignedOrOrdered(), builder);
      }
    }

    assert(0);
    return nullptr;
  }
}
llvm::Value* ModelInitialValueSymbolResolver::loadSymbolValue(
        const std::string& symbol,
        const llvm::ArrayRef<llvm::Value*>& args)
{
    ModelDataIRBuilder mdbuilder(modelData, modelDataSymbols, builder);

    /*************************************************************************/
    /* time */
    /*************************************************************************/
    if (symbol.compare(SBML_TIME_SYMBOL) == 0)
    {
        return ConstantFP::get(builder.getContext(), APFloat(0.0));
    }

    /*************************************************************************/
    /* Function */
    /*************************************************************************/
    {
        Value *funcVal =
            FunctionResolver(*this, model, builder).loadSymbolValue(symbol, args);
        if (funcVal)
        {
            return funcVal;
        }
    }

    /*************************************************************************/
    /* Initial AssignmentRule */
    /*************************************************************************/
    {
        SymbolForest::ConstIterator i =
                modelSymbols.getInitialAssignmentRules().find(symbol);
        if (i != modelSymbols.getInitialAssignmentRules().end())
        {
            recursiveSymbolPush(symbol);
            Value* result =  ASTNodeCodeGen(builder, *this).codeGen(i->second);
            recursiveSymbolPop();
            return result;
        }
    }

    /*************************************************************************/
    /* AssignmentRule */
    /*************************************************************************/
    if (!modelDataSymbols.isConservedMoietySpecies(symbol))
    {
        SymbolForest::ConstIterator i =
                modelSymbols.getAssigmentRules().find(symbol);
        if (i != modelSymbols.getAssigmentRules().end())
        {
            return ASTNodeCodeGen(builder, *this).codeGen(i->second);
        }
    }

    if (modelDataSymbols.isIndependentInitFloatingSpecies(symbol))
    {
        const Species *species = model->getSpecies(symbol);

        assert(species);

        Value *amt = mdbuilder.createInitFloatSpeciesAmtLoad(symbol, symbol + "_amt");

        // now we have an amount, check to see if we need to convert to conc
        if (species->getHasOnlySubstanceUnits())
        {
            return amt;
        }
        else
        {
            // expect a concentration, need to convert amt to conc,
            // so we need to get the compartment its in, but these
            // can vary also...
            Value *comp = loadSymbolValue(species->getCompartment());
            return builder.CreateFDiv(amt, comp, symbol + "_conc");
        }
    }

    else if (modelDataSymbols.isIndependentCompartment(symbol))
    {
        return mdbuilder.createInitCompLoad(symbol);
    }

    /*************************************************************************/
    /* Initial Value */
    /*************************************************************************/
    {
        SymbolForest::ConstIterator i =
                modelSymbols.getInitialValues().find(symbol);

        if (i != modelSymbols.getInitialValues().end())
        {
            return ASTNodeCodeGen(builder, *this).codeGen(i->second);
        }
    }

    /*************************************************************************/
    /* Reaction Rate */
    /*************************************************************************/
    const Reaction* reaction = model->getReaction(symbol);
    if (reaction)
    {
        return loadReactionRate(reaction);
    }

    string msg = "Could not find requested symbol \'";
    msg += symbol;
    msg += "\' in the model";
    throw_llvm_exception(msg);

    return 0;
}
Esempio n. 6
0
void *LLVMFormula::emit (CallExprAST *expr)
{
	// Deal with the if-instruction first, specially
	if (expr->function == "if")
	{
		Value *cond = (Value *)expr->args[0]->generate (this);
		Value *t = (Value *)expr->args[1]->generate (this);
		Value *f = (Value *)expr->args[2]->generate (this);
		if (cond == NULL || t == NULL || f == NULL) return NULL;
		
		Value *one = ConstantFP::get (getGlobalContext (), APFloat (1.0));
		Value *cmp = builder->CreateFCmpOEQ (cond, one, "ifcmptmp");

		return builder->CreateSelect (cmp, t, f, "ifelsetmp");
	}

	// Sign isn't a standard-library function, implement it with a compare
	if (expr->function == "sign")
	{
		Value *v = (Value *)expr->args[0]->generate (this);
		if (!v) return NULL;
		
		Value *zero = ConstantFP::get (getGlobalContext (), APFloat (0.0));
		Value *one = ConstantFP::get (getGlobalContext (), APFloat (1.0));
		Value *none = ConstantFP::get (getGlobalContext (), APFloat (-1.0));

		Value *cmpgzero = builder->CreateFCmpOGT (v, zero, "sgncmpgzero");
		Value *cmplzero = builder->CreateFCmpOLT (v, zero, "sgncmplzero");

		Value *fselect = builder->CreateSelect (cmplzero, none, zero, "sgnsellzero");
		return builder->CreateSelect (cmpgzero, one, fselect, "sgnselgzero");
	}

	//
	// Map our function names to standard libm names
	//
	
	// If we're calling "log", we want "log10"
	if (expr->function == "log")
		expr->function = "log10";
	// If we're calling "ln", we want "log"
	if (expr->function == "ln")
		expr->function = "log";
	// If we're calling "abs", we want "fabs"
	if (expr->function == "abs")
		expr->function = "fabs";
	
	// The following are available as LLVM intrinsics, and we should emit them
	// specially without calling out to libm:
	Intrinsic::ID intrinsicID = Intrinsic::not_intrinsic;
		
	if (expr->function == "cos")
		intrinsicID = Intrinsic::cos;
	else if (expr->function == "exp")
		intrinsicID = Intrinsic::exp;
	else if (expr->function == "log")
		intrinsicID = Intrinsic::log;
	else if (expr->function == "log10")
		intrinsicID = Intrinsic::log10;
	else if (expr->function == "sin")
		intrinsicID = Intrinsic::sin;
	else if (expr->function == "sqrt")
		intrinsicID = Intrinsic::sqrt;

	if (intrinsicID != Intrinsic::not_intrinsic)
	{
		// Most of the floating-point intrinsics are overloaded for multiple types
		Type *types[1] = { Type::getDoubleTy (getGlobalContext ()) };
        ArrayRef<Type *> type_array(types, 1);
		
		Value *arg = (Value *)expr->args[0]->generate (this);
		if (!arg) return NULL;

		Value *func = Intrinsic::getDeclaration (module, intrinsicID, type_array);
		return builder->CreateCall (func, arg, expr->function);
	}
	
	// The rest of these are calls to stdlib floating point math
	// functions.
	
	// atan2 is special, because it has two arguments
	if (expr->function == "atan2")
	{
        Value *arg1 = (Value *)expr->args[0]->generate (this);
        Value *arg2 = (Value *)expr->args[1]->generate (this);
        if (!arg1 || !arg2) return NULL;
        
        Module *M = builder->GetInsertBlock ()->getParent ()->getParent ();
        Value *Callee = M->getOrInsertFunction (expr->function,
                                                Type::getDoubleTy (getGlobalContext ()),
    	                                        Type::getDoubleTy (getGlobalContext ()),
    	                                        Type::getDoubleTy (getGlobalContext ()),
                                                NULL);
        return builder->CreateCall2 (Callee, arg1, arg2, expr->function);
	}
	else
	{
    	// Emit a call to function (arg)
    	Value *arg = (Value *)expr->args[0]->generate (this);
    	if (!arg) return NULL;
	
    	Module *M = builder->GetInsertBlock ()->getParent ()->getParent ();
    	Value *Callee = M->getOrInsertFunction (expr->function,
    	                                        Type::getDoubleTy (getGlobalContext ()),
    	                                        Type::getDoubleTy (getGlobalContext ()),
    	                                        NULL);
    	return builder->CreateCall (Callee, arg, expr->function);
    }
}
Esempio n. 7
0
void *LLVMFormula::emit (NumberExprAST *expr)
{
	return ConstantFP::get (getGlobalContext (), APFloat (expr->val));
}
Esempio n. 8
0
 Value* getDouble(double v){
   return ConstantFP::get(context_, APFloat(v));
 }