text:
namespace swift {

class ASTContext;
class SILInstruction;
class SILModule;
class SILFunctionBuilder;
class SILProfiler;
class BasicBlockBitfield;
class NodeBitfield;

namespace Lowering {
class TypeLowering;
class AbstractionPattern;
}

enum IsBare_t { IsNotBare, IsBare };
enum IsTransparent_t { IsNotTransparent, IsTransparent };
enum Inline_t { InlineDefault, NoInline, AlwaysInline };
enum IsThunk_t {
  IsNotThunk,
  IsThunk,
  IsReabstractionThunk,
  IsSignatureOptimizedThunk
};
enum IsDynamicallyReplaceable_t {
  IsNotDynamic,
  IsDynamic
};
enum IsExactSelfClass_t {
  IsNotExactSelfClass,
  IsExactSelfClass,
};
enum IsDistributed_t {
  IsNotDistributed,
  IsDistributed,
};

enum class PerformanceConstraints : uint8_t {
  None = 0,
  NoAllocation = 1,
  NoLocks = 2,
};

class SILSpecializeAttr final {
  friend SILFunction;
public:
  enum class SpecializationKind {
    Full,
    Partial
  };

  static SILSpecializeAttr *create(SILModule &M,
                                   GenericSignature specializedSignature,
                                   bool exported, SpecializationKind kind,
                                   SILFunction *target, Identifier spiGroup,
                                   const ModuleDecl *spiModule,
                                   AvailabilityContext availability);

  bool isExported() const {
    return exported;
  }

  bool isFullSpecialization() const {
    return kind == SpecializationKind::Full;
  }

  bool isPartialSpecialization() const {
    return kind == SpecializationKind::Partial;
  }

  SpecializationKind getSpecializationKind() const {
    return kind;
  }

  GenericSignature getSpecializedSignature() const {
    return specializedSignature;
  }

  SILFunction *getFunction() const {
    return F;
  }

  SILFunction *getTargetFunction() const {
    return targetFunction;
  }

  Identifier getSPIGroup() const {
    return spiGroup;
  }

  const ModuleDecl *getSPIModule() const {
    return spiModule;
  }

  AvailabilityContext getAvailability() const {
    return availability;
  }

  void print(llvm::raw_ostream &OS) const;

private:
  SpecializationKind kind;
  bool exported;
  GenericSignature specializedSignature;
  Identifier spiGroup;
  AvailabilityContext availability;
  const ModuleDecl *spiModule = nullptr;
  SILFunction *F = nullptr;
  SILFunction *targetFunction = nullptr;

  SILSpecializeAttr(bool exported, SpecializationKind kind,
                    GenericSignature specializedSignature, SILFunction *target,
                    Identifier spiGroup, const ModuleDecl *spiModule,
                    AvailabilityContext availability);
};

/// SILFunction - A function body that has been lowered to SIL. This consists of
/// zero or more SIL SILBasicBlock objects that contain the SILInstruction
/// objects making up the function.
class SILFunction
  : public llvm::ilist_node<SILFunction>, public SILAllocated<SILFunction>,
    public SwiftObjectHeader {

private:
  void *libswiftSpecificData[1];

public:
  using BlockListType = llvm::iplist<SILBasicBlock>;

  // For more information see docs/SIL.rst
  enum class Purpose : uint8_t {
    None,
    GlobalInit,
    GlobalInitOnceFunction,
    LazyPropertyGetter
  };

private:
  friend class SILBasicBlock;
  friend class SILModule;
  friend class SILFunctionBuilder;
  template <typename, unsigned> friend class BasicBlockData;
  template <class, class> friend class SILBitfield;
  friend class BasicBlockBitfield;
  friend class NodeBitfield;

  /// Module - The SIL module that the function belongs to.
  SILModule &Module;

  /// The mangled name of the SIL function, which will be propagated
  /// to the binary.  A pointer into the module's lookup table.
  StringRef Name;

  /// A single-linked list of snapshots of the function.
  ///
  /// Snapshots are copies of the current function at a given point in time.
  SILFunction *snapshots = nullptr;

  /// The snapshot ID of this function.
  ///
  /// 0 means, it's not a snapshot, but the original function.
  int snapshotID = 0;

  /// The lowered type of the function.
  CanSILFunctionType LoweredType;

  /// The context archetypes of the function.
  GenericEnvironment *GenericEnv = nullptr;

  /// The information about specialization.
  /// Only set if this function is a specialization of another function.
  const GenericSpecializationInformation *SpecializationInfo = nullptr;

  /// The forwarding substitution map, lazily computed.
  SubstitutionMap ForwardingSubMap;

  /// The collection of all BasicBlocks in the SILFunction. Empty for external
  /// function references.
  BlockListType BlockList;

  /// The owning declaration of this function's clang node, if applicable.
  ValueDecl *ClangNodeOwner = nullptr;

  /// The source location and scope of the function.
  const SILDebugScope *DebugScope = nullptr;

  /// The AST decl context of the function.
  DeclContext *DeclCtxt = nullptr;

  /// The module that defines this function. This member should only be set as
  /// a fallback when a \c DeclCtxt is unavailable.
  ModuleDecl *ParentModule = nullptr;

  /// The profiler for instrumentation based profiling, or null if profiling is
  /// disabled.
  SILProfiler *Profiler = nullptr;

  /// The function this function is meant to replace. Null if this is not a
  /// @_dynamicReplacement(for:) function.
  SILFunction *ReplacedFunction = nullptr;

  /// This SILFunction REFerences an ad-hoc protocol requirement witness in
  /// order to keep it alive, such that it main be obtained in IRGen. Without
  /// this explicit reference, the witness would seem not-used, and not be
  /// accessible for IRGen.
  ///
  /// Specifically, one such case is the DistributedTargetInvocationDecoder's
  /// 'decodeNextArgument' which must be retained, as it is only used from IRGen
  /// and such, appears as-if unused in SIL and would get optimized away.
  // TODO: Consider making this a general "references adhoc functions" and make it an array?
  SILFunction *RefAdHocRequirementFunction = nullptr;

  Identifier ObjCReplacementFor;

  /// The head of a single-linked list of currently alive BasicBlockBitfield.
  BasicBlockBitfield *newestAliveBlockBitfield = nullptr;

  /// The head of a single-linked list of currently alive NodeBitfield.
  NodeBitfield *newestAliveNodeBitfield = nullptr;

  /// A monotonically increasing ID which is incremented whenever a
  /// BasicBlockBitfield or NodeBitfield is constructed.
  /// For details see SILBitfield::bitfieldID;
  uint64_t currentBitfieldID = 1;

  /// Unique identifier for vector indexing and deterministic sorting.
  /// May be reused when zombie functions are recovered.
  unsigned index;

  /// The function's set of semantics attributes.
  ///
  /// TODO: Why is this using a std::string? Why don't we use uniqued
  /// StringRefs?
  std::vector<std::string> SemanticsAttrSet;

  /// The function's remaining set of specialize attributes.
  std::vector<SILSpecializeAttr*> SpecializeAttrSet;

  /// Has value if there's a profile for this function
  /// Contains Function Entry Count
  ProfileCounter EntryCount;

  /// The availability used to determine if declarations of this function
  /// should use weak linking.
  AvailabilityContext Availability;

  Purpose specialPurpose = Purpose::None;

  PerformanceConstraints perfConstraints = PerformanceConstraints::None;

  /// This is the number of uses of this SILFunction inside the SIL.
  /// It does not include references from debug scopes.
  unsigned RefCount = 0;

  /// Used to verify if a BasicBlockData is not valid anymore.
  /// This counter is incremented every time a BasicBlockData re-assigns new
  /// block indices.
  unsigned BlockListChangeIdx = 0;

  /// The function's bare attribute. Bare means that the function is SIL-only
  /// and does not require debug info.
  unsigned Bare : 1;

  /// The function's transparent attribute.
  unsigned Transparent : 1;

  /// The function's serialized attribute.
  bool Serialized : 1;

  /// Specifies if this function is a thunk or a reabstraction thunk.
  ///
  /// The inliner uses this information to avoid inlining (non-trivial)
  /// functions into the thunk.
  unsigned Thunk : 2;

  /// The scope in which the parent class can be subclassed, if this is a method
  /// which is contained in the vtable of that class.
  unsigned ClassSubclassScope : 2;

  /// The function's global_init attribute.
  unsigned GlobalInitFlag : 1;

  /// The function's noinline attribute.
  unsigned InlineStrategy : 2;

  /// The linkage of the function.
  unsigned Linkage : NumSILLinkageBits;

  /// Set if the function may be referenced from C code and should thus be
  /// preserved and exported more widely than its Swift linkage and usage
  /// would indicate.
  unsigned HasCReferences : 1;

  /// Whether cross-module references to this function should always use weak
  /// linking.
  unsigned IsAlwaysWeakImported : 1;

  /// Whether the implementation can be dynamically replaced.
  unsigned IsDynamicReplaceable : 1;

  /// If true, this indicates that a class method implementation will always be
  /// invoked with a `self` argument of the exact base class type.
  unsigned ExactSelfClass : 1;

  /// Check whether this is a distributed method.
  unsigned IsDistributed : 1;

  unsigned stackProtection : 1;

  /// True if this function is inlined at least once. This means that the
  /// debug info keeps a pointer to this function.
  unsigned Inlined : 1;

  /// True if this function is a zombie function. This means that the function
  /// is dead and not referenced from anywhere inside the SIL. But it is kept
  /// for other purposes:
  /// *) It is inlined and the debug info keeps a reference to the function.
  /// *) It is a dead method of a class which has higher visibility than the
  ///    method itself. In this case we need to create a vtable stub for it.
  /// *) It is a function referenced by the specialization information.
  unsigned Zombie : 1;

  /// True if this function is in Ownership SSA form and thus must pass
  /// ownership verification.
  ///
  /// This enables the verifier to easily prove that before the Ownership Model
  /// Eliminator runs on a function, we only see a non-semantic-arc world and
  /// after the pass runs, we only see a semantic-arc world.
  unsigned HasOwnership : 1;

  /// Set if the function body was deserialized from canonical SIL. This implies
  /// that the function's home module performed SIL diagnostics prior to
  /// serialization.
  unsigned WasDeserializedCanonical : 1;

  /// True if this is a reabstraction thunk of escaping function type whose
  /// single argument is a potentially non-escaping closure. This is an escape
  /// hatch to allow non-escaping functions to be stored or passed as an
  /// argument with escaping function type. The thunk argument's function type
  /// is not necessarily @noescape. The only relevant aspect of the argument is
  /// that it may have unboxed capture (i.e. @inout_aliasable parameters).
  unsigned IsWithoutActuallyEscapingThunk : 1;

  /// If != OptimizationMode::NotSet, the optimization mode specified with an
  /// function attribute.
  unsigned OptMode : NumOptimizationModeBits;

  /// The function's effects attribute.
  unsigned EffectsKindAttr : NumEffectsKindBits;

  /// The function is in a statically linked module.
  unsigned IsStaticallyLinked : 1;

  static void
  validateSubclassScope(SubclassScope scope, IsThunk_t isThunk,
                        const GenericSpecializationInformation *genericInfo) {
#ifndef NDEBUG
    // The _original_ function for a method can turn into a thunk through
    // signature optimization, meaning it needs to retain its subclassScope, but
    // other thunks and specializations are implementation details and so
    // shouldn't be connected to their parent class.
    bool thunkCanHaveSubclassScope;
    switch (isThunk) {
    case IsNotThunk:
    case IsSignatureOptimizedThunk:
      thunkCanHaveSubclassScope = true;
      break;
    case IsThunk:
    case IsReabstractionThunk:
      thunkCanHaveSubclassScope = false;
      break;
    }
    auto allowsInterestingScopes = thunkCanHaveSubclassScope && !genericInfo;
    assert(
        allowsInterestingScopes ||
        scope == SubclassScope::NotApplicable &&
            "SubclassScope on specialization or non-signature-optimized thunk");
#endif
  }

  SILFunction(SILModule &module, SILLinkage linkage, StringRef mangledName,
              CanSILFunctionType loweredType, GenericEnvironment *genericEnv,
              IsBare_t isBareSILFunction, IsTransparent_t isTrans,
              IsSerialized_t isSerialized, ProfileCounter entryCount,
              IsThunk_t isThunk, SubclassScope classSubclassScope,
              Inline_t inlineStrategy, EffectsKind E,
              const SILDebugScope *debugScope,
              IsDynamicallyReplaceable_t isDynamic,
              IsExactSelfClass_t isExactSelfClass,
              IsDistributed_t isDistributed);

  static SILFunction *
  create(SILModule &M, SILLinkage linkage, StringRef name,
         CanSILFunctionType loweredType, GenericEnvironment *genericEnv,
         Optional<SILLocation> loc, IsBare_t isBareSILFunction,
         IsTransparent_t isTrans, IsSerialized_t isSerialized,
         ProfileCounter entryCount, IsDynamicallyReplaceable_t isDynamic,
         IsDistributed_t isDistributed,
         IsExactSelfClass_t isExactSelfClass,
         IsThunk_t isThunk = IsNotThunk,
         SubclassScope classSubclassScope = SubclassScope::NotApplicable,
         Inline_t inlineStrategy = InlineDefault,
         EffectsKind EffectsKindAttr = EffectsKind::Unspecified,
         SILFunction *InsertBefore = nullptr,
         const SILDebugScope *DebugScope = nullptr);

  void init(SILLinkage Linkage, StringRef Name, CanSILFunctionType LoweredType,
            GenericEnvironment *genericEnv, IsBare_t isBareSILFunction,
            IsTransparent_t isTrans, IsSerialized_t isSerialized,
            ProfileCounter entryCount, IsThunk_t isThunk,
            SubclassScope classSubclassScope, Inline_t inlineStrategy,
            EffectsKind E, const SILDebugScope *DebugScope,
            IsDynamicallyReplaceable_t isDynamic,
            IsExactSelfClass_t isExactSelfClass, IsDistributed_t isDistributed);

  /// Set has ownership to the given value. True means that the function has
  /// ownership, false means it does not.
  ///
  /// Only for use by FunctionBuilders!
  void setHasOwnership(bool newValue) { HasOwnership = newValue; }

  void setName(StringRef name) {
    // All the snapshots share the same name.
    SILFunction *sn = this;
    do {
      sn->Name = name;
    } while ((sn = sn->snapshots) != nullptr);
  }

public:
  ~SILFunction();

  SILModule &getModule() const { return Module; }

  /// Creates a snapshot with a given `ID` from the current function.
  void createSnapshot(int ID);

  /// Returns the snapshot with the given `ID` or null if no such snapshot exists.
  SILFunction *getSnapshot(int ID);

  /// Restores the current function from a given snapshot.
  void restoreFromSnapshot(int ID);

  /// Deletes a snapshot with the `ID`.
  void deleteSnapshot(int ID);

  SILType getLoweredType() const {
    return SILType::getPrimitiveObjectType(LoweredType);
  }
  CanSILFunctionType getLoweredFunctionType() const {
    return LoweredType;
  }
  CanSILFunctionType
  getLoweredFunctionTypeInContext(TypeExpansionContext context) const;

  SILType getLoweredTypeInContext(TypeExpansionContext context) const {
    return SILType::getPrimitiveObjectType(
        getLoweredFunctionTypeInContext(context));
  }

  SILFunctionConventions getConventions() const {
    return SILFunctionConventions(LoweredType, getModule());
  }

  SILFunctionConventions getConventionsInContext() const {
    auto fnType = getLoweredFunctionTypeInContext(getTypeExpansionContext());
    return SILFunctionConventions(fnType, getModule());
  }

  unsigned getIndex() const { return index; }

  SILProfiler *getProfiler() const { return Profiler; }

  SILFunction *getDynamicallyReplacedFunction() const {
    return ReplacedFunction;
  }

  static SILFunction *getFunction(SILDeclRef ref, SILModule &M);

  void setDynamicallyReplacedFunction(SILFunction *f) {
    assert(ReplacedFunction == nullptr && "already set");
    assert(!hasObjCReplacement());

    if (f == nullptr)
      return;
    ReplacedFunction = f;
    ReplacedFunction->incrementRefCount();
  }
  /// This function should only be called when SILFunctions are bulk deleted.
  void dropDynamicallyReplacedFunction() {
    if (!ReplacedFunction)
      return;
    ReplacedFunction->decrementRefCount();
    ReplacedFunction = nullptr;
  }

  SILFunction *getReferencedAdHocRequirementWitnessFunction() const {
    return RefAdHocRequirementFunction;
  }
  // Marks that this `SILFunction` uses the passed in ad-hoc protocol
  // requirement witness `f` and therefore must retain it explicitly,
  // otherwise we might not be able to get a reference to it.
  void setReferencedAdHocRequirementWitnessFunction(SILFunction *f) {
    assert(RefAdHocRequirementFunction == nullptr && "already set");

    if (f == nullptr)
      return;
    RefAdHocRequirementFunction = f;
    RefAdHocRequirementFunction->incrementRefCount();
  }
  void dropReferencedAdHocRequirementWitnessFunction() {
    if (!RefAdHocRequirementFunction)
      return;
    RefAdHocRequirementFunction->decrementRefCount();
    RefAdHocRequirementFunction = nullptr;
  }

  bool hasObjCReplacement() const {
    return !ObjCReplacementFor.empty();
  }

  Identifier getObjCReplacement() const {
    return ObjCReplacementFor;
  }

  void setObjCReplacement(AbstractFunctionDecl *replacedDecl);
  void setObjCReplacement(Identifier replacedDecl);

  void setProfiler(SILProfiler *InheritedProfiler) {
    assert(!Profiler && "Function already has a profiler");
    Profiler = InheritedProfiler;
  }

  void createProfiler(ASTNode Root, SILDeclRef forDecl,
                      ForDefinition_t forDefinition);

  void discardProfiler() { Profiler = nullptr; }

  ProfileCounter getEntryCount() const { return EntryCount; }

  void setEntryCount(ProfileCounter Count) { EntryCount = Count; }

  bool isNoReturnFunction(TypeExpansionContext context) const;

  /// Unsafely rewrite the lowered type of this function.
  ///
  /// This routine does not touch the entry block arguments
  /// or return instructions; you need to do that yourself
  /// if you care.
  ///
  /// This routine does not update all the references in the module
  /// You have to do that yourself
  void rewriteLoweredTypeUnsafe(CanSILFunctionType newType) {
    LoweredType = newType;
  }

  /// Return the number of entities referring to this function (other
  /// than the SILModule).
  unsigned getRefCount() const { return RefCount; }

  /// Increment the reference count.
  void incrementRefCount() {
    RefCount++;
    assert(RefCount != 0 && "Overflow of reference count!");
  }

  /// Decrement the reference count.
  void decrementRefCount() {
    assert(RefCount != 0 && "Expected non-zero reference count on decrement!");
    RefCount--;
  }

  /// Drops all uses belonging to instructions in this function. The only valid
  /// operation performable on this object after this is called is called the
  /// destructor or deallocation.
  void dropAllReferences() {
    for (SILBasicBlock &BB : *this)
      BB.dropAllReferences();
  }

  /// Notify that this function was inlined. This implies that it is still
  /// needed for debug info generation, even if it is removed afterwards.
  void setInlined() {
    assert(!isZombie() && "Can't inline a zombie function");
    Inlined = true;
  }

  /// Returns true if this function was inlined.
  bool isInlined() const { return Inlined; }

  /// Mark this function as removed from the module's function list, but kept
  /// as "zombie" for debug info or vtable stub generation.
  void setZombie() {
    assert(!isZombie() && "Function is a zombie function already");
    Zombie = true;
  }

  /// Returns true if this function is dead, but kept in the module's zombie list.
  bool isZombie() const { return Zombie; }

  /// Returns true if this function has qualified ownership instructions in it.
  bool hasOwnership() const { return HasOwnership; }

  /// Sets the HasOwnership flag to false. This signals to SIL that no
  /// ownership instructions should be in this function any more.
  void setOwnershipEliminated() { setHasOwnership(false); }

  /// Returns true if this function was deserialized from canonical
  /// SIL. (.swiftmodule files contain canonical SIL; .sib files may be 'raw'
  /// SIL). If so, diagnostics should not be reapplied.
  bool wasDeserializedCanonical() const { return WasDeserializedCanonical; }

  void setWasDeserializedCanonical(bool val = true) {
    WasDeserializedCanonical = val;
  }

  bool isStaticallyLinked() const { return IsStaticallyLinked; }

  void setIsStaticallyLinked(bool value) {
    IsStaticallyLinked = value;
  }

  /// Returns true if this is a reabstraction thunk of escaping function type
  /// whose single argument is a potentially non-escaping closure. i.e. the
  /// thunks' function argument may itself have @inout_aliasable parameters.
  bool isWithoutActuallyEscapingThunk() const {
    return IsWithoutActuallyEscapingThunk;
  }

  void setWithoutActuallyEscapingThunk(bool val = true) {
    assert(!val || isThunk() == IsReabstractionThunk);
    IsWithoutActuallyEscapingThunk = val;
  }

  bool isAsync() const { return LoweredType->isAsync(); }

  /// Returns the calling convention used by this entry point.
  SILFunctionTypeRepresentation getRepresentation() const {
    return getLoweredFunctionType()->getRepresentation();
  }

  ResilienceExpansion getResilienceExpansion() const {
    return (isSerialized()
            ? ResilienceExpansion::Minimal
            : ResilienceExpansion::Maximal);
  }

  // Returns the type expansion context to be used inside this function.
  TypeExpansionContext getTypeExpansionContext() const {
    return TypeExpansionContext(*this);
  }

  const Lowering::TypeLowering &
  getTypeLowering(Lowering::AbstractionPattern orig, Type subst);

  const Lowering::TypeLowering &getTypeLowering(Type t) const;

  SILType getLoweredType(Lowering::AbstractionPattern orig, Type subst) const;

  SILType getLoweredType(Type t) const;

  SILType getLoweredLoadableType(Type t) const;

  SILType getLoweredType(SILType t) const;

  const Lowering::TypeLowering &getTypeLowering(SILType type) const;

  bool isTypeABIAccessible(SILType type) const;

  /// Returns true if this function has a calling convention that has a self
  /// argument.
  bool hasSelfParam() const {
    return getLoweredFunctionType()->hasSelfParam();
  }

  /// Returns true if the function has parameters that are consumed by the
  // callee.
  bool hasOwnedParameters() const {
    for (auto &ParamInfo : getLoweredFunctionType()->getParameters()) {
      if (ParamInfo.isConsumed())
        return true;
    }
    return false;
  }

  // Returns true if the function has indirect out parameters.
  bool hasIndirectFormalResults() const {
    return getLoweredFunctionType()->hasIndirectFormalResults();
  }

  /// Returns true if this function ie either a class method, or a
  /// closure that captures the 'self' value or its metatype.
  ///
  /// If this returns true, DynamicSelfType can be used in the body
  /// of the function.
  ///
  /// Note that this is not the same as hasSelfParam().
  ///
  /// For closures that capture DynamicSelfType, hasDynamicSelfMetadata()
  /// is true and hasSelfParam() is false. For methods on value types,
  /// hasSelfParam() is true and hasDynamicSelfMetadata() is false.
  bool hasDynamicSelfMetadata() const;

  /// Return the mangled name of this SILFunction.
  StringRef getName() const { return Name; }

  /// A convenience function which checks if the function has a specific
  /// \p name. It is equivalent to getName() == Name, but as it is not
  /// inlined it can be called from the debugger.
  bool hasName(const char *Name) const;

  /// True if this is a declaration of a function defined in another module.
  bool isExternalDeclaration() const { return BlockList.empty(); }

  /// Returns true if this is a definition of a function defined in this module.
  bool isDefinition() const { return !isExternalDeclaration(); }

  /// Returns true if there exist pre-specializations.
  bool hasPrespecialization() const;

  /// Get this function's linkage attribute.
  SILLinkage getLinkage() const { return SILLinkage(Linkage); }

  /// Set the function's linkage attribute.
  void setLinkage(SILLinkage linkage) { Linkage = unsigned(linkage); }

  /// Returns true if this function can be inlined into a fragile function
  /// body.
  bool hasValidLinkageForFragileInline() const { return isSerialized(); }

  /// Returns true if this function can be referenced from a fragile function
  /// body.
  bool hasValidLinkageForFragileRef() const;

  /// Get's the effective linkage which is used to derive the llvm linkage.
  /// Usually this is the same as getLinkage(), except in one case: if this
  /// function is a method in a class which has higher visibility than the
  /// method itself, the function can be referenced from vtables of derived
  /// classes in other compilation units.
  SILLinkage getEffectiveSymbolLinkage() const {
    return effectiveLinkageForClassMember(getLinkage(),
                                          getClassSubclassScope());
  }

  /// Helper method which returns true if this function has "external" linkage.
  bool isAvailableExternally() const {
    return swift::isAvailableExternally(getLinkage());
  }

  /// Helper method which returns true if the linkage of the SILFunction
  /// indicates that the object's definition might be required outside the
  /// current SILModule.
  bool isPossiblyUsedExternally() const;

  /// In addition to isPossiblyUsedExternally() it returns also true if this
  /// is a (private or internal) vtable method which can be referenced by
  /// vtables of derived classes outside the compilation unit.
  bool isExternallyUsedSymbol() const;

  /// Return whether this function may be referenced by C code.
  bool hasCReferences() const { return HasCReferences; }
  void setHasCReferences(bool value) { HasCReferences = value; }

  /// Returns the availability context used to determine if the function's
  /// symbol should be weakly referenced across module boundaries.
  AvailabilityContext getAvailabilityForLinkage() const {
    return Availability;
  }

  void setAvailabilityForLinkage(AvailabilityContext availability) {
    Availability = availability;
  }

  /// Returns whether this function's symbol must always be weakly referenced
  /// across module boundaries.
  bool isAlwaysWeakImported() const { return IsAlwaysWeakImported; }

  void setIsAlwaysWeakImported(bool value) { IsAlwaysWeakImported = value; }

  bool isWeakImported(ModuleDecl *module) const;

  /// Returns whether this function implementation can be dynamically replaced.
  IsDynamicallyReplaceable_t isDynamicallyReplaceable() const {
    return IsDynamicallyReplaceable_t(IsDynamicReplaceable);
  }
  void setIsDynamic(IsDynamicallyReplaceable_t value = IsDynamic) {
    IsDynamicReplaceable = value;
    assert(!Transparent || !IsDynamicReplaceable);
  }

  IsExactSelfClass_t isExactSelfClass() const {
    return IsExactSelfClass_t(ExactSelfClass);
  }
  void setIsExactSelfClass(IsExactSelfClass_t t) {
    ExactSelfClass = t;
  }

  IsDistributed_t isDistributed() const {
    return IsDistributed_t(IsDistributed);
  }
  void
  setIsDistributed(IsDistributed_t value = IsDistributed_t::IsDistributed) {
    IsDistributed = value;
  }

  bool needsStackProtection() const { return stackProtection; }
  void setNeedStackProtection(bool needSP) { stackProtection = needSP; }

  /// Get the DeclContext of this function.
  DeclContext *getDeclContext() const { return DeclCtxt; }

  /// \returns True if the function is marked with the @_semantics attribute
  /// and has special semantics that the optimizer can use to optimize the
  /// function.
  bool hasSemanticsAttrs() const { return !SemanticsAttrSet.empty(); }

  /// \returns True if the function has a semantic attribute that starts with a
  /// specific string.
  ///
  /// TODO: This needs a better name.
  bool hasSemanticsAttrThatStartsWith(StringRef S) {
    return count_if(getSemanticsAttrs(), [&S](const std::string &Attr) -> bool {
      return StringRef(Attr).startswith(S);
    });
  }

  /// \returns the semantics tag that describes this function.
  ArrayRef<std::string> getSemanticsAttrs() const { return SemanticsAttrSet; }

  /// \returns True if the function has the semantics flag \p Value;
  bool hasSemanticsAttr(StringRef Value) const {
    return count(SemanticsAttrSet, Value);
  }

  /// Add the given semantics attribute to the attr list set.
  void addSemanticsAttr(StringRef Ref) {
    if (hasSemanticsAttr(Ref))
      return;
    SemanticsAttrSet.push_back(Ref.str());
    std::sort(SemanticsAttrSet.begin(), SemanticsAttrSet.end());
  }

  /// Remove the semantics
  void removeSemanticsAttr(StringRef Ref) {
    auto Iter =
        std::remove(SemanticsAttrSet.begin(), SemanticsAttrSet.end(), Ref);
    SemanticsAttrSet.erase(Iter);
  }

  /// \returns the range of specialize attributes.
  ArrayRef<SILSpecializeAttr*> getSpecializeAttrs() const {
    return SpecializeAttrSet;
  }

  /// Removes all specialize attributes from this function.
  void clearSpecializeAttrs() {
    forEachSpecializeAttrTargetFunction(
        [](SILFunction *targetFun) { targetFun->decrementRefCount(); });
    SpecializeAttrSet.clear();
  }

  void addSpecializeAttr(SILSpecializeAttr *Attr);

  void removeSpecializeAttr(SILSpecializeAttr *attr);

  void forEachSpecializeAttrTargetFunction(
      llvm::function_ref<void(SILFunction *)> action);

  /// Get this function's optimization mode or OptimizationMode::NotSet if it is
  /// not set for this specific function.
  OptimizationMode getOptimizationMode() const {
    return OptimizationMode(OptMode);
  }

  /// Returns the optimization mode for the function. If no mode is set for the
  /// function, returns the global mode, i.e. the mode of the module's options.
  OptimizationMode getEffectiveOptimizationMode() const;

  void setOptimizationMode(OptimizationMode mode) {
    OptMode = unsigned(mode);
  }

  /// True if debug information must be preserved (-Onone).
  ///
  /// If this is false (-O), then the presence of debug info must not affect the
  /// outcome of any transformations.
  ///
  /// Typically used to determine whether a debug_value is a normal SSA use or
  /// incidental use.
  bool preserveDebugInfo() const;

  PerformanceConstraints getPerfConstraints() const { return perfConstraints; }

  void setPerfConstraints(PerformanceConstraints perfConstr) {
    perfConstraints = perfConstr;
  }

  /// \returns True if the function is optimizable (i.e. not marked as no-opt),
  ///          or is raw SIL (so that the mandatory passes still run).
  bool shouldOptimize() const;

  /// Returns true if this function should be optimized for size.
  bool optimizeForSize() const {
    return getEffectiveOptimizationMode() == OptimizationMode::ForSize;
  }

  /// Returns true if this is a function that should have its ownership
  /// verified.
  bool shouldVerifyOwnership() const;

  /// Check if the function has a location.
  /// FIXME: All functions should have locations, so this method should not be
  /// necessary.
  bool hasLocation() const {
    return DebugScope && !DebugScope->Loc.isNull();
  }

  /// Get the source location of the function.
  SILLocation getLocation() const {
    assert(DebugScope && "no scope/location");
    return getDebugScope()->Loc;
  }

  /// Initialize the debug scope of the function and also set the DeclCtxt.
  void setDebugScope(const SILDebugScope *DS) {
    DebugScope = DS;
    DeclCtxt = (DS ? DebugScope->Loc.getAsDeclContext() : nullptr);
  }

  /// Returns the module that defines this function.
  ModuleDecl *getParentModule() const {
    return DeclCtxt ? DeclCtxt->getParentModule() : ParentModule;
  }

  /// Sets \c ParentModule as fallback if \c DeclCtxt is not available to
  /// provide the parent module.
  void setParentModule(ModuleDecl *module) {
    assert(!DeclCtxt && "already have a DeclCtxt");
    ParentModule = module;
  }

  /// Initialize the debug scope for debug info on SIL level
  /// (-sil-based-debuginfo).
  void setSILDebugScope(const SILDebugScope *DS) {
    DebugScope = DS;
  }

  /// Get the source location of the function.
  const SILDebugScope *getDebugScope() const { return DebugScope; }

  /// Get this function's bare attribute.
  IsBare_t isBare() const { return IsBare_t(Bare); }
  void setBare(IsBare_t isB) { Bare = isB; }

  /// Get this function's transparent attribute.
  IsTransparent_t isTransparent() const { return IsTransparent_t(Transparent); }
  void setTransparent(IsTransparent_t isT) {
    Transparent = isT;
    assert(!Transparent || !IsDynamicReplaceable);
  }

  /// Get this function's serialized attribute.
  IsSerialized_t isSerialized() const { return IsSerialized_t(Serialized); }
  void setSerialized(IsSerialized_t isSerialized) {
    Serialized = isSerialized;
    assert(this->isSerialized() == isSerialized &&
           "too few bits for Serialized storage");
  }

  /// Get this function's thunk attribute.
  IsThunk_t isThunk() const { return IsThunk_t(Thunk); }
  void setThunk(IsThunk_t isThunk) {
    validateSubclassScope(getClassSubclassScope(), isThunk, SpecializationInfo);
    Thunk = isThunk;
  }

  /// Get the class visibility (relevant for class methods).
  SubclassScope getClassSubclassScope() const {
    return SubclassScope(ClassSubclassScope);
  }
  void setClassSubclassScope(SubclassScope scope) {
    validateSubclassScope(scope, isThunk(), SpecializationInfo);
    ClassSubclassScope = static_cast<unsigned>(scope);
  }

  /// Get this function's noinline attribute.
  Inline_t getInlineStrategy() const { return Inline_t(InlineStrategy); }
  void setInlineStrategy(Inline_t inStr) { InlineStrategy = inStr; }

  /// \return the function side effects information.
  EffectsKind getEffectsKind() const { return EffectsKind(EffectsKindAttr); }

  /// \return True if the function is annotated with the @_effects attribute.
  bool hasEffectsKind() const {
    return EffectsKind(EffectsKindAttr) != EffectsKind::Unspecified;
  }

  /// Set the function side effect information.
  void setEffectsKind(EffectsKind E) {
    EffectsKindAttr = unsigned(E);
  }

  std::pair<const char *, int>  parseEffects(StringRef attrs, bool fromSIL,
                                             int argumentIndex, bool isDerived,
                                             ArrayRef<StringRef> paramNames);
  void writeEffect(llvm::raw_ostream &OS, int effectIdx) const;
  void writeEffects(llvm::raw_ostream &OS) const {
    writeEffect(OS, -1);
  }
  void copyEffects(SILFunction *from);
  bool hasArgumentEffects() const;
  void visitArgEffects(std::function<void(int, int, bool)> c) const;

  Purpose getSpecialPurpose() const { return specialPurpose; }

  /// Get this function's global_init attribute.
  ///
  /// The implied semantics are:
  /// - side-effects can occur any time before the first invocation.
  /// - all calls to the same global_init function have the same side-effects.
  /// - any operation that may observe the initializer's side-effects must be
  ///   preceded by a call to the initializer.
  ///
  /// This is currently true if the function is an addressor that was lazily
  /// generated from a global variable access. Note that the initialization
  /// function itself does not need this attribute. It is private and only
  /// called within the addressor.
  bool isGlobalInit() const { return specialPurpose == Purpose::GlobalInit; }

  bool isGlobalInitOnceFunction() const {
    return specialPurpose == Purpose::GlobalInitOnceFunction;
  }

  bool isLazyPropertyGetter() const {
    return specialPurpose == Purpose::LazyPropertyGetter;
  }

  void setSpecialPurpose(Purpose purpose) { specialPurpose = purpose; }

  /// Return whether this function has a foreign implementation which can
  /// be emitted on demand.
  bool hasForeignBody() const;

  /// Return whether this function corresponds to a Clang node.
  bool hasClangNode() const {
    return ClangNodeOwner != nullptr;
  }

  /// Set the owning declaration of the Clang node associated with this
  /// function.  We have to store an owner (a Swift declaration) instead of
  /// directly referencing the original declaration due to current
  /// limitations in the serializer.
  void setClangNodeOwner(ValueDecl *owner) {
    assert(owner->hasClangNode());
    ClangNodeOwner = owner;
  }

  /// Return the owning declaration of the Clang node associated with this
  /// function.  This should only be used for serialization.
  ValueDecl *getClangNodeOwner() const {
    return ClangNodeOwner;
  }

  /// Return the Clang node associated with this function if it has one.
  ClangNode getClangNode() const {
    return (ClangNodeOwner ? ClangNodeOwner->getClangNode() : ClangNode());
  }
  const clang::Decl *getClangDecl() const {
    return (ClangNodeOwner ? ClangNodeOwner->getClangDecl() : nullptr);
  }

  /// Returns whether this function is a specialization.
  bool isSpecialization() const { return SpecializationInfo != nullptr; }

  /// Return the specialization information.
  const GenericSpecializationInformation *getSpecializationInfo() const {
    assert(isSpecialization());
    return SpecializationInfo;
  }

  void setSpecializationInfo(const GenericSpecializationInformation *Info) {
    assert(!isSpecialization());
    validateSubclassScope(getClassSubclassScope(), isThunk(), Info);
    SpecializationInfo = Info;
  }

  /// If this function is a specialization, return the original function from
  /// which this function was specialized.
  const SILFunction *getOriginOfSpecialization() const;

  /// Retrieve the generic environment containing the mapping from interface
  /// types to context archetypes for this function. Only present if the
  /// function has a body.
  GenericEnvironment *getGenericEnvironment() const {
    return GenericEnv;
  }
  void setGenericEnvironment(GenericEnvironment *env) {
    GenericEnv = env;
  }

  /// Retrieve the generic signature from the generic environment of this
  /// function, if any. Else returns the null \c GenericSignature.
  GenericSignature getGenericSignature() const;

  /// Map the given type, which is based on an interface SILFunctionType and may
  /// therefore be dependent, to a type based on the context archetypes of this
  /// SILFunction.
  Type mapTypeIntoContext(Type type) const;

  /// Map the given type, which is based on an interface SILFunctionType and may
  /// therefore be dependent, to a type based on the context archetypes of this
  /// SILFunction.
  SILType mapTypeIntoContext(SILType type) const;

  /// Converts the given function definition to a declaration.
  void convertToDeclaration() {
    assert(isDefinition() && "Can only convert definitions to declarations");
    clear();
  }

  void clear();

  /// Like `clear`, but does not call `dropAllReferences`, which is the
  /// responsibility of the caller.
  void eraseAllBlocks();

  /// Return the identity substitutions necessary to forward this call if it is
  /// generic.
  SubstitutionMap getForwardingSubstitutionMap();

  /// Returns true if this SILFunction must be a defer statement.
  ///
  /// NOTE: This may return false for defer statements that have been
  /// deserialized without a DeclContext. This means that this is guaranteed to
  /// be correct for SILFunctions in Raw SIL that were not deserialized as
  /// canonical. Thus one can use it for diagnostics.
  bool isDefer() const {
    if (auto *dc = getDeclContext())
      if (auto *decl = dyn_cast_or_null<FuncDecl>(dc->getAsDecl()))
        return decl->isDeferBody();
    return false;
  }

  /// Returns true if this function belongs to a declaration that
  /// has `@_alwaysEmitIntoClient` attribute.
  bool markedAsAlwaysEmitIntoClient() const {
    if (!hasLocation())
      return false;

    auto *V = getLocation().getAsASTNode<ValueDecl>();
    return V && V->getAttrs().hasAttribute<AlwaysEmitIntoClientAttr>();
  }

  /// Returns true if this function belongs to a declaration that returns
  /// an opaque result type with one or more availability conditions that are
  /// allowed to produce a different underlying type at runtime.
  bool hasOpaqueResultTypeWithAvailabilityConditions() const {
    if (!hasLocation())
      return false;

    if (auto *V = getLocation().getAsASTNode<ValueDecl>()) {
      auto *opaqueResult = V->getOpaqueResultTypeDecl();
      return opaqueResult &&
             opaqueResult->hasConditionallyAvailableSubstitutions();
    }

    return false;
  }

  //===--------------------------------------------------------------------===//
  // Block List Access
  //===--------------------------------------------------------------------===//

  using iterator = BlockListType::iterator;
  using reverse_iterator = BlockListType::reverse_iterator;
  using const_iterator = BlockListType::const_iterator;

  bool empty() const { return BlockList.empty(); }
  iterator begin() { return BlockList.begin(); }
  iterator end() { return BlockList.end(); }
  reverse_iterator rbegin() { return BlockList.rbegin(); }
  reverse_iterator rend() { return BlockList.rend(); }
  const_iterator begin() const { return BlockList.begin(); }
  const_iterator end() const { return BlockList.end(); }
  unsigned size() const { return BlockList.size(); }

  SILBasicBlock &front() { return *begin(); }
  const SILBasicBlock &front() const { return *begin(); }

  SILBasicBlock *getEntryBlock() { return &front(); }
  const SILBasicBlock *getEntryBlock() const { return &front(); }

  SILBasicBlock *createBasicBlock();
  SILBasicBlock *createBasicBlockAfter(SILBasicBlock *afterBB);
  SILBasicBlock *createBasicBlockBefore(SILBasicBlock *beforeBB);

  /// Removes and destroys \p BB;
  void eraseBlock(SILBasicBlock *BB) {
    assert(BB->getParent() == this);
    BlockList.erase(BB);
  }

  /// Transfer all blocks of \p F into this function, at the begin of the block
  /// list.
  void moveAllBlocksFromOtherFunction(SILFunction *F);

  /// Transfer \p blockInOtherFunction of another function into this function,
  /// before \p insertPointInThisFunction.
  void moveBlockFromOtherFunction(SILBasicBlock *blockInOtherFunction,
                                  iterator insertPointInThisFunction);

  /// Move block \p BB to immediately before the iterator \p IP.
  ///
  /// The block must be part of this function.
  void moveBlockBefore(SILBasicBlock *BB, SILFunction::iterator IP);

  /// Move block \p BB to immediately after block \p After.
  ///
  /// The block must be part of this function.
  void moveBlockAfter(SILBasicBlock *BB, SILBasicBlock *After) {
    moveBlockBefore(BB, std::next(After->getIterator()));
  }

  /// Return the unique basic block containing a return inst if it
  /// exists. Otherwise, returns end.
  iterator findReturnBB() {
    return std::find_if(begin(), end(),
      [](const SILBasicBlock &BB) -> bool {
        const TermInst *TI = BB.getTerminator();
        return isa<ReturnInst>(TI);
    });
  }

  /// Return the unique basic block containing a return inst if it
  /// exists. Otherwise, returns end.
  const_iterator findReturnBB() const {
    return std::find_if(begin(), end(),
      [](const SILBasicBlock &BB) -> bool {
        const TermInst *TI = BB.getTerminator();
        return isa<ReturnInst>(TI);
    });
  }

  /// Return the unique basic block containing a throw inst if it
  /// exists. Otherwise, returns end.
  iterator findThrowBB() {
    return std::find_if(begin(), end(),
                        [](const SILBasicBlock &BB) -> bool {
                          const TermInst *TI = BB.getTerminator();
                          return isa<ThrowInst>(TI);
                        });
  }

  /// Return the unique basic block containing a throw inst if it
  /// exists. Otherwise, returns end.
  const_iterator findThrowBB() const {
    return std::find_if(begin(), end(),
                        [](const SILBasicBlock &BB) -> bool {
                          const TermInst *TI = BB.getTerminator();
                          return isa<ThrowInst>(TI);
                        });
  }

  /// Loop over all blocks in this function and add all function exiting blocks
  /// to output.
  void findExitingBlocks(llvm::SmallVectorImpl<SILBasicBlock *> &output) const {
    for (auto &Block : const_cast<SILFunction &>(*this)) {
      if (Block.getTerminator()->isFunctionExiting()) {
        output.emplace_back(&Block);
      }
    }
  }

  //===--------------------------------------------------------------------===//
  // Argument Helper Methods
  //===--------------------------------------------------------------------===//

  SILArgument *getArgument(unsigned i) {
    assert(!empty() && "Cannot get argument of a function without a body");
    return begin()->getArgument(i);
  }

  const SILArgument *getArgument(unsigned i) const {
    assert(!empty() && "Cannot get argument of a function without a body");
    return begin()->getArgument(i);
  }

  ArrayRef<SILArgument *> getArguments() const {
    assert(!empty() && "Cannot get arguments of a function without a body");
    return begin()->getArguments();
  }

  ArrayRef<SILArgument *> getIndirectResults() const {
    assert(!empty() && "Cannot get arguments of a function without a body");
    return begin()->getArguments().slice(
        0, getConventions().getNumIndirectSILResults());
  }

  ArrayRef<SILArgument *> getArgumentsWithoutIndirectResults() const {
    assert(!empty() && "Cannot get arguments of a function without a body");
    return begin()->getArguments().slice(
        getConventions().getNumIndirectSILResults());
  }

  const SILArgument *getSelfArgument() const {
    assert(hasSelfParam() && "This method can only be called if the "
                             "SILFunction has a self parameter");
    return getArguments().back();
  }

  const SILArgument *getDynamicSelfMetadata() const {
    assert(hasDynamicSelfMetadata() && "This method can only be called if the "
           "SILFunction has a self-metadata parameter");
    return getArguments().back();
  }

  //===--------------------------------------------------------------------===//
  // Miscellaneous
  //===--------------------------------------------------------------------===//

  /// A value's lifetime, determined by looking at annotations on its decl and
  /// the default lifetime for the type.
  Lifetime getLifetime(VarDecl *decl, SILType ty) {
    return ty.getLifetime(*this).getLifetimeForAnnotatedValue(
        decl->getLifetimeAnnotation());
  }

  /// verify - Run the IR verifier to make sure that the SILFunction follows
  /// invariants.
  void verify(bool SingleFunction = true) const;

  /// Verifies the lifetime of memory locations in the function.
  void verifyMemoryLifetime();

  /// Run the SIL ownership verifier to check for ownership invariant failures.
  ///
  /// NOTE: The ownership verifier is always run when performing normal IR
  /// verification, so this verification can be viewed as a subset of
  /// SILFunction::verify.
  void verifyOwnership(DeadEndBlocks *deadEndBlocks) const;

  /// Verify that all non-cond-br critical edges have been split.
  ///
  /// This is a fast subset of the checks performed in the SILVerifier.
  void verifyCriticalEdges() const;

  /// Pretty-print the SILFunction.
  void dump(bool Verbose) const;
  void dump() const;

  /// Pretty-print the SILFunction.
  /// Useful for dumping the function when running in a debugger.
  /// Warning: no error handling is done. Fails with an assert if the file
  /// cannot be opened.
  void dump(const char *FileName) const;

  /// Pretty-print the SILFunction to the tream \p OS.
  ///
  /// \param Verbose Dump SIL location information in verbose mode.
  void print(raw_ostream &OS, bool Verbose = false) const {
    SILPrintContext PrintCtx(OS, Verbose);
    print(PrintCtx);
  }

  /// Pretty-print the SILFunction with the context \p PrintCtx.
  void print(SILPrintContext &PrintCtx) const;

  /// Pretty-print the SILFunction's name using SIL syntax,
  /// '@function_mangled_name'.
  void printName(raw_ostream &OS) const;

  /// Assigns consecutive numbers to all the SILNodes in the function.
  /// For instructions, both the instruction node and the value nodes of
  /// any results will be assigned numbers; the instruction node will
  /// be numbered the same as the first result, if there are any results.
  void numberValues(llvm::DenseMap<const SILNode*, unsigned> &nodeToNumberMap)
    const;

  ASTContext &getASTContext() const;

  /// This function is meant for use from the debugger.  You can just say 'call
  /// F->viewCFG()' and a ghostview window should pop up from the program,
  /// displaying the CFG of the current function with the code for each basic
  /// block inside.  This depends on there being a 'dot' and 'gv' program in
  /// your path.
  void viewCFG() const;
  /// Like ViewCFG, but the graph does not show the contents of basic blocks.
  void viewCFGOnly() const;

};

inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
                                     const SILFunction &F) {
  F.print(OS);
  return OS;
}

} // end swift namespace

//===----------------------------------------------------------------------===//
// ilist_traits for SILFunction
//===----------------------------------------------------------------------===//

namespace llvm {

template <>
struct ilist_traits<::swift::SILFunction> :
public ilist_node_traits<::swift::SILFunction> {
  using SILFunction = ::swift::SILFunction;

public:
  static void deleteNode(SILFunction *V) { V->~SILFunction(); }

private:
  void createNode(const SILFunction &);
};

} // end llvm namespace

#endif


text:
from locust import HttpLocust, TaskSet, task

import random

urls = [l.strip() for l in open('accesslog.txt').readlines()]

class WebsiteTasks(TaskSet):

    @task
    def request(self):
        url = random.choice(urls)
        self.client.get(url, verify=False)

class WebsiteUser(HttpLocust):
    min_wait = 2000
    max_wait = 5000
    task_set = WebsiteTasks

redpajama_set_name: RedPajamaGithub


text:
"use strict;"

require("../dist/crisp-base");

module.exports = require("../test_/BaseJS-xEach_test.js");


text:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="description" content="Blog and website of Panos Sakkos, blogging mainly for tech. Opinions expressed are mine." />
    <meta name="author" content="" />
    <meta name="keywords" content="panos, sakkos, panos sakkos, technology, computer science, Pwn Mail, WriteRight, UoA, di, CERN, MDCN, Microsoft" />
    <link rel="canonical" href="http://panossakkos.github.io/">

    <title>{ Panos Sakkos } </title>

    <link href="/css/bootstrap.min.css" rel="stylesheet">

    <link href="/css/grayscale.css" rel="stylesheet">
    <link href="/css/timeline.css" rel="stylesheet">

    <link href="/font-awesome/css/font-awesome.min.css" rel="stylesheet" type="text/css">
    <link href="//fonts.googleapis.com/css?family=Lora:400,700,400italic,700italic" rel="stylesheet" type="text/css">
    <link href="//fonts.googleapis.com/css?family=Montserrat:400,700" rel="stylesheet" type="text/css">

    <link rel="shortcut icon" type="image/x-icon" href="/img/favicon.ico">

            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-main-collapse">

            </button>

  { Panos Sakkos }

                       About

                       Blog

                       Career

                       Contact

Hope you are visiting while not in your  Dark Playground

About

Thanks for dropping by. I hope that it will not waste your time, but in case it does, at least I tried.
Originally from Athens, Greece, I started my adventures in Computer Science and Technology from University of Athens where I received my Bachelor in Computer Science and Master in Software Engineering.
Between those, I spent a creative year in Geneva, Switzerland where I worked at CERN as a Computer Security researcher.
While attending my master's, I was working as a Machine Learning researcher for the KDD lab, supervised by Dimitrios Gunopulos.
During my last summer break of my studies, I moved to Oslo, Norway, as an intern for Microsoft Development Center Norway.
That place won me and became my first working place in my post-academic life.

But, apart from being a cool guy geek,
I enjoy playing and composing music, messing with hardware, playing card games, yo-yoing and collecting comic books and vinyls.
In general, my mind can zone out during any form of creative act. Opinions expressed here are mine.

Blog

  11 Jul 2015
          . tech .
           Ad Hell
           Comments

I never click on ads, because I don't see any value in them. During the last ten years I clicked (intentionally) on literally one ad from a wallet company. But, this company would be also my first result in my (incognito) Google search. And I was actually planning to buy a slim card wallet, I didn't start googling because of the ad. So, did I buy the product of the ad? Yes. Did the ad convince me to buy the product? No. An image of a product with a catchy phrase will never convince me to buy it. I want to do my research and evaluate my options before buying anything. After I evaluated a few of the "slim card wallets" Google results, I…

View more posts

Career

September 2014 - Today

Software Engineer @ Microsoft Development Center Norway, working @ the  Office Graph

October 2012 - August 2014

Master studies @ Department of Informatics and Telecommunications on Software Engineering + Machine Learning researcher @ KDD lab

October 2011 - September 2012

Security researcher @ CERN, developed linux kernel extensions to prevent cyber attacks

August 2011 - Today

Released WriteRight, an adaptive S/W keyboard for Android devices, which  shrinks the unlikely keys to tap next. Currently it holds > 9,000 downloads

June 2010 - November 2010

Released Pwn Mail, an iPhone app for spoofing emails. It served > 260,000 emails but it was discontinued after a legal threat by Steve Jobs a secretary of Steve Jobs

October 2007 - September 2011

Bachelor studies @ Department of Informatics and Telecommunications on Computer Science and Telecomunications

Contact

Send me an email if you would like to get in touch, hire me for your next project, have questions or feedback on my work, or just want to say hello.

panoss .a:t. microsoft /d|o|t\ com

Copyright ©  2015


text:
package me.qyh.blog.plugin.qiniu;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.UrlResource;
import org.springframework.web.multipart.MultipartFile;

import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.BucketManager.Batch;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.FileInfo;
import com.qiniu.storage.model.FileListing;
import com.qiniu.util.Auth;

import me.qyh.blog.core.exception.LogicException;
import me.qyh.blog.core.exception.SystemException;
import me.qyh.blog.core.message.Message;
import me.qyh.blog.core.util.FileUtils;
import me.qyh.blog.core.util.Jsons;
import me.qyh.blog.core.util.Jsons.ExpressionExecutor;
import me.qyh.blog.core.util.Resources;
import me.qyh.blog.core.util.UrlUtils;
import me.qyh.blog.core.util.Validators;
import me.qyh.blog.file.entity.CommonFile;
import me.qyh.blog.file.store.FileStore;
import me.qyh.blog.file.store.ImageHelper;
import me.qyh.blog.file.store.ImageHelper.ImageInfo;
import me.qyh.blog.file.store.Resize;
import me.qyh.blog.file.store.ThumbnailUrl;

/**
 *
 * @author Administrator
 *
 */
public class QiniuFileStore implements FileStore {

	protected static final Logger LOGGER = LoggerFactory.getLogger(QiniuFileStore.class);

	private final int id;
	private final String name;

	protected Resize smallResize;
	protected Resize middleResize;
	protected Resize largeResize;

	private boolean readOnly;

	private String urlPrefix;// 外链域名
	private Character styleSplitChar;// 样式分隔符
	private boolean sourceProtected;// 原图保护
	private String style;// 样式

	/**
	 * 七牛云推荐的分页条数
	 */
	private static final int RECOMMEND_LIMIT = 100;

	private final String bucket;
	private final Auth auth;

	private static final int FILE_NOT_EXISTS_ERROR_CODE = 612;// 文件不存在错误码

	private static final String IMAGE_INFO_PARAM = "?imageInfo";

	public QiniuFileStore(int id, String name, QiniuConfig config) {
		if (Validators.isEmptyOrNull(config.getAccessKey(), true)
				|| Validators.isEmptyOrNull(config.getSecretKey(), true)) {
			throw new IllegalArgumentException("请提供accessKey和secretKey");
		}

		if (Validators.isEmptyOrNull(config.getBucket(), true)) {
			throw new IllegalArgumentException("请提供bucket");
		}

		String urlPrefix = config.getUrlPrefix();

		if (Validators.isEmptyOrNull(urlPrefix, true)) {
			throw new IllegalArgumentException("外链域名不能为空");
		}
		if (!UrlUtils.isAbsoluteUrl(urlPrefix)) {
			throw new IllegalArgumentException("外链域名必须是一个绝对路径");
		}
		if (!urlPrefix.endsWith("/")) {
			urlPrefix += "/";
		}

		boolean sourceProtected = config.isSourceProtected();

		String style = config.getStyle();
		Character styleSplitChar = config.getStyleSplitChar();

		if (sourceProtected) {
			if (style == null) {
				throw new IllegalArgumentException("开启了原图保护之后请指定一个默认的样式名");
			}
			if (styleSplitChar == null) {
				styleSplitChar = '-';
			}
		}

		this.id = id;
		this.name = name;

		this.auth = Auth.create(config.getAccessKey(), config.getSecretKey());
		this.bucket = config.getBucket();

		if (config.getSmallSize() != null) {
			this.smallResize = new Resize(config.getSmallSize());
		}

		if (config.getMiddleSize() != null) {
			this.middleResize = new Resize(config.getMiddleSize());
		}

		if (config.getLargeSize() != null) {
			this.largeResize = new Resize(config.getLargeSize());
		}

		this.readOnly = config.isReadonly();
		this.styleSplitChar = styleSplitChar;
		this.style = style;
		this.sourceProtected = sourceProtected;
		this.urlPrefix = urlPrefix;
	}

	@Override
	public final CommonFile store(String key, MultipartFile multipartFile) throws LogicException {
		if (!delete(key)) {
			throw new LogicException("file.store.exists", "文件" + key + "已经存在", key);
		}
		String originalFilename = multipartFile.getOriginalFilename();
		String extension = FileUtils.getFileExtension(originalFilename);
		Path tmp = FileUtils.appTemp(extension);
		try (InputStream is = multipartFile.getInputStream()) {
			Files.copy(is, tmp, StandardCopyOption.REPLACE_EXISTING);
		} catch (IOException e) {
			throw new SystemException(e.getMessage(), e);
		}
		CommonFile cf = new CommonFile();

		String vkey = FileUtils.cleanPath(key);
		doUpload(vkey, tmp);

		cf.setExtension(extension);

		if (ImageHelper.isSystemAllowedImage(extension)) {
			try {
				ImageInfo ii = this.readImage(vkey);
				cf.setExtension(ii.getExtension());
			} catch (IOException e) {
				LOGGER.debug(e.getMessage(), e);
				throw new LogicException(new Message("image.corrupt", "不是正确的图片文件或者图片已经损坏"));
			}
		}

		cf.setOriginalFilename(originalFilename);
		cf.setSize(multipartFile.getSize());
		cf.setStore(id);
		return cf;
	}

	private void doUpload(String vkey, Path tmp) {
		try {
			upload(vkey, tmp);
		} catch (IOException e) {
			throw new SystemException(e.getMessage(), e);
		}
	}

	protected void upload(String key, Path file) throws IOException {
		UploadManager uploadManager = new UploadManager();
		try {
			Response resp = uploadManager.put(file.toFile(), key, getUpToken());
			if (!resp.isOK()) {
				throw new IOException("七牛云上传失败,异常信息:" + resp.toString() + ",响应信息:" + resp.bodyString());
			}
		} catch (QiniuException e) {
			Response r = e.response;
			try {
				throw new IOException("七牛云上传失败,异常信息:" + r.toString() + ",响应信息:" + r.bodyString(), e);
			} catch (QiniuException e1) {
				LOGGER.debug(e1.getMessage(), e1);
			}
		}
	}

	// 简单上传,使用默认策略,只需要设置上传的空间名就可以了
	protected String getUpToken() {
		return auth.uploadToken(bucket);
	}

	/**
	 * 读取图片信息
	 *
	 * @param key
	 * @return
	 * @throws IOException
	 *             图片损坏或者格式不被接受
	 */
	protected ImageInfo readImage(String key) throws IOException {
		String json = Resources.readResourceToString(new UrlResource(urlPrefix + key + IMAGE_INFO_PARAM));
		ExpressionExecutor executor = Jsons.readJson(json);
		if (executor.isNull()) {
			throw new IOException("无法将结果转化为json信息:" + json);
		}
		try {
			String format = executor.execute("format").orElseThrow(() -> new SystemException("无法获取图片的格式:" + json));
			Integer width = Integer
					.parseInt(executor.execute("width").orElseThrow(() -> new SystemException("无法获取图片的宽度:" + json)));
			Integer height = Integer
					.parseInt(executor.execute("height").orElseThrow(() -> new SystemException("无法获取图片的高度:" + json)));
			return new ImageInfo(width, height, format);
		} catch (Exception e) {
			throw new IOException("获取图片信息失败:" + json, e);
		}
	}

	@Override
	public int id() {
		return id;
	}

	@Override
	public final boolean deleteBatch(String key) {
		String vkey = FileUtils.cleanPath(key);
		return doDeleteBatch(vkey);
	}

	@Override
	public final boolean delete(String key) {
		String vkey = FileUtils.cleanPath(key);
		return doDelete(vkey);
	}

	@Override
	public String name() {
		return name;
	}

	@Override
	public boolean readOnly() {
		return readOnly;
	}

	@Override
	public boolean move(String oldPath, String path) {
		String vo = FileUtils.cleanPath(oldPath);
		String vp = FileUtils.cleanPath(path);
		if (doCopy(vo, vp)) {
			if (delete(vo)) {
				return true;
			} else {
				delete(vp);
			}
		}
		return false;
	}

	@Override
	public final boolean copy(String oldPath, String path) {
		String vo = FileUtils.cleanPath(oldPath);
		String vp = FileUtils.cleanPath(path);
		return doCopy(vo, vp);
	}

	protected boolean doCopy(String oldPath, String path) {
		try {
			new BucketManager(auth).copy(bucket, oldPath, bucket, path);
			return true;
		} catch (QiniuException e) {
			try {
				Response r = e.response;
				LOGGER.error("七牛云拷贝文件失败,异常信息:" + r.toString() + ",响应信息:" + r.bodyString(), e);
			} catch (QiniuException e1) {
				LOGGER.debug(e1.getMessage(), e1);
			}
		}
		return false;
	}

	protected boolean doDelete(String key) {
		boolean flag = false;
		BucketManager bucketManager = new BucketManager(auth);
		try {
			bucketManager.delete(bucket, key);
			flag = true;
		} catch (QiniuException e) {
			Response r = e.response;
			if (r.statusCode == FILE_NOT_EXISTS_ERROR_CODE) {
				flag = true;
			} else {
				try {
					LOGGER.error("七牛云删除失败,异常信息:" + r.toString() + ",响应信息:" + r.bodyString(), e);
				} catch (QiniuException e1) {
					LOGGER.debug(e1.getMessage(), e1);
				}
			}
		}
		return flag;
	}

	@Override
	public String getUrl(String key) {
		String url = urlPrefix + key;
		if (isSystemAllowedImage(key) && sourceProtected) {
			return url + styleSplitChar + style;
		}
		return url;
	}

	@Override
	public Optional<ThumbnailUrl> getThumbnailUrl(String key) {

		if (isSystemAllowedImage(key)) {
			if (sourceProtected) {
				// 只能采用样式访问
				String url = urlPrefix + key + styleSplitChar + style;
				return Optional.of(new QiniuThumbnailUrl(url, url, url, key));
			} else {
				String small = buildThumbnailUrl(key, smallResize);
				String middle = buildThumbnailUrl(key, middleResize);
				String large = buildThumbnailUrl(key, largeResize);
				return Optional.of(new QiniuThumbnailUrl(small, middle, large, key));
			}
		}
		return Optional.empty();
	}

	private final class QiniuThumbnailUrl extends ThumbnailUrl {

		/**
		 *
		 */
		private static final long serialVersionUID = 1L;
		private final String key;

		private QiniuThumbnailUrl(String small, String middle, String large, String key) {
			super(small, middle, large);
			this.key = key;
		}

		@Override
		public String getThumbUrl(int width, int height, boolean keepRatio) {
			return buildThumbnailUrl(key, new Resize(width, height, keepRatio));
		}

		@Override
		public String getThumbUrl(int size) {
			return buildThumbnailUrl(key, new Resize(size));
		}

	}

	protected boolean doDeleteBatch(String key) {
		try {
			List<String> keys = new ArrayList<>();
			BucketManager bucketManager = new BucketManager(auth);
			FileListing fileListing = bucketManager.listFiles(bucket, key + '/', null, RECOMMEND_LIMIT, null);

			do {
				FileInfo[] items = fileListing.items;
				if (items != null && items.length > 0) {
					for (FileInfo fileInfo : items) {
						keys.add(fileInfo.key);
					}
				}
				fileListing = bucketManager.listFiles(bucket, key + '/', fileListing.marker, RECOMMEND_LIMIT, null);
			} while (!fileListing.isEOF());

			if (keys.isEmpty()) {
				return true;
			}

			Batch batch = new Batch();
			batch.delete(bucket, keys.toArray(new String[] {}));
			return bucketManager.batch(batch).isOK();
		} catch (QiniuException e) {
			// 捕获异常信息
			Response r = e.response;
			LOGGER.error(r.toString(), e);
		}
		return false;
	}

	/**
	 * 构造缩略图信息地址
	 *
	 * @param key
	 *            key
	 * @param resize
	 *            缩放信息,可能为null
	 * @return
	 */
	protected String buildThumbnailUrl(String key, Resize resize) {
		return urlPrefix + key + buildResizeParam(resize).map(param -> "?" + param).orElse("");
	}

	/**
	 * {@link Resize#isKeepRatio()}设置无效
	 *
	 * @return
	 */
	protected Optional<String> buildResizeParam(Resize resize) {
		String result = null;
		if (resize != null) {
			if (resize.getSize() != null) {
				result = "imageView2/2/w/" + resize.getSize() + "/h/" + resize.getSize();
			} else if (resize.getWidth() == 0 && resize.getHeight() == 0) {
				result = null;
			} else if (resize.getWidth() == 0) {
				result = "imageView2/2/h/" + resize.getHeight();
			} else if (resize.getHeight() == 0) {
				result = "imageView2/2/w/" + resize.getWidth();
			} else {
				result = "imageView2/2/w/" + resize.getWidth() + "/h/" + resize.getHeight();
			}
		}
		return Optional.ofNullable(result);
	}

	@Override
	public boolean canStore(MultipartFile multipartFile) {
		return true;// can store any file
	}

	protected final boolean isSystemAllowedImage(String key) {
		return ImageHelper.isSystemAllowedImage(FileUtils.getFileExtension(key));
	}

	public void setSmallResize(Resize smallResize) {
		this.smallResize = smallResize;
	}

	public void setMiddleResize(Resize middleResize) {
		this.middleResize = middleResize;
	}

	public void setLargeResize(Resize largeResize) {
		this.largeResize = largeResize;
	}

	public void setReadOnly(boolean readOnly) {
		this.readOnly = readOnly;
	}
}


text:
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <dlfcn.h>
#include <stdlib.h>
#include <string.h>

#include <security/pam_appl.h>

#include "openpam_impl.h"

/*
 * Locate a matching dynamic or static module.
 */

pam_module_t *
openpam_load_module(const char *modulename)
{
	pam_module_t *module;

	module = openpam_dynamic(modulename);
	openpam_log(PAM_LOG_DEBUG, "%s dynamic %s",
	    (module == NULL) ? "no" : "using", modulename);

#ifdef OPENPAM_STATIC_MODULES
	/* look for a static module */
	if (module == NULL && strchr(modulename, '/') == NULL) {
		module = openpam_static(modulename);
		openpam_log(PAM_LOG_DEBUG, "%s static %s",
		    (module == NULL) ? "no" : "using", modulename);
	}
#endif
	if (module == NULL) {
		openpam_log(PAM_LOG_ERROR, "no %s found", modulename);
		return (NULL);
	}
	return (module);
}

/*
 * Release a module.
 * XXX highly thread-unsafe
 */

static void
openpam_release_module(pam_module_t *module)
{
	if (module == NULL)
		return;
	if (module->dlh == NULL)
		/* static module */
		return;
	dlclose(module->dlh);
	openpam_log(PAM_LOG_DEBUG, "releasing %s", module->path);
	FREE(module->path);
	FREE(module);
}

/*
 * Destroy a chain, freeing all its links and releasing the modules
 * they point to.
 */

static void
openpam_destroy_chain(pam_chain_t *chain)
{
	if (chain == NULL)
		return;
	openpam_destroy_chain(chain->next);
	chain->next = NULL;
	FREEV(chain->optc, chain->optv);
	openpam_release_module(chain->module);
	chain->module = NULL;
	FREE(chain);
}

/*
 * Clear the chains and release the modules
 */

void
openpam_clear_chains(pam_chain_t *policy[])
{
	int i;

	for (i = 0; i < PAM_NUM_FACILITIES; ++i) {
		openpam_destroy_chain(policy[i]);
		policy[i] = NULL;
	}
}

/*
 * NOPARSE
 */


text:
package org.springframework.cloud.contract.verifier.messaging.boot;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.boot.autoconfigure.ImportAutoConfiguration;

/**
 * @author Dave Syer
 *
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ImportAutoConfiguration
public @interface AutoConfigureMessageVerifier {

}


text:
.. _96b_avenger96:

96Boards Avenger96
##################

Overview
********

96Boards Avenger96 board is based on ST Microelectronics STM32MP157A
multi-core processor, composed of a dual Cortex®-A7 and a single Cortex®-M4
core. Zephyr OS is ported to run on the Cortex®-M4 core.

- Board features:

  - PMIC: STPMIC1A
  - RAM: 1024 Mbyte @ 533MHz
  - Storage:

    - eMMC: v4.51: 8 Gbyte
    - QSPI: 2Mbyte
    - EEPROM: 128 byte
    - microSD Socket: UHS-1 v3.01
  - Ethernet: 10/100/1000 Mbit/s, IEEE 802.3 Compliant
  - Wireless:

    - WiFi: 5 GHz & 2.4GHz IEEE 802.11a/b/g/n/ac
    - Bluetooth: v4.2 (BR/EDR/BLE)
  - USB:

    - Host - 2x type A, 2.0 high-speed
    - OTG: - 1x type micro-AB, 2.0 high-speed
  - HDMI: WXGA (1366x768)@ 60 fps, HDMI 1.4
  - Connectors:

    - 40-Pin Low Speed Header
    - 60-Pin High Speed Header
  - LEDs:

    - 4x Green user LEDs
    - 1x Blue Bluetooth LED
    - 1x Yellow WiFi LED
    - 1x Red power supply LED

.. image:: img/96b_avenger96.jpg
     :align: center
     :alt: 96Boards Avenger96

More information about the board can be found at the
`96Boards website`_.

Hardware
********

The STM32MP157A SoC provides the following hardware capabilities:

- Core:

  - 32-bit dual-core Arm® Cortex®-A7

    - L1 32-Kbyte I / 32-Kbyte D for each core
    - 256-Kbyte unified level 2 cache
    - Arm® NEON™

  - 32-bit Arm® Cortex®-M4 with FPU/MPU

    - Up to 209 MHz (Up to 703 CoreMark®)

- Memories:

  - External DDR memory up to 1 Gbyte.
  - 708 Kbytes of internal SRAM: 256 KB of AXI SYSRAM + 384 KB of AHB SRAM +
    64 KB of AHB SRAM in backup domain.
  - Dual mode Quad-SPI memory interface
  - Flexible external memory controller with up to 16-bit data bus

- Clock management:

  - Internal oscillators: 64 MHz HSI oscillator, 4 MHz CSI oscillator, 32 kHz
    LSI oscillator
  - External oscillators: 8-48 MHz HSE oscillator, 32.768 kHz LSE oscillator
  - 6 × PLLs with fractional mode

- General-purpose input/outputs:

  - Up to 176 I/O ports with interrupt capability

- Interconnect matrix

- 3 DMA controllers

- Communication peripherals:

  - 6 × I2C FM+ (1 Mbit/s, SMBus/PMBus)
  - 4 × UART + 4 × USART (12.5 Mbit/s, ISO7816 interface, LIN, IrDA, SPI slave)
  - 6 × SPI (50 Mbit/s, including 3 with full duplex I2S audio class accuracy)
  - 4 × SAI (stereo audio: I2S, PDM, SPDIF Tx)
  - SPDIF Rx with 4 inputs
  - HDMI-CEC interface
  - MDIO Slave interface
  - 3 × SDMMC up to 8-bit (SD / e•MMC™ / SDIO)
  - 2 × CAN controllers supporting CAN FD protocol, TTCAN capability
  - 2 × USB 2.0 high-speed Host+ 1 × USB 2.0 full-speed OTG simultaneously
  - 10/100M or Gigabit Ethernet GMAC (IEEE 1588v2 hardware, MII/RMII/GMII/RGMI)
  - 8- to 14-bit camera interface up to 140 Mbyte/s
  - 6 analog peripherals
  - 2 × ADCs with 16-bit max. resolution.
  - 1 × temperature sensor
  - 2 × 12-bit D/A converters (1 MHz)
  - 1 × digital filters for sigma delta modulator (DFSDM) with 8 channels/6
    filters
  - Internal or external ADC/DAC reference VREF+

- Graphics:

  - 3D GPU: Vivante® - OpenGL® ES 2.0
  - LCD-TFT controller, up to 24-bit // RGB888, up to WXGA (1366 × 768) @60 fps
  - MIPI® DSI 2 data lanes up to 1 GHz each

- Timers:

  - 2 × 32-bit timers with up to 4 IC/OC/PWM or pulse counter and quadrature
    (incremental) encoder input
  - 2 × 16-bit advanced motor control timers
  - 10 × 16-bit general-purpose timers (including 2 basic timers without PWM)
  - 5 × 16-bit low-power timers
  - RTC with sub-second accuracy and hardware calendar
  - 2 × 4 Cortex®-A7 system timers (secure, non-secure, virtual, hypervisor)
  - 1 × SysTick Cortex®-M4 timer

- Hardware acceleration:

  - HASH (MD5, SHA-1, SHA224, SHA256), HMAC
  - 2 × true random number generator (3 oscillators each)
  - 2 × CRC calculation unit

- Debug mode:

  - Arm® CoreSight™ trace and debug: SWD and JTAG interfaces
  - 8-Kbyte embedded trace buffer
  - 3072-bit fuses including 96-bit unique ID, up to 1184-bit available for user

More information about STM32P157A can be found here:

- `STM32MP157A on www.st.com`_
- `STM32MP157A reference manual`_

Supported Features
==================

The Zephyr 96b_avenger96 board configuration supports the following hardware
features:

+-----------+------------+-------------------------------------+
| Interface | Controller | Driver/Component                    |
+===========+============+=====================================+
| NVIC      | on-chip    | nested vector interrupt controller  |
+-----------+------------+-------------------------------------+
| GPIO      | on-chip    | gpio                                |
+-----------+------------+-------------------------------------+
| UART      | on-chip    | serial port-polling;                |
|           |            | serial port-interrupt               |
+-----------+------------+-------------------------------------+
| PINMUX    | on-chip    | pinmux                              |
+-----------+------------+-------------------------------------+

The default configuration can be found in the defconfig file:
``boards/arm/96b_avenger96/96b_avenger96_defconfig``

Connections and IOs
===================

96Boards Avenger96 Board schematic is available here:
`Avenger96 board schematics`_.

Default Zephyr Peripheral Mapping:
----------------------------------

- UART_7 TX/RX/RTS/CTS : PE8/PE7/PE9/PE10 (UART console)
- UART_4 TX/RX : PD1/PB2

System Clock
------------

The Cortex®-M4 Core is configured to run at a 209 MHz clock speed. This value
must match the configured mlhclk_ck frequency.

Serial Port
-----------

96Boards Avenger96 board has 3 U(S)ARTs. The Zephyr console output is assigned
by default to the RAM console to be dumped by the Linux Remoteproc Framework
on Cortex®-A7 core. Alternatively, Zephyr console output can be assigned to
UART7 which is disabled by default. UART console can be enabled through
board's devicetree and 96b_avenger96_defconfig board file (or prj.conf
project files), and will disable existing RAM console output. Default UART
console settings are 115200 8N1.

Programming and Debugging
*************************

The STM32MP157A doesn't have QSPI flash for the Cortex®-M4  and it needs to be
started by the Cortex®-A7 core. The Cortex®-A7 core is responsible to load the
Cortex®-M4 binary application into the RAM, and get the Cortex®-M4 out of reset.
The Cortex®-A7 can perform these steps at bootloader level or after the Linux
system has booted.

The Cortex®-M4 can use up to 2 different RAMs. The program pointer starts at
address 0x00000000 (RETRAM), the vector table should be loaded at this address
These are the memory mappings for Cortex®-A7 and Cortex®-M4:

+------------+-----------------------+------------------------+----------------+
| Region     | Cortex®-A7            | Cortex®-M4             | Size           |
+============+=======================+========================+================+
| RETRAM     | 0x38000000-0x3800FFFF | 0x00000000-0x0000FFFF  | 64KB           |
+------------+-----------------------+------------------------+----------------+
| MCUSRAM    | 0x10000000-0x1005FFFF | 0x10000000-0x1005FFFF  | 384KB          |
+------------+-----------------------+------------------------+----------------+
| DDR        | 0xC0000000-0xFFFFFFFF |                        | up to 1 GB     |
+------------+-----------------------+------------------------+----------------+

Refer to `stm32mp157 boot Cortex-M4 firmware`_ wiki page for instruction
to load and start the Cortex-M4 firmware.

Debugging
=========

You can debug an application using OpenOCD and GDB. The Solution proposed below
is based on the Linux STM32MP1 SDK OpenOCD and is available only for a Linux
environment. The firmware must first be loaded by the Cortex®-A7. Developer
then attaches the debugger to the running Zephyr using OpenOCD.

Prerequisite
------------
install `stm32mp1 developer package`_.

1) start OpenOCD in a dedicated terminal

   - Start up the  sdk environment::

      source <SDK installation directory>/environment-setup-cortexa7hf-neon-vfpv4-openstlinux_weston-linux-gnueabi

   - Start OpenOCD::

      ${OECORE_NATIVE_SYSROOT}/usr/bin/openocd -s ${OECORE_NATIVE_SYSROOT}/usr/share/openocd/scripts -f board/stm32mp15x_ev1_jlink_jtag.cfg

2) run gdb in Zephyr environment

   .. code-block:: console

      # On Linux
      cd $ZEPHYR_BASE/samples/hello_world
      mkdir -p build && cd build

      # Use cmake to configure a Ninja-based build system:
      cmake -GNinja -DBOARD=96b_avenger96 ..

      # Now run ninja on the generated build system:
      ninja debug

.. _96Boards website:
   https://www.96boards.org/product/avenger96/

.. _STM32MP157A on www.st.com:
   https://www.st.com/content/st_com/en/products/microcontrollers-microprocessors/stm32-arm-cortex-mpus/stm32mp1-series/stm32mp157/stm32mp157a.html

.. _STM32MP157A reference manual:
   https://www.st.com/resource/en/reference_manual/DM00327659.pdf

.. _Avenger96 board schematics:
   https://www.96boards.org/documentation/consumer/avenger96/hardware-docs/files/avenger96-schematics.pdf

.. _stm32mp1 developer package:
   https://wiki.st.com/stm32mpu/index.php/STM32MP1_Developer_Package#Installing_the_SDK

.. _stm32mp157 boot Cortex-M4 firmware:
   https://wiki.st.com/stm32mpu/index.php/Linux_remoteproc_framework_overview#How_to_use_the_framework


text:
use futures_core::stream::Stream;
use futures_core::task::{Context, Poll};
use futures_io::AsyncBufRead;
use std::io;
use std::mem;
use std::pin::Pin;
use super::read_line::read_line_internal;

/// Stream for the [`lines`](super::AsyncBufReadExt::lines) method.
#[derive(Debug)]
#[must_use = "streams do nothing unless polled"]
pub struct Lines<R> {
    reader: R,
    buf: String,
    bytes: Vec<u8>,
    read: usize,
}

impl<R: Unpin> Unpin for Lines<R> {}

impl<R: AsyncBufRead> Lines<R> {
    pub(super) fn new(reader: R) -> Self {
        Self {
            reader,
            buf: String::new(),
            bytes: Vec::new(),
            read: 0,
        }
    }
}

impl<R: AsyncBufRead> Stream for Lines<R> {
    type Item = io::Result<String>;

    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        let Self { reader, buf, bytes, read } = unsafe { self.get_unchecked_mut() };
        let reader = unsafe { Pin::new_unchecked(reader) };
        let n = ready!(read_line_internal(reader, cx, buf, bytes, read))?;
        if n == 0 && buf.is_empty() {
            return Poll::Ready(None)
        }
        if buf.ends_with('\n') {
            buf.pop();
            if buf.ends_with('\r') {
                buf.pop();
            }
        }
        Poll::Ready(Some(Ok(mem::replace(buf, String::new()))))
    }
}


text:
module ActiveRecord

  module ConnectionAdapters

    class FdbSqlAdapter < AbstractAdapter

      class FdbSqlSchemaCreation < SchemaCreation
        private

          def visit_AddColumn(o)
            sql_type = type_to_sql(o.type.to_sym, o.limit, o.precision, o.scale)
            sql = "ADD COLUMN #{quote_column_name(o.name)} #{sql_type}"
            add_column_options!(sql, column_options(o))
          end
      end

    end

  end

end


text:
from prer import PreR
import time

class PacketsQueriesAndAnswersPerSecond(PreR):
    """Show the average number of packets, queries and
     answers per second in a window.

    - Result

    Dict which has the average number of packets per second,
    queries per second, and answers per second in the
    current window

    - Example

    {'pps' : 4485.388931577132,
    'qps': 2085.388931577132,
    'aps' :  2485.388931577132}

    - Complexity Note

    <FILL>

    - ReductionRatio Note

    <FILL>
    """

    def __init__(self, f):
        PreR.__init__(self, f)
        self._pcounter = 0
        self._qcounter = 0
        self._acounter = 0
        self._start = time.time()

    def __call__(self, p):
        self._pcounter += 1
        if p.is_answer():
            self._acounter += 1
        else:
            self._qcounter += 1

    def get_data(self):
        data = {}
        t = time.time()
        data['pps'] = self._pcounter / (t - self._start)
        data['qps'] = self._qcounter / (t - self._start)
        data['aps'] = self._acounter / (t - self._start)
        return data

    def reset(self):
        self._pcounter = self._qcounter = self._acounter = 0
        self._start = time.time()


text:
<div>
    <button (click)="dataGrid.columns[0].config.hidden = !dataGrid.columns[0].config.hidden">Toggle</button>
    <input [(ngModel)]="dataGrid.searchPhrase" class="form-control" />
</div>
<data-grid [pageSize]='50' #xenos></data-grid>


text:
// set relative path to this file rather by the default dir from which you are in the time off calling node script
process.chdir(__dirname);

// Documentation - https://github.com/ddsol/speedtest.net
var speedtest = require('speedtest-net');
var fs = require('fs');
var path = require('path');

var test = speedtest({
  pingCount: 10, // default 5
  // maxTime: 100 // default 10000 - here smaller for faster app debug
  // maxServers: 1
});

var processData = function(err, data) {
  var timestamp = new Date().getTime();

  var folder = './logs';
  var file = 'logfile.json';
  var logfilePath = path.join(folder, file);

  // log error
  if(err) {
    data = {
      'error': err
    };
  }

  fs.readFile(logfilePath, 'utf-8', function(err, logfile) {

    // missing folder or file
    if(err){

      // check folder
      if(!fs.existsSync(folder))
        fs.mkdirSync(folder);

      // create log file
      fs.writeFileSync(logfilePath);
    }

    if(!logfile) {
      logfileData = {};
    } else {

      // Stripping and adding 'var dataJson = /* data */;' so that can load it in html with out creating a phython, node, php server.
      logfile = logfile.replace(/^(var dataJSON = )*/, '').replace(/(;*)$/, '');
      logfileData = JSON.parse(logfile);
    }

    logfileData[timestamp] = data;

    var outData = 'var dataJSON = ' + JSON.stringify(logfileData) + ';';
    fs.writeFileSync(logfilePath, outData);

    process.exit();
  });
};

test.on('data',function(data){
  processData(null, data);
});

test.on('error',function(err){
  processData(err);
});