diff options
Diffstat (limited to 'unittests')
30 files changed, 2912 insertions, 293 deletions
diff --git a/unittests/ADT/APFloatTest.cpp b/unittests/ADT/APFloatTest.cpp new file mode 100644 index 0000000..92f020b --- /dev/null +++ b/unittests/ADT/APFloatTest.cpp @@ -0,0 +1,517 @@ +//===- llvm/unittest/ADT/APFloat.cpp - APFloat unit tests ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <ostream> +#include "llvm/Support/raw_ostream.h" +#include "gtest/gtest.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/SmallString.h" + +using namespace llvm; + +static double convertToDoubleFromString(const char *Str) { + llvm::APFloat F(0.0); + F.convertFromString(Str, llvm::APFloat::rmNearestTiesToEven); + return F.convertToDouble(); +} + +namespace { + +TEST(APFloatTest, Zero) { + EXPECT_EQ(0.0f, APFloat(APFloat::IEEEsingle, 0.0f).convertToFloat()); + EXPECT_EQ(-0.0f, APFloat(APFloat::IEEEsingle, -0.0f).convertToFloat()); + + EXPECT_EQ(0.0, APFloat(APFloat::IEEEdouble, 0.0).convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, -0.0).convertToDouble()); +} + +TEST(APFloatTest, fromZeroDecimalString) { + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+0").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0").convertToDouble()); + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0.").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+0.").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0.").convertToDouble()); + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, ".0").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+.0").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-.0").convertToDouble()); + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0.0").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+0.0").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0.0").convertToDouble()); + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "00000.").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+00000.").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-00000.").convertToDouble()); + + EXPECT_EQ(0.0, APFloat(APFloat::IEEEdouble, ".00000").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+.00000").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-.00000").convertToDouble()); + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0000.00000").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+0000.00000").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0000.00000").convertToDouble()); +} + +TEST(APFloatTest, fromZeroDecimalSingleExponentString) { + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0e1").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+0e1").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0e1").convertToDouble()); + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0e+1").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+0e+1").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0e+1").convertToDouble()); + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0e-1").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+0e-1").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0e-1").convertToDouble()); + + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0.e1").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+0.e1").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0.e1").convertToDouble()); + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0.e+1").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+0.e+1").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0.e+1").convertToDouble()); + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0.e-1").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+0.e-1").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0.e-1").convertToDouble()); + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, ".0e1").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+.0e1").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-.0e1").convertToDouble()); + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, ".0e+1").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+.0e+1").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-.0e+1").convertToDouble()); + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, ".0e-1").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+.0e-1").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-.0e-1").convertToDouble()); + + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0.0e1").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+0.0e1").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0.0e1").convertToDouble()); + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0.0e+1").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+0.0e+1").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0.0e+1").convertToDouble()); + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0.0e-1").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+0.0e-1").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0.0e-1").convertToDouble()); + + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "000.0000e1").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+000.0000e+1").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-000.0000e+1").convertToDouble()); +} + +TEST(APFloatTest, fromZeroDecimalLargeExponentString) { + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0e1234").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+0e1234").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0e1234").convertToDouble()); + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0e+1234").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+0e+1234").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0e+1234").convertToDouble()); + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0e-1234").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+0e-1234").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0e-1234").convertToDouble()); + + EXPECT_EQ(0.0, APFloat(APFloat::IEEEdouble, "000.0000e1234").convertToDouble()); + EXPECT_EQ(0.0, APFloat(APFloat::IEEEdouble, "000.0000e-1234").convertToDouble()); + + EXPECT_EQ(0.0, APFloat(APFloat::IEEEdouble, StringRef("0e1234\02", 6)).convertToDouble()); +} + +TEST(APFloatTest, fromZeroHexadecimalString) { + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0x0p1").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+0x0p1").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0x0p1").convertToDouble()); + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0x0p+1").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+0x0p+1").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0x0p+1").convertToDouble()); + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0x0p-1").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+0x0p-1").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0x0p-1").convertToDouble()); + + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0x0.p1").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+0x0.p1").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0x0.p1").convertToDouble()); + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0x0.p+1").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+0x0.p+1").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0x0.p+1").convertToDouble()); + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0x0.p-1").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+0x0.p-1").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0x0.p-1").convertToDouble()); + + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0x.0p1").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+0x.0p1").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0x.0p1").convertToDouble()); + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0x.0p+1").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+0x.0p+1").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0x.0p+1").convertToDouble()); + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0x.0p-1").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+0x.0p-1").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0x.0p-1").convertToDouble()); + + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0x0.0p1").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+0x0.0p1").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0x0.0p1").convertToDouble()); + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0x0.0p+1").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+0x0.0p+1").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0x0.0p+1").convertToDouble()); + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0x0.0p-1").convertToDouble()); + EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble, "+0x0.0p-1").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0x0.0p-1").convertToDouble()); + + + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0x00000.p1").convertToDouble()); + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0x0000.00000p1").convertToDouble()); + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0x.00000p1").convertToDouble()); + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0x0.p1").convertToDouble()); + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0x0p1234").convertToDouble()); + EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble, "-0x0p1234").convertToDouble()); + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0x00000.p1234").convertToDouble()); + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0x0000.00000p1234").convertToDouble()); + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0x.00000p1234").convertToDouble()); + EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble, "0x0.p1234").convertToDouble()); +} + +TEST(APFloatTest, fromDecimalString) { + EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble, "1").convertToDouble()); + EXPECT_EQ(2.0, APFloat(APFloat::IEEEdouble, "2.").convertToDouble()); + EXPECT_EQ(0.5, APFloat(APFloat::IEEEdouble, ".5").convertToDouble()); + EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble, "1.0").convertToDouble()); + EXPECT_EQ(-2.0, APFloat(APFloat::IEEEdouble, "-2").convertToDouble()); + EXPECT_EQ(-4.0, APFloat(APFloat::IEEEdouble, "-4.").convertToDouble()); + EXPECT_EQ(-0.5, APFloat(APFloat::IEEEdouble, "-.5").convertToDouble()); + EXPECT_EQ(-1.5, APFloat(APFloat::IEEEdouble, "-1.5").convertToDouble()); + EXPECT_EQ(1.25e12, APFloat(APFloat::IEEEdouble, "1.25e12").convertToDouble()); + EXPECT_EQ(1.25e+12, APFloat(APFloat::IEEEdouble, "1.25e+12").convertToDouble()); + EXPECT_EQ(1.25e-12, APFloat(APFloat::IEEEdouble, "1.25e-12").convertToDouble()); + EXPECT_EQ(1024.0, APFloat(APFloat::IEEEdouble, "1024.").convertToDouble()); + EXPECT_EQ(1024.05, APFloat(APFloat::IEEEdouble, "1024.05000").convertToDouble()); + EXPECT_EQ(0.05, APFloat(APFloat::IEEEdouble, ".05000").convertToDouble()); + EXPECT_EQ(2.0, APFloat(APFloat::IEEEdouble, "2.").convertToDouble()); + EXPECT_EQ(2.0e2, APFloat(APFloat::IEEEdouble, "2.e2").convertToDouble()); + EXPECT_EQ(2.0e+2, APFloat(APFloat::IEEEdouble, "2.e+2").convertToDouble()); + EXPECT_EQ(2.0e-2, APFloat(APFloat::IEEEdouble, "2.e-2").convertToDouble()); + EXPECT_EQ(2.05e2, APFloat(APFloat::IEEEdouble, "002.05000e2").convertToDouble()); + EXPECT_EQ(2.05e+2, APFloat(APFloat::IEEEdouble, "002.05000e+2").convertToDouble()); + EXPECT_EQ(2.05e-2, APFloat(APFloat::IEEEdouble, "002.05000e-2").convertToDouble()); + EXPECT_EQ(2.05e12, APFloat(APFloat::IEEEdouble, "002.05000e12").convertToDouble()); + EXPECT_EQ(2.05e+12, APFloat(APFloat::IEEEdouble, "002.05000e+12").convertToDouble()); + EXPECT_EQ(2.05e-12, APFloat(APFloat::IEEEdouble, "002.05000e-12").convertToDouble()); +} + +TEST(APFloatTest, fromHexadecimalString) { + EXPECT_EQ( 1.0, APFloat(APFloat::IEEEdouble, "0x1p0").convertToDouble()); + EXPECT_EQ(+1.0, APFloat(APFloat::IEEEdouble, "+0x1p0").convertToDouble()); + EXPECT_EQ(-1.0, APFloat(APFloat::IEEEdouble, "-0x1p0").convertToDouble()); + + EXPECT_EQ( 1.0, APFloat(APFloat::IEEEdouble, "0x1p+0").convertToDouble()); + EXPECT_EQ(+1.0, APFloat(APFloat::IEEEdouble, "+0x1p+0").convertToDouble()); + EXPECT_EQ(-1.0, APFloat(APFloat::IEEEdouble, "-0x1p+0").convertToDouble()); + + EXPECT_EQ( 1.0, APFloat(APFloat::IEEEdouble, "0x1p-0").convertToDouble()); + EXPECT_EQ(+1.0, APFloat(APFloat::IEEEdouble, "+0x1p-0").convertToDouble()); + EXPECT_EQ(-1.0, APFloat(APFloat::IEEEdouble, "-0x1p-0").convertToDouble()); + + + EXPECT_EQ( 2.0, APFloat(APFloat::IEEEdouble, "0x1p1").convertToDouble()); + EXPECT_EQ(+2.0, APFloat(APFloat::IEEEdouble, "+0x1p1").convertToDouble()); + EXPECT_EQ(-2.0, APFloat(APFloat::IEEEdouble, "-0x1p1").convertToDouble()); + + EXPECT_EQ( 2.0, APFloat(APFloat::IEEEdouble, "0x1p+1").convertToDouble()); + EXPECT_EQ(+2.0, APFloat(APFloat::IEEEdouble, "+0x1p+1").convertToDouble()); + EXPECT_EQ(-2.0, APFloat(APFloat::IEEEdouble, "-0x1p+1").convertToDouble()); + + EXPECT_EQ( 0.5, APFloat(APFloat::IEEEdouble, "0x1p-1").convertToDouble()); + EXPECT_EQ(+0.5, APFloat(APFloat::IEEEdouble, "+0x1p-1").convertToDouble()); + EXPECT_EQ(-0.5, APFloat(APFloat::IEEEdouble, "-0x1p-1").convertToDouble()); + + + EXPECT_EQ( 3.0, APFloat(APFloat::IEEEdouble, "0x1.8p1").convertToDouble()); + EXPECT_EQ(+3.0, APFloat(APFloat::IEEEdouble, "+0x1.8p1").convertToDouble()); + EXPECT_EQ(-3.0, APFloat(APFloat::IEEEdouble, "-0x1.8p1").convertToDouble()); + + EXPECT_EQ( 3.0, APFloat(APFloat::IEEEdouble, "0x1.8p+1").convertToDouble()); + EXPECT_EQ(+3.0, APFloat(APFloat::IEEEdouble, "+0x1.8p+1").convertToDouble()); + EXPECT_EQ(-3.0, APFloat(APFloat::IEEEdouble, "-0x1.8p+1").convertToDouble()); + + EXPECT_EQ( 0.75, APFloat(APFloat::IEEEdouble, "0x1.8p-1").convertToDouble()); + EXPECT_EQ(+0.75, APFloat(APFloat::IEEEdouble, "+0x1.8p-1").convertToDouble()); + EXPECT_EQ(-0.75, APFloat(APFloat::IEEEdouble, "-0x1.8p-1").convertToDouble()); + + + EXPECT_EQ( 8192.0, APFloat(APFloat::IEEEdouble, "0x1000.000p1").convertToDouble()); + EXPECT_EQ(+8192.0, APFloat(APFloat::IEEEdouble, "+0x1000.000p1").convertToDouble()); + EXPECT_EQ(-8192.0, APFloat(APFloat::IEEEdouble, "-0x1000.000p1").convertToDouble()); + + EXPECT_EQ( 8192.0, APFloat(APFloat::IEEEdouble, "0x1000.000p+1").convertToDouble()); + EXPECT_EQ(+8192.0, APFloat(APFloat::IEEEdouble, "+0x1000.000p+1").convertToDouble()); + EXPECT_EQ(-8192.0, APFloat(APFloat::IEEEdouble, "-0x1000.000p+1").convertToDouble()); + + EXPECT_EQ( 2048.0, APFloat(APFloat::IEEEdouble, "0x1000.000p-1").convertToDouble()); + EXPECT_EQ(+2048.0, APFloat(APFloat::IEEEdouble, "+0x1000.000p-1").convertToDouble()); + EXPECT_EQ(-2048.0, APFloat(APFloat::IEEEdouble, "-0x1000.000p-1").convertToDouble()); + + + EXPECT_EQ( 8192.0, APFloat(APFloat::IEEEdouble, "0x1000p1").convertToDouble()); + EXPECT_EQ(+8192.0, APFloat(APFloat::IEEEdouble, "+0x1000p1").convertToDouble()); + EXPECT_EQ(-8192.0, APFloat(APFloat::IEEEdouble, "-0x1000p1").convertToDouble()); + + EXPECT_EQ( 8192.0, APFloat(APFloat::IEEEdouble, "0x1000p+1").convertToDouble()); + EXPECT_EQ(+8192.0, APFloat(APFloat::IEEEdouble, "+0x1000p+1").convertToDouble()); + EXPECT_EQ(-8192.0, APFloat(APFloat::IEEEdouble, "-0x1000p+1").convertToDouble()); + + EXPECT_EQ( 2048.0, APFloat(APFloat::IEEEdouble, "0x1000p-1").convertToDouble()); + EXPECT_EQ(+2048.0, APFloat(APFloat::IEEEdouble, "+0x1000p-1").convertToDouble()); + EXPECT_EQ(-2048.0, APFloat(APFloat::IEEEdouble, "-0x1000p-1").convertToDouble()); + + + EXPECT_EQ( 16384.0, APFloat(APFloat::IEEEdouble, "0x10p10").convertToDouble()); + EXPECT_EQ(+16384.0, APFloat(APFloat::IEEEdouble, "+0x10p10").convertToDouble()); + EXPECT_EQ(-16384.0, APFloat(APFloat::IEEEdouble, "-0x10p10").convertToDouble()); + + EXPECT_EQ( 16384.0, APFloat(APFloat::IEEEdouble, "0x10p+10").convertToDouble()); + EXPECT_EQ(+16384.0, APFloat(APFloat::IEEEdouble, "+0x10p+10").convertToDouble()); + EXPECT_EQ(-16384.0, APFloat(APFloat::IEEEdouble, "-0x10p+10").convertToDouble()); + + EXPECT_EQ( 0.015625, APFloat(APFloat::IEEEdouble, "0x10p-10").convertToDouble()); + EXPECT_EQ(+0.015625, APFloat(APFloat::IEEEdouble, "+0x10p-10").convertToDouble()); + EXPECT_EQ(-0.015625, APFloat(APFloat::IEEEdouble, "-0x10p-10").convertToDouble()); + + EXPECT_EQ(1.0625, APFloat(APFloat::IEEEdouble, "0x1.1p0").convertToDouble()); + EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble, "0x1p0").convertToDouble()); + + EXPECT_EQ(2.71828, convertToDoubleFromString("2.71828")); +} + +#ifdef GTEST_HAS_DEATH_TEST +TEST(APFloatTest, SemanticsDeath) { + EXPECT_DEATH(APFloat(APFloat::IEEEsingle, 0.0f).convertToDouble(), "Float semantics are not IEEEdouble"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, 0.0 ).convertToFloat(), "Float semantics are not IEEEsingle"); +} + +TEST(APFloatTest, StringDecimalDeath) { + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, ""), "Invalid string length"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+"), "String has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-"), "String has no digits"); + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, StringRef("\0", 1)), "Invalid character in significand"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, StringRef("1\0", 2)), "Invalid character in significand"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, StringRef("1\02", 3)), "Invalid character in significand"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, StringRef("1\02e1", 5)), "Invalid character in significand"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, StringRef("1e\0", 3)), "Invalid character in exponent"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, StringRef("1e1\0", 4)), "Invalid character in exponent"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, StringRef("1e1\02", 5)), "Invalid character in exponent"); + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "1.0f"), "Invalid character in significand"); + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, ".."), "String contains multiple dots"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "..0"), "String contains multiple dots"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "1.0.0"), "String contains multiple dots"); +} + +TEST(APFloatTest, StringDecimalSignificandDeath) { + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "."), "Significand has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+."), "Significand has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-."), "Significand has no digits"); + + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "e"), "Significand has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+e"), "Significand has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-e"), "Significand has no digits"); + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "e1"), "Significand has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+e1"), "Significand has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-e1"), "Significand has no digits"); + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, ".e1"), "Significand has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+.e1"), "Significand has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-.e1"), "Significand has no digits"); + + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, ".e"), "Significand has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+.e"), "Significand has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-.e"), "Significand has no digits"); +} + +TEST(APFloatTest, StringDecimalExponentDeath) { + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "1e"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+1e"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-1e"), "Exponent has no digits"); + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "1.e"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+1.e"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-1.e"), "Exponent has no digits"); + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, ".1e"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+.1e"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-.1e"), "Exponent has no digits"); + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "1.1e"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+1.1e"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-1.1e"), "Exponent has no digits"); + + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "1e+"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "1e-"), "Exponent has no digits"); + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, ".1e"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, ".1e+"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, ".1e-"), "Exponent has no digits"); + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "1.0e"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "1.0e+"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "1.0e-"), "Exponent has no digits"); +} + +TEST(APFloatTest, StringHexadecimalDeath) { + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "0x"), "Invalid string"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+0x"), "Invalid string"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-0x"), "Invalid string"); + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "0x0"), "Hex strings require an exponent"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+0x0"), "Hex strings require an exponent"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-0x0"), "Hex strings require an exponent"); + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "0x0."), "Hex strings require an exponent"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+0x0."), "Hex strings require an exponent"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-0x0."), "Hex strings require an exponent"); + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "0x.0"), "Hex strings require an exponent"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+0x.0"), "Hex strings require an exponent"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-0x.0"), "Hex strings require an exponent"); + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "0x0.0"), "Hex strings require an exponent"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+0x0.0"), "Hex strings require an exponent"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-0x0.0"), "Hex strings require an exponent"); + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, StringRef("0x\0", 3)), "Invalid character in significand"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, StringRef("0x1\0", 4)), "Invalid character in significand"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, StringRef("0x1\02", 5)), "Invalid character in significand"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, StringRef("0x1\02p1", 7)), "Invalid character in significand"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, StringRef("0x1p\0", 5)), "Invalid character in exponent"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, StringRef("0x1p1\0", 6)), "Invalid character in exponent"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, StringRef("0x1p1\02", 7)), "Invalid character in exponent"); + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "0x1p0f"), "Invalid character in exponent"); + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "0x..p1"), "String contains multiple dots"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "0x..0p1"), "String contains multiple dots"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "0x1.0.0p1"), "String contains multiple dots"); +} + +TEST(APFloatTest, StringHexadecimalSignificandDeath) { + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "0x."), "Significand has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+0x."), "Significand has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-0x."), "Significand has no digits"); + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "0xp"), "Significand has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+0xp"), "Significand has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-0xp"), "Significand has no digits"); + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "0xp+"), "Significand has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+0xp+"), "Significand has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-0xp+"), "Significand has no digits"); + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "0xp-"), "Significand has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+0xp-"), "Significand has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-0xp-"), "Significand has no digits"); + + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "0x.p"), "Significand has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+0x.p"), "Significand has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-0x.p"), "Significand has no digits"); + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "0x.p+"), "Significand has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+0x.p+"), "Significand has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-0x.p+"), "Significand has no digits"); + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "0x.p-"), "Significand has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+0x.p-"), "Significand has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-0x.p-"), "Significand has no digits"); +} + +TEST(APFloatTest, StringHexadecimalExponentDeath) { + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "0x1p"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+0x1p"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-0x1p"), "Exponent has no digits"); + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "0x1p+"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+0x1p+"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-0x1p+"), "Exponent has no digits"); + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "0x1p-"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+0x1p-"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-0x1p-"), "Exponent has no digits"); + + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "0x1.p"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+0x1.p"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-0x1.p"), "Exponent has no digits"); + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "0x1.p+"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+0x1.p+"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-0x1.p+"), "Exponent has no digits"); + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "0x1.p-"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+0x1.p-"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-0x1.p-"), "Exponent has no digits"); + + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "0x.1p"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+0x.1p"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-0x.1p"), "Exponent has no digits"); + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "0x.1p+"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+0x.1p+"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-0x.1p+"), "Exponent has no digits"); + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "0x.1p-"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+0x.1p-"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-0x.1p-"), "Exponent has no digits"); + + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "0x1.1p"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+0x1.1p"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-0x1.1p"), "Exponent has no digits"); + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "0x1.1p+"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+0x1.1p+"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-0x1.1p+"), "Exponent has no digits"); + + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "0x1.1p-"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "+0x1.1p-"), "Exponent has no digits"); + EXPECT_DEATH(APFloat(APFloat::IEEEdouble, "-0x1.1p-"), "Exponent has no digits"); +} +#endif + +} diff --git a/unittests/ADT/APIntTest.cpp b/unittests/ADT/APIntTest.cpp index 648faf1..0b13aa4 100644 --- a/unittests/ADT/APIntTest.cpp +++ b/unittests/ADT/APIntTest.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// #include <ostream> -#include "llvm/Support/raw_ostream.h" #include "gtest/gtest.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/SmallString.h" @@ -164,12 +163,182 @@ TEST(APIntTest, i1) { } TEST(APIntTest, fromString) { - EXPECT_EQ(APInt(1, 0), APInt(1, "0", 1, 10)); - EXPECT_EQ(APInt(1, 1), APInt(1, "1", 1, 10)); - EXPECT_EQ(APInt(1, 1), APInt(1, "-1", 2, 10)); - EXPECT_EQ(APInt(1, 1), APInt(1, "1", 1, 2)); - EXPECT_EQ(APInt(1, 1), APInt(1, "1", 1, 8)); - EXPECT_EQ(APInt(1, 1), APInt(1, "1", 1, 16)); + EXPECT_EQ(APInt(32, 0), APInt(32, "0", 2)); + EXPECT_EQ(APInt(32, 1), APInt(32, "1", 2)); + EXPECT_EQ(APInt(32, 2), APInt(32, "10", 2)); + EXPECT_EQ(APInt(32, 3), APInt(32, "11", 2)); + EXPECT_EQ(APInt(32, 4), APInt(32, "100", 2)); + + EXPECT_EQ(APInt(32, 0), APInt(32, "+0", 2)); + EXPECT_EQ(APInt(32, 1), APInt(32, "+1", 2)); + EXPECT_EQ(APInt(32, 2), APInt(32, "+10", 2)); + EXPECT_EQ(APInt(32, 3), APInt(32, "+11", 2)); + EXPECT_EQ(APInt(32, 4), APInt(32, "+100", 2)); + + EXPECT_EQ(APInt(32, uint64_t(-0LL)), APInt(32, "-0", 2)); + EXPECT_EQ(APInt(32, uint64_t(-1LL)), APInt(32, "-1", 2)); + EXPECT_EQ(APInt(32, uint64_t(-2LL)), APInt(32, "-10", 2)); + EXPECT_EQ(APInt(32, uint64_t(-3LL)), APInt(32, "-11", 2)); + EXPECT_EQ(APInt(32, uint64_t(-4LL)), APInt(32, "-100", 2)); + + + EXPECT_EQ(APInt(32, 0), APInt(32, "0", 8)); + EXPECT_EQ(APInt(32, 1), APInt(32, "1", 8)); + EXPECT_EQ(APInt(32, 7), APInt(32, "7", 8)); + EXPECT_EQ(APInt(32, 8), APInt(32, "10", 8)); + EXPECT_EQ(APInt(32, 15), APInt(32, "17", 8)); + EXPECT_EQ(APInt(32, 16), APInt(32, "20", 8)); + + EXPECT_EQ(APInt(32, +0), APInt(32, "+0", 8)); + EXPECT_EQ(APInt(32, +1), APInt(32, "+1", 8)); + EXPECT_EQ(APInt(32, +7), APInt(32, "+7", 8)); + EXPECT_EQ(APInt(32, +8), APInt(32, "+10", 8)); + EXPECT_EQ(APInt(32, +15), APInt(32, "+17", 8)); + EXPECT_EQ(APInt(32, +16), APInt(32, "+20", 8)); + + EXPECT_EQ(APInt(32, uint64_t(-0LL)), APInt(32, "-0", 8)); + EXPECT_EQ(APInt(32, uint64_t(-1LL)), APInt(32, "-1", 8)); + EXPECT_EQ(APInt(32, uint64_t(-7LL)), APInt(32, "-7", 8)); + EXPECT_EQ(APInt(32, uint64_t(-8LL)), APInt(32, "-10", 8)); + EXPECT_EQ(APInt(32, uint64_t(-15LL)), APInt(32, "-17", 8)); + EXPECT_EQ(APInt(32, uint64_t(-16LL)), APInt(32, "-20", 8)); + + + EXPECT_EQ(APInt(32, 0), APInt(32, "0", 10)); + EXPECT_EQ(APInt(32, 1), APInt(32, "1", 10)); + EXPECT_EQ(APInt(32, 9), APInt(32, "9", 10)); + EXPECT_EQ(APInt(32, 10), APInt(32, "10", 10)); + EXPECT_EQ(APInt(32, 19), APInt(32, "19", 10)); + EXPECT_EQ(APInt(32, 20), APInt(32, "20", 10)); + + EXPECT_EQ(APInt(32, uint64_t(-0LL)), APInt(32, "-0", 10)); + EXPECT_EQ(APInt(32, uint64_t(-1LL)), APInt(32, "-1", 10)); + EXPECT_EQ(APInt(32, uint64_t(-9LL)), APInt(32, "-9", 10)); + EXPECT_EQ(APInt(32, uint64_t(-10LL)), APInt(32, "-10", 10)); + EXPECT_EQ(APInt(32, uint64_t(-19LL)), APInt(32, "-19", 10)); + EXPECT_EQ(APInt(32, uint64_t(-20LL)), APInt(32, "-20", 10)); + + + EXPECT_EQ(APInt(32, 0), APInt(32, "0", 16)); + EXPECT_EQ(APInt(32, 1), APInt(32, "1", 16)); + EXPECT_EQ(APInt(32, 15), APInt(32, "F", 16)); + EXPECT_EQ(APInt(32, 16), APInt(32, "10", 16)); + EXPECT_EQ(APInt(32, 31), APInt(32, "1F", 16)); + EXPECT_EQ(APInt(32, 32), APInt(32, "20", 16)); + + EXPECT_EQ(APInt(32, uint64_t(-0LL)), APInt(32, "-0", 16)); + EXPECT_EQ(APInt(32, uint64_t(-1LL)), APInt(32, "-1", 16)); + EXPECT_EQ(APInt(32, uint64_t(-15LL)), APInt(32, "-F", 16)); + EXPECT_EQ(APInt(32, uint64_t(-16LL)), APInt(32, "-10", 16)); + EXPECT_EQ(APInt(32, uint64_t(-31LL)), APInt(32, "-1F", 16)); + EXPECT_EQ(APInt(32, uint64_t(-32LL)), APInt(32, "-20", 16)); +} + +TEST(APIntTest, StringBitsNeeded2) { + EXPECT_EQ(1U, APInt::getBitsNeeded( "0", 2)); + EXPECT_EQ(1U, APInt::getBitsNeeded( "1", 2)); + EXPECT_EQ(2U, APInt::getBitsNeeded( "10", 2)); + EXPECT_EQ(2U, APInt::getBitsNeeded( "11", 2)); + EXPECT_EQ(3U, APInt::getBitsNeeded("100", 2)); + + EXPECT_EQ(1U, APInt::getBitsNeeded( "+0", 2)); + EXPECT_EQ(1U, APInt::getBitsNeeded( "+1", 2)); + EXPECT_EQ(2U, APInt::getBitsNeeded( "+10", 2)); + EXPECT_EQ(2U, APInt::getBitsNeeded( "+11", 2)); + EXPECT_EQ(3U, APInt::getBitsNeeded("+100", 2)); + + EXPECT_EQ(2U, APInt::getBitsNeeded( "-0", 2)); + EXPECT_EQ(2U, APInt::getBitsNeeded( "-1", 2)); + EXPECT_EQ(3U, APInt::getBitsNeeded( "-10", 2)); + EXPECT_EQ(3U, APInt::getBitsNeeded( "-11", 2)); + EXPECT_EQ(4U, APInt::getBitsNeeded("-100", 2)); +} + +TEST(APIntTest, StringBitsNeeded8) { + EXPECT_EQ(3U, APInt::getBitsNeeded( "0", 8)); + EXPECT_EQ(3U, APInt::getBitsNeeded( "7", 8)); + EXPECT_EQ(6U, APInt::getBitsNeeded("10", 8)); + EXPECT_EQ(6U, APInt::getBitsNeeded("17", 8)); + EXPECT_EQ(6U, APInt::getBitsNeeded("20", 8)); + + EXPECT_EQ(3U, APInt::getBitsNeeded( "+0", 8)); + EXPECT_EQ(3U, APInt::getBitsNeeded( "+7", 8)); + EXPECT_EQ(6U, APInt::getBitsNeeded("+10", 8)); + EXPECT_EQ(6U, APInt::getBitsNeeded("+17", 8)); + EXPECT_EQ(6U, APInt::getBitsNeeded("+20", 8)); + + EXPECT_EQ(4U, APInt::getBitsNeeded( "-0", 8)); + EXPECT_EQ(4U, APInt::getBitsNeeded( "-7", 8)); + EXPECT_EQ(7U, APInt::getBitsNeeded("-10", 8)); + EXPECT_EQ(7U, APInt::getBitsNeeded("-17", 8)); + EXPECT_EQ(7U, APInt::getBitsNeeded("-20", 8)); +} + +TEST(APIntTest, StringBitsNeeded10) { + EXPECT_EQ(1U, APInt::getBitsNeeded( "0", 10)); + EXPECT_EQ(2U, APInt::getBitsNeeded( "3", 10)); + EXPECT_EQ(4U, APInt::getBitsNeeded( "9", 10)); + EXPECT_EQ(4U, APInt::getBitsNeeded("10", 10)); + EXPECT_EQ(5U, APInt::getBitsNeeded("19", 10)); + EXPECT_EQ(5U, APInt::getBitsNeeded("20", 10)); + + EXPECT_EQ(1U, APInt::getBitsNeeded( "+0", 10)); + EXPECT_EQ(4U, APInt::getBitsNeeded( "+9", 10)); + EXPECT_EQ(4U, APInt::getBitsNeeded("+10", 10)); + EXPECT_EQ(5U, APInt::getBitsNeeded("+19", 10)); + EXPECT_EQ(5U, APInt::getBitsNeeded("+20", 10)); + + EXPECT_EQ(2U, APInt::getBitsNeeded( "-0", 10)); + EXPECT_EQ(5U, APInt::getBitsNeeded( "-9", 10)); + EXPECT_EQ(5U, APInt::getBitsNeeded("-10", 10)); + EXPECT_EQ(6U, APInt::getBitsNeeded("-19", 10)); + EXPECT_EQ(6U, APInt::getBitsNeeded("-20", 10)); +} + +TEST(APIntTest, StringBitsNeeded16) { + EXPECT_EQ(4U, APInt::getBitsNeeded( "0", 16)); + EXPECT_EQ(4U, APInt::getBitsNeeded( "F", 16)); + EXPECT_EQ(8U, APInt::getBitsNeeded("10", 16)); + EXPECT_EQ(8U, APInt::getBitsNeeded("1F", 16)); + EXPECT_EQ(8U, APInt::getBitsNeeded("20", 16)); + + EXPECT_EQ(4U, APInt::getBitsNeeded( "+0", 16)); + EXPECT_EQ(4U, APInt::getBitsNeeded( "+F", 16)); + EXPECT_EQ(8U, APInt::getBitsNeeded("+10", 16)); + EXPECT_EQ(8U, APInt::getBitsNeeded("+1F", 16)); + EXPECT_EQ(8U, APInt::getBitsNeeded("+20", 16)); + + EXPECT_EQ(5U, APInt::getBitsNeeded( "-0", 16)); + EXPECT_EQ(5U, APInt::getBitsNeeded( "-F", 16)); + EXPECT_EQ(9U, APInt::getBitsNeeded("-10", 16)); + EXPECT_EQ(9U, APInt::getBitsNeeded("-1F", 16)); + EXPECT_EQ(9U, APInt::getBitsNeeded("-20", 16)); +} + +TEST(APIntTest, Log2) { + EXPECT_EQ(APInt(15, 7).logBase2(), 2U); + EXPECT_EQ(APInt(15, 7).ceilLogBase2(), 3U); + EXPECT_EQ(APInt(15, 7).exactLogBase2(), -1); + EXPECT_EQ(APInt(15, 8).logBase2(), 3U); + EXPECT_EQ(APInt(15, 8).ceilLogBase2(), 3U); + EXPECT_EQ(APInt(15, 8).exactLogBase2(), 3); + EXPECT_EQ(APInt(15, 9).logBase2(), 3U); + EXPECT_EQ(APInt(15, 9).ceilLogBase2(), 4U); + EXPECT_EQ(APInt(15, 9).exactLogBase2(), -1); +} + +#ifdef GTEST_HAS_DEATH_TEST +TEST(APIntTest, StringDeath) { + EXPECT_DEATH(APInt(0, "", 0), "Bitwidth too small"); + EXPECT_DEATH(APInt(32, "", 0), "Invalid string length"); + EXPECT_DEATH(APInt(32, "0", 0), "Radix should be 2, 8, 10, or 16!"); + EXPECT_DEATH(APInt(32, "", 10), "Invalid string length"); + EXPECT_DEATH(APInt(32, "-", 10), "String is only a sign, needs a value."); + EXPECT_DEATH(APInt(1, "1234", 10), "Insufficient bit width"); + EXPECT_DEATH(APInt(32, "\0", 10), "Invalid string length"); + EXPECT_DEATH(APInt(32, StringRef("1\02", 3), 10), "Invalid character in digit string"); + EXPECT_DEATH(APInt(32, "1L", 10), "Invalid character in digit string"); } +#endif } diff --git a/unittests/ADT/SmallStringTest.cpp b/unittests/ADT/SmallStringTest.cpp new file mode 100644 index 0000000..099d815 --- /dev/null +++ b/unittests/ADT/SmallStringTest.cpp @@ -0,0 +1,48 @@ +//===- llvm/unittest/ADT/SmallStringTest.cpp ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// SmallString unit tests. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" +#include "llvm/ADT/SmallString.h" +#include <stdarg.h> +#include <climits> +#include <cstring> + +using namespace llvm; + +namespace { + +// Test fixture class +class SmallStringTest : public testing::Test { +protected: + typedef SmallString<40> StringType; + + StringType theString; + + void assertEmpty(StringType & v) { + // Size tests + EXPECT_EQ(0u, v.size()); + EXPECT_TRUE(v.empty()); + // Iterator tests + EXPECT_TRUE(v.begin() == v.end()); + } +}; + +// New string test. +TEST_F(SmallStringTest, EmptyStringTest) { + SCOPED_TRACE("EmptyStringTest"); + assertEmpty(theString); + EXPECT_TRUE(theString.rbegin() == theString.rend()); +} + +} + diff --git a/unittests/ADT/SmallVectorTest.cpp b/unittests/ADT/SmallVectorTest.cpp index 19ef099..8a81796 100644 --- a/unittests/ADT/SmallVectorTest.cpp +++ b/unittests/ADT/SmallVectorTest.cpp @@ -196,7 +196,8 @@ TEST_F(SmallVectorTest, ResizeGrowTest) { theVector.resize(2); - // XXX: I don't know where the extra construct/destruct is coming from. + // The extra constructor/destructor calls come from the temporary object used + // to initialize the contents of the resized array (via copy construction). EXPECT_EQ(3, Constructable::getNumConstructorCalls()); EXPECT_EQ(1, Constructable::getNumDestructorCalls()); EXPECT_EQ(2u, theVector.size()); @@ -214,16 +215,16 @@ TEST_F(SmallVectorTest, ResizeFillTest) { TEST_F(SmallVectorTest, OverflowTest) { SCOPED_TRACE("OverflowTest"); - // Push more elements than the fixed size + // Push more elements than the fixed size. makeSequence(theVector, 1, 10); - // test size and values + // Test size and values. EXPECT_EQ(10u, theVector.size()); for (int i = 0; i < 10; ++i) { EXPECT_EQ(i+1, theVector[i].getValue()); } - // Now resize back to fixed size + // Now resize back to fixed size. theVector.resize(1); assertValuesInOrder(theVector, 1u, 1); @@ -380,4 +381,22 @@ TEST_F(SmallVectorTest, ConstVectorTest) { EXPECT_TRUE(constVector.begin() == constVector.end()); } +// Direct array access. +TEST_F(SmallVectorTest, DirectVectorTest) { + EXPECT_EQ(0u, theVector.size()); + EXPECT_EQ(4u, theVector.capacity()); + EXPECT_EQ(0, Constructable::getNumConstructorCalls()); + theVector.end()[0] = 1; + theVector.end()[1] = 2; + theVector.end()[2] = 3; + theVector.end()[3] = 4; + theVector.set_size(4); + EXPECT_EQ(4u, theVector.size()); + EXPECT_EQ(4, Constructable::getNumConstructorCalls()); + EXPECT_EQ(1, theVector[0].getValue()); + EXPECT_EQ(2, theVector[1].getValue()); + EXPECT_EQ(3, theVector[2].getValue()); + EXPECT_EQ(4, theVector[3].getValue()); +} + } diff --git a/unittests/ADT/SparseBitVectorTest.cpp b/unittests/ADT/SparseBitVectorTest.cpp new file mode 100644 index 0000000..d8fc5ce --- /dev/null +++ b/unittests/ADT/SparseBitVectorTest.cpp @@ -0,0 +1,36 @@ +//===- llvm/unittest/ADT/SparseBitVectorTest.cpp - SparseBitVector tests --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/SparseBitVector.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +TEST(SparseBitVectorTest, TrivialOperation) { + SparseBitVector<> Vec; + EXPECT_EQ(0U, Vec.count()); + EXPECT_FALSE(Vec.test(17)); + Vec.set(5); + EXPECT_TRUE(Vec.test(5)); + EXPECT_FALSE(Vec.test(17)); + Vec.reset(6); + EXPECT_TRUE(Vec.test(5)); + EXPECT_FALSE(Vec.test(6)); + Vec.reset(5); + EXPECT_FALSE(Vec.test(5)); + EXPECT_TRUE(Vec.test_and_set(17)); + EXPECT_FALSE(Vec.test_and_set(17)); + EXPECT_TRUE(Vec.test(17)); + Vec.clear(); + EXPECT_FALSE(Vec.test(17)); +} + +} diff --git a/unittests/ADT/StringMapTest.cpp b/unittests/ADT/StringMapTest.cpp index 9f9f2e4..8ee166b 100644 --- a/unittests/ADT/StringMapTest.cpp +++ b/unittests/ADT/StringMapTest.cpp @@ -9,6 +9,7 @@ #include "gtest/gtest.h" #include "llvm/ADT/StringMap.h" +#include "llvm/Support/DataTypes.h" using namespace llvm; namespace { @@ -21,7 +22,7 @@ protected: static const char testKey[]; static const uint32_t testValue; static const char* testKeyFirst; - static const char* testKeyLast; + static size_t testKeyLength; static const std::string testKeyStr; void assertEmptyMap() { @@ -34,10 +35,11 @@ protected: // Lookup tests EXPECT_EQ(0u, testMap.count(testKey)); - EXPECT_EQ(0u, testMap.count(testKeyFirst, testKeyLast)); + EXPECT_EQ(0u, testMap.count(StringRef(testKeyFirst, testKeyLength))); EXPECT_EQ(0u, testMap.count(testKeyStr)); EXPECT_TRUE(testMap.find(testKey) == testMap.end()); - EXPECT_TRUE(testMap.find(testKeyFirst, testKeyLast) == testMap.end()); + EXPECT_TRUE(testMap.find(StringRef(testKeyFirst, testKeyLength)) == + testMap.end()); EXPECT_TRUE(testMap.find(testKeyStr) == testMap.end()); } @@ -56,10 +58,11 @@ protected: // Lookup tests EXPECT_EQ(1u, testMap.count(testKey)); - EXPECT_EQ(1u, testMap.count(testKeyFirst, testKeyLast)); + EXPECT_EQ(1u, testMap.count(StringRef(testKeyFirst, testKeyLength))); EXPECT_EQ(1u, testMap.count(testKeyStr)); EXPECT_TRUE(testMap.find(testKey) == testMap.begin()); - EXPECT_TRUE(testMap.find(testKeyFirst, testKeyLast) == testMap.begin()); + EXPECT_TRUE(testMap.find(StringRef(testKeyFirst, testKeyLength)) == + testMap.begin()); EXPECT_TRUE(testMap.find(testKeyStr) == testMap.begin()); } }; @@ -67,7 +70,7 @@ protected: const char StringMapTest::testKey[] = "key"; const uint32_t StringMapTest::testValue = 1u; const char* StringMapTest::testKeyFirst = testKey; -const char* StringMapTest::testKeyLast = testKey + sizeof(testKey) - 1; +size_t StringMapTest::testKeyLength = sizeof(testKey) - 1; const std::string StringMapTest::testKeyStr(testKey); // Empty map tests. @@ -89,10 +92,10 @@ TEST_F(StringMapTest, ConstEmptyMapTest) { // Lookup tests EXPECT_EQ(0u, constTestMap.count(testKey)); - EXPECT_EQ(0u, constTestMap.count(testKeyFirst, testKeyLast)); + EXPECT_EQ(0u, constTestMap.count(StringRef(testKeyFirst, testKeyLength))); EXPECT_EQ(0u, constTestMap.count(testKeyStr)); EXPECT_TRUE(constTestMap.find(testKey) == constTestMap.end()); - EXPECT_TRUE(constTestMap.find(testKeyFirst, testKeyLast) == + EXPECT_TRUE(constTestMap.find(StringRef(testKeyFirst, testKeyLength)) == constTestMap.end()); EXPECT_TRUE(constTestMap.find(testKeyStr) == constTestMap.end()); } @@ -185,7 +188,7 @@ namespace { TEST_F(StringMapTest, StringMapEntryTest) { StringMap<uint32_t>::value_type* entry = StringMap<uint32_t>::value_type::Create( - testKeyFirst, testKeyLast, 1u); + testKeyFirst, testKeyFirst + testKeyLength, 1u); EXPECT_STREQ(testKey, entry->first()); EXPECT_EQ(1u, entry->second); } @@ -195,7 +198,8 @@ TEST_F(StringMapTest, InsertTest) { SCOPED_TRACE("InsertTest"); testMap.insert( StringMap<uint32_t>::value_type::Create( - testKeyFirst, testKeyLast, testMap.getAllocator(), 1u)); + testKeyFirst, testKeyFirst + testKeyLength, + testMap.getAllocator(), 1u)); assertSingleItemMap(); } diff --git a/unittests/ADT/StringRefTest.cpp b/unittests/ADT/StringRefTest.cpp new file mode 100644 index 0000000..cdc476e --- /dev/null +++ b/unittests/ADT/StringRefTest.cpp @@ -0,0 +1,155 @@ +//===- llvm/unittest/ADT/StringRefTest.cpp - StringRef unit tests ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + +std::ostream &operator<<(std::ostream &OS, const StringRef &S) { + OS << S; + return OS; +} + +std::ostream &operator<<(std::ostream &OS, + const std::pair<StringRef, StringRef> &P) { + OS << "(" << P.first << ", " << P.second << ")"; + return OS; +} + +TEST(StringRefTest, Construction) { + EXPECT_EQ("", StringRef()); + EXPECT_EQ("hello", StringRef("hello")); + EXPECT_EQ("hello", StringRef("hello world", 5)); + EXPECT_EQ("hello", StringRef(std::string("hello"))); +} + +TEST(StringRefTest, Iteration) { + StringRef S("hello"); + const char *p = "hello"; + for (const char *it = S.begin(), *ie = S.end(); it != ie; ++it, ++p) + EXPECT_EQ(*it, *p); +} + +TEST(StringRefTest, StringOps) { + const char *p = "hello"; + EXPECT_EQ(p, StringRef(p, 0).data()); + EXPECT_TRUE(StringRef().empty()); + EXPECT_EQ((size_t) 5, StringRef("hello").size()); + EXPECT_EQ(-1, StringRef("aab").compare("aad")); + EXPECT_EQ( 0, StringRef("aab").compare("aab")); + EXPECT_EQ( 1, StringRef("aab").compare("aaa")); + EXPECT_EQ(-1, StringRef("aab").compare("aabb")); + EXPECT_EQ( 1, StringRef("aab").compare("aa")); +} + +TEST(StringRefTest, Operators) { + EXPECT_EQ("", StringRef()); + EXPECT_TRUE(StringRef("aab") < StringRef("aad")); + EXPECT_FALSE(StringRef("aab") < StringRef("aab")); + EXPECT_TRUE(StringRef("aab") <= StringRef("aab")); + EXPECT_FALSE(StringRef("aab") <= StringRef("aaa")); + EXPECT_TRUE(StringRef("aad") > StringRef("aab")); + EXPECT_FALSE(StringRef("aab") > StringRef("aab")); + EXPECT_TRUE(StringRef("aab") >= StringRef("aab")); + EXPECT_FALSE(StringRef("aaa") >= StringRef("aab")); + EXPECT_EQ(StringRef("aab"), StringRef("aab")); + EXPECT_FALSE(StringRef("aab") == StringRef("aac")); + EXPECT_FALSE(StringRef("aab") != StringRef("aab")); + EXPECT_TRUE(StringRef("aab") != StringRef("aac")); + EXPECT_EQ('a', StringRef("aab")[1]); +} + +TEST(StringRefTest, Substr) { + StringRef Str("hello"); + EXPECT_EQ("lo", Str.substr(3)); + EXPECT_EQ("", Str.substr(100)); + EXPECT_EQ("hello", Str.substr(0, 100)); + EXPECT_EQ("o", Str.substr(4, 10)); +} + +TEST(StringRefTest, Slice) { + StringRef Str("hello"); + EXPECT_EQ("l", Str.slice(2, 3)); + EXPECT_EQ("ell", Str.slice(1, 4)); + EXPECT_EQ("llo", Str.slice(2, 100)); + EXPECT_EQ("", Str.slice(2, 1)); + EXPECT_EQ("", Str.slice(10, 20)); +} + +TEST(StringRefTest, Split) { + StringRef Str("hello"); + EXPECT_EQ(std::make_pair(StringRef("hello"), StringRef("")), + Str.split('X')); + EXPECT_EQ(std::make_pair(StringRef("h"), StringRef("llo")), + Str.split('e')); + EXPECT_EQ(std::make_pair(StringRef(""), StringRef("ello")), + Str.split('h')); + EXPECT_EQ(std::make_pair(StringRef("he"), StringRef("lo")), + Str.split('l')); + EXPECT_EQ(std::make_pair(StringRef("hell"), StringRef("")), + Str.split('o')); + + EXPECT_EQ(std::make_pair(StringRef("hello"), StringRef("")), + Str.rsplit('X')); + EXPECT_EQ(std::make_pair(StringRef("h"), StringRef("llo")), + Str.rsplit('e')); + EXPECT_EQ(std::make_pair(StringRef(""), StringRef("ello")), + Str.rsplit('h')); + EXPECT_EQ(std::make_pair(StringRef("hel"), StringRef("o")), + Str.rsplit('l')); + EXPECT_EQ(std::make_pair(StringRef("hell"), StringRef("")), + Str.rsplit('o')); +} + +TEST(StringRefTest, StartsWith) { + StringRef Str("hello"); + EXPECT_TRUE(Str.startswith("he")); + EXPECT_FALSE(Str.startswith("helloworld")); + EXPECT_FALSE(Str.startswith("hi")); +} + +TEST(StringRefTest, Find) { + StringRef Str("hello"); + EXPECT_EQ(2U, Str.find('l')); + EXPECT_EQ(StringRef::npos, Str.find('z')); + EXPECT_EQ(StringRef::npos, Str.find("helloworld")); + EXPECT_EQ(0U, Str.find("hello")); + EXPECT_EQ(1U, Str.find("ello")); + EXPECT_EQ(StringRef::npos, Str.find("zz")); + + EXPECT_EQ(3U, Str.rfind('l')); + EXPECT_EQ(StringRef::npos, Str.rfind('z')); + EXPECT_EQ(StringRef::npos, Str.rfind("helloworld")); + EXPECT_EQ(0U, Str.rfind("hello")); + EXPECT_EQ(1U, Str.rfind("ello")); + EXPECT_EQ(StringRef::npos, Str.rfind("zz")); +} + +TEST(StringRefTest, Count) { + StringRef Str("hello"); + EXPECT_EQ(2U, Str.count('l')); + EXPECT_EQ(1U, Str.count('o')); + EXPECT_EQ(0U, Str.count('z')); + EXPECT_EQ(0U, Str.count("helloworld")); + EXPECT_EQ(1U, Str.count("hello")); + EXPECT_EQ(1U, Str.count("ello")); + EXPECT_EQ(0U, Str.count("zz")); +} + +TEST(StringRefTest, Misc) { + std::string Storage; + raw_string_ostream OS(Storage); + OS << StringRef("hello"); + EXPECT_EQ("hello", OS.str()); +} + +} // end anonymous namespace diff --git a/unittests/ADT/TripleTest.cpp b/unittests/ADT/TripleTest.cpp index dee09f4..1a9e81a 100644 --- a/unittests/ADT/TripleTest.cpp +++ b/unittests/ADT/TripleTest.cpp @@ -18,58 +18,58 @@ TEST(TripleTest, BasicParsing) { Triple T; T = Triple(""); - EXPECT_EQ("", T.getArchName()); - EXPECT_EQ("", T.getVendorName()); - EXPECT_EQ("", T.getOSName()); - EXPECT_EQ("", T.getEnvironmentName()); + EXPECT_EQ("", T.getArchName().str()); + EXPECT_EQ("", T.getVendorName().str()); + EXPECT_EQ("", T.getOSName().str()); + EXPECT_EQ("", T.getEnvironmentName().str()); T = Triple("-"); - EXPECT_EQ("", T.getArchName()); - EXPECT_EQ("", T.getVendorName()); - EXPECT_EQ("", T.getOSName()); - EXPECT_EQ("", T.getEnvironmentName()); + EXPECT_EQ("", T.getArchName().str()); + EXPECT_EQ("", T.getVendorName().str()); + EXPECT_EQ("", T.getOSName().str()); + EXPECT_EQ("", T.getEnvironmentName().str()); T = Triple("--"); - EXPECT_EQ("", T.getArchName()); - EXPECT_EQ("", T.getVendorName()); - EXPECT_EQ("", T.getOSName()); - EXPECT_EQ("", T.getEnvironmentName()); + EXPECT_EQ("", T.getArchName().str()); + EXPECT_EQ("", T.getVendorName().str()); + EXPECT_EQ("", T.getOSName().str()); + EXPECT_EQ("", T.getEnvironmentName().str()); T = Triple("---"); - EXPECT_EQ("", T.getArchName()); - EXPECT_EQ("", T.getVendorName()); - EXPECT_EQ("", T.getOSName()); - EXPECT_EQ("", T.getEnvironmentName()); + EXPECT_EQ("", T.getArchName().str()); + EXPECT_EQ("", T.getVendorName().str()); + EXPECT_EQ("", T.getOSName().str()); + EXPECT_EQ("", T.getEnvironmentName().str()); T = Triple("----"); - EXPECT_EQ("", T.getArchName()); - EXPECT_EQ("", T.getVendorName()); - EXPECT_EQ("", T.getOSName()); - EXPECT_EQ("-", T.getEnvironmentName()); + EXPECT_EQ("", T.getArchName().str()); + EXPECT_EQ("", T.getVendorName().str()); + EXPECT_EQ("", T.getOSName().str()); + EXPECT_EQ("-", T.getEnvironmentName().str()); T = Triple("a"); - EXPECT_EQ("a", T.getArchName()); - EXPECT_EQ("", T.getVendorName()); - EXPECT_EQ("", T.getOSName()); - EXPECT_EQ("", T.getEnvironmentName()); + EXPECT_EQ("a", T.getArchName().str()); + EXPECT_EQ("", T.getVendorName().str()); + EXPECT_EQ("", T.getOSName().str()); + EXPECT_EQ("", T.getEnvironmentName().str()); T = Triple("a-b"); - EXPECT_EQ("a", T.getArchName()); - EXPECT_EQ("b", T.getVendorName()); - EXPECT_EQ("", T.getOSName()); - EXPECT_EQ("", T.getEnvironmentName()); + EXPECT_EQ("a", T.getArchName().str()); + EXPECT_EQ("b", T.getVendorName().str()); + EXPECT_EQ("", T.getOSName().str()); + EXPECT_EQ("", T.getEnvironmentName().str()); T = Triple("a-b-c"); - EXPECT_EQ("a", T.getArchName()); - EXPECT_EQ("b", T.getVendorName()); - EXPECT_EQ("c", T.getOSName()); - EXPECT_EQ("", T.getEnvironmentName()); + EXPECT_EQ("a", T.getArchName().str()); + EXPECT_EQ("b", T.getVendorName().str()); + EXPECT_EQ("c", T.getOSName().str()); + EXPECT_EQ("", T.getEnvironmentName().str()); T = Triple("a-b-c-d"); - EXPECT_EQ("a", T.getArchName()); - EXPECT_EQ("b", T.getVendorName()); - EXPECT_EQ("c", T.getOSName()); - EXPECT_EQ("d", T.getEnvironmentName()); + EXPECT_EQ("a", T.getArchName().str()); + EXPECT_EQ("b", T.getVendorName().str()); + EXPECT_EQ("c", T.getOSName().str()); + EXPECT_EQ("d", T.getEnvironmentName().str()); } TEST(TripleTest, ParsedIDs) { @@ -92,6 +92,18 @@ TEST(TripleTest, ParsedIDs) { T = Triple("huh"); EXPECT_EQ(Triple::UnknownArch, T.getArch()); + + // Two exceptional cases. + + T = Triple("i386-mingw32"); + EXPECT_EQ(Triple::x86, T.getArch()); + EXPECT_EQ(Triple::PC, T.getVendor()); + EXPECT_EQ(Triple::MinGW32, T.getOS()); + + T = Triple("arm-elf"); + EXPECT_EQ(Triple::arm, T.getArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::UnknownOS, T.getOS()); } TEST(TripleTest, MutateName) { diff --git a/unittests/ADT/TwineTest.cpp b/unittests/ADT/TwineTest.cpp new file mode 100644 index 0000000..61e8a0a --- /dev/null +++ b/unittests/ADT/TwineTest.cpp @@ -0,0 +1,75 @@ +//===- TwineTest.cpp - Twine unit tests -----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + +std::string repr(const Twine &Value) { + std::string res; + llvm::raw_string_ostream OS(res); + Value.printRepr(OS); + return OS.str(); +} + +TEST(TwineTest, Construction) { + EXPECT_EQ("", Twine().str()); + EXPECT_EQ("hi", Twine("hi").str()); + EXPECT_EQ("hi", Twine(std::string("hi")).str()); + EXPECT_EQ("hi", Twine(StringRef("hi")).str()); + EXPECT_EQ("hi", Twine(StringRef(std::string("hi"))).str()); + EXPECT_EQ("hi", Twine(StringRef("hithere", 2)).str()); +} + +TEST(TwineTest, Numbers) { + EXPECT_EQ("123", Twine(123U).str()); + EXPECT_EQ("123", Twine(123).str()); + EXPECT_EQ("-123", Twine(-123).str()); + EXPECT_EQ("123", Twine(123).str()); + EXPECT_EQ("-123", Twine(-123).str()); + EXPECT_EQ("123", Twine((char) 123).str()); + EXPECT_EQ("-123", Twine((signed char) -123).str()); + + EXPECT_EQ("7b", Twine::utohexstr(123).str()); +} + +TEST(TwineTest, Concat) { + // Check verse repr, since we care about the actual representation not just + // the result. + + // Concat with null. + EXPECT_EQ("(Twine null empty)", + repr(Twine("hi").concat(Twine::createNull()))); + EXPECT_EQ("(Twine null empty)", + repr(Twine::createNull().concat(Twine("hi")))); + + // Concat with empty. + EXPECT_EQ("(Twine cstring:\"hi\" empty)", + repr(Twine("hi").concat(Twine()))); + EXPECT_EQ("(Twine cstring:\"hi\" empty)", + repr(Twine().concat(Twine("hi")))); + + // Concatenation of unary ropes. + EXPECT_EQ("(Twine cstring:\"a\" cstring:\"b\")", + repr(Twine("a").concat(Twine("b")))); + + // Concatenation of other ropes. + EXPECT_EQ("(Twine rope:(Twine cstring:\"a\" cstring:\"b\") cstring:\"c\")", + repr(Twine("a").concat(Twine("b")).concat(Twine("c")))); + EXPECT_EQ("(Twine cstring:\"a\" rope:(Twine cstring:\"b\" cstring:\"c\"))", + repr(Twine("a").concat(Twine("b").concat(Twine("c"))))); +} + + // I suppose linking in the entire code generator to add a unit test to check + // the code size of the concat operation is overkill... :) + +} // end anonymous namespace diff --git a/unittests/ExecutionEngine/ExecutionEngineTest.cpp b/unittests/ExecutionEngine/ExecutionEngineTest.cpp new file mode 100644 index 0000000..904ee2b --- /dev/null +++ b/unittests/ExecutionEngine/ExecutionEngineTest.cpp @@ -0,0 +1,129 @@ +//===- ExecutionEngineTest.cpp - Unit tests for ExecutionEngine -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DerivedTypes.h" +#include "llvm/GlobalVariable.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ExecutionEngine/Interpreter.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +class ExecutionEngineTest : public testing::Test { +protected: + ExecutionEngineTest() + : M(new Module("<main>", getGlobalContext())), + Engine(EngineBuilder(M).create()) { + } + + virtual void SetUp() { + ASSERT_TRUE(Engine.get() != NULL); + } + + GlobalVariable *NewExtGlobal(const Type *T, const Twine &Name) { + return new GlobalVariable(*M, T, false, // Not constant. + GlobalValue::ExternalLinkage, NULL, Name); + } + + Module *const M; + const OwningPtr<ExecutionEngine> Engine; +}; + +TEST_F(ExecutionEngineTest, ForwardGlobalMapping) { + GlobalVariable *G1 = + NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global1"); + int32_t Mem1 = 3; + Engine->addGlobalMapping(G1, &Mem1); + EXPECT_EQ(&Mem1, Engine->getPointerToGlobalIfAvailable(G1)); + int32_t Mem2 = 4; + Engine->updateGlobalMapping(G1, &Mem2); + EXPECT_EQ(&Mem2, Engine->getPointerToGlobalIfAvailable(G1)); + Engine->updateGlobalMapping(G1, NULL); + EXPECT_EQ(NULL, Engine->getPointerToGlobalIfAvailable(G1)); + Engine->updateGlobalMapping(G1, &Mem2); + EXPECT_EQ(&Mem2, Engine->getPointerToGlobalIfAvailable(G1)); + + GlobalVariable *G2 = + NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global1"); + EXPECT_EQ(NULL, Engine->getPointerToGlobalIfAvailable(G2)) + << "The NULL return shouldn't depend on having called" + << " updateGlobalMapping(..., NULL)"; + // Check that update...() can be called before add...(). + Engine->updateGlobalMapping(G2, &Mem1); + EXPECT_EQ(&Mem1, Engine->getPointerToGlobalIfAvailable(G2)); + EXPECT_EQ(&Mem2, Engine->getPointerToGlobalIfAvailable(G1)) + << "A second mapping shouldn't affect the first."; +} + +TEST_F(ExecutionEngineTest, ReverseGlobalMapping) { + GlobalVariable *G1 = + NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global1"); + + int32_t Mem1 = 3; + Engine->addGlobalMapping(G1, &Mem1); + EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem1)); + int32_t Mem2 = 4; + Engine->updateGlobalMapping(G1, &Mem2); + EXPECT_EQ(NULL, Engine->getGlobalValueAtAddress(&Mem1)); + EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem2)); + + GlobalVariable *G2 = + NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global2"); + Engine->updateGlobalMapping(G2, &Mem1); + EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem1)); + EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem2)); + Engine->updateGlobalMapping(G1, NULL); + EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem1)) + << "Removing one mapping doesn't affect a different one."; + EXPECT_EQ(NULL, Engine->getGlobalValueAtAddress(&Mem2)); + Engine->updateGlobalMapping(G2, &Mem2); + EXPECT_EQ(NULL, Engine->getGlobalValueAtAddress(&Mem1)); + EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem2)) + << "Once a mapping is removed, we can point another GV at the" + << " now-free address."; +} + +TEST_F(ExecutionEngineTest, ClearModuleMappings) { + GlobalVariable *G1 = + NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global1"); + + int32_t Mem1 = 3; + Engine->addGlobalMapping(G1, &Mem1); + EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem1)); + + Engine->clearGlobalMappingsFromModule(M); + + EXPECT_EQ(NULL, Engine->getGlobalValueAtAddress(&Mem1)); + + GlobalVariable *G2 = + NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global2"); + // After clearing the module mappings, we can assign a new GV to the + // same address. + Engine->addGlobalMapping(G2, &Mem1); + EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem1)); +} + +TEST_F(ExecutionEngineTest, DestructionRemovesGlobalMapping) { + GlobalVariable *G1 = + NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global1"); + int32_t Mem1 = 3; + Engine->addGlobalMapping(G1, &Mem1); + // Make sure the reverse mapping is enabled. + EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem1)); + // When the GV goes away, the ExecutionEngine should remove any + // mappings that refer to it. + G1->eraseFromParent(); + EXPECT_EQ(NULL, Engine->getGlobalValueAtAddress(&Mem1)); +} + +} diff --git a/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp b/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp index 1007ae1..87e3280 100644 --- a/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp +++ b/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp @@ -65,8 +65,10 @@ struct RecordingJITEventListener : public JITEventListener { class JITEventListenerTest : public testing::Test { protected: JITEventListenerTest() - : M(new Module("module", *new LLVMContext())), - EE(ExecutionEngine::createJIT(new ExistingModuleProvider(M))) { + : M(new Module("module", getGlobalContext())), + EE(EngineBuilder(M) + .setEngineKind(EngineKind::JIT) + .create()) { } Module *M; @@ -75,11 +77,11 @@ class JITEventListenerTest : public testing::Test { Function *buildFunction(Module *M) { Function *Result = Function::Create( - TypeBuilder<int32_t(int32_t), false>::get(), + TypeBuilder<int32_t(int32_t), false>::get(getGlobalContext()), GlobalValue::ExternalLinkage, "id", M); Value *Arg = Result->arg_begin(); - BasicBlock *BB = BasicBlock::Create("entry", Result); - ReturnInst::Create(Arg, BB); + BasicBlock *BB = BasicBlock::Create(M->getContext(), "entry", Result); + ReturnInst::Create(M->getContext(), Arg, BB); return Result; } @@ -232,7 +234,7 @@ TEST_F(JITEventListenerTest, MatchesMachineCodeInfo) { class JITEnvironment : public testing::Environment { virtual void SetUp() { - // Required for ExecutionEngine::createJIT to create a JIT. + // Required to create a JIT. InitializeNativeTarget(); } }; diff --git a/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp b/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp new file mode 100644 index 0000000..89a4be7 --- /dev/null +++ b/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp @@ -0,0 +1,277 @@ +//===- JITMemoryManagerTest.cpp - Unit tests for the JIT memory manager ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ExecutionEngine/JITMemoryManager.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/GlobalValue.h" + +using namespace llvm; + +namespace { + +Function *makeFakeFunction() { + std::vector<const Type*> params; + const FunctionType *FTy = + FunctionType::get(Type::getVoidTy(getGlobalContext()), params, false); + return Function::Create(FTy, GlobalValue::ExternalLinkage); +} + +// Allocate three simple functions that fit in the initial slab. This exercises +// the code in the case that we don't have to allocate more memory to store the +// function bodies. +TEST(JITMemoryManagerTest, NoAllocations) { + OwningPtr<JITMemoryManager> MemMgr( + JITMemoryManager::CreateDefaultMemManager()); + uintptr_t size; + uint8_t *start; + std::string Error; + + // Allocate the functions. + OwningPtr<Function> F1(makeFakeFunction()); + size = 1024; + start = MemMgr->startFunctionBody(F1.get(), size); + memset(start, 0xFF, 1024); + MemMgr->endFunctionBody(F1.get(), start, start + 1024); + EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; + + OwningPtr<Function> F2(makeFakeFunction()); + size = 1024; + start = MemMgr->startFunctionBody(F2.get(), size); + memset(start, 0xFF, 1024); + MemMgr->endFunctionBody(F2.get(), start, start + 1024); + EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; + + OwningPtr<Function> F3(makeFakeFunction()); + size = 1024; + start = MemMgr->startFunctionBody(F3.get(), size); + memset(start, 0xFF, 1024); + MemMgr->endFunctionBody(F3.get(), start, start + 1024); + EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; + + // Deallocate them out of order, in case that matters. + MemMgr->deallocateMemForFunction(F2.get()); + EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; + MemMgr->deallocateMemForFunction(F1.get()); + EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; + MemMgr->deallocateMemForFunction(F3.get()); + EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; +} + +// Make three large functions that take up most of the space in the slab. Then +// try allocating three smaller functions that don't require additional slabs. +TEST(JITMemoryManagerTest, TestCodeAllocation) { + OwningPtr<JITMemoryManager> MemMgr( + JITMemoryManager::CreateDefaultMemManager()); + uintptr_t size; + uint8_t *start; + std::string Error; + + // Big functions are a little less than the largest block size. + const uintptr_t smallFuncSize = 1024; + const uintptr_t bigFuncSize = (MemMgr->GetDefaultCodeSlabSize() - + smallFuncSize * 2); + + // Allocate big functions + OwningPtr<Function> F1(makeFakeFunction()); + size = bigFuncSize; + start = MemMgr->startFunctionBody(F1.get(), size); + ASSERT_LE(bigFuncSize, size); + memset(start, 0xFF, bigFuncSize); + MemMgr->endFunctionBody(F1.get(), start, start + bigFuncSize); + EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; + + OwningPtr<Function> F2(makeFakeFunction()); + size = bigFuncSize; + start = MemMgr->startFunctionBody(F2.get(), size); + ASSERT_LE(bigFuncSize, size); + memset(start, 0xFF, bigFuncSize); + MemMgr->endFunctionBody(F2.get(), start, start + bigFuncSize); + EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; + + OwningPtr<Function> F3(makeFakeFunction()); + size = bigFuncSize; + start = MemMgr->startFunctionBody(F3.get(), size); + ASSERT_LE(bigFuncSize, size); + memset(start, 0xFF, bigFuncSize); + MemMgr->endFunctionBody(F3.get(), start, start + bigFuncSize); + EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; + + // Check that each large function took it's own slab. + EXPECT_EQ(3U, MemMgr->GetNumCodeSlabs()); + + // Allocate small functions + OwningPtr<Function> F4(makeFakeFunction()); + size = smallFuncSize; + start = MemMgr->startFunctionBody(F4.get(), size); + ASSERT_LE(smallFuncSize, size); + memset(start, 0xFF, smallFuncSize); + MemMgr->endFunctionBody(F4.get(), start, start + smallFuncSize); + EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; + + OwningPtr<Function> F5(makeFakeFunction()); + size = smallFuncSize; + start = MemMgr->startFunctionBody(F5.get(), size); + ASSERT_LE(smallFuncSize, size); + memset(start, 0xFF, smallFuncSize); + MemMgr->endFunctionBody(F5.get(), start, start + smallFuncSize); + EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; + + OwningPtr<Function> F6(makeFakeFunction()); + size = smallFuncSize; + start = MemMgr->startFunctionBody(F6.get(), size); + ASSERT_LE(smallFuncSize, size); + memset(start, 0xFF, smallFuncSize); + MemMgr->endFunctionBody(F6.get(), start, start + smallFuncSize); + EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; + + // Check that the small functions didn't allocate any new slabs. + EXPECT_EQ(3U, MemMgr->GetNumCodeSlabs()); + + // Deallocate them out of order, in case that matters. + MemMgr->deallocateMemForFunction(F2.get()); + EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; + MemMgr->deallocateMemForFunction(F1.get()); + EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; + MemMgr->deallocateMemForFunction(F4.get()); + EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; + MemMgr->deallocateMemForFunction(F3.get()); + EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; + MemMgr->deallocateMemForFunction(F5.get()); + EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; + MemMgr->deallocateMemForFunction(F6.get()); + EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; +} + +// Allocate five global ints of varying widths and alignment, and check their +// alignment and overlap. +TEST(JITMemoryManagerTest, TestSmallGlobalInts) { + OwningPtr<JITMemoryManager> MemMgr( + JITMemoryManager::CreateDefaultMemManager()); + uint8_t *a = (uint8_t *)MemMgr->allocateGlobal(8, 0); + uint16_t *b = (uint16_t*)MemMgr->allocateGlobal(16, 2); + uint32_t *c = (uint32_t*)MemMgr->allocateGlobal(32, 4); + uint64_t *d = (uint64_t*)MemMgr->allocateGlobal(64, 8); + + // Check the alignment. + EXPECT_EQ(0U, ((uintptr_t)b) & 0x1); + EXPECT_EQ(0U, ((uintptr_t)c) & 0x3); + EXPECT_EQ(0U, ((uintptr_t)d) & 0x7); + + // Initialize them each one at a time and make sure they don't overlap. + *a = 0xff; + *b = 0U; + *c = 0U; + *d = 0U; + EXPECT_EQ(0xffU, *a); + EXPECT_EQ(0U, *b); + EXPECT_EQ(0U, *c); + EXPECT_EQ(0U, *d); + *a = 0U; + *b = 0xffffU; + EXPECT_EQ(0U, *a); + EXPECT_EQ(0xffffU, *b); + EXPECT_EQ(0U, *c); + EXPECT_EQ(0U, *d); + *b = 0U; + *c = 0xffffffffU; + EXPECT_EQ(0U, *a); + EXPECT_EQ(0U, *b); + EXPECT_EQ(0xffffffffU, *c); + EXPECT_EQ(0U, *d); + *c = 0U; + *d = 0xffffffffffffffffULL; + EXPECT_EQ(0U, *a); + EXPECT_EQ(0U, *b); + EXPECT_EQ(0U, *c); + EXPECT_EQ(0xffffffffffffffffULL, *d); + + // Make sure we didn't allocate any extra slabs for this tiny amount of data. + EXPECT_EQ(1U, MemMgr->GetNumDataSlabs()); +} + +// Allocate a small global, a big global, and a third global, and make sure we +// only use two slabs for that. +TEST(JITMemoryManagerTest, TestLargeGlobalArray) { + OwningPtr<JITMemoryManager> MemMgr( + JITMemoryManager::CreateDefaultMemManager()); + size_t Size = 4 * MemMgr->GetDefaultDataSlabSize(); + uint64_t *a = (uint64_t*)MemMgr->allocateGlobal(64, 8); + uint8_t *g = MemMgr->allocateGlobal(Size, 8); + uint64_t *b = (uint64_t*)MemMgr->allocateGlobal(64, 8); + + // Check the alignment. + EXPECT_EQ(0U, ((uintptr_t)a) & 0x7); + EXPECT_EQ(0U, ((uintptr_t)g) & 0x7); + EXPECT_EQ(0U, ((uintptr_t)b) & 0x7); + + // Initialize them to make sure we don't segfault and make sure they don't + // overlap. + memset(a, 0x1, 8); + memset(g, 0x2, Size); + memset(b, 0x3, 8); + EXPECT_EQ(0x0101010101010101ULL, *a); + // Just check the edges. + EXPECT_EQ(0x02U, g[0]); + EXPECT_EQ(0x02U, g[Size - 1]); + EXPECT_EQ(0x0303030303030303ULL, *b); + + // Check the number of slabs. + EXPECT_EQ(2U, MemMgr->GetNumDataSlabs()); +} + +// Allocate lots of medium globals so that we can test moving the bump allocator +// to a new slab. +TEST(JITMemoryManagerTest, TestManyGlobals) { + OwningPtr<JITMemoryManager> MemMgr( + JITMemoryManager::CreateDefaultMemManager()); + size_t SlabSize = MemMgr->GetDefaultDataSlabSize(); + size_t Size = 128; + int Iters = (SlabSize / Size) + 1; + + // We should start with one slab. + EXPECT_EQ(1U, MemMgr->GetNumDataSlabs()); + + // After allocating a bunch of globals, we should have two. + for (int I = 0; I < Iters; ++I) + MemMgr->allocateGlobal(Size, 8); + EXPECT_EQ(2U, MemMgr->GetNumDataSlabs()); + + // And after much more, we should have three. + for (int I = 0; I < Iters; ++I) + MemMgr->allocateGlobal(Size, 8); + EXPECT_EQ(3U, MemMgr->GetNumDataSlabs()); +} + +// Allocate lots of function stubs so that we can test moving the stub bump +// allocator to a new slab. +TEST(JITMemoryManagerTest, TestManyStubs) { + OwningPtr<JITMemoryManager> MemMgr( + JITMemoryManager::CreateDefaultMemManager()); + size_t SlabSize = MemMgr->GetDefaultStubSlabSize(); + size_t Size = 128; + int Iters = (SlabSize / Size) + 1; + + // We should start with one slab. + EXPECT_EQ(1U, MemMgr->GetNumStubSlabs()); + + // After allocating a bunch of stubs, we should have two. + for (int I = 0; I < Iters; ++I) + MemMgr->allocateStub(NULL, Size, 8); + EXPECT_EQ(2U, MemMgr->GetNumStubSlabs()); + + // And after much more, we should have three. + for (int I = 0; I < Iters; ++I) + MemMgr->allocateStub(NULL, Size, 8); + EXPECT_EQ(3U, MemMgr->GetNumStubSlabs()); +} + +} diff --git a/unittests/ExecutionEngine/JIT/JITTest.cpp b/unittests/ExecutionEngine/JIT/JITTest.cpp new file mode 100644 index 0000000..55d3749 --- /dev/null +++ b/unittests/ExecutionEngine/JIT/JITTest.cpp @@ -0,0 +1,277 @@ +//===- JITTest.cpp - Unit tests for the JIT -------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/BasicBlock.h" +#include "llvm/Constant.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/ExecutionEngine/JITMemoryManager.h" +#include "llvm/Function.h" +#include "llvm/GlobalValue.h" +#include "llvm/GlobalVariable.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/ModuleProvider.h" +#include "llvm/Support/IRBuilder.h" +#include "llvm/Support/TypeBuilder.h" +#include "llvm/Target/TargetSelect.h" +#include "llvm/Type.h" + +using namespace llvm; + +namespace { + +Function *makeReturnGlobal(std::string Name, GlobalVariable *G, Module *M) { + std::vector<const Type*> params; + const FunctionType *FTy = FunctionType::get(G->getType()->getElementType(), + params, false); + Function *F = Function::Create(FTy, GlobalValue::ExternalLinkage, Name, M); + BasicBlock *Entry = BasicBlock::Create(M->getContext(), "entry", F); + IRBuilder<> builder(Entry); + Value *Load = builder.CreateLoad(G); + const Type *GTy = G->getType()->getElementType(); + Value *Add = builder.CreateAdd(Load, ConstantInt::get(GTy, 1LL)); + builder.CreateStore(Add, G); + builder.CreateRet(Add); + return F; +} + +class JITTest : public testing::Test { + protected: + virtual void SetUp() { + M = new Module("<main>", Context); + std::string Error; + TheJIT.reset(EngineBuilder(M).setEngineKind(EngineKind::JIT) + .setErrorStr(&Error).create()); + ASSERT_TRUE(TheJIT.get() != NULL) << Error; + } + + LLVMContext Context; + Module *M; // Owned by ExecutionEngine. + OwningPtr<ExecutionEngine> TheJIT; +}; + +// Regression test for a bug. The JIT used to allocate globals inside the same +// memory block used for the function, and when the function code was freed, +// the global was left in the same place. This test allocates a function +// that uses and global, deallocates it, and then makes sure that the global +// stays alive after that. +TEST(JIT, GlobalInFunction) { + LLVMContext context; + Module *M = new Module("<main>", context); + ExistingModuleProvider *MP = new ExistingModuleProvider(M); + + JITMemoryManager *MemMgr = JITMemoryManager::CreateDefaultMemManager(); + // Tell the memory manager to poison freed memory so that accessing freed + // memory is more easily tested. + MemMgr->setPoisonMemory(true); + std::string Error; + OwningPtr<ExecutionEngine> JIT(EngineBuilder(MP) + .setEngineKind(EngineKind::JIT) + .setErrorStr(&Error) + .setJITMemoryManager(MemMgr) + // The next line enables the fix: + .setAllocateGVsWithCode(false) + .create()); + ASSERT_EQ(Error, ""); + + // Create a global variable. + const Type *GTy = Type::getInt32Ty(context); + GlobalVariable *G = new GlobalVariable( + *M, + GTy, + false, // Not constant. + GlobalValue::InternalLinkage, + Constant::getNullValue(GTy), + "myglobal"); + + // Make a function that points to a global. + Function *F1 = makeReturnGlobal("F1", G, M); + + // Get the pointer to the native code to force it to JIT the function and + // allocate space for the global. + void (*F1Ptr)() = + reinterpret_cast<void(*)()>((intptr_t)JIT->getPointerToFunction(F1)); + + // Since F1 was codegen'd, a pointer to G should be available. + int32_t *GPtr = (int32_t*)JIT->getPointerToGlobalIfAvailable(G); + ASSERT_NE((int32_t*)NULL, GPtr); + EXPECT_EQ(0, *GPtr); + + // F1() should increment G. + F1Ptr(); + EXPECT_EQ(1, *GPtr); + + // Make a second function identical to the first, referring to the same + // global. + Function *F2 = makeReturnGlobal("F2", G, M); + void (*F2Ptr)() = + reinterpret_cast<void(*)()>((intptr_t)JIT->getPointerToFunction(F2)); + + // F2() should increment G. + F2Ptr(); + EXPECT_EQ(2, *GPtr); + + // Deallocate F1. + JIT->freeMachineCodeForFunction(F1); + + // F2() should *still* increment G. + F2Ptr(); + EXPECT_EQ(3, *GPtr); +} + +int PlusOne(int arg) { + return arg + 1; +} + +TEST_F(JITTest, FarCallToKnownFunction) { + // x86-64 can only make direct calls to functions within 32 bits of + // the current PC. To call anything farther away, we have to load + // the address into a register and call through the register. The + // current JIT does this by allocating a stub for any far call. + // There was a bug in which the JIT tried to emit a direct call when + // the target was already in the JIT's global mappings and lazy + // compilation was disabled. + + Function *KnownFunction = Function::Create( + TypeBuilder<int(int), false>::get(Context), + GlobalValue::ExternalLinkage, "known", M); + TheJIT->addGlobalMapping(KnownFunction, (void*)(intptr_t)PlusOne); + + // int test() { return known(7); } + Function *TestFunction = Function::Create( + TypeBuilder<int(), false>::get(Context), + GlobalValue::ExternalLinkage, "test", M); + BasicBlock *Entry = BasicBlock::Create(Context, "entry", TestFunction); + IRBuilder<> Builder(Entry); + Value *result = Builder.CreateCall( + KnownFunction, + ConstantInt::get(TypeBuilder<int, false>::get(Context), 7)); + Builder.CreateRet(result); + + TheJIT->EnableDlsymStubs(false); + TheJIT->DisableLazyCompilation(); + int (*TestFunctionPtr)() = reinterpret_cast<int(*)()>( + (intptr_t)TheJIT->getPointerToFunction(TestFunction)); + // This used to crash in trying to call PlusOne(). + EXPECT_EQ(8, TestFunctionPtr()); +} + +// Test a function C which calls A and B which call each other. +TEST_F(JITTest, NonLazyCompilationStillNeedsStubs) { + TheJIT->DisableLazyCompilation(); + + const FunctionType *Func1Ty = + cast<FunctionType>(TypeBuilder<void(void), false>::get(Context)); + std::vector<const Type*> arg_types; + arg_types.push_back(Type::getInt1Ty(Context)); + const FunctionType *FuncTy = FunctionType::get( + Type::getVoidTy(Context), arg_types, false); + Function *Func1 = Function::Create(Func1Ty, Function::ExternalLinkage, + "func1", M); + Function *Func2 = Function::Create(FuncTy, Function::InternalLinkage, + "func2", M); + Function *Func3 = Function::Create(FuncTy, Function::InternalLinkage, + "func3", M); + BasicBlock *Block1 = BasicBlock::Create(Context, "block1", Func1); + BasicBlock *Block2 = BasicBlock::Create(Context, "block2", Func2); + BasicBlock *True2 = BasicBlock::Create(Context, "cond_true", Func2); + BasicBlock *False2 = BasicBlock::Create(Context, "cond_false", Func2); + BasicBlock *Block3 = BasicBlock::Create(Context, "block3", Func3); + BasicBlock *True3 = BasicBlock::Create(Context, "cond_true", Func3); + BasicBlock *False3 = BasicBlock::Create(Context, "cond_false", Func3); + + // Make Func1 call Func2(0) and Func3(0). + IRBuilder<> Builder(Block1); + Builder.CreateCall(Func2, ConstantInt::getTrue(Context)); + Builder.CreateCall(Func3, ConstantInt::getTrue(Context)); + Builder.CreateRetVoid(); + + // void Func2(bool b) { if (b) { Func3(false); return; } return; } + Builder.SetInsertPoint(Block2); + Builder.CreateCondBr(Func2->arg_begin(), True2, False2); + Builder.SetInsertPoint(True2); + Builder.CreateCall(Func3, ConstantInt::getFalse(Context)); + Builder.CreateRetVoid(); + Builder.SetInsertPoint(False2); + Builder.CreateRetVoid(); + + // void Func3(bool b) { if (b) { Func2(false); return; } return; } + Builder.SetInsertPoint(Block3); + Builder.CreateCondBr(Func3->arg_begin(), True3, False3); + Builder.SetInsertPoint(True3); + Builder.CreateCall(Func2, ConstantInt::getFalse(Context)); + Builder.CreateRetVoid(); + Builder.SetInsertPoint(False3); + Builder.CreateRetVoid(); + + // Compile the function to native code + void (*F1Ptr)() = + reinterpret_cast<void(*)()>((intptr_t)TheJIT->getPointerToFunction(Func1)); + + F1Ptr(); +} + +// Regression test for PR5162. This used to trigger an AssertingVH inside the +// JIT's Function to stub mapping. +TEST_F(JITTest, NonLazyLeaksNoStubs) { + TheJIT->DisableLazyCompilation(); + + // Create two functions with a single basic block each. + const FunctionType *FuncTy = + cast<FunctionType>(TypeBuilder<int(), false>::get(Context)); + Function *Func1 = Function::Create(FuncTy, Function::ExternalLinkage, + "func1", M); + Function *Func2 = Function::Create(FuncTy, Function::InternalLinkage, + "func2", M); + BasicBlock *Block1 = BasicBlock::Create(Context, "block1", Func1); + BasicBlock *Block2 = BasicBlock::Create(Context, "block2", Func2); + + // The first function calls the second and returns the result + IRBuilder<> Builder(Block1); + Value *Result = Builder.CreateCall(Func2); + Builder.CreateRet(Result); + + // The second function just returns a constant + Builder.SetInsertPoint(Block2); + Builder.CreateRet(ConstantInt::get(TypeBuilder<int, false>::get(Context),42)); + + // Compile the function to native code + (void)TheJIT->getPointerToFunction(Func1); + + // Free the JIT state for the functions + TheJIT->freeMachineCodeForFunction(Func1); + TheJIT->freeMachineCodeForFunction(Func2); + + // Delete the first function (and show that is has no users) + EXPECT_EQ(Func1->getNumUses(), 0u); + Func1->eraseFromParent(); + + // Delete the second function (and show that it has no users - it had one, + // func1 but that's gone now) + EXPECT_EQ(Func2->getNumUses(), 0u); + Func2->eraseFromParent(); +} + +// This code is copied from JITEventListenerTest, but it only runs once for all +// the tests in this directory. Everything seems fine, but that's strange +// behavior. +class JITEnvironment : public testing::Environment { + virtual void SetUp() { + // Required to create a JIT. + InitializeNativeTarget(); + } +}; +testing::Environment* const jit_env = + testing::AddGlobalTestEnvironment(new JITEnvironment); + +} diff --git a/unittests/ExecutionEngine/Makefile b/unittests/ExecutionEngine/Makefile index e837a7d..d4ef92f 100644 --- a/unittests/ExecutionEngine/Makefile +++ b/unittests/ExecutionEngine/Makefile @@ -8,12 +8,11 @@ ##===----------------------------------------------------------------------===## LEVEL = ../.. +TESTNAME = ExecutionEngine +LINK_COMPONENTS := engine interpreter include $(LEVEL)/Makefile.config PARALLEL_DIRS = JIT -include $(LEVEL)/Makefile.common - -clean:: - $(Verb) $(RM) -f *Tests +include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/Makefile b/unittests/Makefile index 1eb69ab..9f377cd 100644 --- a/unittests/Makefile +++ b/unittests/Makefile @@ -9,14 +9,7 @@ LEVEL = .. -include $(LEVEL)/Makefile.config - -LIBRARYNAME = UnitTestMain -BUILD_ARCHIVE = 1 -CPP.Flags += -I$(LLVM_SRC_ROOT)/utils/unittest/googletest/include/ -CPP.Flags += -Wno-variadic-macros - -PARALLEL_DIRS = ADT ExecutionEngine Support VMCore MC +PARALLEL_DIRS = ADT ExecutionEngine Support Transforms VMCore include $(LEVEL)/Makefile.common diff --git a/unittests/Makefile.unittest b/unittests/Makefile.unittest index 1c75e44..76051e4 100644 --- a/unittests/Makefile.unittest +++ b/unittests/Makefile.unittest @@ -20,16 +20,18 @@ LLVMUnitTestExe = $(BuildMode)/$(TESTNAME)Tests$(EXEEXT) CPP.Flags += -I$(LLVM_SRC_ROOT)/utils/unittest/googletest/include/ CPP.Flags += -Wno-variadic-macros -LIBS += -lGoogleTest -lUnitTestMain +TESTLIBS = -lGoogleTest -lUnitTestMain $(LLVMUnitTestExe): $(ObjectsO) $(ProjLibsPaths) $(LLVMLibsPaths) $(Echo) Linking $(BuildMode) unit test $(TESTNAME) $(StripWarnMsg) $(Verb) $(Link) -o $@ $(TOOLLINKOPTS) $(ObjectsO) $(ProjLibsOptions) \ - $(LLVMLibsOptions) $(ExtraLibs) $(TOOLLINKOPTSB) $(LIBS) + $(TESTLIBS) $(LLVMLibsOptions) $(ExtraLibs) $(TOOLLINKOPTSB) $(LIBS) $(Echo) ======= Finished Linking $(BuildMode) Unit test $(TESTNAME) \ $(StripWarnMsg) all:: $(LLVMUnitTestExe) + +unitcheck:: $(LLVMUnitTestExe) $(LLVMUnitTestExe) endif diff --git a/unittests/Support/AllocatorTest.cpp b/unittests/Support/AllocatorTest.cpp new file mode 100644 index 0000000..2a01f3a --- /dev/null +++ b/unittests/Support/AllocatorTest.cpp @@ -0,0 +1,143 @@ +//===- llvm/unittest/Support/AllocatorTest.cpp - BumpPtrAllocator tests ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Allocator.h" + +#include "gtest/gtest.h" +#include <cstdlib> + +using namespace llvm; + +namespace { + +TEST(AllocatorTest, Basics) { + BumpPtrAllocator Alloc; + int *a = (int*)Alloc.Allocate(sizeof(int), 0); + int *b = (int*)Alloc.Allocate(sizeof(int) * 10, 0); + int *c = (int*)Alloc.Allocate(sizeof(int), 0); + *a = 1; + b[0] = 2; + b[9] = 2; + *c = 3; + EXPECT_EQ(1, *a); + EXPECT_EQ(2, b[0]); + EXPECT_EQ(2, b[9]); + EXPECT_EQ(3, *c); + EXPECT_EQ(1U, Alloc.GetNumSlabs()); +} + +// Allocate enough bytes to create three slabs. +TEST(AllocatorTest, ThreeSlabs) { + BumpPtrAllocator Alloc(4096, 4096); + Alloc.Allocate(3000, 0); + EXPECT_EQ(1U, Alloc.GetNumSlabs()); + Alloc.Allocate(3000, 0); + EXPECT_EQ(2U, Alloc.GetNumSlabs()); + Alloc.Allocate(3000, 0); + EXPECT_EQ(3U, Alloc.GetNumSlabs()); +} + +// Allocate enough bytes to create two slabs, reset the allocator, and do it +// again. +TEST(AllocatorTest, TestReset) { + BumpPtrAllocator Alloc(4096, 4096); + Alloc.Allocate(3000, 0); + EXPECT_EQ(1U, Alloc.GetNumSlabs()); + Alloc.Allocate(3000, 0); + EXPECT_EQ(2U, Alloc.GetNumSlabs()); + Alloc.Reset(); + EXPECT_EQ(1U, Alloc.GetNumSlabs()); + Alloc.Allocate(3000, 0); + EXPECT_EQ(1U, Alloc.GetNumSlabs()); + Alloc.Allocate(3000, 0); + EXPECT_EQ(2U, Alloc.GetNumSlabs()); +} + +// Test some allocations at varying alignments. +TEST(AllocatorTest, TestAlignment) { + BumpPtrAllocator Alloc; + uintptr_t a; + a = (uintptr_t)Alloc.Allocate(1, 2); + EXPECT_EQ(0U, a & 1); + a = (uintptr_t)Alloc.Allocate(1, 4); + EXPECT_EQ(0U, a & 3); + a = (uintptr_t)Alloc.Allocate(1, 8); + EXPECT_EQ(0U, a & 7); + a = (uintptr_t)Alloc.Allocate(1, 16); + EXPECT_EQ(0U, a & 15); + a = (uintptr_t)Alloc.Allocate(1, 32); + EXPECT_EQ(0U, a & 31); + a = (uintptr_t)Alloc.Allocate(1, 64); + EXPECT_EQ(0U, a & 63); + a = (uintptr_t)Alloc.Allocate(1, 128); + EXPECT_EQ(0U, a & 127); +} + +// Test allocating just over the slab size. This tests a bug where before the +// allocator incorrectly calculated the buffer end pointer. +TEST(AllocatorTest, TestOverflow) { + BumpPtrAllocator Alloc(4096, 4096); + + // Fill the slab right up until the end pointer. + Alloc.Allocate(4096 - sizeof(MemSlab), 0); + EXPECT_EQ(1U, Alloc.GetNumSlabs()); + + // If we dont't allocate a new slab, then we will have overflowed. + Alloc.Allocate(1, 0); + EXPECT_EQ(2U, Alloc.GetNumSlabs()); +} + +// Mock slab allocator that returns slabs aligned on 4096 bytes. There is no +// easy portable way to do this, so this is kind of a hack. +class MockSlabAllocator : public SlabAllocator { + MemSlab *LastSlab; + +public: + virtual ~MockSlabAllocator() { } + + virtual MemSlab *Allocate(size_t Size) { + // Allocate space for the alignment, the slab, and a void* that goes right + // before the slab. + size_t Alignment = 4096; + void *MemBase = malloc(Size + Alignment - 1 + sizeof(void*)); + + // Make the slab. + MemSlab *Slab = (MemSlab*)(((uintptr_t)MemBase+sizeof(void*)+Alignment-1) & + ~(uintptr_t)(Alignment - 1)); + Slab->Size = Size; + Slab->NextPtr = 0; + + // Hold a pointer to the base so we can free the whole malloced block. + ((void**)Slab)[-1] = MemBase; + + LastSlab = Slab; + return Slab; + } + + virtual void Deallocate(MemSlab *Slab) { + free(((void**)Slab)[-1]); + } + + MemSlab *GetLastSlab() { + return LastSlab; + } +}; + +// Allocate a large-ish block with a really large alignment so that the +// allocator will think that it has space, but after it does the alignment it +// will not. +TEST(AllocatorTest, TestBigAlignment) { + MockSlabAllocator SlabAlloc; + BumpPtrAllocator Alloc(4096, 4096, SlabAlloc); + uintptr_t Ptr = (uintptr_t)Alloc.Allocate(3000, 2048); + MemSlab *Slab = SlabAlloc.GetLastSlab(); + EXPECT_LE(Ptr + 3000, ((uintptr_t)Slab) + Slab->Size); +} + +} // anonymous namespace diff --git a/unittests/Support/CommandLineTest.cpp b/unittests/Support/CommandLineTest.cpp new file mode 100644 index 0000000..72fa24a --- /dev/null +++ b/unittests/Support/CommandLineTest.cpp @@ -0,0 +1,60 @@ +//===- llvm/unittest/Support/CommandLineTest.cpp - CommandLine tests ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/CommandLine.h" +#include "llvm/Config/config.h" + +#include "gtest/gtest.h" + +#include <string> +#include <stdlib.h> + +using namespace llvm; + +namespace { + +class TempEnvVar { + public: + TempEnvVar(const char *name, const char *value) + : name(name) { + const char *old_value = getenv(name); + EXPECT_EQ(NULL, old_value) << old_value; +#if HAVE_SETENV + setenv(name, value, true); +#else +# define SKIP_ENVIRONMENT_TESTS +#endif + } + + ~TempEnvVar() { +#if HAVE_SETENV + // Assume setenv and unsetenv come together. + unsetenv(name); +#endif + } + + private: + const char *const name; +}; + +#ifndef SKIP_ENVIRONMENT_TESTS + +const char test_env_var[] = "LLVM_TEST_COMMAND_LINE_FLAGS"; + +cl::opt<std::string> EnvironmentTestOption("env-test-opt"); +TEST(CommandLineTest, ParseEnvironment) { + TempEnvVar TEV(test_env_var, "-env-test-opt=hello"); + EXPECT_EQ("", EnvironmentTestOption); + cl::ParseEnvironmentOptions("CommandLineTest", test_env_var); + EXPECT_EQ("hello", EnvironmentTestOption); +} + +#endif // SKIP_ENVIRONMENT_TESTS + +} // anonymous namespace diff --git a/unittests/Support/ConstantRangeTest.cpp b/unittests/Support/ConstantRangeTest.cpp new file mode 100644 index 0000000..6b8d01d --- /dev/null +++ b/unittests/Support/ConstantRangeTest.cpp @@ -0,0 +1,351 @@ +//===- llvm/unittest/Support/ConstantRangeTest.cpp - ConstantRange tests --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/ConstantRange.h" + +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +class ConstantRangeTest : public ::testing::Test { +protected: + static ConstantRange Full; + static ConstantRange Empty; + static ConstantRange One; + static ConstantRange Some; + static ConstantRange Wrap; +}; + +ConstantRange ConstantRangeTest::Full(16); +ConstantRange ConstantRangeTest::Empty(16, false); +ConstantRange ConstantRangeTest::One(APInt(16, 0xa)); +ConstantRange ConstantRangeTest::Some(APInt(16, 0xa), APInt(16, 0xaaa)); +ConstantRange ConstantRangeTest::Wrap(APInt(16, 0xaaa), APInt(16, 0xa)); + +TEST_F(ConstantRangeTest, Basics) { + EXPECT_TRUE(Full.isFullSet()); + EXPECT_FALSE(Full.isEmptySet()); + EXPECT_FALSE(Full.isWrappedSet()); + EXPECT_TRUE(Full.contains(APInt(16, 0x0))); + EXPECT_TRUE(Full.contains(APInt(16, 0x9))); + EXPECT_TRUE(Full.contains(APInt(16, 0xa))); + EXPECT_TRUE(Full.contains(APInt(16, 0xaa9))); + EXPECT_TRUE(Full.contains(APInt(16, 0xaaa))); + + EXPECT_FALSE(Empty.isFullSet()); + EXPECT_TRUE(Empty.isEmptySet()); + EXPECT_FALSE(Empty.isWrappedSet()); + EXPECT_FALSE(Empty.contains(APInt(16, 0x0))); + EXPECT_FALSE(Empty.contains(APInt(16, 0x9))); + EXPECT_FALSE(Empty.contains(APInt(16, 0xa))); + EXPECT_FALSE(Empty.contains(APInt(16, 0xaa9))); + EXPECT_FALSE(Empty.contains(APInt(16, 0xaaa))); + + EXPECT_FALSE(One.isFullSet()); + EXPECT_FALSE(One.isEmptySet()); + EXPECT_FALSE(One.isWrappedSet()); + EXPECT_FALSE(One.contains(APInt(16, 0x0))); + EXPECT_FALSE(One.contains(APInt(16, 0x9))); + EXPECT_TRUE(One.contains(APInt(16, 0xa))); + EXPECT_FALSE(One.contains(APInt(16, 0xaa9))); + EXPECT_FALSE(One.contains(APInt(16, 0xaaa))); + + EXPECT_FALSE(Some.isFullSet()); + EXPECT_FALSE(Some.isEmptySet()); + EXPECT_FALSE(Some.isWrappedSet()); + EXPECT_FALSE(Some.contains(APInt(16, 0x0))); + EXPECT_FALSE(Some.contains(APInt(16, 0x9))); + EXPECT_TRUE(Some.contains(APInt(16, 0xa))); + EXPECT_TRUE(Some.contains(APInt(16, 0xaa9))); + EXPECT_FALSE(Some.contains(APInt(16, 0xaaa))); + + EXPECT_FALSE(Wrap.isFullSet()); + EXPECT_FALSE(Wrap.isEmptySet()); + EXPECT_TRUE(Wrap.isWrappedSet()); + EXPECT_TRUE(Wrap.contains(APInt(16, 0x0))); + EXPECT_TRUE(Wrap.contains(APInt(16, 0x9))); + EXPECT_FALSE(Wrap.contains(APInt(16, 0xa))); + EXPECT_FALSE(Wrap.contains(APInt(16, 0xaa9))); + EXPECT_TRUE(Wrap.contains(APInt(16, 0xaaa))); +} + +TEST_F(ConstantRangeTest, Equality) { + EXPECT_EQ(Full, Full); + EXPECT_EQ(Empty, Empty); + EXPECT_EQ(One, One); + EXPECT_EQ(Some, Some); + EXPECT_EQ(Wrap, Wrap); + EXPECT_NE(Full, Empty); + EXPECT_NE(Full, One); + EXPECT_NE(Full, Some); + EXPECT_NE(Full, Wrap); + EXPECT_NE(Empty, One); + EXPECT_NE(Empty, Some); + EXPECT_NE(Empty, Wrap); + EXPECT_NE(One, Some); + EXPECT_NE(One, Wrap); + EXPECT_NE(Some, Wrap); +} + +TEST_F(ConstantRangeTest, SingleElement) { + EXPECT_EQ(Full.getSingleElement(), static_cast<APInt *>(NULL)); + EXPECT_EQ(Empty.getSingleElement(), static_cast<APInt *>(NULL)); + EXPECT_EQ(*One.getSingleElement(), APInt(16, 0xa)); + EXPECT_EQ(Some.getSingleElement(), static_cast<APInt *>(NULL)); + EXPECT_EQ(Wrap.getSingleElement(), static_cast<APInt *>(NULL)); + + EXPECT_FALSE(Full.isSingleElement()); + EXPECT_FALSE(Empty.isSingleElement()); + EXPECT_TRUE(One.isSingleElement()); + EXPECT_FALSE(Some.isSingleElement()); + EXPECT_FALSE(Wrap.isSingleElement()); +} + +TEST_F(ConstantRangeTest, GetSetSize) { + EXPECT_EQ(Full.getSetSize(), APInt(16, 0)); + EXPECT_EQ(Empty.getSetSize(), APInt(16, 0)); + EXPECT_EQ(One.getSetSize(), APInt(16, 1)); + EXPECT_EQ(Some.getSetSize(), APInt(16, 0xaa0)); + EXPECT_EQ(Wrap.getSetSize(), APInt(16, 0x10000 - 0xaa0)); +} + +TEST_F(ConstantRangeTest, GetMinsAndMaxes) { + EXPECT_EQ(Full.getUnsignedMax(), APInt(16, UINT16_MAX)); + EXPECT_EQ(One.getUnsignedMax(), APInt(16, 0xa)); + EXPECT_EQ(Some.getUnsignedMax(), APInt(16, 0xaa9)); + EXPECT_EQ(Wrap.getUnsignedMax(), APInt(16, UINT16_MAX)); + + EXPECT_EQ(Full.getUnsignedMin(), APInt(16, 0)); + EXPECT_EQ(One.getUnsignedMin(), APInt(16, 0xa)); + EXPECT_EQ(Some.getUnsignedMin(), APInt(16, 0xa)); + EXPECT_EQ(Wrap.getUnsignedMin(), APInt(16, 0)); + + EXPECT_EQ(Full.getSignedMax(), APInt(16, INT16_MAX)); + EXPECT_EQ(One.getSignedMax(), APInt(16, 0xa)); + EXPECT_EQ(Some.getSignedMax(), APInt(16, 0xaa9)); + EXPECT_EQ(Wrap.getSignedMax(), APInt(16, INT16_MAX)); + + EXPECT_EQ(Full.getSignedMin(), APInt(16, (uint64_t)INT16_MIN)); + EXPECT_EQ(One.getSignedMin(), APInt(16, 0xa)); + EXPECT_EQ(Some.getSignedMin(), APInt(16, 0xa)); + EXPECT_EQ(Wrap.getSignedMin(), APInt(16, (uint64_t)INT16_MIN)); + + // Found by Klee + EXPECT_EQ(ConstantRange(APInt(4, 7), APInt(4, 0)).getSignedMax(), + APInt(4, 7)); +} + +TEST_F(ConstantRangeTest, Trunc) { + ConstantRange TFull = Full.truncate(10); + ConstantRange TEmpty = Empty.truncate(10); + ConstantRange TOne = One.truncate(10); + ConstantRange TSome = Some.truncate(10); + ConstantRange TWrap = Wrap.truncate(10); + EXPECT_TRUE(TFull.isFullSet()); + EXPECT_TRUE(TEmpty.isEmptySet()); + EXPECT_EQ(TOne, ConstantRange(APInt(One.getLower()).trunc(10), + APInt(One.getUpper()).trunc(10))); + EXPECT_TRUE(TSome.isFullSet()); +} + +TEST_F(ConstantRangeTest, ZExt) { + ConstantRange ZFull = Full.zeroExtend(20); + ConstantRange ZEmpty = Empty.zeroExtend(20); + ConstantRange ZOne = One.zeroExtend(20); + ConstantRange ZSome = Some.zeroExtend(20); + ConstantRange ZWrap = Wrap.zeroExtend(20); + EXPECT_EQ(ZFull, ConstantRange(APInt(20, 0), APInt(20, 0x10000))); + EXPECT_TRUE(ZEmpty.isEmptySet()); + EXPECT_EQ(ZOne, ConstantRange(APInt(One.getLower()).zext(20), + APInt(One.getUpper()).zext(20))); + EXPECT_EQ(ZSome, ConstantRange(APInt(Some.getLower()).zext(20), + APInt(Some.getUpper()).zext(20))); + EXPECT_EQ(ZWrap, ConstantRange(APInt(Wrap.getLower()).zext(20), + APInt(Wrap.getUpper()).zext(20))); +} + +TEST_F(ConstantRangeTest, SExt) { + ConstantRange SFull = Full.signExtend(20); + ConstantRange SEmpty = Empty.signExtend(20); + ConstantRange SOne = One.signExtend(20); + ConstantRange SSome = Some.signExtend(20); + ConstantRange SWrap = Wrap.signExtend(20); + EXPECT_EQ(SFull, ConstantRange(APInt(20, (uint64_t)INT16_MIN, true), + APInt(20, INT16_MAX + 1, true))); + EXPECT_TRUE(SEmpty.isEmptySet()); + EXPECT_EQ(SOne, ConstantRange(APInt(One.getLower()).sext(20), + APInt(One.getUpper()).sext(20))); + EXPECT_EQ(SSome, ConstantRange(APInt(Some.getLower()).sext(20), + APInt(Some.getUpper()).sext(20))); + EXPECT_EQ(SWrap, ConstantRange(APInt(Wrap.getLower()).sext(20), + APInt(Wrap.getUpper()).sext(20))); +} + +TEST_F(ConstantRangeTest, IntersectWith) { + EXPECT_EQ(Empty.intersectWith(Full), Empty); + EXPECT_EQ(Empty.intersectWith(Empty), Empty); + EXPECT_EQ(Empty.intersectWith(One), Empty); + EXPECT_EQ(Empty.intersectWith(Some), Empty); + EXPECT_EQ(Empty.intersectWith(Wrap), Empty); + EXPECT_EQ(Full.intersectWith(Full), Full); + EXPECT_EQ(Some.intersectWith(Some), Some); + EXPECT_EQ(Some.intersectWith(One), One); + EXPECT_EQ(Full.intersectWith(One), One); + EXPECT_EQ(Full.intersectWith(Some), Some); + EXPECT_EQ(Some.intersectWith(Wrap), Empty); + EXPECT_EQ(One.intersectWith(Wrap), Empty); + EXPECT_EQ(One.intersectWith(Wrap), Wrap.intersectWith(One)); + + // Klee generated testcase from PR4545. + // The intersection of i16 [4, 2) and [6, 5) is disjoint, looking like + // 01..4.6789ABCDEF where the dots represent values not in the intersection. + ConstantRange LHS(APInt(16, 4), APInt(16, 2)); + ConstantRange RHS(APInt(16, 6), APInt(16, 5)); + EXPECT_TRUE(LHS.intersectWith(RHS) == LHS); +} + +TEST_F(ConstantRangeTest, UnionWith) { + EXPECT_EQ(Wrap.unionWith(One), + ConstantRange(APInt(16, 0xaaa), APInt(16, 0xb))); + EXPECT_EQ(One.unionWith(Wrap), Wrap.unionWith(One)); + EXPECT_EQ(Empty.unionWith(Empty), Empty); + EXPECT_EQ(Full.unionWith(Full), Full); + EXPECT_EQ(Some.unionWith(Wrap), Full); + + // PR4545 + EXPECT_EQ(ConstantRange(APInt(16, 14), APInt(16, 1)).unionWith( + ConstantRange(APInt(16, 0), APInt(16, 8))), + ConstantRange(APInt(16, 14), APInt(16, 8))); + EXPECT_EQ(ConstantRange(APInt(16, 6), APInt(16, 4)).unionWith( + ConstantRange(APInt(16, 4), APInt(16, 0))), + ConstantRange(16)); + EXPECT_EQ(ConstantRange(APInt(16, 1), APInt(16, 0)).unionWith( + ConstantRange(APInt(16, 2), APInt(16, 1))), + ConstantRange(16)); +} + +TEST_F(ConstantRangeTest, SubtractAPInt) { + EXPECT_EQ(Full.subtract(APInt(16, 4)), Full); + EXPECT_EQ(Empty.subtract(APInt(16, 4)), Empty); + EXPECT_EQ(Some.subtract(APInt(16, 4)), + ConstantRange(APInt(16, 0x6), APInt(16, 0xaa6))); + EXPECT_EQ(Wrap.subtract(APInt(16, 4)), + ConstantRange(APInt(16, 0xaa6), APInt(16, 0x6))); + EXPECT_EQ(One.subtract(APInt(16, 4)), + ConstantRange(APInt(16, 0x6))); +} + +TEST_F(ConstantRangeTest, Add) { + EXPECT_EQ(Full.add(APInt(16, 4)), Full); + EXPECT_EQ(Full.add(Full), Full); + EXPECT_EQ(Full.add(Empty), Empty); + EXPECT_EQ(Full.add(One), Full); + EXPECT_EQ(Full.add(Some), Full); + EXPECT_EQ(Full.add(Wrap), Full); + EXPECT_EQ(Empty.add(Empty), Empty); + EXPECT_EQ(Empty.add(One), Empty); + EXPECT_EQ(Empty.add(Some), Empty); + EXPECT_EQ(Empty.add(Wrap), Empty); + EXPECT_EQ(Empty.add(APInt(16, 4)), Empty); + EXPECT_EQ(Some.add(APInt(16, 4)), + ConstantRange(APInt(16, 0xe), APInt(16, 0xaae))); + EXPECT_EQ(Wrap.add(APInt(16, 4)), + ConstantRange(APInt(16, 0xaae), APInt(16, 0xe))); + EXPECT_EQ(One.add(APInt(16, 4)), + ConstantRange(APInt(16, 0xe))); +} + +TEST_F(ConstantRangeTest, Multiply) { + EXPECT_EQ(Full.multiply(Full), Full); + EXPECT_EQ(Full.multiply(Empty), Empty); + EXPECT_EQ(Full.multiply(One), Full); + EXPECT_EQ(Full.multiply(Some), Full); + EXPECT_EQ(Full.multiply(Wrap), Full); + EXPECT_EQ(Empty.multiply(Empty), Empty); + EXPECT_EQ(Empty.multiply(One), Empty); + EXPECT_EQ(Empty.multiply(Some), Empty); + EXPECT_EQ(Empty.multiply(Wrap), Empty); + EXPECT_EQ(One.multiply(One), ConstantRange(APInt(16, 0xa*0xa), + APInt(16, 0xa*0xa + 1))); + EXPECT_EQ(One.multiply(Some), ConstantRange(APInt(16, 0xa*0xa), + APInt(16, 0xa*0xaa9 + 1))); + EXPECT_EQ(One.multiply(Wrap), Full); + EXPECT_EQ(Some.multiply(Some), Full); + EXPECT_EQ(Some.multiply(Wrap), Full); + EXPECT_EQ(Wrap.multiply(Wrap), Full); + + // http://llvm.org/PR4545 + EXPECT_EQ(ConstantRange(APInt(4, 1), APInt(4, 6)).multiply( + ConstantRange(APInt(4, 6), APInt(4, 2))), + ConstantRange(4, /*isFullSet=*/true)); +} + +TEST_F(ConstantRangeTest, UMax) { + EXPECT_EQ(Full.umax(Full), Full); + EXPECT_EQ(Full.umax(Empty), Empty); + EXPECT_EQ(Full.umax(Some), ConstantRange(APInt(16, 0xa), APInt(16, 0))); + EXPECT_EQ(Full.umax(Wrap), Full); + EXPECT_EQ(Full.umax(Some), ConstantRange(APInt(16, 0xa), APInt(16, 0))); + EXPECT_EQ(Empty.umax(Empty), Empty); + EXPECT_EQ(Empty.umax(Some), Empty); + EXPECT_EQ(Empty.umax(Wrap), Empty); + EXPECT_EQ(Empty.umax(One), Empty); + EXPECT_EQ(Some.umax(Some), Some); + EXPECT_EQ(Some.umax(Wrap), ConstantRange(APInt(16, 0xa), APInt(16, 0))); + EXPECT_EQ(Some.umax(One), Some); + // TODO: ConstantRange is currently over-conservative here. + EXPECT_EQ(Wrap.umax(Wrap), Full); + EXPECT_EQ(Wrap.umax(One), ConstantRange(APInt(16, 0xa), APInt(16, 0))); + EXPECT_EQ(One.umax(One), One); +} + +TEST_F(ConstantRangeTest, SMax) { + EXPECT_EQ(Full.smax(Full), Full); + EXPECT_EQ(Full.smax(Empty), Empty); + EXPECT_EQ(Full.smax(Some), ConstantRange(APInt(16, 0xa), + APInt::getSignedMinValue(16))); + EXPECT_EQ(Full.smax(Wrap), Full); + EXPECT_EQ(Full.smax(One), ConstantRange(APInt(16, 0xa), + APInt::getSignedMinValue(16))); + EXPECT_EQ(Empty.smax(Empty), Empty); + EXPECT_EQ(Empty.smax(Some), Empty); + EXPECT_EQ(Empty.smax(Wrap), Empty); + EXPECT_EQ(Empty.smax(One), Empty); + EXPECT_EQ(Some.smax(Some), Some); + EXPECT_EQ(Some.smax(Wrap), ConstantRange(APInt(16, 0xa), + APInt(16, (uint64_t)INT16_MIN))); + EXPECT_EQ(Some.smax(One), Some); + EXPECT_EQ(Wrap.smax(One), ConstantRange(APInt(16, 0xa), + APInt(16, (uint64_t)INT16_MIN))); + EXPECT_EQ(One.smax(One), One); +} + +TEST_F(ConstantRangeTest, UDiv) { + EXPECT_EQ(Full.udiv(Full), Full); + EXPECT_EQ(Full.udiv(Empty), Empty); + EXPECT_EQ(Full.udiv(One), ConstantRange(APInt(16, 0), + APInt(16, 0xffff / 0xa + 1))); + EXPECT_EQ(Full.udiv(Some), ConstantRange(APInt(16, 0), + APInt(16, 0xffff / 0xa + 1))); + EXPECT_EQ(Full.udiv(Wrap), Full); + EXPECT_EQ(Empty.udiv(Empty), Empty); + EXPECT_EQ(Empty.udiv(One), Empty); + EXPECT_EQ(Empty.udiv(Some), Empty); + EXPECT_EQ(Empty.udiv(Wrap), Empty); + EXPECT_EQ(One.udiv(One), ConstantRange(APInt(16, 1))); + EXPECT_EQ(One.udiv(Some), ConstantRange(APInt(16, 0), APInt(16, 2))); + EXPECT_EQ(One.udiv(Wrap), ConstantRange(APInt(16, 0), APInt(16, 0xb))); + EXPECT_EQ(Some.udiv(Some), ConstantRange(APInt(16, 0), APInt(16, 0x111))); + EXPECT_EQ(Some.udiv(Wrap), ConstantRange(APInt(16, 0), APInt(16, 0xaaa))); + EXPECT_EQ(Wrap.udiv(Wrap), Full); +} + +} // anonymous namespace diff --git a/unittests/Support/MathExtrasTest.cpp b/unittests/Support/MathExtrasTest.cpp index 1f19468..3db1f77 100644 --- a/unittests/Support/MathExtrasTest.cpp +++ b/unittests/Support/MathExtrasTest.cpp @@ -1,4 +1,4 @@ -//===- llvm/unittest/Support/MathExtrasTest.cpp - math utils tests --------===// +//===- unittests/Support/MathExtrasTest.cpp - math utils tests ------------===// // // The LLVM Compiler Infrastructure // diff --git a/unittests/Support/RegexTest.cpp b/unittests/Support/RegexTest.cpp new file mode 100644 index 0000000..44c7e55 --- /dev/null +++ b/unittests/Support/RegexTest.cpp @@ -0,0 +1,65 @@ +//===- llvm/unittest/Support/RegexTest.cpp - Regex tests --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" +#include "llvm/Support/Regex.h" +#include "llvm/ADT/SmallVector.h" +#include <cstring> + +using namespace llvm; +namespace { + +class RegexTest : public ::testing::Test { +}; + +TEST_F(RegexTest, Basics) { + Regex r1("^[0-9]+$"); + EXPECT_TRUE(r1.match("916")); + EXPECT_TRUE(r1.match("9")); + EXPECT_FALSE(r1.match("9a")); + + SmallVector<StringRef, 1> Matches; + Regex r2("[0-9]+"); + EXPECT_TRUE(r2.match("aa216b", &Matches)); + EXPECT_EQ(1u, Matches.size()); + EXPECT_EQ("216", Matches[0].str()); + + Regex r3("[0-9]+([a-f])?:([0-9]+)"); + EXPECT_TRUE(r3.match("9a:513b", &Matches)); + EXPECT_EQ(3u, Matches.size()); + EXPECT_EQ("9a:513", Matches[0].str()); + EXPECT_EQ("a", Matches[1].str()); + EXPECT_EQ("513", Matches[2].str()); + + EXPECT_TRUE(r3.match("9:513b", &Matches)); + EXPECT_EQ(3u, Matches.size()); + EXPECT_EQ("9:513", Matches[0].str()); + EXPECT_EQ("", Matches[1].str()); + EXPECT_EQ("513", Matches[2].str()); + + Regex r4("a[^b]+b"); + std::string String="axxb"; + String[2] = '\0'; + EXPECT_FALSE(r4.match("abb")); + EXPECT_TRUE(r4.match(String, &Matches)); + EXPECT_EQ(1u, Matches.size()); + EXPECT_EQ(String, Matches[0].str()); + + + std::string NulPattern="X[0-9]+X([a-f])?:([0-9]+)"; + String="YX99a:513b"; + NulPattern[7] = '\0'; + Regex r5(NulPattern); + EXPECT_FALSE(r5.match(String)); + EXPECT_FALSE(r5.match("X9")); + String[3]='\0'; + EXPECT_TRUE(r5.match(String)); +} + +} diff --git a/unittests/Support/TypeBuilderTest.cpp b/unittests/Support/TypeBuilderTest.cpp index 425ee6b..a5c5e67 100644 --- a/unittests/Support/TypeBuilderTest.cpp +++ b/unittests/Support/TypeBuilderTest.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/TypeBuilder.h" +#include "llvm/LLVMContext.h" #include "gtest/gtest.h" @@ -16,134 +17,146 @@ using namespace llvm; namespace { TEST(TypeBuilderTest, Void) { - EXPECT_EQ(Type::VoidTy, (TypeBuilder<void, true>::get())); - EXPECT_EQ(Type::VoidTy, (TypeBuilder<void, false>::get())); + EXPECT_EQ(Type::getVoidTy(getGlobalContext()), (TypeBuilder<void, true>::get(getGlobalContext()))); + EXPECT_EQ(Type::getVoidTy(getGlobalContext()), (TypeBuilder<void, false>::get(getGlobalContext()))); // Special case for C compatibility: - EXPECT_EQ(PointerType::getUnqual(Type::Int8Ty), - (TypeBuilder<void*, false>::get())); + EXPECT_EQ(Type::getInt8PtrTy(getGlobalContext()), + (TypeBuilder<void*, false>::get(getGlobalContext()))); } TEST(TypeBuilderTest, HostIntegers) { - EXPECT_EQ(Type::Int8Ty, (TypeBuilder<int8_t, false>::get())); - EXPECT_EQ(Type::Int8Ty, (TypeBuilder<uint8_t, false>::get())); - EXPECT_EQ(Type::Int16Ty, (TypeBuilder<int16_t, false>::get())); - EXPECT_EQ(Type::Int16Ty, (TypeBuilder<uint16_t, false>::get())); - EXPECT_EQ(Type::Int32Ty, (TypeBuilder<int32_t, false>::get())); - EXPECT_EQ(Type::Int32Ty, (TypeBuilder<uint32_t, false>::get())); - EXPECT_EQ(Type::Int64Ty, (TypeBuilder<int64_t, false>::get())); - EXPECT_EQ(Type::Int64Ty, (TypeBuilder<uint64_t, false>::get())); - - EXPECT_EQ(IntegerType::get(sizeof(size_t) * CHAR_BIT), - (TypeBuilder<size_t, false>::get())); - EXPECT_EQ(IntegerType::get(sizeof(ptrdiff_t) * CHAR_BIT), - (TypeBuilder<ptrdiff_t, false>::get())); + EXPECT_EQ(Type::getInt8Ty(getGlobalContext()), (TypeBuilder<int8_t, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getInt8Ty(getGlobalContext()), (TypeBuilder<uint8_t, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getInt16Ty(getGlobalContext()), (TypeBuilder<int16_t, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getInt16Ty(getGlobalContext()), (TypeBuilder<uint16_t, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (TypeBuilder<int32_t, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (TypeBuilder<uint32_t, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getInt64Ty(getGlobalContext()), (TypeBuilder<int64_t, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getInt64Ty(getGlobalContext()), (TypeBuilder<uint64_t, false>::get(getGlobalContext()))); + + EXPECT_EQ(IntegerType::get(getGlobalContext(), sizeof(size_t) * CHAR_BIT), + (TypeBuilder<size_t, false>::get(getGlobalContext()))); + EXPECT_EQ(IntegerType::get(getGlobalContext(), sizeof(ptrdiff_t) * CHAR_BIT), + (TypeBuilder<ptrdiff_t, false>::get(getGlobalContext()))); } TEST(TypeBuilderTest, CrossCompilableIntegers) { - EXPECT_EQ(IntegerType::get(1), (TypeBuilder<types::i<1>, true>::get())); - EXPECT_EQ(IntegerType::get(1), (TypeBuilder<types::i<1>, false>::get())); - EXPECT_EQ(IntegerType::get(72), (TypeBuilder<types::i<72>, true>::get())); - EXPECT_EQ(IntegerType::get(72), (TypeBuilder<types::i<72>, false>::get())); + EXPECT_EQ(IntegerType::get(getGlobalContext(), 1), (TypeBuilder<types::i<1>, true>::get(getGlobalContext()))); + EXPECT_EQ(IntegerType::get(getGlobalContext(), 1), (TypeBuilder<types::i<1>, false>::get(getGlobalContext()))); + EXPECT_EQ(IntegerType::get(getGlobalContext(), 72), (TypeBuilder<types::i<72>, true>::get(getGlobalContext()))); + EXPECT_EQ(IntegerType::get(getGlobalContext(), 72), (TypeBuilder<types::i<72>, false>::get(getGlobalContext()))); } TEST(TypeBuilderTest, Float) { - EXPECT_EQ(Type::FloatTy, (TypeBuilder<float, false>::get())); - EXPECT_EQ(Type::DoubleTy, (TypeBuilder<double, false>::get())); + EXPECT_EQ(Type::getFloatTy(getGlobalContext()), (TypeBuilder<float, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getDoubleTy(getGlobalContext()), (TypeBuilder<double, false>::get(getGlobalContext()))); // long double isn't supported yet. - EXPECT_EQ(Type::FloatTy, (TypeBuilder<types::ieee_float, true>::get())); - EXPECT_EQ(Type::FloatTy, (TypeBuilder<types::ieee_float, false>::get())); - EXPECT_EQ(Type::DoubleTy, (TypeBuilder<types::ieee_double, true>::get())); - EXPECT_EQ(Type::DoubleTy, (TypeBuilder<types::ieee_double, false>::get())); - EXPECT_EQ(Type::X86_FP80Ty, (TypeBuilder<types::x86_fp80, true>::get())); - EXPECT_EQ(Type::X86_FP80Ty, (TypeBuilder<types::x86_fp80, false>::get())); - EXPECT_EQ(Type::FP128Ty, (TypeBuilder<types::fp128, true>::get())); - EXPECT_EQ(Type::FP128Ty, (TypeBuilder<types::fp128, false>::get())); - EXPECT_EQ(Type::PPC_FP128Ty, (TypeBuilder<types::ppc_fp128, true>::get())); - EXPECT_EQ(Type::PPC_FP128Ty, (TypeBuilder<types::ppc_fp128, false>::get())); + EXPECT_EQ(Type::getFloatTy(getGlobalContext()), (TypeBuilder<types::ieee_float, true>::get(getGlobalContext()))); + EXPECT_EQ(Type::getFloatTy(getGlobalContext()), (TypeBuilder<types::ieee_float, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getDoubleTy(getGlobalContext()), (TypeBuilder<types::ieee_double, true>::get(getGlobalContext()))); + EXPECT_EQ(Type::getDoubleTy(getGlobalContext()), (TypeBuilder<types::ieee_double, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getX86_FP80Ty(getGlobalContext()), (TypeBuilder<types::x86_fp80, true>::get(getGlobalContext()))); + EXPECT_EQ(Type::getX86_FP80Ty(getGlobalContext()), (TypeBuilder<types::x86_fp80, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getFP128Ty(getGlobalContext()), (TypeBuilder<types::fp128, true>::get(getGlobalContext()))); + EXPECT_EQ(Type::getFP128Ty(getGlobalContext()), (TypeBuilder<types::fp128, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getPPC_FP128Ty(getGlobalContext()), (TypeBuilder<types::ppc_fp128, true>::get(getGlobalContext()))); + EXPECT_EQ(Type::getPPC_FP128Ty(getGlobalContext()), (TypeBuilder<types::ppc_fp128, false>::get(getGlobalContext()))); } TEST(TypeBuilderTest, Derived) { - EXPECT_EQ(PointerType::getUnqual(PointerType::getUnqual(Type::Int8Ty)), - (TypeBuilder<int8_t**, false>::get())); - EXPECT_EQ(ArrayType::get(Type::Int8Ty, 7), - (TypeBuilder<int8_t[7], false>::get())); - EXPECT_EQ(ArrayType::get(Type::Int8Ty, 0), - (TypeBuilder<int8_t[], false>::get())); - - EXPECT_EQ(PointerType::getUnqual(PointerType::getUnqual(Type::Int8Ty)), - (TypeBuilder<types::i<8>**, false>::get())); - EXPECT_EQ(ArrayType::get(Type::Int8Ty, 7), - (TypeBuilder<types::i<8>[7], false>::get())); - EXPECT_EQ(ArrayType::get(Type::Int8Ty, 0), - (TypeBuilder<types::i<8>[], false>::get())); - - EXPECT_EQ(PointerType::getUnqual(PointerType::getUnqual(Type::Int8Ty)), - (TypeBuilder<types::i<8>**, true>::get())); - EXPECT_EQ(ArrayType::get(Type::Int8Ty, 7), - (TypeBuilder<types::i<8>[7], true>::get())); - EXPECT_EQ(ArrayType::get(Type::Int8Ty, 0), - (TypeBuilder<types::i<8>[], true>::get())); - - - EXPECT_EQ(Type::Int8Ty, - (TypeBuilder<const int8_t, false>::get())); - EXPECT_EQ(Type::Int8Ty, - (TypeBuilder<volatile int8_t, false>::get())); - EXPECT_EQ(Type::Int8Ty, - (TypeBuilder<const volatile int8_t, false>::get())); - - EXPECT_EQ(Type::Int8Ty, - (TypeBuilder<const types::i<8>, false>::get())); - EXPECT_EQ(Type::Int8Ty, - (TypeBuilder<volatile types::i<8>, false>::get())); - EXPECT_EQ(Type::Int8Ty, - (TypeBuilder<const volatile types::i<8>, false>::get())); - - EXPECT_EQ(Type::Int8Ty, - (TypeBuilder<const types::i<8>, true>::get())); - EXPECT_EQ(Type::Int8Ty, - (TypeBuilder<volatile types::i<8>, true>::get())); - EXPECT_EQ(Type::Int8Ty, - (TypeBuilder<const volatile types::i<8>, true>::get())); - - EXPECT_EQ(PointerType::getUnqual(Type::Int8Ty), - (TypeBuilder<const volatile int8_t*const volatile, false>::get())); + EXPECT_EQ(PointerType::getUnqual(Type::getInt8PtrTy(getGlobalContext())), + (TypeBuilder<int8_t**, false>::get(getGlobalContext()))); + EXPECT_EQ(ArrayType::get(Type::getInt8Ty(getGlobalContext()), 7), + (TypeBuilder<int8_t[7], false>::get(getGlobalContext()))); + EXPECT_EQ(ArrayType::get(Type::getInt8Ty(getGlobalContext()), 0), + (TypeBuilder<int8_t[], false>::get(getGlobalContext()))); + + EXPECT_EQ(PointerType::getUnqual(Type::getInt8PtrTy(getGlobalContext())), + (TypeBuilder<types::i<8>**, false>::get(getGlobalContext()))); + EXPECT_EQ(ArrayType::get(Type::getInt8Ty(getGlobalContext()), 7), + (TypeBuilder<types::i<8>[7], false>::get(getGlobalContext()))); + EXPECT_EQ(ArrayType::get(Type::getInt8Ty(getGlobalContext()), 0), + (TypeBuilder<types::i<8>[], false>::get(getGlobalContext()))); + + EXPECT_EQ(PointerType::getUnqual(Type::getInt8PtrTy(getGlobalContext())), + (TypeBuilder<types::i<8>**, true>::get(getGlobalContext()))); + EXPECT_EQ(ArrayType::get(Type::getInt8Ty(getGlobalContext()), 7), + (TypeBuilder<types::i<8>[7], true>::get(getGlobalContext()))); + EXPECT_EQ(ArrayType::get(Type::getInt8Ty(getGlobalContext()), 0), + (TypeBuilder<types::i<8>[], true>::get(getGlobalContext()))); + + + EXPECT_EQ(Type::getInt8Ty(getGlobalContext()), + (TypeBuilder<const int8_t, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getInt8Ty(getGlobalContext()), + (TypeBuilder<volatile int8_t, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getInt8Ty(getGlobalContext()), + (TypeBuilder<const volatile int8_t, false>::get(getGlobalContext()))); + + EXPECT_EQ(Type::getInt8Ty(getGlobalContext()), + (TypeBuilder<const types::i<8>, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getInt8Ty(getGlobalContext()), + (TypeBuilder<volatile types::i<8>, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getInt8Ty(getGlobalContext()), + (TypeBuilder<const volatile types::i<8>, false>::get(getGlobalContext()))); + + EXPECT_EQ(Type::getInt8Ty(getGlobalContext()), + (TypeBuilder<const types::i<8>, true>::get(getGlobalContext()))); + EXPECT_EQ(Type::getInt8Ty(getGlobalContext()), + (TypeBuilder<volatile types::i<8>, true>::get(getGlobalContext()))); + EXPECT_EQ(Type::getInt8Ty(getGlobalContext()), + (TypeBuilder<const volatile types::i<8>, true>::get(getGlobalContext()))); + + EXPECT_EQ(Type::getInt8PtrTy(getGlobalContext()), + (TypeBuilder<const volatile int8_t*const volatile, false>::get(getGlobalContext()))); } TEST(TypeBuilderTest, Functions) { std::vector<const Type*> params; - EXPECT_EQ(FunctionType::get(Type::VoidTy, params, false), - (TypeBuilder<void(), true>::get())); - EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, true), - (TypeBuilder<int8_t(...), false>::get())); - params.push_back(TypeBuilder<int32_t*, false>::get()); - EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, false), - (TypeBuilder<int8_t(const int32_t*), false>::get())); - EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, true), - (TypeBuilder<int8_t(const int32_t*, ...), false>::get())); - params.push_back(TypeBuilder<char*, false>::get()); - EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, false), - (TypeBuilder<int8_t(int32_t*, void*), false>::get())); - EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, true), - (TypeBuilder<int8_t(int32_t*, char*, ...), false>::get())); - params.push_back(TypeBuilder<char, false>::get()); - EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, false), - (TypeBuilder<int8_t(int32_t*, void*, char), false>::get())); - EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, true), - (TypeBuilder<int8_t(int32_t*, char*, char, ...), false>::get())); - params.push_back(TypeBuilder<char, false>::get()); - EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, false), - (TypeBuilder<int8_t(int32_t*, void*, char, char), false>::get())); - EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, true), + EXPECT_EQ(FunctionType::get(Type::getVoidTy(getGlobalContext()), params, false), + (TypeBuilder<void(), true>::get(getGlobalContext()))); + EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, true), + (TypeBuilder<int8_t(...), false>::get(getGlobalContext()))); + params.push_back(TypeBuilder<int32_t*, false>::get(getGlobalContext())); + EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, false), + (TypeBuilder<int8_t(const int32_t*), false>::get(getGlobalContext()))); + EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, true), + (TypeBuilder<int8_t(const int32_t*, ...), false>::get(getGlobalContext()))); + params.push_back(TypeBuilder<char*, false>::get(getGlobalContext())); + EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, false), + (TypeBuilder<int8_t(int32_t*, void*), false>::get(getGlobalContext()))); + EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, true), + (TypeBuilder<int8_t(int32_t*, char*, ...), false>::get(getGlobalContext()))); + params.push_back(TypeBuilder<char, false>::get(getGlobalContext())); + EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, false), + (TypeBuilder<int8_t(int32_t*, void*, char), false>::get(getGlobalContext()))); + EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, true), + (TypeBuilder<int8_t(int32_t*, char*, char, ...), false>::get(getGlobalContext()))); + params.push_back(TypeBuilder<char, false>::get(getGlobalContext())); + EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, false), + (TypeBuilder<int8_t(int32_t*, void*, char, char), false>::get(getGlobalContext()))); + EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, true), (TypeBuilder<int8_t(int32_t*, char*, char, char, ...), - false>::get())); - params.push_back(TypeBuilder<char, false>::get()); - EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, false), + false>::get(getGlobalContext()))); + params.push_back(TypeBuilder<char, false>::get(getGlobalContext())); + EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, false), (TypeBuilder<int8_t(int32_t*, void*, char, char, char), - false>::get())); - EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, true), + false>::get(getGlobalContext()))); + EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, true), (TypeBuilder<int8_t(int32_t*, char*, char, char, char, ...), - false>::get())); + false>::get(getGlobalContext()))); +} + +TEST(TypeBuilderTest, Context) { + // We used to cache TypeBuilder results in static local variables. This + // produced the same type for different contexts, which of course broke + // things. + LLVMContext context1; + EXPECT_EQ(&context1, + &(TypeBuilder<types::i<1>, true>::get(context1))->getContext()); + LLVMContext context2; + EXPECT_EQ(&context2, + &(TypeBuilder<types::i<1>, true>::get(context2))->getContext()); } class MyType { @@ -163,14 +176,14 @@ class MyPortableType { namespace llvm { template<bool cross> class TypeBuilder<MyType, cross> { public: - static const StructType *get() { + static const StructType *get(LLVMContext &Context) { // Using the static result variable ensures that the type is // only looked up once. - static const StructType *const result = StructType::get( - TypeBuilder<int, cross>::get(), - TypeBuilder<int*, cross>::get(), - TypeBuilder<void*[], cross>::get(), - NULL); + std::vector<const Type*> st; + st.push_back(TypeBuilder<int, cross>::get(Context)); + st.push_back(TypeBuilder<int*, cross>::get(Context)); + st.push_back(TypeBuilder<void*[], cross>::get(Context)); + static const StructType *const result = StructType::get(Context, st); return result; } @@ -186,14 +199,14 @@ public: template<bool cross> class TypeBuilder<MyPortableType, cross> { public: - static const StructType *get() { + static const StructType *get(LLVMContext &Context) { // Using the static result variable ensures that the type is // only looked up once. - static const StructType *const result = StructType::get( - TypeBuilder<types::i<32>, cross>::get(), - TypeBuilder<types::i<32>*, cross>::get(), - TypeBuilder<types::i<8>*[], cross>::get(), - NULL); + std::vector<const Type*> st; + st.push_back(TypeBuilder<types::i<32>, cross>::get(Context)); + st.push_back(TypeBuilder<types::i<32>*, cross>::get(Context)); + st.push_back(TypeBuilder<types::i<8>*[], cross>::get(Context)); + static const StructType *const result = StructType::get(Context, st); return result; } @@ -210,24 +223,24 @@ public: namespace { TEST(TypeBuilderTest, Extensions) { - EXPECT_EQ(PointerType::getUnqual(StructType::get( - TypeBuilder<int, false>::get(), - TypeBuilder<int*, false>::get(), - TypeBuilder<void*[], false>::get(), + EXPECT_EQ(PointerType::getUnqual(StructType::get(getGlobalContext(), + TypeBuilder<int, false>::get(getGlobalContext()), + TypeBuilder<int*, false>::get(getGlobalContext()), + TypeBuilder<void*[], false>::get(getGlobalContext()), NULL)), - (TypeBuilder<MyType*, false>::get())); - EXPECT_EQ(PointerType::getUnqual(StructType::get( - TypeBuilder<types::i<32>, false>::get(), - TypeBuilder<types::i<32>*, false>::get(), - TypeBuilder<types::i<8>*[], false>::get(), + (TypeBuilder<MyType*, false>::get(getGlobalContext()))); + EXPECT_EQ(PointerType::getUnqual(StructType::get(getGlobalContext(), + TypeBuilder<types::i<32>, false>::get(getGlobalContext()), + TypeBuilder<types::i<32>*, false>::get(getGlobalContext()), + TypeBuilder<types::i<8>*[], false>::get(getGlobalContext()), NULL)), - (TypeBuilder<MyPortableType*, false>::get())); - EXPECT_EQ(PointerType::getUnqual(StructType::get( - TypeBuilder<types::i<32>, false>::get(), - TypeBuilder<types::i<32>*, false>::get(), - TypeBuilder<types::i<8>*[], false>::get(), + (TypeBuilder<MyPortableType*, false>::get(getGlobalContext()))); + EXPECT_EQ(PointerType::getUnqual(StructType::get(getGlobalContext(), + TypeBuilder<types::i<32>, false>::get(getGlobalContext()), + TypeBuilder<types::i<32>*, false>::get(getGlobalContext()), + TypeBuilder<types::i<8>*[], false>::get(getGlobalContext()), NULL)), - (TypeBuilder<MyPortableType*, true>::get())); + (TypeBuilder<MyPortableType*, true>::get(getGlobalContext()))); } } // anonymous namespace diff --git a/unittests/Support/ValueHandleTest.cpp b/unittests/Support/ValueHandleTest.cpp index 336e7d9..c89a7af 100644 --- a/unittests/Support/ValueHandleTest.cpp +++ b/unittests/Support/ValueHandleTest.cpp @@ -11,6 +11,7 @@ #include "llvm/Constants.h" #include "llvm/Instructions.h" +#include "llvm/ADT/OwningPtr.h" #include "gtest/gtest.h" @@ -25,8 +26,9 @@ protected: Constant *ConstantV; std::auto_ptr<BitCastInst> BitcastV; - ValueHandle() : ConstantV(ConstantInt::get(Type::Int32Ty, 0)), - BitcastV(new BitCastInst(ConstantV, Type::Int32Ty)) { + ValueHandle() : + ConstantV(ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 0)), + BitcastV(new BitCastInst(ConstantV, Type::getInt32Ty(getGlobalContext()))) { } }; @@ -44,8 +46,8 @@ TEST_F(ValueHandle, WeakVH_BasicOperation) { // Make sure I can call a method on the underlying Value. It // doesn't matter which method. - EXPECT_EQ(Type::Int32Ty, WVH->getType()); - EXPECT_EQ(Type::Int32Ty, (*WVH).getType()); + EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), WVH->getType()); + EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (*WVH).getType()); } TEST_F(ValueHandle, WeakVH_Comparisons) { @@ -119,6 +121,13 @@ TEST_F(ValueHandle, AssertingVH_BasicOperation) { EXPECT_FALSE((*AVH).mayWriteToMemory()); } +TEST_F(ValueHandle, AssertingVH_Const) { + const CastInst *ConstBitcast = BitcastV.get(); + AssertingVH<const CastInst> AVH(ConstBitcast); + const CastInst *implicit_to_exact_type = AVH; + implicit_to_exact_type = implicit_to_exact_type; // Avoid warning. +} + TEST_F(ValueHandle, AssertingVH_Comparisons) { AssertingVH<Value> BitcastAVH(BitcastV.get()); AssertingVH<Value> ConstantAVH(ConstantV); @@ -192,8 +201,8 @@ TEST_F(ValueHandle, CallbackVH_BasicOperation) { // Make sure I can call a method on the underlying Value. It // doesn't matter which method. - EXPECT_EQ(Type::Int32Ty, CVH->getType()); - EXPECT_EQ(Type::Int32Ty, (*CVH).getType()); + EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), CVH->getType()); + EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (*CVH).getType()); } TEST_F(ValueHandle, CallbackVH_Comparisons) { @@ -284,14 +293,17 @@ TEST_F(ValueHandle, CallbackVH_DeletionCanRAUW) { public: int DeletedCalls; Value *AURWArgument; + LLVMContext *Context; - RecoveringVH() : DeletedCalls(0), AURWArgument(NULL) {} + RecoveringVH() : DeletedCalls(0), AURWArgument(NULL), + Context(&getGlobalContext()) {} RecoveringVH(Value *V) - : CallbackVH(V), DeletedCalls(0), AURWArgument(NULL) {} + : CallbackVH(V), DeletedCalls(0), AURWArgument(NULL), + Context(&getGlobalContext()) {} private: virtual void deleted() { - getValPtr()->replaceAllUsesWith(Constant::getNullValue(Type::Int32Ty)); + getValPtr()->replaceAllUsesWith(Constant::getNullValue(Type::getInt32Ty(getGlobalContext()))); setValPtr(NULL); } virtual void allUsesReplacedWith(Value *new_value) { @@ -307,11 +319,93 @@ TEST_F(ValueHandle, CallbackVH_DeletionCanRAUW) { RecoveringVH RVH; RVH = BitcastV.get(); std::auto_ptr<BinaryOperator> BitcastUser( - BinaryOperator::CreateAdd(RVH, Constant::getNullValue(Type::Int32Ty))); + BinaryOperator::CreateAdd(RVH, + Constant::getNullValue(Type::getInt32Ty(getGlobalContext())))); EXPECT_EQ(BitcastV.get(), BitcastUser->getOperand(0)); BitcastV.reset(); // Would crash without the ValueHandler. - EXPECT_EQ(Constant::getNullValue(Type::Int32Ty), RVH.AURWArgument); - EXPECT_EQ(Constant::getNullValue(Type::Int32Ty), BitcastUser->getOperand(0)); + EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(getGlobalContext())), RVH.AURWArgument); + EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(getGlobalContext())), + BitcastUser->getOperand(0)); +} + +TEST_F(ValueHandle, DestroyingOtherVHOnSameValueDoesntBreakIteration) { + // When a CallbackVH modifies other ValueHandles in its callbacks, + // that shouldn't interfere with non-modified ValueHandles receiving + // their appropriate callbacks. + // + // We create the active CallbackVH in the middle of a palindromic + // arrangement of other VHs so that the bad behavior would be + // triggered in whichever order callbacks run. + + class DestroyingVH : public CallbackVH { + public: + OwningPtr<WeakVH> ToClear[2]; + DestroyingVH(Value *V) { + ToClear[0].reset(new WeakVH(V)); + setValPtr(V); + ToClear[1].reset(new WeakVH(V)); + } + virtual void deleted() { + ToClear[0].reset(); + ToClear[1].reset(); + CallbackVH::deleted(); + } + virtual void allUsesReplacedWith(Value *) { + ToClear[0].reset(); + ToClear[1].reset(); + } + }; + + { + WeakVH ShouldBeVisited1(BitcastV.get()); + DestroyingVH C(BitcastV.get()); + WeakVH ShouldBeVisited2(BitcastV.get()); + + BitcastV->replaceAllUsesWith(ConstantV); + EXPECT_EQ(ConstantV, static_cast<Value*>(ShouldBeVisited1)); + EXPECT_EQ(ConstantV, static_cast<Value*>(ShouldBeVisited2)); + } + + { + WeakVH ShouldBeVisited1(BitcastV.get()); + DestroyingVH C(BitcastV.get()); + WeakVH ShouldBeVisited2(BitcastV.get()); + + BitcastV.reset(); + EXPECT_EQ(NULL, static_cast<Value*>(ShouldBeVisited1)); + EXPECT_EQ(NULL, static_cast<Value*>(ShouldBeVisited2)); + } +} + +TEST_F(ValueHandle, AssertingVHCheckedLast) { + // If a CallbackVH exists to clear out a group of AssertingVHs on + // Value deletion, the CallbackVH should get a chance to do so + // before the AssertingVHs assert. + + class ClearingVH : public CallbackVH { + public: + AssertingVH<Value> *ToClear[2]; + ClearingVH(Value *V, + AssertingVH<Value> &A0, AssertingVH<Value> &A1) + : CallbackVH(V) { + ToClear[0] = &A0; + ToClear[1] = &A1; + } + + virtual void deleted() { + *ToClear[0] = 0; + *ToClear[1] = 0; + CallbackVH::deleted(); + } + }; + + AssertingVH<Value> A1, A2; + A1 = BitcastV.get(); + ClearingVH C(BitcastV.get(), A1, A2); + A2 = BitcastV.get(); + // C.deleted() should run first, clearing the two AssertingVHs, + // which should prevent them from asserting. + BitcastV.reset(); } } diff --git a/unittests/Support/raw_ostream_test.cpp b/unittests/Support/raw_ostream_test.cpp index feb0152..bd2e95c 100644 --- a/unittests/Support/raw_ostream_test.cpp +++ b/unittests/Support/raw_ostream_test.cpp @@ -8,6 +8,8 @@ //===----------------------------------------------------------------------===// #include "gtest/gtest.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -20,6 +22,23 @@ template<typename T> std::string printToString(const T &Value) { return res; } +/// printToString - Print the given value to a stream which only has \arg +/// BytesLeftInBuffer bytes left in the buffer. This is useful for testing edge +/// cases in the buffer handling logic. +template<typename T> std::string printToString(const T &Value, + unsigned BytesLeftInBuffer) { + // FIXME: This is relying on internal knowledge of how raw_ostream works to + // get the buffer position right. + SmallString<256> SVec; + assert(BytesLeftInBuffer < 256 && "Invalid buffer count!"); + llvm::raw_svector_ostream OS(SVec); + unsigned StartIndex = 256 - BytesLeftInBuffer; + for (unsigned i = 0; i != StartIndex; ++i) + OS << '?'; + OS << Value; + return OS.str().substr(StartIndex); +} + template<typename T> std::string printToStringUnbuffered(const T &Value) { std::string res; llvm::raw_string_ostream OS(res); @@ -53,6 +72,10 @@ TEST(raw_ostreamTest, Types_Buffered) { EXPECT_EQ("0x0", printToString((void*) 0)); EXPECT_EQ("0xbeef", printToString((void*) 0xbeef)); EXPECT_EQ("0xdeadbeef", printToString((void*) 0xdeadbeef)); + + // Min and max. + EXPECT_EQ("18446744073709551615", printToString(UINT64_MAX)); + EXPECT_EQ("-9223372036854775808", printToString(INT64_MIN)); } TEST(raw_ostreamTest, Types_Unbuffered) { @@ -80,6 +103,28 @@ TEST(raw_ostreamTest, Types_Unbuffered) { EXPECT_EQ("0x0", printToStringUnbuffered((void*) 0)); EXPECT_EQ("0xbeef", printToStringUnbuffered((void*) 0xbeef)); EXPECT_EQ("0xdeadbeef", printToStringUnbuffered((void*) 0xdeadbeef)); + + // Min and max. + EXPECT_EQ("18446744073709551615", printToStringUnbuffered(UINT64_MAX)); + EXPECT_EQ("-9223372036854775808", printToStringUnbuffered(INT64_MIN)); +} + +TEST(raw_ostreamTest, BufferEdge) { + EXPECT_EQ("1.20", printToString(format("%.2f", 1.2), 1)); + EXPECT_EQ("1.20", printToString(format("%.2f", 1.2), 2)); + EXPECT_EQ("1.20", printToString(format("%.2f", 1.2), 3)); + EXPECT_EQ("1.20", printToString(format("%.2f", 1.2), 4)); + EXPECT_EQ("1.20", printToString(format("%.2f", 1.2), 10)); +} + +TEST(raw_ostreamTest, TinyBuffer) { + std::string Str; + raw_string_ostream OS(Str); + OS.SetBufferSize(1); + OS << "hello"; + OS << 1; + OS << 'w' << 'o' << 'r' << 'l' << 'd'; + EXPECT_EQ("hello1world", OS.str()); } } diff --git a/unittests/Transforms/Makefile b/unittests/Transforms/Makefile new file mode 100644 index 0000000..599b18a --- /dev/null +++ b/unittests/Transforms/Makefile @@ -0,0 +1,17 @@ +##===- unittests/Transforms/Makefile -----------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. + +PARALLEL_DIRS = Utils + +include $(LEVEL)/Makefile.common + +clean:: + $(Verb) $(RM) -f *Tests diff --git a/unittests/Transforms/Utils/Cloning.cpp b/unittests/Transforms/Utils/Cloning.cpp new file mode 100644 index 0000000..b14114a --- /dev/null +++ b/unittests/Transforms/Utils/Cloning.cpp @@ -0,0 +1,87 @@ +//===- Cloning.cpp - Unit tests for the Cloner ----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" +#include "llvm/Argument.h" +#include "llvm/Instructions.h" + +using namespace llvm; + +TEST(CloneInstruction, OverflowBits) { + LLVMContext context; + Value *V = new Argument(Type::getInt32Ty(context)); + + BinaryOperator *Add = BinaryOperator::Create(Instruction::Add, V, V); + BinaryOperator *Sub = BinaryOperator::Create(Instruction::Sub, V, V); + BinaryOperator *Mul = BinaryOperator::Create(Instruction::Mul, V, V); + + EXPECT_FALSE(Add->clone()->hasNoUnsignedWrap()); + EXPECT_FALSE(Add->clone()->hasNoSignedWrap()); + EXPECT_FALSE(Sub->clone()->hasNoUnsignedWrap()); + EXPECT_FALSE(Sub->clone()->hasNoSignedWrap()); + EXPECT_FALSE(Mul->clone()->hasNoUnsignedWrap()); + EXPECT_FALSE(Mul->clone()->hasNoSignedWrap()); + + Add->setHasNoUnsignedWrap(); + Sub->setHasNoUnsignedWrap(); + Mul->setHasNoUnsignedWrap(); + + EXPECT_TRUE(Add->clone()->hasNoUnsignedWrap()); + EXPECT_FALSE(Add->clone()->hasNoSignedWrap()); + EXPECT_TRUE(Sub->clone()->hasNoUnsignedWrap()); + EXPECT_FALSE(Sub->clone()->hasNoSignedWrap()); + EXPECT_TRUE(Mul->clone()->hasNoUnsignedWrap()); + EXPECT_FALSE(Mul->clone()->hasNoSignedWrap()); + + Add->setHasNoSignedWrap(); + Sub->setHasNoSignedWrap(); + Mul->setHasNoSignedWrap(); + + EXPECT_TRUE(Add->clone()->hasNoUnsignedWrap()); + EXPECT_TRUE(Add->clone()->hasNoSignedWrap()); + EXPECT_TRUE(Sub->clone()->hasNoUnsignedWrap()); + EXPECT_TRUE(Sub->clone()->hasNoSignedWrap()); + EXPECT_TRUE(Mul->clone()->hasNoUnsignedWrap()); + EXPECT_TRUE(Mul->clone()->hasNoSignedWrap()); + + Add->setHasNoUnsignedWrap(false); + Sub->setHasNoUnsignedWrap(false); + Mul->setHasNoUnsignedWrap(false); + + EXPECT_FALSE(Add->clone()->hasNoUnsignedWrap()); + EXPECT_TRUE(Add->clone()->hasNoSignedWrap()); + EXPECT_FALSE(Sub->clone()->hasNoUnsignedWrap()); + EXPECT_TRUE(Sub->clone()->hasNoSignedWrap()); + EXPECT_FALSE(Mul->clone()->hasNoUnsignedWrap()); + EXPECT_TRUE(Mul->clone()->hasNoSignedWrap()); +} + +TEST(CloneInstruction, Inbounds) { + LLVMContext context; + Value *V = new Argument(Type::getInt32PtrTy(context)); + Constant *Z = Constant::getNullValue(Type::getInt32Ty(context)); + std::vector<Value *> ops; + ops.push_back(Z); + GetElementPtrInst *GEP = GetElementPtrInst::Create(V, ops.begin(), ops.end()); + EXPECT_FALSE(GEP->clone()->isInBounds()); + + GEP->setIsInBounds(); + EXPECT_TRUE(GEP->clone()->isInBounds()); +} + +TEST(CloneInstruction, Exact) { + LLVMContext context; + Value *V = new Argument(Type::getInt32Ty(context)); + + BinaryOperator *SDiv = BinaryOperator::Create(Instruction::SDiv, V, V); + EXPECT_FALSE(SDiv->clone()->isExact()); + + SDiv->setIsExact(true); + EXPECT_TRUE(SDiv->clone()->isExact()); +} diff --git a/unittests/Transforms/Utils/Makefile b/unittests/Transforms/Utils/Makefile new file mode 100644 index 0000000..fdf4be0 --- /dev/null +++ b/unittests/Transforms/Utils/Makefile @@ -0,0 +1,15 @@ +##===- unittests/Transforms/Utils/Makefile -----------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +TESTNAME = Utils +LINK_COMPONENTS := core support transformutils + +include $(LEVEL)/Makefile.config +include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/VMCore/ConstantsTest.cpp b/unittests/VMCore/ConstantsTest.cpp index 519d928..8f28407 100644 --- a/unittests/VMCore/ConstantsTest.cpp +++ b/unittests/VMCore/ConstantsTest.cpp @@ -9,13 +9,14 @@ #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" +#include "llvm/LLVMContext.h" #include "gtest/gtest.h" namespace llvm { namespace { TEST(ConstantsTest, Integer_i1) { - const IntegerType* Int1 = IntegerType::get(1); + const IntegerType* Int1 = IntegerType::get(getGlobalContext(), 1); Constant* One = ConstantInt::get(Int1, 1, true); Constant* Zero = ConstantInt::get(Int1, 0); Constant* NegOne = ConstantInt::get(Int1, static_cast<uint64_t>(-1), true); @@ -96,7 +97,7 @@ TEST(ConstantsTest, Integer_i1) { } TEST(ConstantsTest, IntSigns) { - const IntegerType* Int8Ty = Type::Int8Ty; + const IntegerType* Int8Ty = Type::getInt8Ty(getGlobalContext()); EXPECT_EQ(100, ConstantInt::get(Int8Ty, 100, false)->getSExtValue()); EXPECT_EQ(100, ConstantInt::get(Int8Ty, 100, true)->getSExtValue()); EXPECT_EQ(100, ConstantInt::getSigned(Int8Ty, 100)->getSExtValue()); diff --git a/unittests/VMCore/MetadataTest.cpp b/unittests/VMCore/MetadataTest.cpp index 2de3a92..b92b068 100644 --- a/unittests/VMCore/MetadataTest.cpp +++ b/unittests/VMCore/MetadataTest.cpp @@ -10,22 +10,24 @@ #include "gtest/gtest.h" #include "llvm/Constants.h" #include "llvm/Instructions.h" -#include "llvm/MDNode.h" +#include "llvm/Metadata.h" +#include "llvm/Module.h" #include "llvm/Type.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Support/ValueHandle.h" -#include <sstream> - using namespace llvm; namespace { +LLVMContext &Context = getGlobalContext(); + // Test that construction of MDString with different value produces different // MDString objects, even with the same string pointer and nulls in the string. TEST(MDStringTest, CreateDifferent) { char x[3] = { 'f', 0, 'A' }; - MDString *s1 = MDString::get(&x[0], &x[3]); + MDString *s1 = MDString::get(Context, StringRef(&x[0], 3)); x[2] = 'B'; - MDString *s2 = MDString::get(&x[0], &x[3]); + MDString *s2 = MDString::get(Context, StringRef(&x[0], 3)); EXPECT_NE(s1, s2); } @@ -35,8 +37,8 @@ TEST(MDStringTest, CreateSame) { char x[4] = { 'a', 'b', 'c', 'X' }; char y[4] = { 'a', 'b', 'c', 'Y' }; - MDString *s1 = MDString::get(&x[0], &x[3]); - MDString *s2 = MDString::get(&y[0], &y[3]); + MDString *s1 = MDString::get(Context, StringRef(&x[0], 3)); + MDString *s2 = MDString::get(Context, StringRef(&y[0], 3)); EXPECT_EQ(s1, s2); } @@ -44,11 +46,12 @@ TEST(MDStringTest, CreateSame) { TEST(MDStringTest, PrintingSimple) { char *str = new char[13]; strncpy(str, "testing 1 2 3", 13); - MDString *s = MDString::get(str, str+13); + MDString *s = MDString::get(Context, StringRef(str, 13)); strncpy(str, "aaaaaaaaaaaaa", 13); delete[] str; - std::ostringstream oss; + std::string Str; + raw_string_ostream oss(Str); s->print(oss); EXPECT_STREQ("metadata !\"testing 1 2 3\"", oss.str().c_str()); } @@ -56,8 +59,9 @@ TEST(MDStringTest, PrintingSimple) { // Test printing of MDString with non-printable characters. TEST(MDStringTest, PrintingComplex) { char str[5] = {0, '\n', '"', '\\', -1}; - MDString *s = MDString::get(str+0, str+5); - std::ostringstream oss; + MDString *s = MDString::get(Context, StringRef(str+0, 5)); + std::string Str; + raw_string_ostream oss(Str); s->print(oss); EXPECT_STREQ("metadata !\"\\00\\0A\\22\\5C\\FF\"", oss.str().c_str()); } @@ -67,21 +71,25 @@ TEST(MDNodeTest, Simple) { char x[3] = { 'a', 'b', 'c' }; char y[3] = { '1', '2', '3' }; - MDString *s1 = MDString::get(&x[0], &x[3]); - MDString *s2 = MDString::get(&y[0], &y[3]); - ConstantInt *CI = ConstantInt::get(APInt(8, 0)); + MDString *s1 = MDString::get(Context, StringRef(&x[0], 3)); + MDString *s2 = MDString::get(Context, StringRef(&y[0], 3)); + ConstantInt *CI = ConstantInt::get(getGlobalContext(), APInt(8, 0)); std::vector<Value *> V; V.push_back(s1); V.push_back(CI); V.push_back(s2); - MDNode *n1 = MDNode::get(&V[0], 3); + MDNode *n1 = MDNode::get(Context, &V[0], 3); Value *const c1 = n1; - MDNode *n2 = MDNode::get(&c1, 1); - MDNode *n3 = MDNode::get(&V[0], 3); + MDNode *n2 = MDNode::get(Context, &c1, 1); + MDNode *n3 = MDNode::get(Context, &V[0], 3); EXPECT_NE(n1, n2); +#ifdef ENABLE_MDNODE_UNIQUING EXPECT_EQ(n1, n3); +#else + (void) n3; +#endif EXPECT_EQ(3u, n1->getNumElements()); EXPECT_EQ(s1, n1->getElement(0)); @@ -91,49 +99,55 @@ TEST(MDNodeTest, Simple) { EXPECT_EQ(1u, n2->getNumElements()); EXPECT_EQ(n1, n2->getElement(0)); - std::ostringstream oss1, oss2; - n1->print(oss1); - n2->print(oss2); - EXPECT_STREQ("metadata !{metadata !\"abc\", i8 0, metadata !\"123\"}", - oss1.str().c_str()); - EXPECT_STREQ("metadata !{metadata !{metadata !\"abc\", i8 0, " - "metadata !\"123\"}}", - oss2.str().c_str()); -} - -TEST(MDNodeTest, RAUW) { - Constant *C = ConstantInt::get(Type::Int32Ty, 1); - Instruction *I = new BitCastInst(C, Type::Int32Ty); - - Value *const V1 = I; - MDNode *n1 = MDNode::get(&V1, 1); - WeakVH wn1 = n1; - - Value *const V2 = C; - MDNode *n2 = MDNode::get(&V2, 1); - WeakVH wn2 = n2; - - EXPECT_NE(wn1, wn2); - - I->replaceAllUsesWith(C); - - EXPECT_EQ(wn1, wn2); + std::string Str; + raw_string_ostream oss(Str); + n1->print(oss); + EXPECT_STREQ("!0 = metadata !{metadata !\"abc\", i8 0, metadata !\"123\"}\n", + oss.str().c_str()); + Str.clear(); + n2->print(oss); + EXPECT_STREQ("!0 = metadata !{metadata !1}\n" + "!1 = metadata !{metadata !\"abc\", i8 0, metadata !\"123\"}\n", + oss.str().c_str()); } TEST(MDNodeTest, Delete) { - Constant *C = ConstantInt::get(Type::Int32Ty, 1); - Instruction *I = new BitCastInst(C, Type::Int32Ty); + Constant *C = ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 1); + Instruction *I = new BitCastInst(C, Type::getInt32Ty(getGlobalContext())); Value *const V = I; - MDNode *n = MDNode::get(&V, 1); + MDNode *n = MDNode::get(Context, &V, 1); WeakVH wvh = n; EXPECT_EQ(n, wvh); delete I; - std::ostringstream oss; + std::string Str; + raw_string_ostream oss(Str); wvh->print(oss); - EXPECT_STREQ("metadata !{null}", oss.str().c_str()); + EXPECT_STREQ("!0 = metadata !{null}\n", oss.str().c_str()); +} + +TEST(NamedMDNodeTest, Search) { + Constant *C = ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 1); + Constant *C2 = ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 2); + + Value *const V = C; + Value *const V2 = C2; + MDNode *n = MDNode::get(Context, &V, 1); + MDNode *n2 = MDNode::get(Context, &V2, 1); + + MetadataBase *Nodes[2] = { n, n2 }; + + Module *M = new Module("MyModule", getGlobalContext()); + const char *Name = "llvm.NMD1"; + NamedMDNode *NMD = NamedMDNode::Create(getGlobalContext(), Name, &Nodes[0], 2, M); + std::string Str; + raw_string_ostream oss(Str); + NMD->print(oss); + EXPECT_STREQ("!llvm.NMD1 = !{!0, !1}\n!0 = metadata !{i32 1}\n" + "!1 = metadata !{i32 2}\n", + oss.str().c_str()); } } diff --git a/unittests/VMCore/PassManagerTest.cpp b/unittests/VMCore/PassManagerTest.cpp index 8122e2c..cb8f9eb 100644 --- a/unittests/VMCore/PassManagerTest.cpp +++ b/unittests/VMCore/PassManagerTest.cpp @@ -154,7 +154,7 @@ namespace llvm { struct CGPass : public PassTest<CallGraph, CallGraphSCCPass> { public: - virtual bool runOnSCC(const std::vector<CallGraphNode*> &SCMM) { + virtual bool runOnSCC(std::vector<CallGraphNode*> &SCMM) { EXPECT_TRUE(getAnalysisIfAvailable<TargetData>()); run(); return false; @@ -272,7 +272,7 @@ namespace llvm { char OnTheFlyTest::ID=0; TEST(PassManager, RunOnce) { - Module M("test-once", *new LLVMContext()); + Module M("test-once", getGlobalContext()); struct ModuleNDNM *mNDNM = new ModuleNDNM(); struct ModuleDNM *mDNM = new ModuleDNM(); struct ModuleNDM *mNDM = new ModuleNDM(); @@ -296,7 +296,7 @@ namespace llvm { } TEST(PassManager, ReRun) { - Module M("test-rerun", *new LLVMContext()); + Module M("test-rerun", getGlobalContext()); struct ModuleNDNM *mNDNM = new ModuleNDNM(); struct ModuleDNM *mDNM = new ModuleDNM(); struct ModuleNDM *mNDM = new ModuleNDM(); @@ -387,7 +387,7 @@ namespace llvm { Module* makeLLVMModule() { // Module Construction - Module* mod = new Module("test-mem", *new LLVMContext()); + Module* mod = new Module("test-mem", getGlobalContext()); mod->setDataLayout("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-" "a0:0:64-s0:64:64-f80:128:128"); @@ -396,14 +396,14 @@ namespace llvm { // Type Definitions std::vector<const Type*>FuncTy_0_args; FunctionType* FuncTy_0 = FunctionType::get( - /*Result=*/IntegerType::get(32), + /*Result=*/IntegerType::get(getGlobalContext(), 32), /*Params=*/FuncTy_0_args, /*isVarArg=*/false); std::vector<const Type*>FuncTy_2_args; - FuncTy_2_args.push_back(IntegerType::get(1)); + FuncTy_2_args.push_back(IntegerType::get(getGlobalContext(), 1)); FunctionType* FuncTy_2 = FunctionType::get( - /*Result=*/Type::VoidTy, + /*Result=*/Type::getVoidTy(getGlobalContext()), /*Params=*/FuncTy_2_args, /*isVarArg=*/false); @@ -454,7 +454,7 @@ namespace llvm { // Function: test1 (func_test1) { - BasicBlock* label_entry = BasicBlock::Create("entry",func_test1,0); + BasicBlock* label_entry = BasicBlock::Create(getGlobalContext(), "entry",func_test1,0); // Block entry (label_entry) CallInst* int32_3 = CallInst::Create(func_test2, "", label_entry); @@ -462,14 +462,14 @@ namespace llvm { int32_3->setTailCall(false);AttrListPtr int32_3_PAL; int32_3->setAttributes(int32_3_PAL); - ReturnInst::Create(int32_3, label_entry); + ReturnInst::Create(getGlobalContext(), int32_3, label_entry); } // Function: test2 (func_test2) { - BasicBlock* label_entry_5 = BasicBlock::Create("entry",func_test2,0); + BasicBlock* label_entry_5 = BasicBlock::Create(getGlobalContext(), "entry",func_test2,0); // Block entry (label_entry_5) CallInst* int32_6 = CallInst::Create(func_test3, "", label_entry_5); @@ -477,14 +477,14 @@ namespace llvm { int32_6->setTailCall(false);AttrListPtr int32_6_PAL; int32_6->setAttributes(int32_6_PAL); - ReturnInst::Create(int32_6, label_entry_5); + ReturnInst::Create(getGlobalContext(), int32_6, label_entry_5); } // Function: test3 (func_test3) { - BasicBlock* label_entry_8 = BasicBlock::Create("entry",func_test3,0); + BasicBlock* label_entry_8 = BasicBlock::Create(getGlobalContext(), "entry",func_test3,0); // Block entry (label_entry_8) CallInst* int32_9 = CallInst::Create(func_test1, "", label_entry_8); @@ -492,7 +492,7 @@ namespace llvm { int32_9->setTailCall(false);AttrListPtr int32_9_PAL; int32_9->setAttributes(int32_9_PAL); - ReturnInst::Create(int32_9, label_entry_8); + ReturnInst::Create(getGlobalContext(), int32_9, label_entry_8); } @@ -502,10 +502,10 @@ namespace llvm { Value* int1_f = args++; int1_f->setName("f"); - BasicBlock* label_entry_11 = BasicBlock::Create("entry",func_test4,0); - BasicBlock* label_bb = BasicBlock::Create("bb",func_test4,0); - BasicBlock* label_bb1 = BasicBlock::Create("bb1",func_test4,0); - BasicBlock* label_return = BasicBlock::Create("return",func_test4,0); + BasicBlock* label_entry_11 = BasicBlock::Create(getGlobalContext(), "entry",func_test4,0); + BasicBlock* label_bb = BasicBlock::Create(getGlobalContext(), "bb",func_test4,0); + BasicBlock* label_bb1 = BasicBlock::Create(getGlobalContext(), "bb1",func_test4,0); + BasicBlock* label_return = BasicBlock::Create(getGlobalContext(), "return",func_test4,0); // Block entry (label_entry_11) BranchInst::Create(label_bb, label_entry_11); @@ -517,7 +517,7 @@ namespace llvm { BranchInst::Create(label_bb1, label_return, int1_f, label_bb1); // Block return (label_return) - ReturnInst::Create(label_return); + ReturnInst::Create(getGlobalContext(), label_return); } return mod; |