[flang] Fix frontend build with -DBUILD_SHARED_LIBS=On
authorpeter klausler <pklausler@nvidia.com>
Thu, 9 Jul 2020 18:08:41 +0000 (11:08 -0700)
committerpeter klausler <pklausler@nvidia.com>
Thu, 9 Jul 2020 22:54:19 +0000 (15:54 -0700)
Fix fronted shared library builds by eliminating dependences of
the parser on other component libraries, moving some code around that
wasn't in the right library, and making some dependences
explicit in the CMakeLists.txt files.  The lowering library
does not yet build as a shared library due to some undefined
names.

Reviewed By: tskeith

Differential Revision: https://reviews.llvm.org/D83515

20 files changed:
flang/include/flang/Common/indirection.h
flang/include/flang/Evaluate/call.h
flang/include/flang/Evaluate/expression.h
flang/include/flang/Evaluate/tools.h
flang/include/flang/Parser/parse-tree.h
flang/include/flang/Semantics/expression.h
flang/include/flang/Semantics/tools.h
flang/lib/Evaluate/CMakeLists.txt
flang/lib/Evaluate/call.cpp
flang/lib/Evaluate/expression.cpp
flang/lib/Evaluate/tools.cpp
flang/lib/Lower/CMakeLists.txt
flang/lib/Parser/parse-tree.cpp
flang/lib/Semantics/CMakeLists.txt
flang/lib/Semantics/expression.cpp
flang/lib/Semantics/tools.cpp
flang/tools/f18-parse-demo/stub-evaluate.cpp
flang/tools/f18/CMakeLists.txt
flang/unittests/Evaluate/CMakeLists.txt
flang/unittests/Runtime/CMakeLists.txt

index f34d561..fec3bc7 100644 (file)
@@ -122,20 +122,49 @@ private:
 
 template <typename A> using CopyableIndirection = Indirection<A, true>;
 
-// For use with std::unique_ptr<> when declaring owning pointers to
-// forward-referenced types, here's a minimal custom deleter that avoids
-// some of the drama with std::default_delete<>.  Invoke DEFINE_DELETER()
-// later in exactly one C++ source file where a complete definition of the
-// type is visible.  Be advised, std::unique_ptr<> does not have copy
-// semantics; if you need ownership, copy semantics, and nullability,
-// std::optional<CopyableIndirection<>> works.
-template <typename A> class Deleter {
+// A variation of std::unique_ptr<> with a reified deletion routine.
+// Used to avoid dependence cycles between shared libraries.
+template <typename A> class ForwardOwningPointer {
 public:
-  void operator()(A *) const;
+  ForwardOwningPointer() {}
+  ForwardOwningPointer(A *p, void (*del)(A *)) : p_{p}, deleter_{del} {}
+  ForwardOwningPointer(ForwardOwningPointer &&that)
+      : p_{that.p_}, deleter_{that.deleter_} {
+    that.p_ = nullptr;
+  }
+  ForwardOwningPointer &operator=(ForwardOwningPointer &&that) {
+    p_ = that.p_;
+    that.p_ = nullptr;
+    deleter_ = that.deleter_;
+    return *this;
+  }
+  ~ForwardOwningPointer() {
+    if (p_) {
+      deleter_(p_);
+    }
+  }
+
+  A &operator*() const { return *p_; }
+  A *operator->() const { return p_; }
+  operator bool() const { return p_ != nullptr; }
+  A *get() { return p_; }
+  A *release() {
+    A *result{p_};
+    p_ = nullptr;
+    return result;
+  }
+
+  void Reset(A *p, void (*del)(A *)) {
+    if (p_) {
+      deleter_(p_);
+    }
+    p_ = p;
+    deleter_ = del;
+  }
+
+private:
+  A *p_{nullptr};
+  void (*deleter_)(A *){nullptr};
 };
 } // namespace Fortran::common
-#define DEFINE_DELETER(A) \
-  template <> void Fortran::common::Deleter<A>::operator()(A *p) const { \
-    delete p; \
-  }
 #endif // FORTRAN_COMMON_INDIRECTION_H_
index 3ad77ce..71e0610 100644 (file)
@@ -195,6 +195,7 @@ public:
       : proc_{std::move(p)}, arguments_{std::move(a)},
         hasAlternateReturns_{hasAlternateReturns} {}
   ~ProcedureRef();
+  static void Deleter(ProcedureRef *);
 
   ProcedureDesignator &proc() { return proc_; }
   const ProcedureDesignator &proc() const { return proc_; }
index 0957832..3569b68 100644 (file)
@@ -841,6 +841,7 @@ struct GenericExprWrapper {
   explicit GenericExprWrapper(std::optional<Expr<SomeType>> &&x)
       : v{std::move(x)} {}
   ~GenericExprWrapper();
+  static void Deleter(GenericExprWrapper *);
   std::optional<Expr<SomeType>> v; // vacant if error
 };
 
@@ -849,6 +850,7 @@ struct GenericAssignmentWrapper {
   GenericAssignmentWrapper() {}
   explicit GenericAssignmentWrapper(Assignment &&x) : v{std::move(x)} {}
   ~GenericAssignmentWrapper();
+  static void Deleter(GenericAssignmentWrapper *);
   std::optional<Assignment> v; // vacant if error
 };
 
index 84de29b..e64aaec 100644 (file)
@@ -908,6 +908,7 @@ bool IsProcedure(const Symbol &);
 bool IsProcedurePointer(const Symbol &);
 bool IsSaved(const Symbol &); // saved implicitly or explicitly
 bool IsDummy(const Symbol &);
+bool IsFunctionResult(const Symbol &);
 
 // Follow use, host, and construct assocations to a variable, if any.
 const Symbol *GetAssociationRoot(const Symbol &);
index 28a343c..67fd574 100644 (file)
@@ -1395,8 +1395,7 @@ WRAPPER_CLASS(ContiguousStmt, std::list<ObjectName>);
 using ConstantSubobject = Constant<common::Indirection<Designator>>;
 
 // Represents an analyzed expression
-using TypedExpr = std::unique_ptr<evaluate::GenericExprWrapper,
-    common::Deleter<evaluate::GenericExprWrapper>>;
+using TypedExpr = common::ForwardOwningPointer<evaluate::GenericExprWrapper>;
 
 // R845 data-stmt-constant ->
 //        scalar-constant | scalar-constant-subobject |
@@ -1919,8 +1918,8 @@ struct DeallocateStmt {
 // R1032 assignment-stmt -> variable = expr
 struct AssignmentStmt {
   TUPLE_CLASS_BOILERPLATE(AssignmentStmt);
-  using TypedAssignment = std::unique_ptr<evaluate::GenericAssignmentWrapper,
-      common::Deleter<evaluate::GenericAssignmentWrapper>>;
+  using TypedAssignment =
+      common::ForwardOwningPointer<evaluate::GenericAssignmentWrapper>;
   mutable TypedAssignment typedAssignment;
   std::tuple<Variable, Expr> t;
 };
@@ -3140,8 +3139,7 @@ struct FunctionReference {
 // R1521 call-stmt -> CALL procedure-designator [( [actual-arg-spec-list] )]
 struct CallStmt {
   WRAPPER_CLASS_BOILERPLATE(CallStmt, Call);
-  mutable std::unique_ptr<evaluate::ProcedureRef,
-      common::Deleter<evaluate::ProcedureRef>>
+  mutable common::ForwardOwningPointer<evaluate::ProcedureRef>
       typedCall; // filled by semantics
 };
 
index 1b94ce6..4148a0d 100644 (file)
@@ -70,7 +70,8 @@ class IntrinsicProcTable;
 struct SetExprHelper {
   explicit SetExprHelper(GenericExprWrapper &&expr) : expr_{std::move(expr)} {}
   void Set(parser::TypedExpr &x) {
-    x.reset(new GenericExprWrapper{std::move(expr_)});
+    x.Reset(new GenericExprWrapper{std::move(expr_)},
+        evaluate::GenericExprWrapper::Deleter);
   }
   void Set(const parser::Expr &x) { Set(x.typedExpr); }
   void Set(const parser::Variable &x) { Set(x.typedExpr); }
index 7f58751..f63e4cc 100644 (file)
@@ -85,7 +85,6 @@ bool IsPointerDummy(const Symbol &);
 bool IsBindCProcedure(const Symbol &);
 bool IsBindCProcedure(const Scope &);
 bool IsProcName(const Symbol &); // proc-name
-bool IsFunctionResult(const Symbol &);
 bool IsFunctionResultWithSameNameAsFunction(const Symbol &);
 bool IsExtensibleType(const DerivedTypeSpec *);
 bool IsBuiltinDerivedType(const DerivedTypeSpec *derived, const char *name);
index 3c8cf63..9ab83d7 100644 (file)
@@ -41,7 +41,6 @@ add_flang_library(FortranEvaluate
   LINK_LIBS
   FortranCommon
   FortranDecimal
-  FortranSemantics
   FortranParser
   ${LIBPGMATH}
 
index c9d6fe0..b4cf0dc 100644 (file)
@@ -212,6 +212,7 @@ int ProcedureRef::Rank() const {
 
 ProcedureRef::~ProcedureRef() {}
 
+void ProcedureRef::Deleter(ProcedureRef *p) { delete p; }
+
 FOR_EACH_SPECIFIC_TYPE(template class FunctionRef, )
 } // namespace Fortran::evaluate
-DEFINE_DELETER(Fortran::evaluate::ProcedureRef)
index 604e4ff..5a45664 100644 (file)
@@ -223,8 +223,14 @@ StructureConstructor &StructureConstructor::Add(
 
 GenericExprWrapper::~GenericExprWrapper() {}
 
+void GenericExprWrapper::Deleter(GenericExprWrapper *p) { delete p; }
+
 GenericAssignmentWrapper::~GenericAssignmentWrapper() {}
 
+void GenericAssignmentWrapper::Deleter(GenericAssignmentWrapper *p) {
+  delete p;
+}
+
 template <TypeCategory CAT> int Expr<SomeKind<CAT>>::GetKind() const {
   return std::visit(
       [](const auto &kx) { return std::decay_t<decltype(kx)>::Result::kind; },
@@ -243,5 +249,3 @@ std::optional<Expr<SubscriptInteger>> Expr<SomeCharacter>::LEN() const {
 
 INSTANTIATE_EXPRESSION_TEMPLATES
 } // namespace Fortran::evaluate
-DEFINE_DELETER(Fortran::evaluate::GenericExprWrapper)
-DEFINE_DELETER(Fortran::evaluate::GenericAssignmentWrapper)
index 16cc39f..677b263 100644 (file)
@@ -1026,6 +1026,13 @@ bool IsDummy(const Symbol &symbol) {
       symbol.details());
 }
 
+bool IsFunctionResult(const Symbol &symbol) {
+  return (symbol.has<ObjectEntityDetails>() &&
+             symbol.get<ObjectEntityDetails>().isFuncResult()) ||
+      (symbol.has<ProcEntityDetails>() &&
+          symbol.get<ProcEntityDetails>().isFuncResult());
+}
+
 int CountLenParameters(const DerivedTypeSpec &type) {
   return std::count_if(type.parameters().begin(), type.parameters().end(),
       [](const auto &pair) { return pair.second.isLen(); });
index da2c716..3cd71c0 100644 (file)
@@ -22,6 +22,10 @@ add_flang_library(FortranLower
   LINK_LIBS
   FIROptimizer
   ${dialect_libs}
+  FortranCommon
+  FortranParser
+  FortranEvaluate
+  FortranSemantics
   MLIRAffineToStandard
   MLIRLLVMIR
   MLIRSCFToStandard
index 650635e..e86735c 100644 (file)
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
 
-// So "delete Expr;" calls an external destructor for its typedExpr.
-namespace Fortran::evaluate {
-struct GenericExprWrapper {
-  ~GenericExprWrapper();
-};
-struct GenericAssignmentWrapper {
-  ~GenericAssignmentWrapper();
-};
-} // namespace Fortran::evaluate
-
 namespace Fortran::parser {
 
 // R867
@@ -258,6 +248,3 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Name &x) {
 }
 
 } // namespace Fortran::parser
-
-template class std::unique_ptr<Fortran::evaluate::GenericExprWrapper>;
-template class std::unique_ptr<Fortran::evaluate::GenericAssignmentWrapper>;
index b0e40bd..05295f5 100644 (file)
@@ -44,6 +44,7 @@ add_flang_library(FortranSemantics
 
   LINK_LIBS
   FortranCommon
+  FortranParser
   FortranEvaluate
 
   LINK_COMPONENTS
index dca0f62..f22f8a9 100644 (file)
@@ -2031,8 +2031,10 @@ void ExpressionAnalyzer::Analyze(const parser::CallStmt &callStmt) {
       if (CheckCall(call.source, *proc, callee->arguments)) {
         bool hasAlternateReturns{
             callee->arguments.size() < actualArgList.size()};
-        callStmt.typedCall.reset(new ProcedureRef{std::move(*proc),
-            std::move(callee->arguments), hasAlternateReturns});
+        callStmt.typedCall.Reset(
+            new ProcedureRef{std::move(*proc), std::move(callee->arguments),
+                hasAlternateReturns},
+            ProcedureRef::Deleter);
       }
     }
   }
@@ -2044,7 +2046,8 @@ const Assignment *ExpressionAnalyzer::Analyze(const parser::AssignmentStmt &x) {
     analyzer.Analyze(std::get<parser::Variable>(x.t));
     analyzer.Analyze(std::get<parser::Expr>(x.t));
     if (analyzer.fatalErrors()) {
-      x.typedAssignment.reset(new GenericAssignmentWrapper{});
+      x.typedAssignment.Reset(
+          new GenericAssignmentWrapper{}, GenericAssignmentWrapper::Deleter);
     } else {
       std::optional<ProcedureRef> procRef{analyzer.TryDefinedAssignment()};
       Assignment assignment{
@@ -2052,8 +2055,9 @@ const Assignment *ExpressionAnalyzer::Analyze(const parser::AssignmentStmt &x) {
       if (procRef) {
         assignment.u = std::move(*procRef);
       }
-      x.typedAssignment.reset(
-          new GenericAssignmentWrapper{std::move(assignment)});
+      x.typedAssignment.Reset(
+          new GenericAssignmentWrapper{std::move(assignment)},
+          GenericAssignmentWrapper::Deleter);
     }
   }
   return common::GetPtrFromOptional(x.typedAssignment->v);
@@ -2065,7 +2069,8 @@ const Assignment *ExpressionAnalyzer::Analyze(
     MaybeExpr lhs{Analyze(std::get<parser::DataRef>(x.t))};
     MaybeExpr rhs{Analyze(std::get<parser::Expr>(x.t))};
     if (!lhs || !rhs) {
-      x.typedAssignment.reset(new GenericAssignmentWrapper{});
+      x.typedAssignment.Reset(
+          new GenericAssignmentWrapper{}, GenericAssignmentWrapper::Deleter);
     } else {
       Assignment assignment{std::move(*lhs), std::move(*rhs)};
       std::visit(common::visitors{
@@ -2092,8 +2097,9 @@ const Assignment *ExpressionAnalyzer::Analyze(
                      },
                  },
           std::get<parser::PointerAssignmentStmt::Bounds>(x.t).u);
-      x.typedAssignment.reset(
-          new GenericAssignmentWrapper{std::move(assignment)});
+      x.typedAssignment.Reset(
+          new GenericAssignmentWrapper{std::move(assignment)},
+          GenericAssignmentWrapper::Deleter);
     }
   }
   return common::GetPtrFromOptional(x.typedAssignment->v);
@@ -2934,7 +2940,7 @@ std::optional<ActualArgument> ArgumentAnalyzer::AnalyzeExpr(
     const parser::Expr &expr) {
   source_.ExtendToCover(expr.source);
   if (const Symbol * assumedTypeDummy{AssumedTypeDummy(expr)}) {
-    expr.typedExpr.reset(new GenericExprWrapper{});
+    expr.typedExpr.Reset(new GenericExprWrapper{}, GenericExprWrapper::Deleter);
     if (allowAssumedType_) {
       return ActualArgument{ActualArgument::AssumedType{*assumedTypeDummy}};
     } else {
index 889b5b2..2607011 100644 (file)
@@ -1217,13 +1217,6 @@ const Symbol *FindImmediateComponent(const DerivedTypeSpec &type,
   return nullptr;
 }
 
-bool IsFunctionResult(const Symbol &symbol) {
-  return (symbol.has<ObjectEntityDetails>() &&
-             symbol.get<ObjectEntityDetails>().isFuncResult()) ||
-      (symbol.has<ProcEntityDetails>() &&
-          symbol.get<ProcEntityDetails>().isFuncResult());
-}
-
 bool IsFunctionResultWithSameNameAsFunction(const Symbol &symbol) {
   if (IsFunctionResult(symbol)) {
     if (const Symbol * function{symbol.owner().symbol()}) {
index d673eca..854e575 100644 (file)
@@ -9,25 +9,19 @@
 // The parse tree has slots in which pointers to the results of semantic
 // analysis may be placed.  When using the parser without the semantics
 // libraries, as here, we need to stub out the dependences on the external
-// destructors, which will never actually be called.
-
-#include "flang/Common/indirection.h"
+// deleters, which will never actually be called.
 
 namespace Fortran::evaluate {
 struct GenericExprWrapper {
-  ~GenericExprWrapper();
+  static void Deleter(GenericExprWrapper *);
 };
-GenericExprWrapper::~GenericExprWrapper() {}
+void GenericExprWrapper::Deleter(GenericExprWrapper *) {}
 struct GenericAssignmentWrapper {
-  ~GenericAssignmentWrapper();
+  static void Deleter(GenericAssignmentWrapper *);
 };
-GenericAssignmentWrapper::~GenericAssignmentWrapper() {}
+void GenericAssignmentWrapper::Deleter(GenericAssignmentWrapper *) {}
 struct ProcedureRef {
-  ~ProcedureRef();
+  static void Deleter(ProcedureRef *);
 };
-ProcedureRef::~ProcedureRef() {}
+void ProcedureRef::Deleter(ProcedureRef *) {}
 } // namespace Fortran::evaluate
-
-DEFINE_DELETER(Fortran::evaluate::GenericExprWrapper)
-DEFINE_DELETER(Fortran::evaluate::GenericAssignmentWrapper)
-DEFINE_DELETER(Fortran::evaluate::ProcedureRef)
index 86434b2..8738561 100644 (file)
@@ -1,4 +1,5 @@
 set(LLVM_LINK_COMPONENTS
+  FrontendOpenMP
   Support
   )
 add_flang_tool(f18
index a4315b1..54676b0 100644 (file)
@@ -4,6 +4,10 @@ add_library(FortranEvaluateTesting
   fp-testing.cpp
 )
 
+target_link_libraries(FortranEvaluateTesting
+  LLVMSupport
+)
+
 add_executable(leading-zero-bit-count-test
   leading-zero-bit-count.cpp
 )
index aa18918..b13c84e 100644 (file)
@@ -8,6 +8,11 @@ add_library(RuntimeTesting
 )
 llvm_update_compile_flags(RuntimeTesting)
 
+target_link_libraries(RuntimeTesting
+  FortranRuntime
+  LLVMSupport
+)
+
 add_executable(format-test
   format.cpp
 )