brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.9 KiB · 1e549f1 Raw
154 lines · c
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8// Helper class for splitting a coroutine into separate functions. For example9// the returned-continuation coroutine is split into separate continuation10// functions.11//===----------------------------------------------------------------------===//12 13#ifndef LLVM_LIB_TRANSFORMS_COROUTINES_COROCLONER_H14#define LLVM_LIB_TRANSFORMS_COROUTINES_COROCLONER_H15 16#include "llvm/IR/Function.h"17#include "llvm/IR/IRBuilder.h"18#include "llvm/Support/TimeProfiler.h"19#include "llvm/Transforms/Coroutines/ABI.h"20#include "llvm/Transforms/Coroutines/CoroInstr.h"21#include "llvm/Transforms/Utils/ValueMapper.h"22 23namespace llvm::coro {24 25enum class CloneKind {26  /// The shared resume function for a switch lowering.27  SwitchResume,28 29  /// The shared unwind function for a switch lowering.30  SwitchUnwind,31 32  /// The shared cleanup function for a switch lowering.33  SwitchCleanup,34 35  /// An individual continuation function.36  Continuation,37 38  /// An async resume function.39  Async,40};41 42class BaseCloner {43protected:44  Function &OrigF;45  const Twine &Suffix;46  coro::Shape &Shape;47  CloneKind FKind;48  IRBuilder<> Builder;49  TargetTransformInfo &TTI;50 51  ValueToValueMapTy VMap;52  Function *NewF = nullptr;53  Value *NewFramePtr = nullptr;54 55  /// The active suspend instruction; meaningful only for continuation and async56  /// ABIs.57  AnyCoroSuspendInst *ActiveSuspend = nullptr;58 59  /// Create a cloner for a continuation lowering.60  BaseCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape,61             Function *NewF, AnyCoroSuspendInst *ActiveSuspend,62             TargetTransformInfo &TTI)63      : OrigF(OrigF), Suffix(Suffix), Shape(Shape),64        FKind(Shape.ABI == ABI::Async ? CloneKind::Async65                                      : CloneKind::Continuation),66        Builder(OrigF.getContext()), TTI(TTI), NewF(NewF),67        ActiveSuspend(ActiveSuspend) {68    assert(Shape.ABI == ABI::Retcon || Shape.ABI == ABI::RetconOnce ||69           Shape.ABI == ABI::Async);70    assert(NewF && "need existing function for continuation");71    assert(ActiveSuspend && "need active suspend point for continuation");72  }73 74public:75  BaseCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape,76             CloneKind FKind, TargetTransformInfo &TTI)77      : OrigF(OrigF), Suffix(Suffix), Shape(Shape), FKind(FKind),78        Builder(OrigF.getContext()), TTI(TTI) {}79 80  virtual ~BaseCloner() = default;81 82  /// Create a clone for a continuation lowering.83  static Function *createClone(Function &OrigF, const Twine &Suffix,84                               coro::Shape &Shape, Function *NewF,85                               AnyCoroSuspendInst *ActiveSuspend,86                               TargetTransformInfo &TTI) {87    assert(Shape.ABI == ABI::Retcon || Shape.ABI == ABI::RetconOnce ||88           Shape.ABI == ABI::Async);89    TimeTraceScope FunctionScope("BaseCloner");90 91    BaseCloner Cloner(OrigF, Suffix, Shape, NewF, ActiveSuspend, TTI);92    Cloner.create();93    return Cloner.getFunction();94  }95 96  Function *getFunction() const {97    assert(NewF != nullptr && "declaration not yet set");98    return NewF;99  }100 101  virtual void create();102 103protected:104  bool isSwitchDestroyFunction() {105    switch (FKind) {106    case CloneKind::Async:107    case CloneKind::Continuation:108    case CloneKind::SwitchResume:109      return false;110    case CloneKind::SwitchUnwind:111    case CloneKind::SwitchCleanup:112      return true;113    }114    llvm_unreachable("Unknown ClonerKind enum");115  }116 117  void replaceEntryBlock();118  Value *deriveNewFramePointer();119  void replaceRetconOrAsyncSuspendUses();120  void replaceCoroSuspends();121  void replaceCoroEnds();122  void replaceCoroIsInRamp();123  void replaceSwiftErrorOps();124  void salvageDebugInfo();125  void handleFinalSuspend();126};127 128class SwitchCloner : public BaseCloner {129protected:130  /// Create a cloner for a switch lowering.131  SwitchCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape,132               CloneKind FKind, TargetTransformInfo &TTI)133      : BaseCloner(OrigF, Suffix, Shape, FKind, TTI) {}134 135  void create() override;136 137public:138  /// Create a clone for a switch lowering.139  static Function *createClone(Function &OrigF, const Twine &Suffix,140                               coro::Shape &Shape, CloneKind FKind,141                               TargetTransformInfo &TTI) {142    assert(Shape.ABI == ABI::Switch);143    TimeTraceScope FunctionScope("SwitchCloner");144 145    SwitchCloner Cloner(OrigF, Suffix, Shape, FKind, TTI);146    Cloner.create();147    return Cloner.getFunction();148  }149};150 151} // end namespace llvm::coro152 153#endif // LLVM_LIB_TRANSFORMS_COROUTINES_COROCLONER_H154