Add tests for SEA IR types infrastructure.
type_data_test.cc: Tests the type store used to record info on
the types of results from instructions.
type_inferecen_visitor_test.cc: Tests type merging and related
operations.
Android.gtest.mk: Included new tests.
type_inference_visitor.h/.cc: Marked function as const
and made public.
scoped_hashtable_test.cc: Included full header path in #include.
Change-Id: I868461dcaed1e7f75db15958b83a3db7e17f6a64
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index e069d88..4d1e18d 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -60,7 +60,9 @@
ifeq ($(ART_SEA_IR_MODE),true)
TEST_COMMON_SRC_FILES += \
- compiler/utils/scoped_hashtable_test.cc
+ compiler/utils/scoped_hashtable_test.cc \
+ compiler/sea_ir/types/type_data_test.cc \
+ compiler/sea_ir/types/type_inference_visitor_test.cc
endif
TEST_TARGET_SRC_FILES := \
diff --git a/compiler/sea_ir/types/type_data_test.cc b/compiler/sea_ir/types/type_data_test.cc
new file mode 100644
index 0000000..a66ebce
--- /dev/null
+++ b/compiler/sea_ir/types/type_data_test.cc
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common_test.h"
+#include "sea_ir/types/types.h"
+
+namespace sea_ir {
+
+class TypeDataTest : public art::CommonTest {
+};
+
+TEST_F(TypeDataTest, Basics) {
+ TypeData td;
+ art::verifier::RegTypeCache type_cache(false);
+ int first_instruction_id = 1;
+ int second_instruction_id = 3;
+ EXPECT_TRUE(NULL == td.FindTypeOf(first_instruction_id));
+ const Type* int_type = &type_cache.Integer();
+ const Type* byte_type = &type_cache.Byte();
+ td.SetTypeOf(first_instruction_id, int_type);
+ EXPECT_TRUE(int_type == td.FindTypeOf(first_instruction_id));
+ EXPECT_TRUE(NULL == td.FindTypeOf(second_instruction_id));
+ td.SetTypeOf(second_instruction_id, byte_type);
+ EXPECT_TRUE(int_type == td.FindTypeOf(first_instruction_id));
+ EXPECT_TRUE(byte_type == td.FindTypeOf(second_instruction_id));
+}
+
+} // namespace art
diff --git a/compiler/sea_ir/types/type_inference_visitor.cc b/compiler/sea_ir/types/type_inference_visitor.cc
index 30537bd..3da2fc1 100644
--- a/compiler/sea_ir/types/type_inference_visitor.cc
+++ b/compiler/sea_ir/types/type_inference_visitor.cc
@@ -62,7 +62,8 @@
crt_type_.push_back(result_type);
}
-std::vector<const Type*> TypeInferenceVisitor::GetOperandTypes(InstructionNode* instruction) {
+std::vector<const Type*> TypeInferenceVisitor::GetOperandTypes(
+ InstructionNode* instruction) const {
std::vector<InstructionNode*> sources = instruction->GetSSAProducers();
std::vector<const Type*> types_to_merge;
for (std::vector<InstructionNode*>::const_iterator cit = sources.begin(); cit != sources.end();
diff --git a/compiler/sea_ir/types/type_inference_visitor.h b/compiler/sea_ir/types/type_inference_visitor.h
index be1ad43..200b9f0 100644
--- a/compiler/sea_ir/types/type_inference_visitor.h
+++ b/compiler/sea_ir/types/type_inference_visitor.h
@@ -58,7 +58,7 @@
const Type* MergeTypes(std::vector<const Type*>& types) const;
const Type* MergeTypes(const Type* t1, const Type* t2) const;
-
+ std::vector<const Type*> GetOperandTypes(InstructionNode* instruction) const;
const Type* GetType() {
// TODO: Currently multiple defined types are not supported.
if (crt_type_.size()>0) {
@@ -74,9 +74,6 @@
TypeData* type_data_;
art::verifier::RegTypeCache* type_cache_;
std::vector<const Type*> crt_type_; // Stored temporarily between two calls to Visit.
-
- private:
- std::vector<const Type*> GetOperandTypes(InstructionNode* instruction);
};
} // namespace sea_ir
diff --git a/compiler/sea_ir/types/type_inference_visitor_test.cc b/compiler/sea_ir/types/type_inference_visitor_test.cc
new file mode 100644
index 0000000..8a249eb
--- /dev/null
+++ b/compiler/sea_ir/types/type_inference_visitor_test.cc
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common_test.h"
+#include "sea_ir/types/type_inference_visitor.h"
+#include "sea_ir/ir/sea.h"
+
+namespace sea_ir {
+
+class TestInstructionNode:public InstructionNode {
+ public:
+ explicit TestInstructionNode(std::vector<InstructionNode*> prods): InstructionNode(NULL),
+ producers_(prods) { }
+ std::vector<InstructionNode*> GetSSAProducers() {
+ return producers_;
+ }
+ protected:
+ std::vector<InstructionNode*> producers_;
+};
+
+class TypeInferenceVisitorTest : public art::CommonTest {
+};
+
+TEST_F(TypeInferenceVisitorTest, MergeIntWithByte) {
+ TypeData td;
+ art::verifier::RegTypeCache type_cache(false);
+ TypeInferenceVisitor tiv(NULL, &td, &type_cache);
+ const Type* int_type = &type_cache.Integer();
+ const Type* byte_type = &type_cache.Byte();
+ const Type* ib_type = tiv.MergeTypes(int_type, byte_type);
+ const Type* bi_type = tiv.MergeTypes(byte_type, int_type);
+ EXPECT_TRUE(ib_type == int_type);
+ EXPECT_TRUE(bi_type == int_type);
+}
+
+TEST_F(TypeInferenceVisitorTest, MergeIntWithShort) {
+ TypeData td;
+ art::verifier::RegTypeCache type_cache(false);
+ TypeInferenceVisitor tiv(NULL, &td, &type_cache);
+ const Type* int_type = &type_cache.Integer();
+ const Type* short_type = &type_cache.Short();
+ const Type* is_type = tiv.MergeTypes(int_type, short_type);
+ const Type* si_type = tiv.MergeTypes(short_type, int_type);
+ EXPECT_TRUE(is_type == int_type);
+ EXPECT_TRUE(si_type == int_type);
+}
+
+TEST_F(TypeInferenceVisitorTest, MergeMultipleInts) {
+ int N = 10; // Number of types to merge.
+ TypeData td;
+ art::verifier::RegTypeCache type_cache(false);
+ TypeInferenceVisitor tiv(NULL, &td, &type_cache);
+ std::vector<const Type*> types;
+ for (int i = 0; i < N; i++) {
+ const Type* new_type = &type_cache.Integer();
+ types.push_back(new_type);
+ }
+ const Type* merged_type = tiv.MergeTypes(types);
+ EXPECT_TRUE(merged_type == &type_cache.Integer());
+}
+
+TEST_F(TypeInferenceVisitorTest, MergeMultipleShorts) {
+ int N = 10; // Number of types to merge.
+ TypeData td;
+ art::verifier::RegTypeCache type_cache(false);
+ TypeInferenceVisitor tiv(NULL, &td, &type_cache);
+ std::vector<const Type*> types;
+ for (int i = 0; i < N; i++) {
+ const Type* new_type = &type_cache.Short();
+ types.push_back(new_type);
+ }
+ const Type* merged_type = tiv.MergeTypes(types);
+ EXPECT_TRUE(merged_type == &type_cache.Short());
+}
+
+TEST_F(TypeInferenceVisitorTest, MergeMultipleIntsWithShorts) {
+ int N = 10; // Number of types to merge.
+ TypeData td;
+ art::verifier::RegTypeCache type_cache(false);
+ TypeInferenceVisitor tiv(NULL, &td, &type_cache);
+ std::vector<const Type*> types;
+ for (int i = 0; i < N; i++) {
+ const Type* short_type = &type_cache.Short();
+ const Type* int_type = &type_cache.Integer();
+ types.push_back(short_type);
+ types.push_back(int_type);
+ }
+ const Type* merged_type = tiv.MergeTypes(types);
+ EXPECT_TRUE(merged_type == &type_cache.Integer());
+}
+
+TEST_F(TypeInferenceVisitorTest, GetOperandTypes) {
+ int N = 10; // Number of types to merge.
+ TypeData td;
+ art::verifier::RegTypeCache type_cache(false);
+ TypeInferenceVisitor tiv(NULL, &td, &type_cache);
+ std::vector<const Type*> types;
+ std::vector<InstructionNode*> preds;
+ for (int i = 0; i < N; i++) {
+ const Type* short_type = &type_cache.Short();
+ const Type* int_type = &type_cache.Integer();
+ TestInstructionNode* short_inst =
+ new TestInstructionNode(std::vector<InstructionNode*>());
+ TestInstructionNode* int_inst =
+ new TestInstructionNode(std::vector<InstructionNode*>());
+ preds.push_back(short_inst);
+ preds.push_back(int_inst);
+ td.SetTypeOf(short_inst->Id(), short_type);
+ td.SetTypeOf(int_inst->Id(), int_type);
+ types.push_back(short_type);
+ types.push_back(int_type);
+ }
+ TestInstructionNode* inst_to_test = new TestInstructionNode(preds);
+ std::vector<const Type*> result = tiv.GetOperandTypes(inst_to_test);
+ EXPECT_TRUE(result.size() == types.size());
+ EXPECT_TRUE(true == std::equal(types.begin(), types.begin() + 2, result.begin()));
+}
+
+
+} // namespace art
diff --git a/compiler/utils/scoped_hashtable_test.cc b/compiler/utils/scoped_hashtable_test.cc
index d5f9f7d..68608f0 100644
--- a/compiler/utils/scoped_hashtable_test.cc
+++ b/compiler/utils/scoped_hashtable_test.cc
@@ -15,7 +15,7 @@
*/
#include "common_test.h"
-#include "scoped_hashtable.h"
+#include "utils/scoped_hashtable.h"
using utils::ScopedHashtable;