Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide way to debug delta relations and expose iteration counter #2414

Merged
merged 10 commits into from
Jun 5, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ set(SOUFFLE_SOURCES
ast/FunctorDeclaration.cpp
ast/FunctionalConstraint.cpp
ast/IntrinsicFunctor.cpp
ast/IterationCounter.cpp
ast/Negation.cpp
ast/NilConstant.cpp
ast/Node.cpp
Expand Down Expand Up @@ -79,6 +80,7 @@ set(SOUFFLE_SOURCES
ast/transform/ComponentChecker.cpp
ast/transform/ComponentInstantiation.cpp
ast/transform/DebugReporter.cpp
ast/transform/DebugDeltaRelation.cpp
ast/transform/ExecutionPlanChecker.cpp
ast/transform/ExpandEqrels.cpp
ast/transform/FoldAnonymousRecords.cpp
Expand Down
2 changes: 2 additions & 0 deletions src/MainDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "ast/transform/ComponentChecker.h"
#include "ast/transform/ComponentInstantiation.h"
#include "ast/transform/Conditional.h"
#include "ast/transform/DebugDeltaRelation.h"
#include "ast/transform/ExecutionPlanChecker.h"
#include "ast/transform/ExpandEqrels.h"
#include "ast/transform/Fixpoint.h"
Expand Down Expand Up @@ -478,6 +479,7 @@ Own<ast::transform::PipelineTransformer> astTransformationPipeline(Global& glb)
// Main pipeline
auto pipeline = mk<ast::transform::PipelineTransformer>(mk<ast::transform::ComponentChecker>(),
mk<ast::transform::ComponentInstantiationTransformer>(),
mk<ast::transform::DebugDeltaRelationTransformer>(),
mk<ast::transform::IODefaultsTransformer>(),
mk<ast::transform::SimplifyAggregateTargetExpressionTransformer>(),
mk<ast::transform::UniqueAggregationVariablesTransformer>(),
Expand Down
22 changes: 22 additions & 0 deletions src/ast/IterationCounter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Souffle - A Datalog Compiler
* Copyright (c) 2023, The Souffle Developers. All rights reserved
* Licensed under the Universal Permissive License v 1.0 as shown at:
* - https://opensource.org/licenses/UPL
* - <souffle root>/licenses/SOUFFLE-UPL.txt
*/

#include "ast/IterationCounter.h"
#include <ostream>

namespace souffle::ast {

void IterationCounter::print(std::ostream& os) const {
os << "recursive_iteration_cnt()";
}

IterationCounter* IterationCounter::cloning() const {
return new IterationCounter(getSrcLoc());
}

} // namespace souffle::ast
39 changes: 39 additions & 0 deletions src/ast/IterationCounter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Souffle - A Datalog Compiler
* Copyright (c) 2023, The Souffle Developers. All rights reserved
* Licensed under the Universal Permissive License v 1.0 as shown at:
* - https://opensource.org/licenses/UPL
* - <souffle root>/licenses/SOUFFLE-UPL.txt
*/

/************************************************************************
*
* @file IterationCounter.h
*
* Defines a counter functor class
*
***********************************************************************/

#pragma once

#include "ast/Argument.h"
#include <iosfwd>

namespace souffle::ast {

/**
* @class IterationCounter
* @brief iteration counter for recursive strata
*/
class IterationCounter : public Argument {
public:
using Argument::Argument;

protected:
void print(std::ostream& os) const override;

private:
IterationCounter* cloning() const override;
};

} // namespace souffle::ast
6 changes: 5 additions & 1 deletion src/ast/Relation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,17 @@ void Relation::print(std::ostream& os) const {
if (!functionalDependencies.empty()) {
os << " choice-domain " << join(functionalDependencies, ", ");
}
if (isDeltaDebug) {
os << " delta_debug(" << isDeltaDebug.value() << ")";
}
}

bool Relation::equal(const Node& node) const {
const auto& other = asAssert<Relation>(node);
return name == other.name && equal_targets(attributes, other.attributes) &&
qualifiers == other.qualifiers &&
equal_targets(functionalDependencies, other.functionalDependencies) &&
representation == other.representation;
representation == other.representation && isDeltaDebug == other.isDeltaDebug;
}

Relation* Relation::cloning() const {
Expand All @@ -77,6 +80,7 @@ Relation* Relation::cloning() const {
res->qualifiers = qualifiers;
res->functionalDependencies = clone(functionalDependencies);
res->representation = representation;
res->isDeltaDebug = isDeltaDebug;
return res;
}

Expand Down
10 changes: 10 additions & 0 deletions src/ast/Relation.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,14 @@ class Relation : public Node {

void apply(const NodeMapper& map) override;

void setIsDeltaDebug(QualifiedName rel) {
isDeltaDebug = rel;
}

std::optional<QualifiedName> getIsDeltaDebug() const {
return isDeltaDebug;
}

protected:
void print(std::ostream& os) const override;

Expand All @@ -122,6 +130,8 @@ class Relation : public Node {

/** Datastructure to use for this relation */
RelationRepresentation representation{RelationRepresentation::DEFAULT};

std::optional<QualifiedName> isDeltaDebug;
};

/**
Expand Down
7 changes: 7 additions & 0 deletions src/ast/analysis/PrecedenceGraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ void PrecedenceGraphAnalysis::run(const TranslationUnit& translationUnit) {
souffle::visit(literals[i], addEdgeToR);
}
}

// delta_debug relation are computed from the original relation
if (const auto deltaDebug = r->getIsDeltaDebug()) {
const auto* dbg = program.getRelation(deltaDebug.value());
backingGraph.insert(r, dbg);
backingGraph.insert(dbg, r);
}
}
}

Expand Down
7 changes: 7 additions & 0 deletions src/ast/analysis/typesystem/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,8 @@ void TypeAnnotationPrinter::branchOnArgument(const Argument* cur, const Type& ty
print_(type_identity<UserDefinedFunctor>(), *as<UserDefinedFunctor>(cur));
} else if (isA<Counter>(*cur)) {
print_(type_identity<Counter>(), *as<Counter>(cur));
} else if (isA<IterationCounter>(*cur)) {
print_(type_identity<IterationCounter>(), *as<IterationCounter>(cur));
} else if (isA<Aggregator>(*cur)) {
print_(type_identity<Aggregator>(), *as<Aggregator>(cur));
} else {
Expand Down Expand Up @@ -719,6 +721,11 @@ void TypeAnnotationPrinter::print_(type_identity<Counter>, [[maybe_unused]] cons
os << "$∈{number}";
}

void TypeAnnotationPrinter::print_(
type_identity<IterationCounter>, [[maybe_unused]] const IterationCounter& counter) {
os << "$∈{unsigned}";
}

void TypeAnnotationPrinter::print_(type_identity<TypeCast>, const ast::TypeCast& typeCast) {
os << "as(";
auto& ty = typeEnv.getType(typeCast.getType());
Expand Down
2 changes: 2 additions & 0 deletions src/ast/analysis/typesystem/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class Clause;
class Functor;
class FunctorDeclaration;
class IntrinsicFunctor;
class IterationCounter;
class NumericConstant;
class Type;
class UserDefinedFunctor;
Expand Down Expand Up @@ -189,6 +190,7 @@ class TypeAnnotationPrinter {
void print_(type_identity<IntrinsicFunctor>, const IntrinsicFunctor& fun);
void print_(type_identity<UserDefinedFunctor>, const UserDefinedFunctor& fun);
void print_(type_identity<Counter>, const Counter& counter);
void print_(type_identity<IterationCounter>, const IterationCounter& counter);
void print_(type_identity<TypeCast>, const ast::TypeCast& typeCast);
void print_(type_identity<RecordInit>, const RecordInit& record, const RecordType&);
void print_(type_identity<BranchInit>, const BranchInit& adt);
Expand Down
4 changes: 4 additions & 0 deletions src/ast/analysis/typesystem/TypeConstrainsAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,10 @@ void TypeConstraintsAnalysis::visit_(type_identity<Counter>, const Counter& coun
addConstraint(isSubtypeOf(getVar(counter), typeEnv.getConstantType(TypeAttribute::Signed)));
}

void TypeConstraintsAnalysis::visit_(type_identity<IterationCounter>, const IterationCounter& counter) {
addConstraint(isSubtypeOf(getVar(counter), typeEnv.getConstantType(TypeAttribute::Unsigned)));
}

void TypeConstraintsAnalysis::visit_(type_identity<TypeCast>, const ast::TypeCast& typeCast) {
auto& typeName = typeCast.getType();
if (!typeEnv.isType(typeName)) {
Expand Down
1 change: 1 addition & 0 deletions src/ast/analysis/typesystem/TypeConstrainsAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class TypeConstraintsAnalysis : public ConstraintAnalysis<TypeVar> {
void visit_(type_identity<IntrinsicFunctor>, const IntrinsicFunctor& fun) override;
void visit_(type_identity<UserDefinedFunctor>, const UserDefinedFunctor& fun) override;
void visit_(type_identity<Counter>, const Counter& counter) override;
void visit_(type_identity<IterationCounter>, const IterationCounter& counter) override;
void visit_(type_identity<TypeCast>, const ast::TypeCast& typeCast) override;
void visit_(type_identity<RecordInit>, const RecordInit& record) override;
void visit_(type_identity<BranchInit>, const BranchInit& adt) override;
Expand Down
9 changes: 9 additions & 0 deletions src/ast/transform/ComponentInstantiation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,15 @@ ComponentContent getInstantiatedContent(Program& program, const ComponentInit& c
}
});

visit(node, [&](Relation& rel) {
if (rel.getIsDeltaDebug()) {
auto pos = relationNameMapping.find(rel.getIsDeltaDebug().value());
if (pos != relationNameMapping.end()) {
rel.setIsDeltaDebug(pos->second);
}
}
});

// rename directives
visit(node, [&](Directive& directive) {
auto pos = relationNameMapping.find(directive.getQualifiedName());
Expand Down
58 changes: 58 additions & 0 deletions src/ast/transform/DebugDeltaRelation.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Souffle - A Datalog Compiler
* Copyright (c) 2023, The Souffle Developers. All rights reserved
* Licensed under the Universal Permissive License v 1.0 as shown at:
* - https://opensource.org/licenses/UPL
* - <souffle root>/licenses/SOUFFLE-UPL.txt
*/

/************************************************************************
*
* @file DebugDeltaRelation.cpp
*
***********************************************************************/

#include "ast/transform/DebugDeltaRelation.h"
#include "ast/Argument.h"
#include "ast/Atom.h"
#include "ast/Clause.h"
#include "ast/Program.h"
#include "ast/QualifiedName.h"
#include "ast/RecordInit.h"
#include "ast/Relation.h"
#include "ast/TranslationUnit.h"
#include "ast/Variable.h"
#include "ast/analysis/IOType.h"
#include "ast/utility/Utils.h"
#include "ast/utility/Visitor.h"
#include "souffle/utility/ContainerUtil.h"
#include <algorithm>
#include <cassert>
#include <map>
#include <set>
#include <utility>
#include <vector>

namespace souffle::ast::transform {

bool DebugDeltaRelationTransformer::updateSignature(TranslationUnit& translationUnit) {
bool changed = false;
Program& program = translationUnit.getProgram();

for (Relation* rel : program.getRelations()) {
if (!rel->getIsDeltaDebug().has_value()) {
continue;
}
const QualifiedName originalRelName = rel->getIsDeltaDebug().value();
Relation* orig = program.getRelation(originalRelName);
assert(orig != nullptr);


rel->setAttributes(clone(orig->getAttributes()));
changed = true;
rel->addAttribute(mk<Attribute>("<iteration>", "unsigned"));
}
return changed;
}

} // namespace souffle::ast::transform
44 changes: 44 additions & 0 deletions src/ast/transform/DebugDeltaRelation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Souffle - A Datalog Compiler
* Copyright (c) 2023, The Souffle Developers. All rights reserved
* Licensed under the Universal Permissive License v 1.0 as shown at:
* - https://opensource.org/licenses/UPL
* - <souffle root>/licenses/SOUFFLE-UPL.txt
*/

/************************************************************************
*
* @file DebugDeltaRelation.h
*
***********************************************************************/

#pragma once

#include "ast/TranslationUnit.h"
#include "ast/transform/Transformer.h"
#include <string>

namespace souffle::ast::transform {

/**
* Pass that assign the correct signature to relations declared as delta_debug
*/
class DebugDeltaRelationTransformer : public Transformer {
public:
std::string getName() const override {
return "DebugDeltaRelationTransformer";
}

private:
DebugDeltaRelationTransformer* cloning() const override {
return new DebugDeltaRelationTransformer();
}

bool updateSignature(TranslationUnit& translationUnit);

bool transform(TranslationUnit& translationUnit) override {
return updateSignature(translationUnit);
}
};

} // namespace souffle::ast::transform
13 changes: 13 additions & 0 deletions src/ast/transform/SemanticChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "ast/Functor.h"
#include "ast/IntrinsicAggregator.h"
#include "ast/IntrinsicFunctor.h"
#include "ast/IterationCounter.h"
#include "ast/Literal.h"
#include "ast/Negation.h"
#include "ast/NilConstant.h"
Expand Down Expand Up @@ -414,6 +415,8 @@ bool isConstantArgument(const Argument* arg) {
// if all argument of functor are constant, then
// assume functor returned value is constant.
return all_of(udf->getArguments(), isConstantArgument);
} else if (isA<IterationCounter>(arg)) {
return false;
} else if (isA<Counter>(arg)) {
return false;
} else if (auto* typeCast = as<ast::TypeCast>(arg)) {
Expand Down Expand Up @@ -668,11 +671,21 @@ void SemanticCheckerImpl::checkRelation(const Relation& relation) {

// check whether this relation is empty
if (program.getClauses(relation).empty() && !ioTypes.isInput(&relation) &&
!relation.getIsDeltaDebug().has_value() &&
!relation.hasQualifier(RelationQualifier::SUPPRESSED)) {
report.addWarning(WarnType::NoRulesNorFacts,
"No rules/facts defined for relation " + toString(relation.getQualifiedName()),
relation.getSrcLoc());
}

// if the relation is a delta_debug, make sure if has no clause
if (relation.getIsDeltaDebug().has_value()) {
if (!program.getClauses(relation).empty() || ioTypes.isInput(&relation)) {
report.addError("Unexpected rules/facts for delta_debug relation " +
toString(relation.getQualifiedName()),
relation.getSrcLoc());
}
}
}

void SemanticCheckerImpl::checkIO() {
Expand Down
3 changes: 3 additions & 0 deletions src/ast/utility/Visitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "ast/FunctorDeclaration.h"
#include "ast/IntrinsicAggregator.h"
#include "ast/IntrinsicFunctor.h"
#include "ast/IterationCounter.h"
#include "ast/Literal.h"
#include "ast/Negation.h"
#include "ast/NilConstant.h"
Expand Down Expand Up @@ -88,6 +89,7 @@ struct Visitor : souffle::detail::VisitorBase<R, NodeType, Params...> {
SOUFFLE_VISITOR_FORWARD(Variable)
SOUFFLE_VISITOR_FORWARD(UnnamedVariable)
SOUFFLE_VISITOR_FORWARD(IntrinsicFunctor)
SOUFFLE_VISITOR_FORWARD(IterationCounter)
SOUFFLE_VISITOR_FORWARD(UserDefinedFunctor)
SOUFFLE_VISITOR_FORWARD(Counter)
SOUFFLE_VISITOR_FORWARD(NumericConstant)
Expand Down Expand Up @@ -137,6 +139,7 @@ struct Visitor : souffle::detail::VisitorBase<R, NodeType, Params...> {
SOUFFLE_VISITOR_LINK(Variable, Argument)
SOUFFLE_VISITOR_LINK(UnnamedVariable, Argument)
SOUFFLE_VISITOR_LINK(Counter, Argument)
SOUFFLE_VISITOR_LINK(IterationCounter, Argument)
SOUFFLE_VISITOR_LINK(TypeCast, Argument)
SOUFFLE_VISITOR_LINK(BranchInit, Argument)

Expand Down
Loading