[flang-commits] [flang] 8a8bb07 - [flang] Fix frontend build with -DBUILD_SHARED_LIBS=On

peter klausler via flang-commits flang-commits at lists.llvm.org
Thu Jul 9 15:54:59 PDT 2020


Author: peter klausler
Date: 2020-07-09T15:54:19-07:00
New Revision: 8a8bb078a3c839f0708917d9920ed4299680de1e

URL: https://github.com/llvm/llvm-project/commit/8a8bb078a3c839f0708917d9920ed4299680de1e
DIFF: https://github.com/llvm/llvm-project/commit/8a8bb078a3c839f0708917d9920ed4299680de1e.diff

LOG: [flang] Fix frontend build with -DBUILD_SHARED_LIBS=On

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

Added: 
    

Modified: 
    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

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Common/indirection.h b/flang/include/flang/Common/indirection.h
index f34d561ae049..fec3bc7ae8da 100644
--- a/flang/include/flang/Common/indirection.h
+++ b/flang/include/flang/Common/indirection.h
@@ -122,20 +122,49 @@ template <typename A> class Indirection<A, true> {
 
 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_

diff  --git a/flang/include/flang/Evaluate/call.h b/flang/include/flang/Evaluate/call.h
index 3ad77ceecc56..71e061054928 100644
--- a/flang/include/flang/Evaluate/call.h
+++ b/flang/include/flang/Evaluate/call.h
@@ -195,6 +195,7 @@ class ProcedureRef {
       : 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_; }

diff  --git a/flang/include/flang/Evaluate/expression.h b/flang/include/flang/Evaluate/expression.h
index 095783231b66..3569b68fd9d2 100644
--- a/flang/include/flang/Evaluate/expression.h
+++ b/flang/include/flang/Evaluate/expression.h
@@ -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
 };
 

diff  --git a/flang/include/flang/Evaluate/tools.h b/flang/include/flang/Evaluate/tools.h
index 84de29bd7fec..e64aaece15bf 100644
--- a/flang/include/flang/Evaluate/tools.h
+++ b/flang/include/flang/Evaluate/tools.h
@@ -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 &);

diff  --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 28a343c58c66..67fd5741b097 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -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
 };
 

diff  --git a/flang/include/flang/Semantics/expression.h b/flang/include/flang/Semantics/expression.h
index 1b94ce62a996..4148a0d605d8 100644
--- a/flang/include/flang/Semantics/expression.h
+++ b/flang/include/flang/Semantics/expression.h
@@ -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); }

diff  --git a/flang/include/flang/Semantics/tools.h b/flang/include/flang/Semantics/tools.h
index 7f58751da061..f63e4ccbc687 100644
--- a/flang/include/flang/Semantics/tools.h
+++ b/flang/include/flang/Semantics/tools.h
@@ -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);

diff  --git a/flang/lib/Evaluate/CMakeLists.txt b/flang/lib/Evaluate/CMakeLists.txt
index 3c8cf638ca68..9ab83d7c1c25 100644
--- a/flang/lib/Evaluate/CMakeLists.txt
+++ b/flang/lib/Evaluate/CMakeLists.txt
@@ -41,7 +41,6 @@ add_flang_library(FortranEvaluate
   LINK_LIBS
   FortranCommon
   FortranDecimal
-  FortranSemantics
   FortranParser
   ${LIBPGMATH}
 

diff  --git a/flang/lib/Evaluate/call.cpp b/flang/lib/Evaluate/call.cpp
index c9d6fe0ddb80..b4cf0dc3af3a 100644
--- a/flang/lib/Evaluate/call.cpp
+++ b/flang/lib/Evaluate/call.cpp
@@ -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)

diff  --git a/flang/lib/Evaluate/expression.cpp b/flang/lib/Evaluate/expression.cpp
index 604e4ff41ce2..5a456648b825 100644
--- a/flang/lib/Evaluate/expression.cpp
+++ b/flang/lib/Evaluate/expression.cpp
@@ -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)

diff  --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp
index 16cc39f78291..677b263408b3 100644
--- a/flang/lib/Evaluate/tools.cpp
+++ b/flang/lib/Evaluate/tools.cpp
@@ -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(); });

diff  --git a/flang/lib/Lower/CMakeLists.txt b/flang/lib/Lower/CMakeLists.txt
index da2c71684601..3cd71c007a00 100644
--- a/flang/lib/Lower/CMakeLists.txt
+++ b/flang/lib/Lower/CMakeLists.txt
@@ -22,6 +22,10 @@ add_flang_library(FortranLower
   LINK_LIBS
   FIROptimizer
   ${dialect_libs}
+  FortranCommon
+  FortranParser
+  FortranEvaluate
+  FortranSemantics
   MLIRAffineToStandard
   MLIRLLVMIR
   MLIRSCFToStandard

diff  --git a/flang/lib/Parser/parse-tree.cpp b/flang/lib/Parser/parse-tree.cpp
index 650635ec97bc..e86735c0bcb0 100644
--- a/flang/lib/Parser/parse-tree.cpp
+++ b/flang/lib/Parser/parse-tree.cpp
@@ -14,16 +14,6 @@
 #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>;

diff  --git a/flang/lib/Semantics/CMakeLists.txt b/flang/lib/Semantics/CMakeLists.txt
index b0e40bd3251d..05295f590095 100644
--- a/flang/lib/Semantics/CMakeLists.txt
+++ b/flang/lib/Semantics/CMakeLists.txt
@@ -44,6 +44,7 @@ add_flang_library(FortranSemantics
 
   LINK_LIBS
   FortranCommon
+  FortranParser
   FortranEvaluate
 
   LINK_COMPONENTS

diff  --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index dca0f6259bbe..f22f8a966924 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -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 {

diff  --git a/flang/lib/Semantics/tools.cpp b/flang/lib/Semantics/tools.cpp
index 889b5b26eafc..260701133396 100644
--- a/flang/lib/Semantics/tools.cpp
+++ b/flang/lib/Semantics/tools.cpp
@@ -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()}) {

diff  --git a/flang/tools/f18-parse-demo/stub-evaluate.cpp b/flang/tools/f18-parse-demo/stub-evaluate.cpp
index d673eca5fa50..854e5758743d 100644
--- a/flang/tools/f18-parse-demo/stub-evaluate.cpp
+++ b/flang/tools/f18-parse-demo/stub-evaluate.cpp
@@ -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)

diff  --git a/flang/tools/f18/CMakeLists.txt b/flang/tools/f18/CMakeLists.txt
index 86434b253bef..8738561fe45e 100644
--- a/flang/tools/f18/CMakeLists.txt
+++ b/flang/tools/f18/CMakeLists.txt
@@ -1,4 +1,5 @@
 set(LLVM_LINK_COMPONENTS
+  FrontendOpenMP
   Support
   )
 add_flang_tool(f18

diff  --git a/flang/unittests/Evaluate/CMakeLists.txt b/flang/unittests/Evaluate/CMakeLists.txt
index a4315b1072ce..54676b0b5a0a 100644
--- a/flang/unittests/Evaluate/CMakeLists.txt
+++ b/flang/unittests/Evaluate/CMakeLists.txt
@@ -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
 )

diff  --git a/flang/unittests/Runtime/CMakeLists.txt b/flang/unittests/Runtime/CMakeLists.txt
index aa189188903b..b13c84e88a02 100644
--- a/flang/unittests/Runtime/CMakeLists.txt
+++ b/flang/unittests/Runtime/CMakeLists.txt
@@ -8,6 +8,11 @@ add_library(RuntimeTesting
 )
 llvm_update_compile_flags(RuntimeTesting)
 
+target_link_libraries(RuntimeTesting
+  FortranRuntime
+  LLVMSupport
+)
+
 add_executable(format-test
   format.cpp
 )


        


More information about the flang-commits mailing list