forked from OSchip/llvm-project
[flang] Begin folding, with simple test, as sanity check on usability.
Original-commit: flang-compiler/f18@3839c65cd5 Reviewed-on: https://github.com/flang-compiler/f18/pull/111 Tree-same-pre-rewrite: false
This commit is contained in:
parent
efcbf1f7df
commit
cf410675cf
|
@ -18,6 +18,8 @@
|
|||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
using namespace Fortran::parser::literals;
|
||||
|
||||
namespace Fortran::evaluate {
|
||||
|
||||
template<typename A>
|
||||
|
@ -70,6 +72,62 @@ std::ostream &IntegerExpr<KIND>::Dump(std::ostream &o) const {
|
|||
return o;
|
||||
}
|
||||
|
||||
template<int KIND>
|
||||
void IntegerExpr<KIND>::Fold(
|
||||
const parser::CharBlock &at, parser::Messages *messages) {
|
||||
std::visit(common::visitors{[&](const Parentheses &p) {
|
||||
p.Mutable()->Fold(at, messages);
|
||||
if (auto c{std::get_if<Constant>(&p.x->u)}) {
|
||||
u = *c;
|
||||
}
|
||||
},
|
||||
[&](const Negate &n) {
|
||||
n.Mutable()->Fold(at, messages);
|
||||
if (auto c{std::get_if<Constant>(&n.x->u)}) {
|
||||
auto negated{c->Negate()};
|
||||
if (negated.overflow && messages != nullptr) {
|
||||
messages->Say(at, "integer negation overflowed"_en_US);
|
||||
}
|
||||
u = negated.value;
|
||||
}
|
||||
},
|
||||
[&](const Add &a) {
|
||||
a.MutableX()->Fold(at, messages);
|
||||
a.MutableY()->Fold(at, messages);
|
||||
if (auto xc{std::get_if<Constant>(&a.x->u)}) {
|
||||
if (auto yc{std::get_if<Constant>(&a.y->u)}) {
|
||||
auto sum{xc->AddSigned(*yc)};
|
||||
if (sum.overflow && messages != nullptr) {
|
||||
messages->Say(at, "integer addition overflowed"_en_US);
|
||||
}
|
||||
u = sum.value;
|
||||
}
|
||||
}
|
||||
},
|
||||
[&](const Multiply &a) {
|
||||
a.MutableX()->Fold(at, messages);
|
||||
a.MutableY()->Fold(at, messages);
|
||||
if (auto xc{std::get_if<Constant>(&a.x->u)}) {
|
||||
if (auto yc{std::get_if<Constant>(&a.y->u)}) {
|
||||
auto product{xc->MultiplySigned(*yc)};
|
||||
if (product.SignedMultiplicationOverflowed() &&
|
||||
messages != nullptr) {
|
||||
messages->Say(
|
||||
at, "integer multiplication overflowed"_en_US);
|
||||
}
|
||||
u = product.lower;
|
||||
}
|
||||
}
|
||||
},
|
||||
[&](const Bin &b) {
|
||||
b.MutableX()->Fold(at, messages);
|
||||
b.MutableY()->Fold(at, messages);
|
||||
},
|
||||
[&](const auto &) { // TODO: more
|
||||
}},
|
||||
u);
|
||||
}
|
||||
|
||||
template<int KIND> std::ostream &RealExpr<KIND>::Dump(std::ostream &o) const {
|
||||
std::visit(
|
||||
common::visitors{[&](const Constant &n) { o << n.DumpHexadecimal(); },
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
|
||||
#include "common.h"
|
||||
#include "type.h"
|
||||
#include "../lib/parser/char-block.h"
|
||||
#include "../lib/parser/message.h"
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <variant>
|
||||
|
@ -56,6 +58,7 @@ template<typename A> struct Unary {
|
|||
return *this;
|
||||
}
|
||||
Unary &operator=(Unary &&) = default;
|
||||
A *Mutable() const { return const_cast<A *>(x.get()); }
|
||||
std::unique_ptr<const A> x;
|
||||
};
|
||||
|
||||
|
@ -76,6 +79,8 @@ template<typename A, typename B> struct Binary {
|
|||
return *this;
|
||||
}
|
||||
Binary &operator=(Binary &&) = default;
|
||||
A *MutableX() const { return const_cast<A *>(x.get()); }
|
||||
B *MutableY() const { return const_cast<B *>(y.get()); }
|
||||
std::unique_ptr<const A> x;
|
||||
std::unique_ptr<const B> y;
|
||||
};
|
||||
|
@ -121,6 +126,7 @@ template<int KIND> struct IntegerExpr {
|
|||
IntegerExpr &operator=(IntegerExpr &&) = default;
|
||||
|
||||
std::ostream &Dump(std::ostream &) const;
|
||||
void Fold(const parser::CharBlock &, parser::Messages *);
|
||||
|
||||
std::variant<Constant, Convert, Parentheses, Negate, Add, Subtract, Multiply,
|
||||
Divide, Power>
|
||||
|
|
|
@ -89,6 +89,9 @@ public:
|
|||
};
|
||||
|
||||
struct Product {
|
||||
bool SignedMultiplicationOverflowed() const {
|
||||
return lower.IsNegative() ? (upper.POPCNT() != bits) : !upper.IsZero();
|
||||
}
|
||||
Integer upper, lower;
|
||||
};
|
||||
|
||||
|
|
|
@ -24,6 +24,10 @@ void OffsetToProvenanceMappings::swap(OffsetToProvenanceMappings &that) {
|
|||
provenanceMap_.swap(that.provenanceMap_);
|
||||
}
|
||||
|
||||
void OffsetToProvenanceMappings::shrink_to_fit() {
|
||||
provenanceMap_.shrink_to_fit();
|
||||
}
|
||||
|
||||
std::size_t OffsetToProvenanceMappings::size() const {
|
||||
if (provenanceMap_.empty()) {
|
||||
return 0;
|
||||
|
@ -322,7 +326,7 @@ static void DumpRange(std::ostream &o, const ProvenanceRange &r) {
|
|||
<< r.size() << " bytes)";
|
||||
}
|
||||
|
||||
void OffsetToProvenanceMappings::Dump(std::ostream &o) const {
|
||||
std::ostream &OffsetToProvenanceMappings::Dump(std::ostream &o) const {
|
||||
for (const ContiguousProvenanceMapping &m : provenanceMap_) {
|
||||
std::size_t n{m.range.size()};
|
||||
o << "offsets [" << m.start << ".." << (m.start + n - 1)
|
||||
|
@ -330,9 +334,10 @@ void OffsetToProvenanceMappings::Dump(std::ostream &o) const {
|
|||
DumpRange(o, m.range);
|
||||
o << '\n';
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
void AllSources::Dump(std::ostream &o) const {
|
||||
std::ostream &AllSources::Dump(std::ostream &o) const {
|
||||
o << "AllSources range_ ";
|
||||
DumpRange(o, range_);
|
||||
o << '\n';
|
||||
|
@ -362,13 +367,15 @@ void AllSources::Dump(std::ostream &o) const {
|
|||
}
|
||||
o << '\n';
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
void CookedSource::Dump(std::ostream &o) const {
|
||||
std::ostream &CookedSource::Dump(std::ostream &o) const {
|
||||
o << "CookedSource:\n";
|
||||
allSources_.Dump(o);
|
||||
o << "CookedSource::provenanceMap_:\n";
|
||||
provenanceMap_.Dump(o);
|
||||
return o;
|
||||
}
|
||||
|
||||
} // namespace Fortran::parser
|
||||
|
|
|
@ -91,12 +91,12 @@ public:
|
|||
std::size_t size() const;
|
||||
void clear();
|
||||
void swap(OffsetToProvenanceMappings &);
|
||||
void shrink_to_fit() { provenanceMap_.shrink_to_fit(); }
|
||||
void shrink_to_fit();
|
||||
void Put(ProvenanceRange);
|
||||
void Put(const OffsetToProvenanceMappings &);
|
||||
ProvenanceRange Map(std::size_t at) const;
|
||||
void RemoveLastBytes(std::size_t);
|
||||
void Dump(std::ostream &) const;
|
||||
std::ostream &Dump(std::ostream &) const;
|
||||
|
||||
private:
|
||||
struct ContiguousProvenanceMapping {
|
||||
|
@ -139,7 +139,7 @@ public:
|
|||
int GetLineNumber(Provenance) const; // __LINE__
|
||||
Provenance CompilerInsertionProvenance(char ch);
|
||||
Provenance CompilerInsertionProvenance(const char *, std::size_t);
|
||||
void Dump(std::ostream &) const;
|
||||
std::ostream &Dump(std::ostream &) const;
|
||||
|
||||
private:
|
||||
struct Inclusion {
|
||||
|
@ -211,7 +211,7 @@ public:
|
|||
provenanceMap_.Put(pm);
|
||||
}
|
||||
void Marshal(); // marshals all text into one contiguous block
|
||||
void Dump(std::ostream &) const;
|
||||
std::ostream &Dump(std::ostream &) const;
|
||||
|
||||
private:
|
||||
AllSources &allSources_;
|
||||
|
|
|
@ -31,7 +31,11 @@ int main() {
|
|||
TEST(DefaultIntegerExpr::Result::Dump() == "Integer(4)");
|
||||
MATCH("666", Dump(DefaultIntegerExpr{666}));
|
||||
MATCH("(-1)", Dump(-DefaultIntegerExpr{1}));
|
||||
MATCH("(2+(3*4))", Dump(DefaultIntegerExpr{2} + DefaultIntegerExpr{3} * DefaultIntegerExpr{4}));
|
||||
auto ex1{DefaultIntegerExpr{2} + DefaultIntegerExpr{3} * -DefaultIntegerExpr{4}};
|
||||
MATCH("(2+(3*(-4)))", Dump(ex1));
|
||||
Fortran::parser::CharBlock src;
|
||||
ex1.Fold(src, nullptr);
|
||||
MATCH("-10", Dump(ex1));
|
||||
MATCH("(6.LE.7)", Dump(DefaultIntegerExpr{6} <= DefaultIntegerExpr{7}));
|
||||
DefaultIntegerExpr a{1};
|
||||
DefaultIntegerExpr b{2};
|
||||
|
|
Loading…
Reference in New Issue