Exemplo n.º 1
0
void saveAtomTypes(const TypeVec &types)
{
  for (TypeVec::const_iterator it = types.begin(); it != types.end(); ++it)
  {
    out << it->name << "\t" << it->count << endl;
  }
}
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;
}
Exemplo n.º 3
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;
    }
}