mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-14 11:39:35 +00:00
[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
This commit is contained in:
parent
8be204fe75
commit
8a8bb078a3
@ -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_
|
||||
|
@ -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_; }
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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 &);
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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); }
|
||||
|
@ -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);
|
||||
|
@ -41,7 +41,6 @@ add_flang_library(FortranEvaluate
|
||||
LINK_LIBS
|
||||
FortranCommon
|
||||
FortranDecimal
|
||||
FortranSemantics
|
||||
FortranParser
|
||||
${LIBPGMATH}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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(); });
|
||||
|
@ -22,6 +22,10 @@ add_flang_library(FortranLower
|
||||
LINK_LIBS
|
||||
FIROptimizer
|
||||
${dialect_libs}
|
||||
FortranCommon
|
||||
FortranParser
|
||||
FortranEvaluate
|
||||
FortranSemantics
|
||||
MLIRAffineToStandard
|
||||
MLIRLLVMIR
|
||||
MLIRSCFToStandard
|
||||
|
@ -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>;
|
||||
|
@ -44,6 +44,7 @@ add_flang_library(FortranSemantics
|
||||
|
||||
LINK_LIBS
|
||||
FortranCommon
|
||||
FortranParser
|
||||
FortranEvaluate
|
||||
|
||||
LINK_COMPONENTS
|
||||
|
@ -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 {
|
||||
|
@ -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()}) {
|
||||
|
@ -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)
|
||||
|
@ -1,4 +1,5 @@
|
||||
set(LLVM_LINK_COMPONENTS
|
||||
FrontendOpenMP
|
||||
Support
|
||||
)
|
||||
add_flang_tool(f18
|
||||
|
@ -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
|
||||
)
|
||||
|
@ -8,6 +8,11 @@ add_library(RuntimeTesting
|
||||
)
|
||||
llvm_update_compile_flags(RuntimeTesting)
|
||||
|
||||
target_link_libraries(RuntimeTesting
|
||||
FortranRuntime
|
||||
LLVMSupport
|
||||
)
|
||||
|
||||
add_executable(format-test
|
||||
format.cpp
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user