[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:
peter klausler 2018-06-22 14:51:15 -07:00
parent efcbf1f7df
commit cf410675cf
6 changed files with 86 additions and 8 deletions

View File

@ -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(); },

View File

@ -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>

View File

@ -89,6 +89,9 @@ public:
};
struct Product {
bool SignedMultiplicationOverflowed() const {
return lower.IsNegative() ? (upper.POPCNT() != bits) : !upper.IsZero();
}
Integer upper, lower;
};

View File

@ -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

View File

@ -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_;

View File

@ -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};