blob: a03dc2bef9d7f1c33954d92da174233b6771b34b [file] [log] [blame]
//===- llvm/tools/gollvm/unittests/BackendCore/BackendTreeIntegrity.cpp -===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "TestUtils.h"
#include "go-llvm-backend.h"
#include "gtest/gtest.h"
using namespace llvm;
using namespace goBackendUnitTests;
namespace {
TEST(BackendTreeIntegrity, CheckTreeIntegrity1) {
FcnTestHarness h("foo");
Llvm_backend *be = h.be();
Bfunction *func = h.func();
Location loc;
// So that we can test the checker itself
be->disableIntegrityChecks();
// Create "2 + x"
Btype *bi64t = be->integer_type(false, 64);
Bvariable *xv = h.mkLocal("x", bi64t);
Bexpression *vex = be->var_expression(xv, loc);
Bexpression *bl1 = mkInt64Const(be, 2);
Bexpression *badd1 = be->binary_expression(OPERATOR_PLUS, bl1, vex, loc);
Bstatement *es = be->expression_statement(func, badd1);
h.addStmt(es);
// Grab pointer to the add expr above, post-materialization.
badd1 = es->children()[0]->castToBexpression();
// Create "4"
Bexpression *b4 = mkInt64Const(be, 4);
Bstatement *es2 = be->expression_statement(func, b4);
h.addStmt(es2);
// Mangle the IR so that we have a some instructions
// parented by more than one Bexpression. Warning to our viewers at
// home -- don't do this.
for (auto inst : badd1->instructions())
b4->appendInstruction(inst);
TreeIntegCtl control(NoDumpPointers, ReportRepairableSharing, BatchMode);
std::pair<bool, std::string> result =
be->checkTreeIntegrity(h.block(), control);
EXPECT_FALSE(result.first);
EXPECT_TRUE(containstokens(result.second,
"instruction has multiple parents"));
// Undo the mangling to avoid asserts later on
b4->clear();
h.finish(PreserveDebugInfo);
}
TEST(BackendTreeIntegrity, CheckTreeIntegrity2) {
// Add the same Expression to more than one statement
LLVMContext C;
std::unique_ptr<Llvm_backend> be(new Llvm_backend(C, nullptr, nullptr));
be->disableIntegrityChecks();
Location loc;
Bfunction *func = mkFunci32o64(be.get(), "foo");
Btype *bi64t = be->integer_type(false, 64);
Bvariable *loc1 = be->local_variable(func, "loc1", bi64t, true, loc);
Bvariable *loc2 = be->local_variable(func, "loc2", bi64t, true, loc);
// Create "loc1" varexpr, then supply to more than one statement
Bexpression *ve = be->var_expression(loc1, loc);
Bstatement *es1 = be->expression_statement(func, ve);
Bblock *block = mkBlockFromStmt(be.get(), func, es1);
Bstatement *es2 = be->expression_statement(func, ve);
addStmtToBlock(be.get(), block, es2);
TreeIntegCtl control(NoDumpPointers, ReportRepairableSharing, BatchMode);
std::pair<bool, std::string> result =
be->checkTreeIntegrity(block, control);
EXPECT_FALSE(result.first);
EXPECT_TRUE(containstokens(result.second, "expr has multiple parents"));
be->nodeBuilder().destroy(block, DelBoth);
Bexpression *ve3 = be->var_expression(loc2, loc);
Bstatement *es3 = be->expression_statement(func, ve3);
Bblock *block2 = mkBlockFromStmt(be.get(), func, es3);
be->disableDebugMetaDataGeneration();
be->function_set_body(func, block2);
}
TEST(BackendTreeIntegrity, CheckTreeIntegrity3) {
// Same statement with more than one parent.
LLVMContext C;
std::unique_ptr<Llvm_backend> be(new Llvm_backend(C, nullptr, nullptr));
be->disableIntegrityChecks();
Location loc;
Bfunction *func = mkFunci32o64(be.get(), "foo");
// Create expr stmt, add to block more than once
Bexpression *b2 = mkInt64Const(be.get(), 2);
Bstatement *es = be->expression_statement(func, b2);
Bblock *block = mkBlockFromStmt(be.get(), func, es);
addStmtToBlock(be.get(), block, es);
TreeIntegCtl control(NoDumpPointers, ReportRepairableSharing, BatchMode);
std::pair<bool, std::string> result =
be->checkTreeIntegrity(block, control);
EXPECT_FALSE(result.first);
EXPECT_TRUE(containstokens(result.second, "stmt has multiple parents"));
Bexpression *b3 = mkInt64Const(be.get(), 3);
Bstatement *es2 = be->expression_statement(func, b3);
Bblock *block2 = mkBlockFromStmt(be.get(), func, es2);
be->disableDebugMetaDataGeneration();
be->function_set_body(func, block2);
}
}