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; }
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; } }