Пример #1
0
TypeVec getTypes()
{
  TypeVec types;
  // init types with predefined species (if any)
  vector<string> species = strsplit(args.getCString("species"));
  for (size_t i = 0; i < species.size(); ++i)
  {
    types.push_back(Type(species[i].c_str(), types.size()));
  }

  return types;
}
Пример #2
0
  NNModule_(NNModule* o)
  : o_(o),
    context_(getGlobalContext()),
    module_("NNModule", context_),
    builder_(context_){

    _mutex.lock();
    if(!_initialized){
      InitializeNativeTarget();
      _initialized = true;
    }  
    _mutex.unlock();

    engine_ = EngineBuilder(&module_).setUseMCJIT(true).create();

    TypeVec args;
    args.push_back(doubleType());
    createExtern("llvm.exp.f64", doubleType(), args);
  }
static const TypeVec
throwsException(const FunctionDecl *Func,
                llvm::SmallSet<const FunctionDecl *, 32> &CallStack) {
  if (CallStack.count(Func))
    return TypeVec();

  if (const Stmt *Body = Func->getBody()) {
    CallStack.insert(Func);
    const TypeVec Result = throwsException(Body, TypeVec(), CallStack);
    CallStack.erase(Func);
    return Result;
  }

  TypeVec Result;
  if (const auto *FPT = Func->getType()->getAs<FunctionProtoType>()) {
    for (const QualType Ex : FPT->exceptions()) {
      Result.push_back(Ex.getTypePtr());
    }
  }
  return Result;
}
static const TypeVec
throwsException(const Stmt *St, const TypeVec &Caught,
                llvm::SmallSet<const FunctionDecl *, 32> &CallStack) {
  TypeVec Results;

  if (!St)
    return Results;

  if (const auto *Throw = dyn_cast<CXXThrowExpr>(St)) {
    if (const auto *ThrownExpr = Throw->getSubExpr()) {
      const auto *ThrownType =
          ThrownExpr->getType()->getUnqualifiedDesugaredType();
      if (ThrownType->isReferenceType()) {
        ThrownType = ThrownType->castAs<ReferenceType>()
                         ->getPointeeType()
                         ->getUnqualifiedDesugaredType();
      }
      if (const auto *TD = ThrownType->getAsTagDecl()) {
        if (TD->getDeclName().isIdentifier() && TD->getName() == "bad_alloc"
            && TD->isInStdNamespace())
          return Results;
      }
      Results.push_back(ThrownExpr->getType()->getUnqualifiedDesugaredType());
    } else {
      Results.append(Caught.begin(), Caught.end());
    }
  } else if (const auto *Try = dyn_cast<CXXTryStmt>(St)) {
    TypeVec Uncaught = throwsException(Try->getTryBlock(), Caught, CallStack);
    for (unsigned i = 0; i < Try->getNumHandlers(); ++i) {
      const CXXCatchStmt *Catch = Try->getHandler(i);
      if (!Catch->getExceptionDecl()) {
        const TypeVec Rethrown =
            throwsException(Catch->getHandlerBlock(), Uncaught, CallStack);
        Results.append(Rethrown.begin(), Rethrown.end());
        Uncaught.clear();
      } else {
        const auto *CaughtType =
            Catch->getCaughtType()->getUnqualifiedDesugaredType();
        if (CaughtType->isReferenceType()) {
          CaughtType = CaughtType->castAs<ReferenceType>()
                           ->getPointeeType()
                           ->getUnqualifiedDesugaredType();
        }
        auto NewEnd =
            llvm::remove_if(Uncaught, [&CaughtType](const Type *ThrownType) {
              return ThrownType == CaughtType ||
                     isBaseOf(ThrownType, CaughtType);
            });
        if (NewEnd != Uncaught.end()) {
          Uncaught.erase(NewEnd, Uncaught.end());
          const TypeVec Rethrown = throwsException(
              Catch->getHandlerBlock(), TypeVec(1, CaughtType), CallStack);
          Results.append(Rethrown.begin(), Rethrown.end());
        }
      }
    }
    Results.append(Uncaught.begin(), Uncaught.end());
  } else if (const auto *Call = dyn_cast<CallExpr>(St)) {
    if (const FunctionDecl *Func = Call->getDirectCallee()) {
      TypeVec Excs = throwsException(Func, CallStack);
      Results.append(Excs.begin(), Excs.end());
    }
  } else {
    for (const Stmt *Child : St->children()) {
      TypeVec Excs = throwsException(Child, Caught, CallStack);
      Results.append(Excs.begin(), Excs.end());
    }
  }
  return Results;
}
Пример #5
0
void HLIRTask::setFunction(const HLIRFunction& func){
  auto& b = module_->builder();
  auto& c = module_->context();

  (*this)["function"] = func;

  TypeVec params = {module_->voidPtrTy};

  auto funcType = FunctionType::get(module_->voidTy, params, false);

  Function* wrapperFunc =
    Function::Create(funcType,
                     llvm::Function::ExternalLinkage,
                     "hlir.task_wrapper",
                     module_->module());

  auto aitr = wrapperFunc->arg_begin();
  aitr->setName("args.ptr");
  Value* argsVoidPtr = aitr++;

  BasicBlock* entry = BasicBlock::Create(c, "entry", wrapperFunc);
  b.SetInsertPoint(entry);

  TypeVec fields;
  fields.push_back(module_->voidPtrTy);
  fields.push_back(module_->i32Ty);
  fields.push_back(func->getReturnType());

  for(auto pitr = func->arg_begin(), pitrEnd = func->arg_end();
    pitr != pitrEnd; ++pitr){
    fields.push_back(pitr->getType());
  }

  StructType* argsType = StructType::create(c, fields, "struct.func_args");

  ValueVec args;
  Value* argsPtr = 
    b.CreateBitCast(argsVoidPtr, PointerType::get(argsType, 0), "argsPtr");

  size_t idx = 3;
  for(auto pitr = func->arg_begin(), pitrEnd = func->arg_end();
    pitr != pitrEnd; ++pitr){
    Value* arg = b.CreateStructGEP(nullptr, argsPtr, idx, "arg.ptr");
    arg = b.CreateLoad(arg, "arg");
    args.push_back(arg);
    ++idx;
  }

  Value* ret = b.CreateCall(func, args, "ret");
  Value* retPtr = b.CreateStructGEP(nullptr, argsPtr, 2, "retPtr");
  b.CreateStore(ret, retPtr);

  Function* releaseFunc = 
    module_->getFunction("__ares_task_release_future", {module_->voidPtrTy});

  args = {argsVoidPtr};
  b.CreateCall(releaseFunc, args);

  b.CreateRetVoid();

  (*this)["wrapperFunction"] = HLIRFunction(wrapperFunc);
}
Пример #6
0
void HLIRModule::lowerTask_(HLIRTask* task){
  auto& b = builder();
  auto& c = context();

  DataLayout layout(module_);

  Function* func = task->function();
  Function* wrapperFunc = task->wrapperFunction();

  for(auto itr = func->use_begin(), itrEnd = func->use_end();
    itr != itrEnd; ++itr){
    if(CallInst* ci = dyn_cast<CallInst>(itr->getUser())){
      BasicBlock* parentBlock = ci->getParent();
      Function* parentFunc = parentBlock->getParent();
      
      if(parentFunc == wrapperFunc){
        continue;
      }

      b.SetInsertPoint(ci);

      TypeVec fields;
      fields.push_back(voidPtrTy);
      fields.push_back(i32Ty);
      fields.push_back(func->getReturnType());

      for(auto pitr = func->arg_begin(), pitrEnd = func->arg_end();
        pitr != pitrEnd; ++pitr){
        fields.push_back(pitr->getType());
      }

      StructType* argsType = StructType::create(c, fields, "struct.func_args");

      size_t size = layout.getTypeAllocSize(argsType);

      Function* allocFunc = getFunction("__ares_alloc", {i64Ty}, voidPtrTy);

      ValueVec args = {ConstantInt::get(i64Ty, size)};

      Value* argsVoidPtr = b.CreateCall(allocFunc, args, "args.void.ptr");

      Value* argsPtr = 
        b.CreateBitCast(argsVoidPtr, PointerType::get(argsType, 0), "args.ptr");

      Value* depth = b.CreateStructGEP(nullptr, argsPtr, 1, "depth.ptr");
      depth = b.CreateLoad(depth, "depth");

      size_t idx = 3;
      for(auto& arg : ci->arg_operands()){
        Value* argPtr = b.CreateStructGEP(nullptr, argsPtr, idx, "arg.ptr");
        b.CreateStore(arg, argPtr);
        ++idx;
      }

      Function* queueFunc = 
        getFunction("__ares_task_queue", {voidPtrTy, voidPtrTy});

      Value* funcVoidPtr = b.CreateBitCast(wrapperFunc, voidPtrTy, "funcVoidPtr");

      args = {funcVoidPtr, argsVoidPtr};
      b.CreateCall(queueFunc, args);

      for(auto itr = ci->use_begin(), itrEnd = ci->use_end();
        itr != itrEnd; ++itr){

        if(Instruction* i = dyn_cast<Instruction>(itr->getUser())){
          b.SetInsertPoint(i);

          Function* awaitFunc = 
            getFunction("__ares_task_await_future", {voidPtrTy});

          args = {argsVoidPtr};
          b.CreateCall(awaitFunc, args);

          Value* retPtr = b.CreateStructGEP(nullptr, argsPtr, 2, "retPtr");
          Value* retVal = b.CreateLoad(retPtr, "retVal"); 

          ci->replaceAllUsesWith(retVal);

          break;
        }
      }

      ci->eraseFromParent();

      //parentFunc->dump();
    }
  }
}
Пример #7
0
static void DtoCreateNestedContextType(FuncDeclaration* fd) {
    Logger::println("DtoCreateNestedContextType for %s", fd->toChars());
    LOG_SCOPE

    DtoDeclareFunction(fd);

    if (fd->ir.irFunc->nestedContextCreated)
        return;
    fd->ir.irFunc->nestedContextCreated = true;

    if (fd->nestedVars.empty()) {
        // fill nestedVars
        size_t nnest = fd->closureVars.dim;
        for (size_t i = 0; i < nnest; ++i)
        {
            VarDeclaration* vd = static_cast<VarDeclaration*>(fd->closureVars.data[i]);
            fd->nestedVars.insert(vd);
        }
    }

    // construct nested variables array
    if (!fd->nestedVars.empty())
    {
        Logger::println("has nested frame");
        // start with adding all enclosing parent frames until a static parent is reached

        LLStructType* innerFrameType = NULL;
        unsigned depth = -1;
        if (!fd->isStatic()) {
            if (FuncDeclaration* parfd = getParentFunc(fd, true)) {
                // Make sure the parent has already been analyzed.
                DtoCreateNestedContextType(parfd);

                innerFrameType = parfd->ir.irFunc->frameType;
                if (innerFrameType)
                    depth = parfd->ir.irFunc->depth;
            }
        }
        fd->ir.irFunc->depth = ++depth;

        Logger::cout() << "Function " << fd->toChars() << " has depth " << depth << '\n';

        typedef std::vector<LLType*> TypeVec;
        TypeVec types;
        if (depth != 0) {
            assert(innerFrameType);
            // Add frame pointer types for all but last frame
            if (depth > 1) {
                for (unsigned i = 0; i < (depth - 1); ++i) {
                    types.push_back(innerFrameType->getElementType(i));
                }
            }
            // Add frame pointer type for last frame
            types.push_back(LLPointerType::getUnqual(innerFrameType));
        }

        if (Logger::enabled() && depth != 0) {
            Logger::println("Frame types: ");
            LOG_SCOPE;
            for (TypeVec::iterator i = types.begin(); i != types.end(); ++i)
                Logger::cout() << **i << '\n';
        }

        // Add the direct nested variables of this function, and update their indices to match.
        // TODO: optimize ordering for minimal space usage?
        for (std::set<VarDeclaration*>::iterator i=fd->nestedVars.begin(); i!=fd->nestedVars.end(); ++i)
        {
            VarDeclaration* vd = *i;
            if (!vd->ir.irLocal)
                vd->ir.irLocal = new IrLocal(vd);

            vd->ir.irLocal->nestedIndex = types.size();
            vd->ir.irLocal->nestedDepth = depth;
            if (vd->isParameter()) {
                // Parameters will have storage associated with them (to handle byref etc.),
                // so handle those cases specially by storing a pointer instead of a value.
                const IrParameter* irparam = vd->ir.irParam;
                const bool refout = vd->storage_class & (STCref | STCout);
                const bool lazy = vd->storage_class & STClazy;
                const bool byref = irparam->arg->byref;
                const bool isVthisPtr = irparam->isVthis && !byref;
                if (!(refout || (byref && !lazy)) || isVthisPtr) {
                    // This will be copied to the nesting frame.
                    if (lazy)
                        types.push_back(irparam->value->getType()->getContainedType(0));
                    else
                        types.push_back(DtoType(vd->type));
                } else {
                    types.push_back(irparam->value->getType());
                }
            } else if (isSpecialRefVar(vd)) {
                types.push_back(DtoType(vd->type->pointerTo()));
            } else {
                types.push_back(DtoType(vd->type));
            }
            if (Logger::enabled()) {
                Logger::cout() << "Nested var '" << vd->toChars() <<
                    "' of type " << *types.back() << "\n";
            }
        }

        LLStructType* frameType = LLStructType::create(gIR->context(), types,
                                                       std::string("nest.") + fd->toChars());

        Logger::cout() << "frameType = " << *frameType << '\n';

        // Store type in IrFunction
        fd->ir.irFunc->frameType = frameType;
    } else if (FuncDeclaration* parFunc = getParentFunc(fd, true)) {
        // Propagate context arg properties if the context arg is passed on unmodified.
        DtoCreateNestedContextType(parFunc);
        fd->ir.irFunc->frameType = parFunc->ir.irFunc->frameType;
        fd->ir.irFunc->depth = parFunc->ir.irFunc->depth;
    }
}
Пример #8
0
  bool compile(const nstr& name,
               NNet& network,
               size_t threads){

    RunNetwork* runNetwork = new RunNetwork;

    NNet::Layer* inputLayer = network.layer(0);

    size_t numLayers = network.numLayers();

    RunLayer* lastRunLayer = 0;

    for(size_t l = 1; l < numLayers; ++l){
      RunLayer* runLayer = new RunLayer;
      runLayer->queue = new Queue(threads);

      size_t inputLayerSize = inputLayer->size();

      NNet::Layer* layer = network.layer(l);

      size_t layerSize  = layer->size();

      if(l > 1){
        runLayer->inputVecStart = lastRunLayer->outputVecStart;
        runLayer->inputVec = lastRunLayer->outputVec;
      }

      if(l < numLayers - 1){
        double* outputVecPtrStart;
        double* outputVecPtr;
        allocVector(layerSize, &outputVecPtrStart, &outputVecPtr);
        runLayer->outputVecStart = outputVecPtrStart;
        runLayer->outputVec = outputVecPtr;
      }

      TypeVec args;
      args.push_back(getPointer(doubleVecType(inputLayerSize)));
      args.push_back(getPointer(doubleVecType(inputLayerSize)));
      args.push_back(getPointer(doubleType()));
      args.push_back(int32Type());

      FunctionType* ft = FunctionType::get(voidType(), args, false);
      
      Function* f = 
        Function::Create(ft, Function::ExternalLinkage,
                         name.c_str(), &module_);

      BasicBlock* entry = BasicBlock::Create(context_, "entry", f);
      
      builder_.SetInsertPoint(entry);

      auto aitr = f->arg_begin();
      
      Value* inputVecPtr = aitr;
      inputVecPtr->setName("input_vec_ptr");

      ++aitr;
      Value* weightVecPtr = aitr;
      weightVecPtr->setName("weight_vec_ptr");

      ++aitr;
      Value* outputVecPtr = aitr;
      outputVecPtr->setName("output_vec_ptr");

      ++aitr;
      Value* outputIndex = aitr;
      outputIndex->setName("output_index");

      Value* inputVec = 
        builder_.CreateLoad(inputVecPtr, "input_vec");

      Value* weightVec = 
        builder_.CreateLoad(weightVecPtr, "weight_vec");

      Value* mulVec = 
        builder_.CreateFMul(inputVec, weightVec, "mul_vec");
      
      Value* sumActivation = 
        builder_.CreateExtractElement(mulVec, getInt32(0), "sum_elem");

      for(size_t i = 1; i < inputLayerSize; ++i){
        Value* elem = 
          builder_.CreateExtractElement(mulVec, getInt32(i), "sum_elem");
        
        sumActivation = 
          builder_.CreateFAdd(sumActivation, elem, "sum_activation");
      }

      Value* output = 
        getActivationOutput(layer->neuron(0), sumActivation);

      Value* outputElement = 
        builder_.CreateGEP(outputVecPtr, outputIndex, "out_elem");

      builder_.CreateStore(output, outputElement);

      builder_.CreateRetVoid(); 

      runLayer->f = f;

      runLayer->fp = (void (*)(void*, void*, void*, int))
        engine_->getPointerToFunction(f);

      for(size_t j = 0; j < layerSize; ++j){
        NNet::Neuron* nj = layer->neuron(j);

        RunNeuron* runNeuron = new RunNeuron;
        runNeuron->layer = runLayer;
        runNeuron->outputIndex = j;

        double* weightVecPtrStart;
        double* weightVecPtr;
        allocVector(inputLayerSize, &weightVecPtrStart, &weightVecPtr);
        runNeuron->weightVecStart = weightVecPtrStart;
        runNeuron->weightVec = weightVecPtr;

        for(size_t i = 0; i < inputLayerSize; ++i){
          NNet::Neuron* ni = inputLayer->neuron(i);
          weightVecPtr[i] = nj->weight(ni);
        }

        runLayer->queue->add(runNeuron);
      }

      runNetwork->layerVec.push_back(runLayer);

      inputLayer = layer;
      lastRunLayer = runLayer;
    }

    networkMap_.insert(make_pair(name, runNetwork));

    return true;
  }