Remove files not part of quick, portable or iceland builds.
These files aren't built and are bit rotting. Removing to relieve
maintenance burden.
Change-Id: I6f86d22538370a7e7d31e6f4d6a6e62243c9fece
diff --git a/src/greenland/arm/arm_codegen_machine.cc b/src/greenland/arm/arm_codegen_machine.cc
deleted file mode 100644
index c85aeed..0000000
--- a/src/greenland/arm/arm_codegen_machine.cc
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2012 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 "arm_codegen_machine.h"
-
-#include "greenland/target_registry.h"
-
-namespace art {
-namespace greenland {
-
-ARMCodeGenMachine::ARMCodeGenMachine() : TargetCodeGenMachine() {
-}
-
-ARMCodeGenMachine::~ARMCodeGenMachine() {
-}
-
-void InitializeARMCodeGenMachine() {
- RegisterTargetCodeGenMachine<ARMCodeGenMachine> X(kArm);
- RegisterTargetCodeGenMachine<ARMCodeGenMachine> Y(kThumb2);
-}
-
-} // namespace greenland
-} // namespace art
diff --git a/src/greenland/arm/arm_codegen_machine.h b/src/greenland/arm/arm_codegen_machine.h
deleted file mode 100644
index 8639417..0000000
--- a/src/greenland/arm/arm_codegen_machine.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#ifndef ART_SRC_GREENLAND_ARM_CODEGEN_MACHINE_H_
-#define ART_SRC_GREENLAND_ARM_CODEGEN_MACHINE_H_
-
-#include "greenland/target_codegen_machine.h"
-
-namespace art {
-namespace greenland {
-
-class ARMCodeGenMachine : public TargetCodeGenMachine {
- private:
-
- public:
- ARMCodeGenMachine();
- virtual ~ARMCodeGenMachine();
-
- virtual TargetLIREmitter* CreateLIREmitter() {
- return NULL;
- }
-
- virtual const TargetDataLayout* GetDataLayout() const {
- return NULL;
- }
-
- virtual const TargetLIRInfo* GetLIRInfo() const {
- return NULL;
- }
-
- virtual const TargetRegisterInfo* GetRegisterInfo() const {
- return NULL;
- }
-
- virtual const char* GetConditionCodeName(unsigned cond) const {
- return NULL;
- }
-
- virtual TargetLIRBuilder* CreateLIRBuilder() {
- return NULL;
- }
-
- virtual RegisterAllocator* GetRegisterAllocator() {
- return NULL;
- }
-
- virtual TargetAssembler* GetAssembler() {
- return NULL;
- }
-
- virtual std::string PrettyTargeteLIR(const LIR& lir) const {
- return "";
- }
-};
-
-} // namespace greenland
-} // namespace art
-
-#endif // ART_SRC_GREENLAND_ARM_CODEGEN_MACHINE_H_
diff --git a/src/greenland/arm/arm_invoke_stub_compiler.cc b/src/greenland/arm/arm_invoke_stub_compiler.cc
deleted file mode 100644
index 2360ed7..0000000
--- a/src/greenland/arm/arm_invoke_stub_compiler.cc
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2011 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 "asm_support.h"
-#include "compiled_method.h"
-#include "compiler.h"
-#include "greenland/target_registry.h"
-#include "oat/utils/arm/assembler_arm.h"
-#include "oat/utils/assembler.h"
-#include "object.h"
-
-#include <stdint.h>
-
-#include <algorithm>
-
-using namespace art;
-using namespace art::arm;
-
-namespace {
-
-// Creates a function which invokes a managed method with an array of
-// arguments.
-//
-// At the time of call, the environment looks something like this:
-//
-// R0 = method pointer
-// R1 = receiver pointer or NULL for static methods
-// R2 = (managed) thread pointer
-// R3 = argument array or NULL for no argument methods
-// [SP] = JValue* result or NULL for void returns
-//
-// As the JNI call has already transitioned the thread into the
-// "running" state the remaining responsibilities of this routine are
-// to save the native register value and restore the managed thread
-// register and transfer arguments from the array into register and on
-// the stack, if needed. On return, the thread register must be
-// shuffled and the return value must be store into the result JValue.
-CompiledInvokeStub* CreateInvokeStub(bool is_static, const char* shorty, uint32_t shorty_len) {
- UniquePtr<ArmAssembler> assembler(down_cast<ArmAssembler*>(Assembler::Create(kArm)));
-#define __ assembler->
- size_t num_arg_array_bytes = NumArgArrayBytes(shorty, shorty_len);
- // Size of frame = spill of R4,R9/LR + Method* + possible receiver + arg array size
- // Note, space is left in the frame to flush arguments in registers back to out locations.
- size_t unpadded_frame_size = (4 * kPointerSize) +
- (is_static ? 0 : kPointerSize) +
- num_arg_array_bytes;
- size_t frame_size = RoundUp(unpadded_frame_size, kStackAlignment);
-
- // Spill R4,R9 and LR
- RegList save = (1 << R9) | (1 << R4);
- __ PushList(save | (1 << LR));
-
- // Move the managed thread pointer into R9.
- __ mov(R9, ShifterOperand(R2));
-
- // Reset R4 to suspend check interval
- __ LoadImmediate(R4, SUSPEND_CHECK_INTERVAL);
-
- // Move frame down for arguments less 3 pushed values above
- __ AddConstant(SP, -frame_size + (3 * kPointerSize));
-
- // Can either get 3 or 2 arguments into registers
- size_t reg_bytes = (is_static ? 3 : 2) * kPointerSize;
- // Bytes passed by stack
- size_t stack_bytes;
- if (num_arg_array_bytes > reg_bytes) {
- stack_bytes = num_arg_array_bytes - reg_bytes;
- } else {
- stack_bytes = 0;
- reg_bytes = num_arg_array_bytes;
- }
-
- // Method* at bottom of frame is null thereby terminating managed stack crawls
- __ LoadImmediate(IP, 0, AL);
- __ StoreToOffset(kStoreWord, IP, SP, 0);
-
- // Copy values onto the stack.
- size_t src_offset = 0;
- size_t dst_offset = (is_static ? 1 : 2) * kPointerSize;
- for (size_t i = 1; i < shorty_len; ++i) {
- switch (shorty[i]) {
- case 'D':
- case 'J':
- // Move both pointers 64 bits.
- __ LoadFromOffset(kLoadWord, IP, R3, src_offset);
- src_offset += kPointerSize;
- __ StoreToOffset(kStoreWord, IP, SP, dst_offset);
- dst_offset += kPointerSize;
-
- __ LoadFromOffset(kLoadWord, IP, R3, src_offset);
- src_offset += kPointerSize;
- __ StoreToOffset(kStoreWord, IP, SP, dst_offset);
- dst_offset += kPointerSize;
- break;
- default:
- // Move the source pointer sizeof(JValue) and the destination pointer 32 bits.
- __ LoadFromOffset(kLoadWord, IP, R3, src_offset);
- src_offset += sizeof(JValue);
- __ StoreToOffset(kStoreWord, IP, SP, dst_offset);
- dst_offset += kPointerSize;
- break;
- }
- }
-
- // Move all the register arguments into place.
- dst_offset = (is_static ? 1 : 2) * kPointerSize;
- if (is_static) {
- if (reg_bytes > 0 && num_arg_array_bytes > 0) {
- __ LoadFromOffset(kLoadWord, R1, SP, dst_offset + 0);
- if (reg_bytes > 4 && num_arg_array_bytes > 4) {
- __ LoadFromOffset(kLoadWord, R2, SP, dst_offset + 4);
- if (reg_bytes > 8 && num_arg_array_bytes > 8) {
- __ LoadFromOffset(kLoadWord, R3, SP, dst_offset + 8);
- }
- }
- }
- } else {
- if (reg_bytes > 0 && num_arg_array_bytes > 0) {
- __ LoadFromOffset(kLoadWord, R2, SP, dst_offset + 0);
- if (reg_bytes > 4 && num_arg_array_bytes > 4) {
- __ LoadFromOffset(kLoadWord, R3, SP, dst_offset + 4);
- }
- }
- }
-
- // Load the code pointer we are about to call.
- __ LoadFromOffset(kLoadWord, IP, R0, AbstractMethod::GetCodeOffset().Int32Value());
-
- // Do the call.
- __ blx(IP);
-
- // If the method returns a value, store it to the result pointer.
- if (shorty[0] != 'V') {
- // Load the result JValue pointer of the stub caller's out args.
- __ LoadFromOffset(kLoadWord, IP, SP, frame_size);
- StoreOperandType type = (shorty[0] == 'J' || shorty[0] == 'D') ? kStoreWordPair : kStoreWord;
- __ StoreToOffset(type, R0, IP, 0);
- }
-
- // Remove the frame less the spilled R4, R9 and LR
- __ AddConstant(SP, frame_size - (3 * kPointerSize));
-
- // Pop R4, R9 and the LR into PC
- __ PopList(save | (1 << PC));
- // TODO: store native_entry in the stub table
- std::vector<uint8_t> code(assembler->CodeSize());
- MemoryRegion region(&code[0], code.size());
- assembler->FinalizeInstructions(region);
- return new CompiledInvokeStub(code);
-#undef __
-}
-
-CompiledInvokeStub* ARMInvokeStubCompiler(art::Compiler& /*compiler*/,
- bool is_static,
- const char* shorty,
- uint32_t shorty_len) {
- return CreateInvokeStub(is_static, shorty, shorty_len);
-}
-
-} // anonymous namespace
-
-namespace art {
-namespace greenland {
-
-void InitializeARMInvokeStubCompiler() {
- TargetRegistry::RegisterInvokeStubCompiler(kArm, ARMInvokeStubCompiler);
- TargetRegistry::RegisterInvokeStubCompiler(kThumb2, ARMInvokeStubCompiler);
-}
-
-} // namespace greenland
-} // namespace art
diff --git a/src/greenland/dalvik_reg.cc b/src/greenland/dalvik_reg.cc
deleted file mode 100644
index a97a646..0000000
--- a/src/greenland/dalvik_reg.cc
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright (C) 2012 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 "dalvik_reg.h"
-
-#include "ir_builder.h"
-#include "dex_lang.h"
-
-namespace art {
-namespace greenland {
-
-//----------------------------------------------------------------------------
-// Dalvik Register
-//----------------------------------------------------------------------------
-
-DalvikReg::DalvikReg(DexLang& dex_lang, unsigned reg_idx)
-: dex_lang_(dex_lang), irb_(dex_lang.GetIRBuilder()),
- reg_idx_(reg_idx), reg_32_(NULL), reg_64_(NULL), reg_obj_(NULL) {
-}
-
-DalvikReg::~DalvikReg() {
-}
-
-llvm::Type* DalvikReg::GetRegCategoryEquivSizeTy(IRBuilder& irb, RegCategory reg_cat) {
- switch (reg_cat) {
- case kRegCat1nr: return irb.GetJIntTy();
- case kRegCat2: return irb.GetJLongTy();
- case kRegObject: return irb.GetJObjectTy();
- default:
- LOG(FATAL) << "Unknown register category: " << reg_cat;
- return NULL;
- }
-}
-
-char DalvikReg::GetRegCategoryNamePrefix(RegCategory reg_cat) {
- switch (reg_cat) {
- case kRegCat1nr: return 'r';
- case kRegCat2: return 'w';
- case kRegObject: return 'p';
- default:
- LOG(FATAL) << "Unknown register category: " << reg_cat;
- return '\0';
- }
-}
-
-inline llvm::Value* DalvikReg::RegCat1SExt(llvm::Value* value) {
- return irb_.CreateSExt(value, irb_.GetJIntTy());
-}
-
-inline llvm::Value* DalvikReg::RegCat1ZExt(llvm::Value* value) {
- return irb_.CreateZExt(value, irb_.GetJIntTy());
-}
-
-inline llvm::Value* DalvikReg::RegCat1Trunc(llvm::Value* value,
- llvm::Type* ty) {
- return irb_.CreateTrunc(value, ty);
-}
-
-llvm::Value* DalvikReg::GetValue(JType jty, JTypeSpace space) {
- DCHECK_NE(jty, kVoid) << "Dalvik register will never be void type";
-
- llvm::Value* value = NULL;
- switch (space) {
- case kReg:
- case kField:
- value = irb_.CreateLoad(GetAddr(jty));
- break;
-
- case kAccurate:
- case kArray:
- switch (jty) {
- case kVoid:
- LOG(FATAL) << "Dalvik register with void type has no value";
- return NULL;
-
- case kBoolean:
- case kChar:
- case kByte:
- case kShort:
- // NOTE: In array type space, boolean is truncated from i32 to i8, while
- // in accurate type space, boolean is truncated from i32 to i1.
- // For the other cases, array type space is equal to accurate type space.
- value = RegCat1Trunc(irb_.CreateLoad(GetAddr(jty)),
- irb_.GetJType(jty, space));
- break;
-
- case kInt:
- case kLong:
- case kFloat:
- case kDouble:
- case kObject:
- value = irb_.CreateLoad(GetAddr(jty));
- break;
-
- default:
- LOG(FATAL) << "Unknown java type: " << jty;
- return NULL;
- }
- break;
-
- default:
- LOG(FATAL) << "Couldn't GetValue of JType " << jty;
- return NULL;
- }
-
- if (jty == kFloat || jty == kDouble) {
- value = irb_.CreateBitCast(value, irb_.GetJType(jty, space));
- }
- return value;
-}
-
-void DalvikReg::SetValue(JType jty, JTypeSpace space, llvm::Value* value) {
- DCHECK_NE(jty, kVoid) << "Dalvik register will never be void type";
-
- if (jty == kFloat || jty == kDouble) {
- value = irb_.CreateBitCast(value, irb_.GetJType(jty, kReg));
- }
-
- switch (space) {
- case kReg:
- case kField:
- irb_.CreateStore(value, GetAddr(jty));
- return;
-
- case kAccurate:
- case kArray:
- switch (jty) {
- case kVoid:
- break;
-
- case kBoolean:
- case kChar:
- // NOTE: In accurate type space, we have to zero extend boolean from
- // i1 to i32, and char from i16 to i32. In array type space, we have
- // to zero extend boolean from i8 to i32, and char from i16 to i32.
- irb_.CreateStore(RegCat1ZExt(value), GetAddr(jty));
- break;
-
- case kByte:
- case kShort:
- // NOTE: In accurate type space, we have to signed extend byte from
- // i8 to i32, and short from i16 to i32. In array type space, we have
- // to sign extend byte from i8 to i32, and short from i16 to i32.
- irb_.CreateStore(RegCat1SExt(value), GetAddr(jty));
- break;
-
- case kInt:
- case kLong:
- case kFloat:
- case kDouble:
- case kObject:
- irb_.CreateStore(value, GetAddr(jty));
- break;
-
- default:
- LOG(FATAL) << "Unknown java type: " << jty;
- }
- }
-}
-
-llvm::Value* DalvikReg::GetAddr(JType jty) {
- switch (GetRegCategoryFromJType(jty)) {
- case kRegCat1nr:
- if (reg_32_ == NULL) {
- reg_32_ = dex_lang_.AllocateDalvikReg(kRegCat1nr, reg_idx_);
- }
- return reg_32_;
-
- case kRegCat2:
- if (reg_64_ == NULL) {
- reg_64_ = dex_lang_.AllocateDalvikReg(kRegCat2, reg_idx_);
- }
- return reg_64_;
-
- case kRegObject:
- if (reg_obj_ == NULL) {
- reg_obj_ = dex_lang_.AllocateDalvikReg(kRegObject, reg_idx_);
- }
- return reg_obj_;
-
- default:
- LOG(FATAL) << "Unexpected register category: "
- << GetRegCategoryFromJType(jty);
- return NULL;
- }
-}
-
-} // namespace greenland
-} // namespace art
diff --git a/src/greenland/dalvik_reg.h b/src/greenland/dalvik_reg.h
deleted file mode 100644
index 83157f3..0000000
--- a/src/greenland/dalvik_reg.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#ifndef ART_SRC_GREENLAND_DALVIK_REG_H_
-#define ART_SRC_GREENLAND_DALVIK_REG_H_
-
-#include "backend_types.h"
-
-#include <stdint.h>
-#include <string>
-
-namespace llvm {
- class Type;
- class Value;
-}
-
-namespace art {
-namespace greenland {
-
-class IRBuilder;
-class DexLang;
-
-class DalvikReg {
- public:
- static llvm::Type* GetRegCategoryEquivSizeTy(IRBuilder& irb, RegCategory reg_cat);
-
- static char GetRegCategoryNamePrefix(RegCategory reg_cat);
-
- DalvikReg(DexLang& dex_lang, unsigned reg_idx);
-
- ~DalvikReg();
-
- llvm::Value* GetValue(JType jty, JTypeSpace space);
-
- llvm::Value* GetValue(char shorty, JTypeSpace space) {
- return GetValue(GetJTypeFromShorty(shorty), space);
- }
-
- void SetValue(JType jty, JTypeSpace space, llvm::Value* value);
-
- void SetValue(char shorty, JTypeSpace space, llvm::Value* value) {
- return SetValue(GetJTypeFromShorty(shorty), space, value);
- }
-
- private:
- llvm::Value* GetAddr(JType jty);
-
- llvm::Value* RegCat1SExt(llvm::Value* value);
- llvm::Value* RegCat1ZExt(llvm::Value* value);
-
- llvm::Value* RegCat1Trunc(llvm::Value* value, llvm::Type* ty);
-
- DexLang& dex_lang_;
- IRBuilder& irb_;
-
- unsigned reg_idx_;
-
- llvm::Value* reg_32_;
- llvm::Value* reg_64_;
- llvm::Value* reg_obj_;
-};
-
-} // namespace greenland
-} // namespace art
-
-#endif // ART_SRC_GREENLAND_DALVIK_REG_H_
diff --git a/src/greenland/dex_lang.cc b/src/greenland/dex_lang.cc
deleted file mode 100644
index f0ecdc6..0000000
--- a/src/greenland/dex_lang.cc
+++ /dev/null
@@ -1,4353 +0,0 @@
-/*
- * Copyright (C) 2012 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 "dex_lang.h"
-
-#include "intrinsic_helper.h"
-
-#include "greenland/inferred_reg_category_map.h"
-#include "object.h" // FIXME: include this in oat_compilation_unit.h
-#include "oat_compilation_unit.h"
-#include "stl_util.h"
-#include "stringprintf.h"
-#include "verifier/method_verifier.h"
-
-#include <llvm/Analysis/Passes.h>
-#include <llvm/Analysis/Verifier.h>
-#include <llvm/BasicBlock.h>
-#include <llvm/Function.h>
-#include <llvm/Module.h>
-#include <llvm/PassManager.h>
-#include <llvm/Support/InstIterator.h>
-#include <llvm/Transforms/Scalar.h>
-
-namespace art {
-namespace greenland {
-
-//----------------------------------------------------------------------------
-// DexLang::Context
-//----------------------------------------------------------------------------
-DexLang::Context::Context(llvm::Module& module)
- : module_(module), intrinsic_helper_(NULL) {
- // Initalize the DexLang intrinsics
- intrinsic_helper_ = new IntrinsicHelper(GetLLVMContext(), module_);
- return;
-}
-
-DexLang::Context::~Context() {
- delete intrinsic_helper_;
- return;
-}
-
-//----------------------------------------------------------------------------
-// Constructor, Destructor and APIs
-//----------------------------------------------------------------------------
-DexLang::DexLang(DexLang::Context& context, Compiler& compiler,
- OatCompilationUnit& cunit)
- : dex_lang_ctx_(context), compiler_(compiler), cunit_(cunit),
- dex_file_(cunit.GetDexFile()), code_item_(cunit.GetCodeItem()),
- method_idx_(cunit.GetDexMethodIndex()),
- context_(context.GetLLVMContext()), module_(context.GetOutputModule()),
- intrinsic_helper_(context.GetIntrinsicHelper()),
- irb_(context.GetLLVMContext(), context.GetOutputModule(),
- context.GetIntrinsicHelper()),
- func_(NULL), reg_alloc_bb_(NULL), arg_reg_init_bb_(NULL),
- basic_blocks_(cunit.GetCodeItem()->insns_size_in_code_units_),
- retval_reg_(NULL),
- num_shadow_frame_entries_(0),
- reg_to_shadow_frame_index_(code_item_->registers_size_, -1),
- landing_pads_bb_(cunit.GetCodeItem()->tries_size_, NULL),
- exception_unwind_bb_(NULL), cur_try_item_offset(-1)
-{
- if (cunit.GetCodeItem()->tries_size_ > 0) {
- cur_try_item_offset = 0;
- }
- return;
-}
-
-DexLang::~DexLang() {
- delete retval_reg_;
- return;
-}
-
-llvm::Function* DexLang::Build() {
- if (!CreateFunction() ||
- !EmitPrologue() ||
- !EmitInstructions() ||
- !EmitPrologueAllcaShadowFrame() ||
- !EmitPrologueLinkBasicBlocks() ||
- !PrettyLayoutExceptionBasicBlocks() ||
- !VerifyFunction() ||
- // CompilerLLVM has its own optimizer
-#ifndef ART_USE_LLVM_COMPILER
- !OptimizeFunction() ||
- !RemoveRedundantPendingExceptionChecks() ||
-#endif
- 0) {
- return NULL;
- }
-
- return func_;
-}
-
-llvm::Value* DexLang::AllocateDalvikReg(RegCategory cat, unsigned reg_idx) {
- // Get reg_type and reg_name from DalvikReg
- llvm::Type* reg_type = DalvikReg::GetRegCategoryEquivSizeTy(irb_, cat);
- std::string reg_name;
-
-#if !defined(NDEBUG)
- StringAppendF(®_name, "%c%u",
- DalvikReg::GetRegCategoryNamePrefix(cat), reg_idx);
-#endif
-
- // Save current IR builder insert point
- DCHECK(reg_alloc_bb_ != NULL);
- llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
- irb_.SetInsertPoint(reg_alloc_bb_);
-
- // Alloca
- llvm::Value* reg_addr = irb_.CreateAlloca(reg_type, 0, reg_name);
-
- // Restore IRBuilder insert point
- irb_.restoreIP(irb_ip_original);
-
- DCHECK_NE(reg_addr, static_cast<llvm::Value*>(NULL));
- return reg_addr;
-}
-
-//----------------------------------------------------------------------------
-// Basic Block Helper Functions
-//----------------------------------------------------------------------------
-llvm::BasicBlock* DexLang::GetBasicBlock(unsigned dex_pc) {
- DCHECK(dex_pc < code_item_->insns_size_in_code_units_);
-
- llvm::BasicBlock* basic_block = basic_blocks_[dex_pc];
-
- if (!basic_block) {
- basic_block = CreateBasicBlockWithDexPC(dex_pc);
- basic_blocks_[dex_pc] = basic_block;
- }
-
- return basic_block;
-}
-
-llvm::BasicBlock* DexLang::CreateBasicBlockWithDexPC(unsigned dex_pc,
- const char* postfix) {
- std::string name;
-
- if (postfix) {
- StringAppendF(&name, "B%04x.%s", dex_pc, postfix);
- } else {
- StringAppendF(&name, "B%04x", dex_pc);
- }
-
- return llvm::BasicBlock::Create(context_, name, func_);
-}
-
-llvm::BasicBlock* DexLang::GetNextBasicBlock(unsigned dex_pc) {
- const Instruction* insn = Instruction::At(code_item_->insns_ + dex_pc);
- return GetBasicBlock(dex_pc + insn->SizeInCodeUnits());
-}
-
-//----------------------------------------------------------------------------
-// Exception Handling
-//----------------------------------------------------------------------------
-int32_t DexLang::GetTryItemOffset(unsigned dex_pc) {
- if (cur_try_item_offset >= 0) {
- // Search over the try item.
- do {
- const DexFile::TryItem* ti =
- DexFile::GetTryItems(*code_item_, cur_try_item_offset);
- if (dex_pc < ti->start_addr_) {
- return -1;
- }
-
- if (dex_pc < (ti->start_addr_ + ti->insn_count_)) {
- return cur_try_item_offset;
- }
-
- cur_try_item_offset++;
- } while (cur_try_item_offset < code_item_->tries_size_);
-
- // Search to the end of try items and Cannot find any try item corresponding
- // to the dex_pc.
- cur_try_item_offset = -1;
- }
-
- return cur_try_item_offset;
-}
-
-llvm::BasicBlock* DexLang::GetLandingPadBasicBlock(unsigned dex_pc) {
- // Find the try item for this address in this method
- int32_t ti_offset = GetTryItemOffset(dex_pc);
-
- if (ti_offset == -1) {
- return NULL; // No landing pad is available for this address.
- }
-
- // Check for the existing landing pad basic block
- DCHECK_GT(landing_pads_bb_.size(), static_cast<size_t>(ti_offset));
- llvm::BasicBlock* block_lpad = landing_pads_bb_[ti_offset];
-
- if (block_lpad != NULL) {
- // We have generated landing pad for this try item already. Return the
- // same basic block.
- return block_lpad;
- }
-
- // Get try item from code item
- const DexFile::TryItem* ti = DexFile::GetTryItems(*code_item_, ti_offset);
-
- std::string lpadname;
-
-#ifndef NDEBUG
- StringAppendF(&lpadname, "lpad%d_%04x_to_%04x",
- ti_offset, ti->start_addr_, ti->handler_off_);
-#endif
-
- // Create landing pad basic block
- block_lpad = llvm::BasicBlock::Create(context_, lpadname, func_);
-
- // Change IRBuilder insert point
- llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
- irb_.SetInsertPoint(block_lpad);
-
- // Find catch block with matching type
- llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
-
- // Find catch block with matching type
- llvm::Value* ti_offset_value = irb_.getInt32(ti_offset);
-
- llvm::Value* catch_handler_index_value =
- EmitInvokeIntrinsic2NoThrow(IntrinsicHelper::FindCatchBlock,
- method_object_addr, ti_offset_value);
-
- // Switch instruction (Go to unwind basic block by default)
- llvm::SwitchInst* sw =
- irb_.CreateSwitch(catch_handler_index_value, GetUnwindBasicBlock());
-
- // Cases with matched catch block
- CatchHandlerIterator iter(*code_item_, ti->start_addr_);
-
- for (uint32_t c = 0; iter.HasNext(); iter.Next(), ++c) {
- sw->addCase(irb_.getInt32(c), GetBasicBlock(iter.GetHandlerAddress()));
- }
-
- // Restore the orignal insert point for IRBuilder
- irb_.restoreIP(irb_ip_original);
-
- // Cache this landing pad
- landing_pads_bb_[ti_offset] = block_lpad;
-
- return block_lpad;
-}
-
-llvm::BasicBlock* DexLang::GetUnwindBasicBlock() {
- // Check the existing unwinding baisc block block
- if (exception_unwind_bb_ != NULL) {
- return exception_unwind_bb_;
- }
-
- // Create new basic block for unwinding
- exception_unwind_bb_ =
- llvm::BasicBlock::Create(context_, "exception_unwind", func_);
-
- // Change IRBuilder insert point
- llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
- irb_.SetInsertPoint(exception_unwind_bb_);
-
- // Pop the shadow frame
- EmitPopShadowFrame();
-
- // Emit the code to return default value (zero) for the given return type.
- char ret_shorty = cunit_.GetShorty()[0];
- if (ret_shorty == 'V') {
- irb_.CreateRetVoid();
- } else {
- irb_.CreateRet(irb_.GetJZero(ret_shorty));
- }
-
- // Restore the orignal insert point for IRBuilder
- irb_.restoreIP(irb_ip_original);
-
- return exception_unwind_bb_;
-}
-
-void DexLang::EmitBranchExceptionLandingPad(unsigned dex_pc) {
- if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
- irb_.CreateBr(lpad);
- } else {
- irb_.CreateBr(GetUnwindBasicBlock());
- }
-}
-
-void DexLang::EmitGuard_DivZeroException(unsigned dex_pc,
- llvm::Value* denominator,
- JType op_jty) {
- DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
-
- llvm::Constant* zero = irb_.GetJZero(op_jty);
-
- llvm::Value* equal_zero = irb_.CreateICmpEQ(denominator, zero);
-
- llvm::BasicBlock* block_exception = CreateBasicBlockWithDexPC(dex_pc, "div0");
-
- llvm::BasicBlock* block_continue = CreateBasicBlockWithDexPC(dex_pc, "cont");
-
- irb_.CreateCondBr(equal_zero, block_exception, block_continue);
-
- irb_.SetInsertPoint(block_exception);
- EmitInvokeIntrinsic(dex_pc, false, IntrinsicHelper::ThrowDivZeroException);
-
- irb_.SetInsertPoint(block_continue);
- return;
-}
-
-void DexLang::EmitGuard_NullPointerException(unsigned dex_pc,
- llvm::Value* object) {
- llvm::Value* equal_null = irb_.CreateICmpEQ(object, irb_.GetJNull());
-
- llvm::BasicBlock* block_exception =
- CreateBasicBlockWithDexPC(dex_pc, "nullp");
-
- llvm::BasicBlock* block_continue =
- CreateBasicBlockWithDexPC(dex_pc, "cont");
-
- irb_.CreateCondBr(equal_null, block_exception, block_continue);
-
- irb_.SetInsertPoint(block_exception);
-
- EmitInvokeIntrinsic(dex_pc, false, IntrinsicHelper::ThrowNullPointerException,
- irb_.getInt32(dex_pc));
-
- irb_.SetInsertPoint(block_continue);
- return;
-}
-
-void
-DexLang::EmitGuard_ArrayIndexOutOfBoundsException(unsigned dex_pc,
- llvm::Value* array,
- llvm::Value* index) {
- llvm::Value* array_len = EmitLoadArrayLength(array);
-
- llvm::Value* cmp = irb_.CreateICmpUGE(index, array_len);
-
- llvm::BasicBlock* block_exception =
- CreateBasicBlockWithDexPC(dex_pc, "overflow");
-
- llvm::BasicBlock* block_continue =
- CreateBasicBlockWithDexPC(dex_pc, "cont");
-
- irb_.CreateCondBr(cmp, block_exception, block_continue);
-
- irb_.SetInsertPoint(block_exception);
-
- EmitInvokeIntrinsic2(dex_pc, false, IntrinsicHelper::ThrowIndexOutOfBounds,
- index, array_len);
-
- irb_.SetInsertPoint(block_continue);
- return;
-}
-
-void DexLang::EmitGuard_ArrayException(unsigned dex_pc,
- llvm::Value* array, llvm::Value* index) {
- EmitGuard_NullPointerException(dex_pc, array);
- EmitGuard_ArrayIndexOutOfBoundsException(dex_pc, array, index);
-}
-
-void DexLang::EmitGuard_ExceptionLandingPad(unsigned dex_pc, bool can_skip_unwind) {
- llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc);
- Instruction const* insn = Instruction::At(code_item_->insns_ + dex_pc);
- if (lpad == NULL && can_skip_unwind &&
- IsInstructionDirectToReturn(dex_pc + insn->SizeInCodeUnits())) {
- return;
- }
-
- llvm::Value* exception_pending =
- EmitInvokeIntrinsicNoThrow(IntrinsicHelper::IsExceptionPending);
-
- llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
-
- if (lpad) {
- irb_.CreateCondBr(exception_pending, lpad, block_cont);
- } else {
- irb_.CreateCondBr(exception_pending, GetUnwindBasicBlock(), block_cont);
- }
-
- irb_.SetInsertPoint(block_cont);
- return;
-}
-
-//----------------------------------------------------------------------------
-// Garbage Collection Safe Point
-//----------------------------------------------------------------------------
-void DexLang::EmitGuard_GarbageCollectionSuspend() {
- if (!method_info_.has_invoke) {
- return;
- }
-
- llvm::Value* thread_object_addr = EmitGetCurrentThread();
- EmitInvokeIntrinsicNoThrow(IntrinsicHelper::TestSuspend, thread_object_addr);
- return;
-}
-
-//----------------------------------------------------------------------------
-// Register Helper Functions
-//----------------------------------------------------------------------------
-llvm::Value* DexLang::EmitLoadDalvikReg(unsigned reg_idx, JType jty, JTypeSpace space) {
- return regs_[reg_idx]->GetValue(jty, space);
-}
-
-llvm::Value* DexLang::EmitLoadDalvikReg(unsigned reg_idx, char shorty, JTypeSpace space) {
- return EmitLoadDalvikReg(reg_idx, GetJTypeFromShorty(shorty), space);
-}
-
-void DexLang::EmitStoreDalvikReg(unsigned reg_idx, JType jty,
- JTypeSpace space, llvm::Value* new_value) {
- regs_[reg_idx]->SetValue(jty, space, new_value);
- if (jty == kObject && reg_to_shadow_frame_index_[reg_idx] != -1) {
- EmitInvokeIntrinsic2NoThrow(IntrinsicHelper::SetShadowFrameEntry,
- new_value, irb_.getInt32(reg_to_shadow_frame_index_[reg_idx]));
- }
-}
-
-void DexLang::EmitStoreDalvikReg(unsigned reg_idx, char shorty,
- JTypeSpace space, llvm::Value* new_value) {
- EmitStoreDalvikReg(reg_idx, GetJTypeFromShorty(shorty), space, new_value);
-}
-
-llvm::Value* DexLang::EmitLoadDalvikRetValReg(JType jty, JTypeSpace space) {
- return retval_reg_->GetValue(jty, space);
-}
-
-llvm::Value* DexLang::EmitLoadDalvikRetValReg(char shorty, JTypeSpace space) {
- return EmitLoadDalvikRetValReg(GetJTypeFromShorty(shorty), space);
-}
-
-void DexLang::EmitStoreDalvikRetValReg(JType jty, JTypeSpace space,
- llvm::Value* new_value) {
- retval_reg_->SetValue(jty, space, new_value);
-}
-
-void DexLang::EmitStoreDalvikRetValReg(char shorty, JTypeSpace space,
- llvm::Value* new_value) {
- EmitStoreDalvikRetValReg(GetJTypeFromShorty(shorty), space, new_value);
-}
-
-//----------------------------------------------------------------------------
-// Shadow Frame
-//----------------------------------------------------------------------------
-void DexLang::EmitUpdateDexPC(unsigned dex_pc) {
- if (!method_info_.need_shadow_frame) {
- return;
- }
- EmitInvokeIntrinsicNoThrow(IntrinsicHelper::UpdateDexPC,
- irb_.getInt32(dex_pc));
- return;
-}
-
-void DexLang::EmitPopShadowFrame() {
- if (!method_info_.need_shadow_frame) {
- return;
- }
- EmitInvokeIntrinsicNoThrow(IntrinsicHelper::PopShadowFrame);
- return;
-}
-
-//----------------------------------------------------------------------------
-// Code Generation
-//----------------------------------------------------------------------------
-bool DexLang::CreateFunction() {
- std::string func_name(PrettyMethod(method_idx_, *dex_file_,
- /* with_signature */true));
- llvm::FunctionType* func_type = GetFunctionType();
-
- if (func_type == NULL) {
- return false;
- }
-
- func_ = llvm::Function::Create(func_type, llvm::Function::ExternalLinkage,
- func_name, &module_);
-
- llvm::Function::arg_iterator arg_iter(func_->arg_begin());
- llvm::Function::arg_iterator arg_end(func_->arg_end());
-
- arg_iter->setName("method");
- ++arg_iter;
-
- if (!cunit_.IsStatic()) {
- DCHECK_NE(arg_iter, arg_end);
- arg_iter->setName("this");
- ++arg_iter;
- }
-
- for (unsigned i = 0; arg_iter != arg_end; ++i, ++arg_iter) {
- arg_iter->setName(StringPrintf("a%u", i));
- }
-
- return true;
-}
-
-llvm::FunctionType* DexLang::GetFunctionType() {
- uint32_t shorty_size;
- const char* shorty = cunit_.GetShorty(&shorty_size);
- CHECK_GE(shorty_size, 1u);
-
- // Get return type
- llvm::Type* ret_type = irb_.GetJType(shorty[0], kAccurate);
-
- // Get argument type
- std::vector<llvm::Type*> args_type;
-
- // method object
- args_type.push_back(irb_.GetJMethodTy());
-
- if (!cunit_.IsStatic()) {
- // The first argument to non-static method is "this" object pointer
- args_type.push_back(irb_.GetJObjectTy());
- }
-
- for (uint32_t i = 1; i < shorty_size; ++i) {
- args_type.push_back(irb_.GetJType(shorty[i], kAccurate));
- }
-
- return llvm::FunctionType::get(ret_type, args_type, false);
-}
-
-bool DexLang::EmitPrologue() {
- reg_alloc_bb_ = llvm::BasicBlock::Create(context_, "prologue.alloca", func_);
-
- arg_reg_init_bb_ =
- llvm::BasicBlock::Create(context_, "prologue.arginit", func_);
-
- ComputeMethodInfo();
-
- // Create register array
- const unsigned num_regs = code_item_->registers_size_;
- for (unsigned i = 0; i < num_regs; i++) {
- regs_.push_back(new DalvikReg(*this, i));
- }
-
- // Register hold return value from invoke and filled-new-array
- retval_reg_ = new DalvikReg(*this, num_regs);
-
- // Store argument to dalvik register
- irb_.SetInsertPoint(arg_reg_init_bb_);
- // TODO: Don't emit this at init_bb
- // Garbage collection safe-point
- EmitGuard_GarbageCollectionSuspend();
- if (!EmitPrologueAssignArgRegister()) {
- return false;
- }
-
- irb_.CreateBr(GetBasicBlock(0));
-
- // DalvikReg index to shadow frame index
- num_shadow_frame_entries_ = 0;
- uint16_t arg_reg_start = code_item_->registers_size_ - code_item_->ins_size_;
- if (method_info_.need_shadow_frame_entry) {
- for (uint32_t i = 0, num_of_regs = code_item_->registers_size_; i < num_of_regs; ++i) {
- if (i >= arg_reg_start && !method_info_.set_to_another_object[i]) {
- // If we don't set argument registers to another object, we don't need the shadow frame
- // entry for it. Because the arguments must have been in the caller's shadow frame.
- continue;
- }
-
- if (IsRegCanBeObject(i)) {
- reg_to_shadow_frame_index_[i] = num_shadow_frame_entries_++;
- }
- }
- }
-
- return true;
-}
-
-bool DexLang::EmitPrologueAssignArgRegister() {
- llvm::Function::arg_iterator arg_iter(func_->arg_begin());
-
- const unsigned num_regs = code_item_->registers_size_;
- const unsigned num_ins = code_item_->ins_size_;
- unsigned reg_idx = num_regs - num_ins;
-
- uint32_t shorty_size;
- const char* shorty = cunit_.GetShorty(&shorty_size);
-
- // skip method object
- ++arg_iter;
-
- if (!cunit_.IsStatic()) {
- // The first argument to non-static method is "this" object pointer.
- EmitStoreDalvikReg(reg_idx, kObject, kAccurate, arg_iter);
- arg_iter++;
- reg_idx++;
- }
-
- for (unsigned i = 1; i < shorty_size; i++, arg_iter++) {
- JType jty = GetJTypeFromShorty(shorty[i]);
- EmitStoreDalvikReg(reg_idx, jty, kAccurate, arg_iter);
- reg_idx++;
-
- if (GetRegCategoryFromJType(jty) == kRegCat2) {
- // Wide types
- reg_idx++;
- }
- }
-
- DCHECK_EQ(arg_iter, func_->arg_end());
- DCHECK_EQ(reg_idx, num_regs);
-
- return true;
-}
-
-bool DexLang::EmitPrologueAllcaShadowFrame() {
- if (!method_info_.need_shadow_frame) {
- return true;
- }
-
- // Save current IR builder insert point
- llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
-
- irb_.SetInsertPoint(reg_alloc_bb_);
- EmitInvokeIntrinsicNoThrow(IntrinsicHelper::AllocaShadowFrame,
- irb_.getInt32(num_shadow_frame_entries_));
-
- // Restore IRBuilder insert point
- irb_.restoreIP(irb_ip_original);
-
- return true;
-}
-
-bool DexLang::EmitPrologueLinkBasicBlocks() {
- irb_.SetInsertPoint(reg_alloc_bb_);
- irb_.CreateBr(arg_reg_init_bb_);
- return true;
-}
-
-bool DexLang::PrettyLayoutExceptionBasicBlocks() {
- llvm::BasicBlock* last_non_exception_bb = &func_->back();
- DCHECK(last_non_exception_bb != NULL);
-
- if (last_non_exception_bb == exception_unwind_bb_) {
- // There's no other expcetion landing pads therefore the only exception
- // basic blocks is for exception unwinding which is already the tail basic
- // block of the function
- return true;
- }
-
- if (exception_unwind_bb_ != NULL) {
- exception_unwind_bb_->moveAfter(last_non_exception_bb);
- }
-
- for (std::vector<llvm::BasicBlock*>::reverse_iterator
- landing_pads_bb_iter = landing_pads_bb_.rbegin(),
- landing_pads_bb_end = landing_pads_bb_.rend();
- landing_pads_bb_iter != landing_pads_bb_end; landing_pads_bb_iter++) {
- llvm::BasicBlock* landing_pads_bb = *landing_pads_bb_iter;
- if (landing_pads_bb == NULL) {
- continue;
- }
-
- // Move the successors (the cache handlers) first
- llvm::TerminatorInst* inst = landing_pads_bb->getTerminator();
- CHECK(inst != NULL);
-
- for (unsigned i = 0, e = inst->getNumSuccessors(); i != e; i++) {
- llvm::BasicBlock* catch_handler = inst->getSuccessor(i);
- // One of the catch handler is the unwind basic block which is settled
- // down earlier
- if (catch_handler != exception_unwind_bb_) {
- catch_handler->moveAfter(last_non_exception_bb);
- }
- }
- if (last_non_exception_bb != landing_pads_bb) {
- landing_pads_bb->moveAfter(last_non_exception_bb);
- }
- }
-
- return true;
-}
-
-bool DexLang::VerifyFunction() {
- if (llvm::verifyFunction(*func_, llvm::PrintMessageAction)) {
- LOG(INFO) << "Verification failed on function: "
- << PrettyMethod(method_idx_, *dex_file_);
- return false;
- }
- return true;
-}
-
-bool DexLang::OptimizeFunction() {
- // Add optimization pass
- llvm::FunctionPassManager fpm(&module_);
-
- fpm.add(llvm::createTypeBasedAliasAnalysisPass());
- fpm.add(llvm::createBasicAliasAnalysisPass());
-
- // Perform simple optimizations first to enable the later optimization passes
- // running fast
- {
- fpm.add(llvm::createCFGSimplificationPass());
-
- // mem2reg
- fpm.add(llvm::createPromoteMemoryToRegisterPass());
-
- // Remove redundant instructions
- fpm.add(llvm::createInstructionSimplifierPass());
-
- // Fast CSE
- fpm.add(llvm::createEarlyCSEPass());
- fpm.add(llvm::createCorrelatedValuePropagationPass());
-
- // 4 + (x + 5) -> x + (4 + 5)
- fpm.add(llvm::createReassociatePass());
-
- // Clean up
- fpm.add(llvm::createCFGSimplificationPass()); // Merge & remove BBs
- fpm.add(llvm::createInstructionCombiningPass());// Clean up after everything
- }
-
- {
- // SCCP - Sparse conditional constant propagation
- fpm.add(llvm::createSCCPPass());
-
- // Global value numbering and redundant load elimination
- fpm.add(llvm::createGVNPass());
-
- // Clean up
- fpm.add(llvm::createCFGSimplificationPass()); // Merge & remove BBs
- fpm.add(llvm::createInstructionCombiningPass());// Clean up after everything
- }
-
- {
- // Reorders basic blocks to increase the number of fall-through conditional
- // branches
- fpm.add(llvm::createBlockPlacementPass());
-
- // Clean up
- fpm.add(llvm::createCFGSimplificationPass()); // Merge & remove BBs
- }
-
- // DexLang doesn't use static branch prediction in the mean time
- //fpm.add(llvm::createLowerExpectIntrinsicPass());
- {
- // Constant propagation
- fpm.add(llvm::createConstantPropagationPass());
-
- // Clean up
- fpm.add(llvm::createCFGSimplificationPass()); // Merge & remove BBs
- fpm.add(llvm::createInstructionCombiningPass());// Clean up after everything
- }
-
- {
- // Dead code elimination
- fpm.add(llvm::createDeadCodeEliminationPass());
- fpm.add(llvm::createDeadStoreEliminationPass());
- fpm.add(llvm::createAggressiveDCEPass());
-
- // Do constant propagation again
- fpm.add(llvm::createConstantPropagationPass());
-
- // Clean up
- fpm.add(llvm::createCFGSimplificationPass()); // Merge & remove BBs
- fpm.add(llvm::createInstructionCombiningPass());// Clean up after everything
- }
-
- // Run the per-function optimization
- fpm.doInitialization();
- fpm.run(*func_);
- fpm.doFinalization();
-
- return true;
-}
-
-bool DexLang::RemoveRedundantPendingExceptionChecks() {
-#if 0
- const llvm::Function* exception_checking_function =
- irb_.GetIntrinsics(IntrinsicHelper::IsExceptionPending);
-
- std::vector<llvm::Instruction*> work_list;
-
- unsigned num_removed = 0;
-
- for (llvm::inst_iterator i = llvm::inst_begin(func_),
- e = llvm::inst_end(func_); i != e; ++i) {
- if (llvm::CallInst* call_inst = llvm::dyn_cast<llvm::CallInst>(&*i)) {
- if (call_inst->getCalledFunction() != exception_checking_function) {
- continue;
- }
- }
- }
-
- num_removed = work_list.size();
-
- for (std::vector<llvm::Instruction*>::iterator inst_iter = work_list.begin(),
- inst_end = work_list.end(); inst_iter != inst_end; inst_iter++) {
- llvm::Instruction* inst = *inst_iter;
- if (!inst->use_empty()) {
- inst->replaceAllUsesWith(irb_.getFalse());
- }
- inst->eraseFromParent();
- }
-
- LOG(INFO) << num_removed << " redundant pending exception check removed.";
-#endif
-
- return true;
-}
-
-//----------------------------------------------------------------------------
-// Emit* Helper Functions
-//----------------------------------------------------------------------------
-llvm::Value* DexLang::EmitLoadMethodObjectAddr() {
- return func_->arg_begin();
-}
-
-llvm::Value* DexLang::EmitGetCurrentThread() {
- return EmitInvokeIntrinsicNoThrow(IntrinsicHelper::GetCurrentThread);
-}
-
-void DexLang::EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr) {
- EmitInvokeIntrinsic2NoThrow(IntrinsicHelper::MarkGCCard, value, target_addr);
- return;
-}
-
-llvm::Value*
-DexLang::EmitInvokeIntrinsicNoThrow(IntrinsicHelper::IntrinsicId intr_id,
- llvm::ArrayRef<llvm::Value*> args) {
- DCHECK(IntrinsicHelper::GetAttr(intr_id) & IntrinsicHelper::kAttrNoThrow);
-
- llvm::Function* intr = intrinsic_helper_.GetIntrinsicFunction(intr_id);
- return ((args.empty()) ? irb_.CreateCall(intr) : irb_.CreateCall(intr, args));
-}
-
-llvm::Value* DexLang::EmitInvokeIntrinsic(unsigned dex_pc, bool can_skip_unwind,
- IntrinsicHelper::IntrinsicId intr_id,
- llvm::ArrayRef<llvm::Value*> args) {
- llvm::Function* intr = intrinsic_helper_.GetIntrinsicFunction(intr_id);
- unsigned intr_attr = IntrinsicHelper::GetAttr(intr_id);
- DCHECK(!(intr_attr & IntrinsicHelper::kAttrNoThrow));
-
- // Setup PC before invocation when the intrinsics may generate the exception
- EmitUpdateDexPC(dex_pc);
-
- llvm::Value* ret_val = ((args.empty()) ? irb_.CreateCall(intr) :
- irb_.CreateCall(intr, args));
-
- if (intr_attr & IntrinsicHelper::kAttrDoThrow) {
- // Directly branch to exception landingpad when the intrinsic is known to
- // throw exception always
- EmitBranchExceptionLandingPad(dex_pc);
- } else {
- EmitGuard_ExceptionLandingPad(dex_pc, can_skip_unwind);
- }
-
- return ret_val;
-}
-
-InferredRegCategoryMap const* DexLang::GetInferredRegCategoryMap() {
- Compiler::MethodReference mref(dex_file_, method_idx_);
-
- InferredRegCategoryMap const* map =
- verifier::MethodVerifier::GetInferredRegCategoryMap(mref);
-
- CHECK_NE(map, static_cast<InferredRegCategoryMap*>(NULL));
-
- return map;
-}
-
-RegCategory DexLang::GetInferredRegCategory(unsigned dex_pc,
- unsigned reg_idx) {
- InferredRegCategoryMap const* map = GetInferredRegCategoryMap();
-
- return map->GetRegCategory(dex_pc, reg_idx);
-}
-
-bool DexLang::IsRegCanBeObject(unsigned reg_idx) {
- InferredRegCategoryMap const* map = GetInferredRegCategoryMap();
-
- return map->IsRegCanBeObject(reg_idx);
-}
-
-llvm::Value* DexLang::EmitLoadConstantClass(unsigned dex_pc,
- uint32_t type_idx) {
- llvm::Value* type_idx_value = irb_.getInt32(type_idx);
-
- llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
-
- llvm::Value* thread_object_addr = EmitGetCurrentThread();
-
- if (!compiler_.CanAccessTypeWithoutChecks(method_idx_, *dex_file_, type_idx)) {
- return EmitInvokeIntrinsic3(dex_pc, false, IntrinsicHelper::InitializeTypeAndVerifyAccess,
- type_idx_value, method_object_addr,
- thread_object_addr);
- } else {
- // Try to load the class (type) object from the dex cache
- llvm::Value* type_object_addr =
- EmitInvokeIntrinsicNoThrow(IntrinsicHelper::LoadTypeFromDexCache,
- type_idx_value);
-
- if (compiler_.CanAssumeTypeIsPresentInDexCache(*dex_file_, type_idx)) {
- return type_object_addr;
- }
-
- llvm::BasicBlock* block_original = irb_.GetInsertBlock();
-
- // Test whether class (type) object is in the dex cache or not
- llvm::Value* equal_null =
- irb_.CreateICmpEQ(type_object_addr, irb_.GetJNull());
-
- llvm::BasicBlock* block_cont =
- CreateBasicBlockWithDexPC(dex_pc, "cont");
-
- llvm::BasicBlock* block_load_class =
- CreateBasicBlockWithDexPC(dex_pc, "load_class");
-
- irb_.CreateCondBr(equal_null, block_load_class, block_cont);
-
- // Failback routine to load the class object
- irb_.SetInsertPoint(block_load_class);
-
- llvm::Value* loaded_type_object_addr =
- EmitInvokeIntrinsic3(dex_pc, false, IntrinsicHelper::InitializeType,
- type_idx_value, method_object_addr,
- thread_object_addr);
-
- llvm::BasicBlock* block_after_load_class = irb_.GetInsertBlock();
-
- irb_.CreateBr(block_cont);
-
- // Now the class object must be loaded
- irb_.SetInsertPoint(block_cont);
-
- llvm::PHINode* phi = irb_.CreatePHI(irb_.GetJObjectTy(), 2);
-
- phi->addIncoming(type_object_addr, block_original);
- phi->addIncoming(loaded_type_object_addr, block_after_load_class);
-
- return phi;
- }
-}
-
-llvm::Value* DexLang::EmitLoadArrayLength(llvm::Value* array) {
- // Load array length
- return EmitInvokeIntrinsicNoThrow(IntrinsicHelper::ArrayLength, array);
-}
-
-llvm::Value* DexLang::EmitAllocNewArray(unsigned dex_pc, int32_t length,
- uint32_t type_idx,
- bool is_filled_new_array) {
- bool skip_access_check = compiler_.CanAccessTypeWithoutChecks(method_idx_,
- *dex_file_,
- type_idx);
-
- llvm::Value* array_length_value;
- IntrinsicHelper::IntrinsicId intrinsic;
-
- // Select intrinsic and load the array length
- if (is_filled_new_array) {
- intrinsic =
- skip_access_check ? IntrinsicHelper::CheckAndAllocArray :
- IntrinsicHelper::CheckAndAllocArrayWithAccessCheck;
- array_length_value = irb_.getInt32(length);
- } else {
- intrinsic =
- skip_access_check ? IntrinsicHelper::AllocArray :
- IntrinsicHelper::AllocArrayWithAccessCheck;
- array_length_value = EmitLoadDalvikReg(length, kInt, kAccurate);
- }
-
- llvm::Constant* type_index_value = irb_.getInt32(type_idx);
-
- llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
-
- llvm::Value* thread_object_addr = EmitGetCurrentThread();
-
- llvm::Value* array_addr = EmitInvokeIntrinsic4(dex_pc, false, intrinsic,
- type_index_value,
- method_object_addr,
- array_length_value,
- thread_object_addr);
-
- return array_addr;
-}
-
-llvm::Value* DexLang::EmitCompareResultSelection(llvm::Value* cmp_eq,
- llvm::Value* cmp_lt) {
-
- llvm::Constant* zero = irb_.GetJInt(0);
- llvm::Constant* pos1 = irb_.GetJInt(1);
- llvm::Constant* neg1 = irb_.GetJInt(-1);
-
- llvm::Value* result_lt = irb_.CreateSelect(cmp_lt, neg1, pos1);
- llvm::Value* result_eq = irb_.CreateSelect(cmp_eq, zero, result_lt);
-
- return result_eq;
-}
-
-llvm::Value*
-DexLang::EmitLoadStaticStorage(unsigned dex_pc, unsigned type_idx) {
- llvm::BasicBlock* block_load_static =
- CreateBasicBlockWithDexPC(dex_pc, "load_static");
-
- llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
-
- llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
-
- // Load static storage from dex cache
- llvm::Value* storage_object_addr =
- EmitInvokeIntrinsicNoThrow(IntrinsicHelper::LoadClassSSBFromDexCache,
- type_idx_value);
-
- llvm::BasicBlock* block_original = irb_.GetInsertBlock();
-
- // Test: Is the static storage of this class initialized?
- llvm::Value* equal_null =
- irb_.CreateICmpEQ(storage_object_addr, irb_.GetJNull());
-
- irb_.CreateCondBr(equal_null, block_load_static, block_cont);
-
- // Failback routine to load the class object
- irb_.SetInsertPoint(block_load_static);
-
- llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
-
- llvm::Value* thread_object_addr = EmitGetCurrentThread();
-
- llvm::Value* loaded_storage_object_addr =
- EmitInvokeIntrinsic3(dex_pc, false, IntrinsicHelper::InitializeAndLoadClassSSB,
- type_idx_value, method_object_addr,
- thread_object_addr);
-
- llvm::BasicBlock* block_after_load_static = irb_.GetInsertBlock();
-
- irb_.CreateBr(block_cont);
-
- // Now the class object must be loaded
- irb_.SetInsertPoint(block_cont);
-
- llvm::PHINode* phi = irb_.CreatePHI(irb_.GetJObjectTy(), 2);
-
- phi->addIncoming(storage_object_addr, block_original);
- phi->addIncoming(loaded_storage_object_addr, block_after_load_static);
-
- return phi;
-}
-
-llvm::Value* DexLang::EmitConditionResult(llvm::Value* lhs, llvm::Value* rhs,
- CondBranchKind cond) {
- switch (cond) {
- case kCondBranch_EQ: {
- return irb_.CreateICmpEQ(lhs, rhs);
- }
- case kCondBranch_NE: {
- return irb_.CreateICmpNE(lhs, rhs);
- }
- case kCondBranch_LT: {
- return irb_.CreateICmpSLT(lhs, rhs);
- }
- case kCondBranch_GE: {
- return irb_.CreateICmpSGE(lhs, rhs);
- }
- case kCondBranch_GT: {
- return irb_.CreateICmpSGT(lhs, rhs);
- }
- case kCondBranch_LE: {
- return irb_.CreateICmpSLE(lhs, rhs);
- }
- default: {
- // Unreachable
- LOG(FATAL) << "Unknown conditional branch kind: " << cond;
- break;
- }
- }
- return NULL;
-}
-
-llvm::Value* DexLang::EmitIntArithmResultComputation(unsigned dex_pc,
- llvm::Value* lhs,
- llvm::Value* rhs,
- IntArithmKind arithm,
- JType op_jty) {
- DCHECK((op_jty == kInt) || (op_jty == kLong)) << op_jty;
-
- switch (arithm) {
- case kIntArithm_Add: {
- return irb_.CreateAdd(lhs, rhs);
- }
- case kIntArithm_Sub: {
- return irb_.CreateSub(lhs, rhs);
- }
- case kIntArithm_Mul: {
- return irb_.CreateMul(lhs, rhs);
- }
- case kIntArithm_Div:
- case kIntArithm_Rem: {
- return EmitIntDivRemResultComputation(dex_pc, lhs, rhs, arithm, op_jty);
- }
- case kIntArithm_And: {
- return irb_.CreateAnd(lhs, rhs);
- }
- case kIntArithm_Or: {
- return irb_.CreateOr(lhs, rhs);
- }
- case kIntArithm_Xor: {
- return irb_.CreateXor(lhs, rhs);
- }
- default: {
- LOG(FATAL) << "Unknown integer arithmetic kind: " << arithm;
- break;
- }
- }
- return NULL;
-}
-
-llvm::Value*
-DexLang::EmitIntShiftArithmResultComputation(uint32_t dex_pc,
- llvm::Value* lhs,
- llvm::Value* rhs,
- IntShiftArithmKind arithm,
- JType op_jty) {
- DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
-
- if (op_jty == kInt) {
- rhs = irb_.CreateAnd(rhs, 0x1f);
- } else {
- llvm::Value* masked_rhs = irb_.CreateAnd(rhs, 0x3f);
- rhs = irb_.CreateZExt(masked_rhs, irb_.GetJLongTy());
- }
-
- switch (arithm) {
- case kIntArithm_Shl: {
- return irb_.CreateShl(lhs, rhs);
- }
- case kIntArithm_Shr: {
- return irb_.CreateAShr(lhs, rhs);
- }
- case kIntArithm_UShr: {
- return irb_.CreateLShr(lhs, rhs);
- }
- default: {
- LOG(FATAL) << "Unknown integer shift arithmetic kind: " << arithm;
- return NULL;
- }
- }
-}
-
-llvm::Value* DexLang::EmitIntDivRemResultComputation(unsigned dex_pc,
- llvm::Value* dividend,
- llvm::Value* divisor,
- IntArithmKind arithm,
- JType op_jty) {
- // Throw exception if the divisor is 0.
- EmitGuard_DivZeroException(dex_pc, divisor, op_jty);
-
- // Note that it's not trivial to translate integer div/rem to sdiv/srem in
- // LLVM IR since (MININT / -1) leads undefined behavior in LLVM due to
- // overflow.
-
- // Select intrinsic
- bool is_div = (arithm == kIntArithm_Div);
- IntrinsicHelper::IntrinsicId arithm_intrinsic = IntrinsicHelper::UnknownId;
- switch (op_jty) {
- case kInt: {
- arithm_intrinsic = (is_div) ? IntrinsicHelper::DivInt :
- IntrinsicHelper::RemInt;
- break;
- }
- case kLong: {
- arithm_intrinsic = (is_div) ? IntrinsicHelper::DivLong :
- IntrinsicHelper::RemLong;
- break;
- }
- default: {
- LOG(FATAL) << "Unsupported " << ((is_div) ? "div" : "rem") << " operation"
- " for type: " << op_jty;
- return NULL;
- }
- }
-
- return EmitInvokeIntrinsic2NoThrow(arithm_intrinsic, dividend, divisor);
-}
-
-//----------------------------------------------------------------------------
-// EmitInsn* Functions
-//----------------------------------------------------------------------------
-void DexLang::EmitInsn_Nop(unsigned dex_pc, const Instruction* insn) {
- uint16_t insn_signature = code_item_->insns_[dex_pc];
-
- if (insn_signature == Instruction::kPackedSwitchSignature ||
- insn_signature == Instruction::kSparseSwitchSignature ||
- insn_signature == Instruction::kArrayDataSignature) {
- irb_.CreateUnreachable();
- } else {
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- }
- return;
-}
-
-void DexLang::EmitInsn_Move(unsigned dex_pc, const Instruction* insn,
- JType jty) {
- DecodedInstruction dec_insn(insn);
-
- llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, jty, kReg);
- EmitStoreDalvikReg(dec_insn.vA, jty, kReg, src_value);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_MoveResult(unsigned dex_pc, const Instruction* insn,
- JType jty) {
- DecodedInstruction dec_insn(insn);
-
- llvm::Value* src_value = EmitLoadDalvikRetValReg(jty, kReg);
- EmitStoreDalvikReg(dec_insn.vA, jty, kReg, src_value);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_MoveException(unsigned dex_pc, const Instruction* insn) {
- DecodedInstruction dec_insn(insn);
-
- llvm::Value* exception_object_addr =
- EmitInvokeIntrinsicNoThrow(IntrinsicHelper::GetException);
-
- EmitStoreDalvikReg(dec_insn.vA, kObject, kAccurate, exception_object_addr);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_ThrowException(unsigned dex_pc,
- const Instruction* insn) {
- DecodedInstruction dec_insn(insn);
-
- llvm::Value* exception_addr =
- EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
-
- EmitInvokeIntrinsic(dex_pc, false, IntrinsicHelper::ThrowException, exception_addr);
-
- return;
-}
-
-void DexLang::EmitInsn_ReturnVoid(unsigned dex_pc, const Instruction* insn) {
- // Pop the shadow frame
- EmitPopShadowFrame();
-
- // Return!
- irb_.CreateRetVoid();
- return;
-}
-
-void DexLang::EmitInsn_Return(unsigned dex_pc, const Instruction* insn) {
- DecodedInstruction dec_insn(insn);
-
- // Pop the shadow frame
- //
- // NOTE: It is important to keep this AFTER the GC safe-point. Otherwise,
- // the return value might be collected since the shadow stack is popped.
- EmitPopShadowFrame();
-
- // Return!
- char ret_shorty = cunit_.GetShorty()[0];
- llvm::Value* retval = EmitLoadDalvikReg(dec_insn.vA, ret_shorty, kAccurate);
-
- irb_.CreateRet(retval);
- return;
-}
-
-void DexLang::EmitInsn_LoadConstant(unsigned dex_pc, const Instruction* insn,
- JType imm_jty) {
- DecodedInstruction dec_insn(insn);
-
- DCHECK(imm_jty == kInt || imm_jty == kLong) << imm_jty;
-
- int64_t imm = 0;
-
- switch (insn->Opcode()) {
- // 32-bit Immediate
- case Instruction::CONST_4:
- case Instruction::CONST_16:
- case Instruction::CONST:
- case Instruction::CONST_WIDE_16:
- case Instruction::CONST_WIDE_32: {
- imm = static_cast<int64_t>(static_cast<int32_t>(dec_insn.vB));
- break;
- }
- case Instruction::CONST_HIGH16: {
- imm = static_cast<int64_t>(static_cast<int32_t>(
- static_cast<uint32_t>(static_cast<uint16_t>(dec_insn.vB)) << 16));
- break;
- }
- // 64-bit Immediate
- case Instruction::CONST_WIDE: {
- imm = static_cast<int64_t>(dec_insn.vB_wide);
- break;
- }
- case Instruction::CONST_WIDE_HIGH16: {
- imm = static_cast<int64_t>(
- static_cast<uint64_t>(static_cast<uint16_t>(dec_insn.vB)) << 48);
- break;
- }
- // Unknown opcode for load constant (unreachable)
- default: {
- LOG(FATAL) << "Unknown opcode for load constant: " << insn->Opcode();
- break;
- }
- }
-
- // Store the non-object register
- llvm::Type* imm_type = irb_.GetJType(imm_jty, kAccurate);
- llvm::Constant* imm_value = llvm::ConstantInt::getSigned(imm_type, imm);
- EmitStoreDalvikReg(dec_insn.vA, imm_jty, kAccurate, imm_value);
-
- // Store the object register if it is possible to be null.
- //
- // FIXME: Should we use GetInferredRegCategory() here to avoid store the value
- // twice?
- if (imm_jty == kInt && imm == 0) {
- EmitStoreDalvikReg(dec_insn.vA, kObject, kAccurate, irb_.GetJNull());
- }
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_LoadConstantString(unsigned dex_pc,
- const Instruction* insn) {
- DecodedInstruction dec_insn(insn);
-
- uint32_t string_idx = dec_insn.vB;
- llvm::Value* string_idx_value = irb_.getInt32(string_idx);
-
- llvm::Value* string_addr =
- EmitInvokeIntrinsicNoThrow(IntrinsicHelper::LoadStringFromDexCache,
- string_idx_value);
-
- if (!compiler_.CanAssumeStringIsPresentInDexCache(*dex_file_, string_idx)) {
- llvm::BasicBlock* block_str_exist =
- CreateBasicBlockWithDexPC(dex_pc, "str_exist");
-
- llvm::BasicBlock* block_str_resolve =
- CreateBasicBlockWithDexPC(dex_pc, "str_resolve");
-
- // Test: Is the string resolved and in the dex cache?
- llvm::Value* equal_null = irb_.CreateICmpEQ(string_addr, irb_.GetJNull());
-
- irb_.CreateCondBr(equal_null, block_str_resolve, block_str_exist);
-
- // String is resolved, go to next basic block.
- irb_.SetInsertPoint(block_str_exist);
- EmitStoreDalvikReg(dec_insn.vA, kObject, kAccurate, string_addr);
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
-
- // String is not resolved yet, resolve it now.
- irb_.SetInsertPoint(block_str_resolve);
-
- llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
-
- string_addr = EmitInvokeIntrinsic2(dex_pc, true, IntrinsicHelper::ResolveString,
- method_object_addr, string_idx_value);
- }
-
- EmitStoreDalvikReg(dec_insn.vA, kObject, kAccurate, string_addr);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_LoadConstantClass(unsigned dex_pc,
- const Instruction* insn) {
- DecodedInstruction dec_insn(insn);
-
- llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, dec_insn.vB);
- EmitStoreDalvikReg(dec_insn.vA, kObject, kAccurate, type_object_addr);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_MonitorEnter(unsigned dex_pc, const Instruction* insn) {
- DecodedInstruction dec_insn(insn);
-
- llvm::Value* object_addr =
- EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
-
- if (!(method_info_.this_will_not_be_null && dec_insn.vA == method_info_.this_reg_idx)) {
- EmitGuard_NullPointerException(dex_pc, object_addr);
- }
-
- llvm::Value* thread_object_addr = EmitGetCurrentThread();
-
- EmitInvokeIntrinsic2NoThrow(IntrinsicHelper::LockObject,
- object_addr, thread_object_addr);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_MonitorExit(unsigned dex_pc, const Instruction* insn) {
- DecodedInstruction dec_insn(insn);
-
- llvm::Value* object_addr =
- EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
-
- if (!(method_info_.this_will_not_be_null && dec_insn.vA == method_info_.this_reg_idx)) {
- EmitGuard_NullPointerException(dex_pc, object_addr);
- }
-
- llvm::Value* thread_object_addr = EmitGetCurrentThread();
-
- EmitInvokeIntrinsic2(dex_pc, true, IntrinsicHelper::UnlockObject,
- object_addr, thread_object_addr);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_CheckCast(unsigned dex_pc, const Instruction* insn) {
- DecodedInstruction dec_insn(insn);
-
- llvm::BasicBlock* block_test_class =
- CreateBasicBlockWithDexPC(dex_pc, "test_class");
-
- llvm::BasicBlock* block_test_sub_class =
- CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
-
- llvm::Value* object_addr =
- EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
-
- // Test: Is the reference equal to null? Act as no-op when it is null.
- llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.GetJNull());
-
- irb_.CreateCondBr(equal_null,
- GetNextBasicBlock(dex_pc),
- block_test_class);
-
- // Test: Is the object instantiated from the given class?
- irb_.SetInsertPoint(block_test_class);
- llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, dec_insn.vB);
- DCHECK_EQ(Object::ClassOffset().Int32Value(), 0);
-
- llvm::PointerType* jobject_ptr_ty = irb_.GetJObjectTy();
-
- llvm::Value* object_type_field_addr =
- irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
-
- llvm::Value* object_type_object_addr =
- irb_.CreateLoad(object_type_field_addr);
-
- llvm::Value* equal_class =
- irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
-
- irb_.CreateCondBr(equal_class,
- GetNextBasicBlock(dex_pc),
- block_test_sub_class);
-
- // Test: Is the object instantiated from the subclass of the given class?
- irb_.SetInsertPoint(block_test_sub_class);
-
- EmitInvokeIntrinsic2(dex_pc, true, IntrinsicHelper::CheckCast,
- type_object_addr, object_type_object_addr);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_InstanceOf(unsigned dex_pc, const Instruction* insn) {
- DecodedInstruction dec_insn(insn);
-
- llvm::Constant* zero = irb_.GetJInt(0);
- llvm::Constant* one = irb_.GetJInt(1);
-
- llvm::BasicBlock* block_nullp = CreateBasicBlockWithDexPC(dex_pc, "nullp");
-
- llvm::BasicBlock* block_test_class =
- CreateBasicBlockWithDexPC(dex_pc, "test_class");
-
- llvm::BasicBlock* block_class_equals =
- CreateBasicBlockWithDexPC(dex_pc, "class_eq");
-
- llvm::BasicBlock* block_test_sub_class =
- CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
-
- llvm::Value* object_addr =
- EmitLoadDalvikReg(dec_insn.vB, kObject, kAccurate);
-
- // Overview of the following code :
- // We check for null, if so, then false, otherwise check for class == . If so
- // then true, otherwise do callout slowpath.
- //
- // Test: Is the reference equal to null? Set 0 when it is null.
- llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.GetJNull());
-
- irb_.CreateCondBr(equal_null, block_nullp, block_test_class);
-
- irb_.SetInsertPoint(block_nullp);
- EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, zero);
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
-
- // Test: Is the object instantiated from the given class?
- irb_.SetInsertPoint(block_test_class);
- llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, dec_insn.vC);
- DCHECK_EQ(Object::ClassOffset().Int32Value(), 0);
-
- llvm::PointerType* jobject_ptr_ty = irb_.GetJObjectTy();
-
- llvm::Value* object_type_field_addr =
- irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
-
- llvm::Value* object_type_object_addr =
- irb_.CreateLoad(object_type_field_addr);
-
- llvm::Value* equal_class =
- irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
-
- irb_.CreateCondBr(equal_class, block_class_equals, block_test_sub_class);
-
- irb_.SetInsertPoint(block_class_equals);
- EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, one);
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
-
- // Test: Is the object instantiated from the subclass of the given class?
- irb_.SetInsertPoint(block_test_sub_class);
-
- llvm::Value* result =
- EmitInvokeIntrinsic2NoThrow(IntrinsicHelper::IsAssignable,
- type_object_addr, object_type_object_addr);
-
- EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_NewInstance(unsigned dex_pc, const Instruction* insn) {
- DecodedInstruction dec_insn(insn);
-
- IntrinsicHelper::IntrinsicId alloc_intrinsic;
- if (compiler_.CanAccessInstantiableTypeWithoutChecks(method_idx_,
- *dex_file_,
- dec_insn.vB)) {
- alloc_intrinsic = IntrinsicHelper::AllocObject;
- } else {
- alloc_intrinsic = IntrinsicHelper::AllocObjectWithAccessCheck;
- }
-
- llvm::Constant* type_index_value = irb_.getInt32(dec_insn.vB);
-
- llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
-
- llvm::Value* thread_object_addr = EmitGetCurrentThread();
-
- llvm::Value* object_addr = EmitInvokeIntrinsic3(dex_pc, true, alloc_intrinsic,
- type_index_value,
- method_object_addr,
- thread_object_addr);
-
- EmitStoreDalvikReg(dec_insn.vA, kObject, kAccurate, object_addr);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_UnconditionalBranch(unsigned dex_pc,
- const Instruction* insn) {
- DecodedInstruction dec_insn(insn);
-
- int32_t branch_offset = dec_insn.vA;
-
- irb_.CreateBr(GetBasicBlock(dex_pc + branch_offset));
- return;
-}
-
-void DexLang::EmitInsn_ArrayLength(unsigned dex_pc, const Instruction* insn) {
- DecodedInstruction dec_insn(insn);
-
- // Get the array object address
- llvm::Value* array_addr = EmitLoadDalvikReg(dec_insn.vB, kObject, kAccurate);
-
- // Check whether the array address is null
- EmitGuard_NullPointerException(dex_pc, array_addr);
-
- // Get the array length and store it to the register
- llvm::Value* array_len = EmitLoadArrayLength(array_addr);
- EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, array_len);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_NewArray(unsigned dex_pc, const Instruction* insn) {
- DecodedInstruction dec_insn(insn);
-
- llvm::Value* array_addr = EmitAllocNewArray(dex_pc, dec_insn.vB, dec_insn.vC,
- /* is_filled_new_array */false);
-
- EmitStoreDalvikReg(dec_insn.vA, kObject, kAccurate, array_addr);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_FilledNewArray(unsigned dex_pc, const Instruction* insn,
- bool is_range) {
- DecodedInstruction dec_insn(insn);
-
- llvm::Value* object_addr = EmitAllocNewArray(dex_pc, dec_insn.vA, dec_insn.vB,
- /* is_filled_new_array */true);
-
- if (dec_insn.vA > 0) {
- // Check for the element type
- uint32_t type_desc_len = 0;
- const char* type_desc =
- dex_file_->StringByTypeIdx(dec_insn.vB, &type_desc_len);
-
- DCHECK_GE(type_desc_len, 2u); // should be guaranteed by verifier
- DCHECK_EQ(type_desc[0], '['); // should be guaranteed by verifier
-
- // NOTE: Currently filled-new-array only supports 'L', '[', and 'I' as the
- // element, therefore the element is either a primitive int or a reference
- JType element_jty = ((type_desc[1] == 'I') ? kInt : kObject);
-
- std::vector<llvm::Value*> args;
- // Destination array object
- args.push_back(object_addr);
- // Type of the array element
- //
- // FIXME: Actually, dec_insn.vB (type_idx of the element) should be here to
- // the intrinsic instead of element_jty. However, since GBCExpander cannot
- // know which dex_file this filled-new-array instruction associated with, it
- // is unable to know the exact type of the type_idx is. In the near future,
- // metadata will be used to record the type information (i.e., type_desc)
- args.push_back(irb_.getInt32(element_jty));
-
- for (uint32_t i = 0; i < dec_insn.vA; ++i) {
- int reg_index;
- if (is_range) {
- reg_index = dec_insn.vC + i;
- } else {
- reg_index = dec_insn.arg[i];
- }
-
- llvm::Value* reg_value =
- EmitLoadDalvikReg(reg_index, element_jty, kAccurate);
-
- args.push_back(reg_value);
- }
-
- EmitInvokeIntrinsicNoThrow(IntrinsicHelper::FilledNewArray, args);
- }
-
- EmitStoreDalvikRetValReg(kObject, kAccurate, object_addr);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_FillArrayData(unsigned dex_pc, const Instruction* insn) {
- DecodedInstruction dec_insn(insn);
-
- // Read the payload
- int32_t payload_offset = static_cast<int32_t>(dex_pc) +
- static_cast<int32_t>(dec_insn.vB);
-
- const Instruction::ArrayDataPayload* payload =
- reinterpret_cast<const Instruction::ArrayDataPayload*>(
- code_item_->insns_ + payload_offset);
-
- // Load array object
- llvm::Value* array_addr = EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
-
- if (payload->element_count == 0) {
- // When the number of the elements in the payload is zero, we don't have
- // to copy any numbers. However, we should check whether the array object
- // address is equal to null or not.
- EmitGuard_NullPointerException(dex_pc, array_addr);
- } else {
- // To save the code size, we are going to call the runtime function to
- // copy the content from DexFile.
-
- // NOTE: We will check for the NullPointerException in the runtime.
- llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
-
- EmitInvokeIntrinsic4(dex_pc, true, IntrinsicHelper::FillArrayData,
- method_object_addr, irb_.getInt32(dex_pc), array_addr,
- irb_.getInt32(payload_offset));
- }
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_UnaryConditionalBranch(unsigned dex_pc,
- const Instruction* insn,
- CondBranchKind cond) {
- DecodedInstruction dec_insn(insn);
-
- RegCategory src_reg_cat = GetInferredRegCategory(dex_pc, dec_insn.vA);
-
- DCHECK_NE(kRegUnknown, src_reg_cat);
- DCHECK_NE(kRegCat2, src_reg_cat);
-
- int32_t branch_offset = dec_insn.vB;
-
- llvm::Value* src1_value;
- llvm::Value* src2_value;
-
- if (src_reg_cat == kRegZero) {
- src1_value = irb_.getInt32(0);
- src2_value = irb_.getInt32(0);
- } else if (src_reg_cat == kRegCat1nr) {
- src1_value = EmitLoadDalvikReg(dec_insn.vA, kInt, kReg);
- src2_value = irb_.getInt32(0);
- } else {
- src1_value = EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
- src2_value = irb_.GetJNull();
- }
-
- llvm::Value* cond_value = EmitConditionResult(src1_value, src2_value, cond);
-
- irb_.CreateCondBr(cond_value,
- GetBasicBlock(dex_pc + branch_offset),
- GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_BinaryConditionalBranch(unsigned dex_pc,
- const Instruction* insn,
- CondBranchKind cond) {
- DecodedInstruction dec_insn(insn);
-
- int8_t src1_reg_cat = GetInferredRegCategory(dex_pc, dec_insn.vA);
- int8_t src2_reg_cat = GetInferredRegCategory(dex_pc, dec_insn.vB);
-
- DCHECK_NE(kRegUnknown, src1_reg_cat);
- DCHECK_NE(kRegUnknown, src2_reg_cat);
- DCHECK_NE(kRegCat2, src1_reg_cat);
- DCHECK_NE(kRegCat2, src2_reg_cat);
-
- int32_t branch_offset = dec_insn.vC;
-
- llvm::Value* src1_value;
- llvm::Value* src2_value;
-
- if (src1_reg_cat == kRegZero && src2_reg_cat == kRegZero) {
- src1_value = irb_.getInt32(0);
- src2_value = irb_.getInt32(0);
- } else if (src1_reg_cat != kRegZero && src2_reg_cat != kRegZero) {
- CHECK_EQ(src1_reg_cat, src2_reg_cat);
-
- if (src1_reg_cat == kRegCat1nr) {
- src1_value = EmitLoadDalvikReg(dec_insn.vA, kInt, kAccurate);
- src2_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
- } else {
- src1_value = EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
- src2_value = EmitLoadDalvikReg(dec_insn.vB, kObject, kAccurate);
- }
- } else {
- DCHECK(src1_reg_cat == kRegZero ||
- src2_reg_cat == kRegZero);
-
- if (src1_reg_cat == kRegZero) {
- if (src2_reg_cat == kRegCat1nr) {
- src1_value = irb_.GetJInt(0);
- src2_value = EmitLoadDalvikReg(dec_insn.vA, kInt, kAccurate);
- } else {
- src1_value = irb_.GetJNull();
- src2_value = EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
- }
- } else { // src2_reg_cat == kRegZero
- if (src2_reg_cat == kRegCat1nr) {
- src1_value = EmitLoadDalvikReg(dec_insn.vA, kInt, kAccurate);
- src2_value = irb_.GetJInt(0);
- } else {
- src1_value = EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
- src2_value = irb_.GetJNull();
- }
- }
- }
-
- llvm::Value* cond_value = EmitConditionResult(src1_value, src2_value, cond);
-
- irb_.CreateCondBr(cond_value,
- GetBasicBlock(dex_pc + branch_offset),
- GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_PackedSwitch(unsigned dex_pc, const Instruction* insn) {
- DecodedInstruction dec_insn(insn);
-
- int32_t payload_offset = static_cast<int32_t>(dex_pc) +
- static_cast<int32_t>(dec_insn.vB);
-
- const Instruction::PackedSwitchPayload* payload =
- reinterpret_cast<const Instruction::PackedSwitchPayload*>(
- code_item_->insns_ + payload_offset);
-
- llvm::Value* value = EmitLoadDalvikReg(dec_insn.vA, kInt, kAccurate);
-
- llvm::SwitchInst* sw =
- irb_.CreateSwitch(value, GetNextBasicBlock(dex_pc), payload->case_count);
-
- for (uint16_t i = 0; i < payload->case_count; ++i) {
- sw->addCase(irb_.getInt32(payload->first_key + i),
- GetBasicBlock(dex_pc + payload->targets[i]));
- }
- return;
-}
-
-void DexLang::EmitInsn_SparseSwitch(unsigned dex_pc, const Instruction* insn) {
- DecodedInstruction dec_insn(insn);
-
- int32_t payload_offset = static_cast<int32_t>(dex_pc) +
- static_cast<int32_t>(dec_insn.vB);
-
- const Instruction::SparseSwitchPayload* payload =
- reinterpret_cast<const Instruction::SparseSwitchPayload*>(
- code_item_->insns_ + payload_offset);
-
- const int32_t* keys = payload->GetKeys();
- const int32_t* targets = payload->GetTargets();
-
- llvm::Value* value = EmitLoadDalvikReg(dec_insn.vA, kInt, kAccurate);
-
- llvm::SwitchInst* sw =
- irb_.CreateSwitch(value, GetNextBasicBlock(dex_pc), payload->case_count);
-
- for (size_t i = 0; i < payload->case_count; ++i) {
- sw->addCase(irb_.getInt32(keys[i]), GetBasicBlock(dex_pc + targets[i]));
- }
- return;
-}
-
-void DexLang::EmitInsn_FPCompare(unsigned dex_pc, const Instruction* insn,
- JType fp_jty, bool gt_bias) {
- DecodedInstruction dec_insn(insn);
-
- DCHECK(fp_jty == kFloat || fp_jty == kDouble) << "JType: " << fp_jty;
-
- llvm::Value* src1_value = EmitLoadDalvikReg(dec_insn.vB, fp_jty, kAccurate);
- llvm::Value* src2_value = EmitLoadDalvikReg(dec_insn.vC, fp_jty, kAccurate);
-
- llvm::Value* cmp_eq = irb_.CreateFCmpOEQ(src1_value, src2_value);
- llvm::Value* cmp_lt;
-
- if (gt_bias) {
- cmp_lt = irb_.CreateFCmpOLT(src1_value, src2_value);
- } else {
- cmp_lt = irb_.CreateFCmpULT(src1_value, src2_value);
- }
-
- llvm::Value* result = EmitCompareResultSelection(cmp_eq, cmp_lt);
- EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_LongCompare(unsigned dex_pc, const Instruction* insn) {
- DecodedInstruction dec_insn(insn);
-
- llvm::Value* src1_value = EmitLoadDalvikReg(dec_insn.vB, kLong, kAccurate);
- llvm::Value* src2_value = EmitLoadDalvikReg(dec_insn.vC, kLong, kAccurate);
-
- llvm::Value* cmp_eq = irb_.CreateICmpEQ(src1_value, src2_value);
- llvm::Value* cmp_lt = irb_.CreateICmpSLT(src1_value, src2_value);
-
- llvm::Value* result = EmitCompareResultSelection(cmp_eq, cmp_lt);
- EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_AGet(unsigned dex_pc, const Instruction* insn,
- JType elem_jty) {
- DecodedInstruction dec_insn(insn);
-
- // Select corresponding intrinsic
- IntrinsicHelper::IntrinsicId aget_intrinsic = IntrinsicHelper::UnknownId;
-
- switch (elem_jty) {
- case kInt: {
- aget_intrinsic = IntrinsicHelper::ArrayGet;
- break;
- }
- case kLong: {
- aget_intrinsic = IntrinsicHelper::ArrayGetWide;
- break;
- }
- case kObject: {
- aget_intrinsic = IntrinsicHelper::ArrayGetObject;
- break;
- }
- case kBoolean: {
- aget_intrinsic = IntrinsicHelper::ArrayGetBoolean;
- break;
- }
- case kByte: {
- aget_intrinsic = IntrinsicHelper::ArrayGetByte;
- break;
- }
- case kChar: {
- aget_intrinsic = IntrinsicHelper::ArrayGetChar;
- break;
- }
- case kShort: {
- aget_intrinsic = IntrinsicHelper::ArrayGetShort;
- break;
- }
- default: {
- LOG(FATAL) << "Unexpected element type got in aget instruction!";
- return;
- }
- }
-
- // Construct argument list passed to the intrinsic
- llvm::Value* array_addr = EmitLoadDalvikReg(dec_insn.vB, kObject, kAccurate);
- llvm::Value* index_value = EmitLoadDalvikReg(dec_insn.vC, kInt, kAccurate);
-
- EmitGuard_ArrayException(dex_pc, array_addr, index_value);
-
- llvm::Value* array_element_value = EmitInvokeIntrinsic2NoThrow(aget_intrinsic,
- array_addr,
- index_value);
-
- EmitStoreDalvikReg(dec_insn.vA, elem_jty, kArray, array_element_value);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_APut(unsigned dex_pc, const Instruction* insn,
- JType elem_jty) {
- DecodedInstruction dec_insn(insn);
-
- // Select corresponding intrinsic
- IntrinsicHelper::IntrinsicId aput_intrinsic = IntrinsicHelper::UnknownId;
-
- switch (elem_jty) {
- case kInt: {
- aput_intrinsic = IntrinsicHelper::ArrayPut;
- break;
- }
- case kLong: {
- aput_intrinsic = IntrinsicHelper::ArrayPutWide;
- break;
- }
- case kObject: {
- aput_intrinsic = IntrinsicHelper::ArrayPutObject;
- break;
- }
- case kBoolean: {
- aput_intrinsic = IntrinsicHelper::ArrayPutBoolean;
- break;
- }
- case kByte: {
- aput_intrinsic = IntrinsicHelper::ArrayPutByte;
- break;
- }
- case kChar: {
- aput_intrinsic = IntrinsicHelper::ArrayPutChar;
- break;
- }
- case kShort: {
- aput_intrinsic = IntrinsicHelper::ArrayPutShort;
- break;
- }
- default: {
- LOG(FATAL) << "Unexpected element type got in aput instruction!";
- return;
- }
- }
-
- llvm::Value* array_addr = EmitLoadDalvikReg(dec_insn.vB, kObject, kAccurate);
- llvm::Value* index_value = EmitLoadDalvikReg(dec_insn.vC, kInt, kAccurate);
-
- EmitGuard_ArrayException(dex_pc, array_addr, index_value);
-
- llvm::Value* new_value = EmitLoadDalvikReg(dec_insn.vA, elem_jty, kArray);
-
- // Check the type if an object is putting
- if (elem_jty == kObject) {
- EmitInvokeIntrinsic2(dex_pc, false, IntrinsicHelper::CheckPutArrayElement,
- new_value, array_addr);
-
- EmitMarkGCCard(new_value, array_addr);
- }
-
- EmitInvokeIntrinsic3NoThrow(aput_intrinsic, new_value, array_addr, index_value);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_IGet(unsigned dex_pc, const Instruction* insn,
- JType field_jty) {
- DecodedInstruction dec_insn(insn);
-
- uint32_t reg_idx = dec_insn.vB;
- uint32_t field_idx = dec_insn.vC;
-
- llvm::Value* object_addr = EmitLoadDalvikReg(reg_idx, kObject, kAccurate);
-
- if (!(method_info_.this_will_not_be_null && reg_idx == method_info_.this_reg_idx)) {
- EmitGuard_NullPointerException(dex_pc, object_addr);
- }
-
- int field_offset;
- bool is_volatile;
- bool is_fast_path = compiler_.ComputeInstanceFieldInfo(field_idx, &cunit_,
- field_offset,
- is_volatile,
- /* is_put */false);
-
- // Select corresponding intrinsic accroding to the field type and is_fast_path
- IntrinsicHelper::IntrinsicId iget_intrinsic = IntrinsicHelper::UnknownId;
-
- switch (field_jty) {
- case kInt: {
- iget_intrinsic =
- (is_fast_path) ? IntrinsicHelper::InstanceFieldGetFast :
- IntrinsicHelper::InstanceFieldGet;
- break;
- }
- case kLong: {
- iget_intrinsic =
- (is_fast_path) ? IntrinsicHelper::InstanceFieldGetWideFast :
- IntrinsicHelper::InstanceFieldGetWide;
- break;
- }
- case kObject: {
- iget_intrinsic =
- (is_fast_path) ? IntrinsicHelper::InstanceFieldGetObjectFast :
- IntrinsicHelper::InstanceFieldGetObject;
- break;
- }
- case kBoolean: {
- iget_intrinsic =
- (is_fast_path) ? IntrinsicHelper::InstanceFieldGetBooleanFast :
- IntrinsicHelper::InstanceFieldGetBoolean;
- break;
- }
- case kByte: {
- iget_intrinsic =
- (is_fast_path) ? IntrinsicHelper::InstanceFieldGetByteFast :
- IntrinsicHelper::InstanceFieldGetByte;
- break;
- }
- case kChar: {
- iget_intrinsic =
- (is_fast_path) ? IntrinsicHelper::InstanceFieldGetCharFast :
- IntrinsicHelper::InstanceFieldGetChar;
- break;
- }
- case kShort: {
- iget_intrinsic =
- (is_fast_path) ? IntrinsicHelper::InstanceFieldGetShortFast :
- IntrinsicHelper::InstanceFieldGetShort;
- break;
- }
- default: {
- LOG(FATAL) << "Unexpected element type got in iget instruction!";
- return;
- }
- }
-
- llvm::Value* instance_field_value;
-
- if (!is_fast_path) {
- llvm::Constant* field_idx_value = irb_.getInt32(field_idx);
-
- llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
-
- instance_field_value = EmitInvokeIntrinsic3(dex_pc, true, iget_intrinsic,
- field_idx_value,
- method_object_addr,
- object_addr);
- } else {
- DCHECK_GE(field_offset, 0);
-
- instance_field_value =
- EmitInvokeIntrinsic3NoThrow(iget_intrinsic,
- irb_.getInt32(field_offset),
- irb_.getInt1(is_volatile),
- object_addr);
- }
-
- EmitStoreDalvikReg(dec_insn.vA, field_jty, kField, instance_field_value);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_IPut(unsigned dex_pc, const Instruction* insn,
- JType field_jty) {
- DecodedInstruction dec_insn(insn);
-
- uint32_t reg_idx = dec_insn.vB;
- uint32_t field_idx = dec_insn.vC;
-
- llvm::Value* object_addr = EmitLoadDalvikReg(reg_idx, kObject, kAccurate);
-
- if (!(method_info_.this_will_not_be_null && reg_idx == method_info_.this_reg_idx)) {
- EmitGuard_NullPointerException(dex_pc, object_addr);
- }
-
- llvm::Value* new_value = EmitLoadDalvikReg(dec_insn.vA, field_jty, kField);
-
- int field_offset;
- bool is_volatile;
- bool is_fast_path = compiler_.ComputeInstanceFieldInfo(field_idx, &cunit_,
- field_offset,
- is_volatile,
- /* is_iput */true);
-
- // Select corresponding intrinsic accroding to the field type and is_fast_path
- IntrinsicHelper::IntrinsicId iput_intrinsic = IntrinsicHelper::UnknownId;
-
- switch (field_jty) {
- case kInt: {
- iput_intrinsic =
- (is_fast_path) ? IntrinsicHelper::InstanceFieldPutFast :
- IntrinsicHelper::InstanceFieldPut;
- break;
- }
- case kLong: {
- iput_intrinsic =
- (is_fast_path) ? IntrinsicHelper::InstanceFieldPutWideFast :
- IntrinsicHelper::InstanceFieldPutWide;
- break;
- }
- case kObject: {
- iput_intrinsic =
- (is_fast_path) ? IntrinsicHelper::InstanceFieldPutObjectFast :
- IntrinsicHelper::InstanceFieldPutObject;
- break;
- }
- case kBoolean: {
- iput_intrinsic =
- (is_fast_path) ? IntrinsicHelper::InstanceFieldPutBooleanFast :
- IntrinsicHelper::InstanceFieldPutBoolean;
- break;
- }
- case kByte: {
- iput_intrinsic =
- (is_fast_path) ? IntrinsicHelper::InstanceFieldPutByteFast :
- IntrinsicHelper::InstanceFieldPutByte;
- break;
- }
- case kChar: {
- iput_intrinsic =
- (is_fast_path) ? IntrinsicHelper::InstanceFieldPutCharFast :
- IntrinsicHelper::InstanceFieldPutChar;
- break;
- }
- case kShort: {
- iput_intrinsic =
- (is_fast_path) ? IntrinsicHelper::InstanceFieldPutShortFast :
- IntrinsicHelper::InstanceFieldPutShort;
- break;
- }
- default: {
- LOG(FATAL) << "Unexpected element type got in iput instruction!";
- return;
- }
- }
-
- if (!is_fast_path) {
- llvm::Value* field_idx_value = irb_.getInt32(field_idx);
-
- llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
-
- EmitInvokeIntrinsic4(dex_pc, true, iput_intrinsic, field_idx_value,
- method_object_addr, object_addr, new_value);
-
- } else {
- DCHECK_GE(field_offset, 0);
-
- EmitInvokeIntrinsic4NoThrow(iput_intrinsic, irb_.getInt32(field_offset),
- irb_.getInt1(is_volatile), object_addr,
- new_value);
-
- // If put an object, mark the GC card table
- if (field_jty == kObject) {
- EmitMarkGCCard(new_value, object_addr);
- }
- }
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_SGet(unsigned dex_pc, const Instruction* insn,
- JType field_jty) {
- DecodedInstruction dec_insn(insn);
-
- uint32_t field_idx = dec_insn.vB;
-
- int field_offset;
- int ssb_index;
- bool is_referrers_class;
- bool is_volatile;
- bool is_fast_path = compiler_.ComputeStaticFieldInfo(field_idx, &cunit_,
- field_offset, ssb_index,
- is_referrers_class,
- is_volatile,
- /* is_put */false);
-
- // Select corresponding intrinsic accroding to the field type and is_fast_path
- IntrinsicHelper::IntrinsicId sget_intrinsic = IntrinsicHelper::UnknownId;
-
- switch (field_jty) {
- case kInt: {
- sget_intrinsic =
- (is_fast_path) ? IntrinsicHelper::StaticFieldGetFast :
- IntrinsicHelper::StaticFieldGet;
- break;
- }
- case kLong: {
- sget_intrinsic =
- (is_fast_path) ? IntrinsicHelper::StaticFieldGetWideFast :
- IntrinsicHelper::StaticFieldGetWide;
- break;
- }
- case kObject: {
- sget_intrinsic =
- (is_fast_path) ? IntrinsicHelper::StaticFieldGetObjectFast :
- IntrinsicHelper::StaticFieldGetObject;
- break;
- }
- case kBoolean: {
- sget_intrinsic =
- (is_fast_path) ? IntrinsicHelper::StaticFieldGetBooleanFast :
- IntrinsicHelper::StaticFieldGetBoolean;
- break;
- }
- case kByte: {
- sget_intrinsic =
- (is_fast_path) ? IntrinsicHelper::StaticFieldGetByteFast :
- IntrinsicHelper::StaticFieldGetByte;
- break;
- }
- case kChar: {
- sget_intrinsic =
- (is_fast_path) ? IntrinsicHelper::StaticFieldGetCharFast :
- IntrinsicHelper::StaticFieldGetChar;
- break;
- }
- case kShort: {
- sget_intrinsic =
- (is_fast_path) ? IntrinsicHelper::StaticFieldGetShortFast :
- IntrinsicHelper::StaticFieldGetShort;
- break;
- }
- default: {
- LOG(FATAL) << "Unexpected element type got in sget instruction!";
- return;
- }
- }
-
- llvm::Constant* field_idx_value = irb_.getInt32(field_idx);
-
- llvm::Value* static_field_value;
-
- if (!is_fast_path) {
- llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
-
- static_field_value =
- EmitInvokeIntrinsic2(dex_pc, true, sget_intrinsic,
- field_idx_value, method_object_addr);
- } else {
- DCHECK_GE(field_offset, 0);
-
- llvm::Value* static_storage_addr = NULL;
-
- if (is_referrers_class) {
- // Fast path, static storage base is this method's class
- llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
-
- static_storage_addr =
- EmitInvokeIntrinsicNoThrow(IntrinsicHelper::LoadDeclaringClassSSB,
- method_object_addr);
- } else {
- // Medium path, static storage base in a different class which
- // requires checks that the other class is initialized
- DCHECK_GE(ssb_index, 0);
- static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
- }
-
- static_field_value =
- EmitInvokeIntrinsic3NoThrow(sget_intrinsic,
- static_storage_addr,
- irb_.getInt32(field_offset),
- irb_.getInt1(is_volatile));
- }
-
- EmitStoreDalvikReg(dec_insn.vA, field_jty, kField, static_field_value);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_SPut(unsigned dex_pc, const Instruction* insn,
- JType field_jty) {
- DecodedInstruction dec_insn(insn);
-
- uint32_t field_idx = dec_insn.vB;
-
- llvm::Value* new_value = EmitLoadDalvikReg(dec_insn.vA, field_jty, kField);
-
- int field_offset;
- int ssb_index;
- bool is_referrers_class;
- bool is_volatile;
- bool is_fast_path = compiler_.ComputeStaticFieldInfo(field_idx, &cunit_,
- field_offset, ssb_index,
- is_referrers_class,
- is_volatile,
- /* is_put */true);
-
- // Select corresponding intrinsic accroding to the field type and is_fast_path
- IntrinsicHelper::IntrinsicId sput_intrinsic = IntrinsicHelper::UnknownId;
-
- switch (field_jty) {
- case kInt: {
- sput_intrinsic =
- (is_fast_path) ? IntrinsicHelper::StaticFieldPutFast :
- IntrinsicHelper::StaticFieldPut;
- break;
- }
- case kLong: {
- sput_intrinsic =
- (is_fast_path) ? IntrinsicHelper::StaticFieldPutWideFast :
- IntrinsicHelper::StaticFieldPutWide;
- break;
- }
- case kObject: {
- sput_intrinsic =
- (is_fast_path) ? IntrinsicHelper::StaticFieldPutObjectFast :
- IntrinsicHelper::StaticFieldPutObject;
- break;
- }
- case kBoolean: {
- sput_intrinsic =
- (is_fast_path) ? IntrinsicHelper::StaticFieldPutBooleanFast :
- IntrinsicHelper::StaticFieldPutBoolean;
- break;
- }
- case kByte: {
- sput_intrinsic =
- (is_fast_path) ? IntrinsicHelper::StaticFieldPutByteFast :
- IntrinsicHelper::StaticFieldPutByte;
- break;
- }
- case kChar: {
- sput_intrinsic =
- (is_fast_path) ? IntrinsicHelper::StaticFieldPutCharFast :
- IntrinsicHelper::StaticFieldPutChar;
- break;
- }
- case kShort: {
- sput_intrinsic =
- (is_fast_path) ? IntrinsicHelper::StaticFieldPutShortFast :
- IntrinsicHelper::StaticFieldPutShort;
- break;
- }
- default: {
- LOG(FATAL) << "Unexpected element type got in sput instruction!";
- return;
- }
- }
-
- if (!is_fast_path) {
- llvm::Constant* field_idx_value = irb_.getInt32(dec_insn.vB);
-
- llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
-
- EmitInvokeIntrinsic3(dex_pc, true, sput_intrinsic,
- field_idx_value, method_object_addr, new_value);
- } else {
- DCHECK_GE(field_offset, 0);
-
- llvm::Value* static_storage_addr = NULL;
-
- if (is_referrers_class) {
- // Fast path, static storage base is this method's class
- llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
-
- static_storage_addr =
- EmitInvokeIntrinsicNoThrow(IntrinsicHelper::LoadDeclaringClassSSB,
- method_object_addr);
- } else {
- // Medium path, static storage base in a different class which
- // requires checks that the other class is initialized
- DCHECK_GE(ssb_index, 0);
- static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
- }
-
- EmitInvokeIntrinsic4NoThrow(sput_intrinsic, static_storage_addr,
- irb_.getInt32(field_offset),
- irb_.getInt1(is_volatile), new_value);
-
- // If put an object, mark the GC card table
- if (field_jty == kObject) {
- EmitMarkGCCard(new_value, static_storage_addr);
- }
- }
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_Invoke(unsigned dex_pc, const Instruction* insn,
- InvokeType invoke_type, InvokeArgFmt arg_fmt) {
- DecodedInstruction dec_insn(insn);
-
- bool is_static = (invoke_type == kStatic);
- uint32_t callee_method_idx = dec_insn.vB;
-
- // Compute invoke related information for compiler decision
- int vtable_idx = -1;
- uintptr_t direct_code = 0; // Currently unused
- uintptr_t direct_method = 0;
- bool is_fast_path = compiler_.ComputeInvokeInfo(callee_method_idx, &cunit_,
- invoke_type, vtable_idx,
- direct_code, direct_method);
-
- // Load *this* actual parameter
- uint32_t this_reg = -1u;
- llvm::Value* this_addr = NULL;
-
- if (is_static) {
- this_addr = irb_.GetJNull();
- } else {
- this_reg = (arg_fmt == kArgReg) ? dec_insn.arg[0] : (dec_insn.vC + 0);
- this_addr = EmitLoadDalvikReg(this_reg, kObject, kAccurate);
- }
-
- // Load the method object
- llvm::Value* callee_method_object_addr = NULL;
-
- llvm::Value* callee_method_idx_value = irb_.getInt32(callee_method_idx);
-
- if (!is_fast_path) {
- llvm::Value* caller_method_object_addr = EmitLoadMethodObjectAddr();
-
- llvm::Value* thread_object_addr = EmitGetCurrentThread();
-
- // Select intrinsic according to the invoke_type
- IntrinsicHelper::IntrinsicId invoke_intr = IntrinsicHelper::UnknownId;
- switch (invoke_type) {
- case kStatic: {
- invoke_intr = IntrinsicHelper::FindStaticMethodWithAccessCheck;
- break;
- }
- case kDirect: {
- invoke_intr = IntrinsicHelper::FindDirectMethodWithAccessCheck;
- break;
- }
- case kVirtual: {
- invoke_intr = IntrinsicHelper::FindVirtualMethodWithAccessCheck;
- break;
- }
- case kSuper: {
- invoke_intr = IntrinsicHelper::FindSuperMethodWithAccessCheck;
- break;
- }
- case kInterface: {
- invoke_intr = IntrinsicHelper::FindInterfaceMethodWithAccessCheck;
- break;
- }
- default: {
- LOG(FATAL) << "Unknown type of invoke: " << invoke_type;
- }
- }
-
- callee_method_object_addr =
- EmitInvokeIntrinsic4(dex_pc, false, invoke_intr,
- callee_method_idx_value,
- this_addr,
- caller_method_object_addr,
- thread_object_addr);
-
- if (!is_static && (!method_info_.this_will_not_be_null ||
- this_reg != method_info_.this_reg_idx)) {
- // NOTE: The null pointer test should come after the method resolution.
- // So that the "NoSuchMethodError" can be thrown before the
- // "NullPointerException".
- EmitGuard_NullPointerException(dex_pc, this_addr);
- }
- } else {
- if (!is_static && (!method_info_.this_will_not_be_null ||
- this_reg != method_info_.this_reg_idx)) {
- // NOTE: In the fast path, we should do the null pointer check
- // before the access to the class object and/or direct invocation.
- EmitGuard_NullPointerException(dex_pc, this_addr);
- }
-
- switch (invoke_type) {
- case kStatic:
- case kDirect: {
- if (direct_method != 0u &&
- direct_method != static_cast<uintptr_t>(-1)) {
- callee_method_object_addr =
- irb_.CreateIntToPtr(irb_.GetPtrEquivInt(direct_method),
- irb_.GetJMethodTy());
- } else {
- callee_method_object_addr =
- EmitInvokeIntrinsicNoThrow(IntrinsicHelper::GetSDCalleeMethodObjAddrFast,
- callee_method_idx_value);
- }
- break;
- }
- case kVirtual: {
- DCHECK(vtable_idx != -1);
- callee_method_object_addr =
- EmitInvokeIntrinsic2NoThrow(IntrinsicHelper::GetVirtualCalleeMethodObjAddrFast,
- irb_.getInt32(vtable_idx), this_addr);
- break;
- }
- case kSuper: {
- LOG(FATAL) << "invoke-super should be promoted to invoke-direct in "
- "the fast path.";
- break;
- }
- case kInterface: {
- llvm::Value* caller_method_object_addr = EmitLoadMethodObjectAddr();
-
- llvm::Value* thread_object_addr = EmitGetCurrentThread();
-
- callee_method_object_addr =
- EmitInvokeIntrinsic4(dex_pc, false,
- IntrinsicHelper::GetInterfaceCalleeMethodObjAddrFast,
- callee_method_idx_value,
- this_addr,
- caller_method_object_addr,
- thread_object_addr);
- break;
- }
- }
- }
-
- // Get the shorty of the callee
- uint32_t callee_shorty_size;
- const DexFile::MethodId& callee_method_id =
- dex_file_->GetMethodId(callee_method_idx);
- const char* callee_shorty =
- dex_file_->GetMethodShorty(callee_method_id, &callee_shorty_size);
- CHECK_GE(callee_shorty_size, 1u);
-
- JType callee_ret_jty = GetJTypeFromShorty(callee_shorty[0]);
-
- // Select the corresponding intrinsic according to the return type
- IntrinsicHelper::IntrinsicId invoke_intrinsic = IntrinsicHelper::UnknownId;
-
- switch (callee_ret_jty) {
- case kVoid: {
- invoke_intrinsic = IntrinsicHelper::InvokeRetVoid;
- break;
- }
- case kBoolean: {
- invoke_intrinsic = IntrinsicHelper::InvokeRetBoolean;
- break;
- }
- case kByte: {
- invoke_intrinsic = IntrinsicHelper::InvokeRetByte;
- break;
- }
- case kChar: {
- invoke_intrinsic = IntrinsicHelper::InvokeRetChar;
- break;
- }
- case kShort: {
- invoke_intrinsic = IntrinsicHelper::InvokeRetShort;
- break;
- }
- case kInt: {
- invoke_intrinsic = IntrinsicHelper::InvokeRetInt;
- break;
- }
- case kLong: {
- invoke_intrinsic = IntrinsicHelper::InvokeRetLong;
- break;
- }
- case kFloat: {
- invoke_intrinsic = IntrinsicHelper::InvokeRetFloat;
- break;
- }
- case kDouble: {
- invoke_intrinsic = IntrinsicHelper::InvokeRetDouble;
- break;
- }
- case kObject: {
- invoke_intrinsic = IntrinsicHelper::InvokeRetObject;
- break;
- }
- default: {
- LOG(FATAL) << "Unknown register category for type: " << callee_ret_jty;
- break;
- }
- }
-
- // Load arguments for invoke intrinsics
- std::vector<llvm::Value*> args;
-
- // Callee's method id goes first
- args.push_back(callee_method_object_addr);
-
- // Load arguments listing in the dec_insn
- unsigned arg_idx = 0;
-
- if (!is_static) {
- // Push "this" for non-static method
- args.push_back(this_addr);
- arg_idx++;
- }
-
- // Load argument values according to the shorty
- for (uint32_t i = 1; i < callee_shorty_size; i++) {
- unsigned reg_idx = (arg_fmt == kArgRange) ? (dec_insn.vC + arg_idx) :
- (dec_insn.arg[arg_idx]);
- JType jty = GetJTypeFromShorty(callee_shorty[i]);
- args.push_back(EmitLoadDalvikReg(reg_idx, jty, kAccurate));
- arg_idx++;
-
- if (GetRegCategoryFromJType(jty) == kRegCat2) {
- // Wide types occupied two registers
- arg_idx++;
- }
- }
-
- DCHECK_EQ(arg_idx, dec_insn.vA)
- << "Actual argument mismatch for callee: "
- << PrettyMethod(callee_method_idx, *dex_file_);
-
- llvm::Value* retval = EmitInvokeIntrinsic(dex_pc, true, invoke_intrinsic, args);
-
- // Store the return value for the subsequent move-result
- if (callee_shorty[0] != 'V') {
- EmitStoreDalvikRetValReg(callee_ret_jty, kAccurate, retval);
- }
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_Neg(unsigned dex_pc, const Instruction* insn,
- JType op_jty) {
- DecodedInstruction dec_insn(insn);
-
- DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
-
- llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, op_jty, kAccurate);
- llvm::Value* result_value = irb_.CreateNeg(src_value);
- EmitStoreDalvikReg(dec_insn.vA, op_jty, kAccurate, result_value);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_Not(unsigned dex_pc, const Instruction* insn,
- JType op_jty) {
- DecodedInstruction dec_insn(insn);
-
- DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
-
- llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, op_jty, kAccurate);
- llvm::Value* result_value = irb_.CreateXor(src_value, 0xFFFFFFFFFFFFFFFFLL);
-
- EmitStoreDalvikReg(dec_insn.vA, op_jty, kAccurate, result_value);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_SExt(unsigned dex_pc, const Instruction* insn) {
- DecodedInstruction dec_insn(insn);
-
- llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
- llvm::Value* result_value = irb_.CreateSExt(src_value, irb_.GetJLongTy());
- EmitStoreDalvikReg(dec_insn.vA, kLong, kAccurate, result_value);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_Trunc(unsigned dex_pc, const Instruction* insn) {
- DecodedInstruction dec_insn(insn);
-
- llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kLong, kAccurate);
- llvm::Value* result_value = irb_.CreateTrunc(src_value, irb_.GetJIntTy());
- EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result_value);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_TruncAndSExt(unsigned dex_pc, const Instruction* insn,
- unsigned N) {
- DecodedInstruction dec_insn(insn);
-
- llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
-
- llvm::Value* trunc_value =
- irb_.CreateTrunc(src_value, llvm::Type::getIntNTy(context_, N));
-
- llvm::Value* result_value = irb_.CreateSExt(trunc_value, irb_.GetJIntTy());
-
- EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result_value);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_TruncAndZExt(unsigned dex_pc, const Instruction* insn,
- unsigned N) {
- DecodedInstruction dec_insn(insn);
-
- llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
-
- llvm::Value* trunc_value =
- irb_.CreateTrunc(src_value, llvm::Type::getIntNTy(context_, N));
-
- llvm::Value* result_value = irb_.CreateZExt(trunc_value, irb_.GetJIntTy());
-
- EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result_value);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_FNeg(unsigned dex_pc, const Instruction* insn,
- JType op_jty) {
- DecodedInstruction dec_insn(insn);
-
- DCHECK(op_jty == kFloat || op_jty == kDouble) << op_jty;
-
- llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, op_jty, kAccurate);
- llvm::Value* result_value = irb_.CreateFNeg(src_value);
- EmitStoreDalvikReg(dec_insn.vA, op_jty, kAccurate, result_value);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_IntToFP(unsigned dex_pc, const Instruction* insn,
- JType src_jty, JType dest_jty) {
- DecodedInstruction dec_insn(insn);
-
- DCHECK(src_jty == kInt || src_jty == kLong) << src_jty;
- DCHECK(dest_jty == kFloat || dest_jty == kDouble) << dest_jty;
-
- llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, src_jty, kAccurate);
- llvm::Type* dest_type = irb_.GetJType(dest_jty, kAccurate);
- llvm::Value* dest_value = irb_.CreateSIToFP(src_value, dest_type);
- EmitStoreDalvikReg(dec_insn.vA, dest_jty, kAccurate, dest_value);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_FPToInt(unsigned dex_pc, const Instruction* insn,
- JType src_jty, JType dest_jty,
- IntrinsicHelper::IntrinsicId intr_id) {
- DecodedInstruction dec_insn(insn);
-
- DCHECK(src_jty == kFloat || src_jty == kDouble) << src_jty;
- DCHECK(dest_jty == kInt || dest_jty == kLong) << dest_jty;
-
- llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, src_jty, kAccurate);
- llvm::Value* dest_value = EmitInvokeIntrinsicNoThrow(intr_id, src_value);
- EmitStoreDalvikReg(dec_insn.vA, dest_jty, kAccurate, dest_value);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_FExt(unsigned dex_pc, const Instruction* insn) {
- DecodedInstruction dec_insn(insn);
-
- llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kFloat, kAccurate);
- llvm::Value* result_value = irb_.CreateFPExt(src_value, irb_.GetJDoubleTy());
- EmitStoreDalvikReg(dec_insn.vA, kDouble, kAccurate, result_value);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_FTrunc(unsigned dex_pc, const Instruction* insn) {
- DecodedInstruction dec_insn(insn);
-
- llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kDouble, kAccurate);
- llvm::Value* result_value = irb_.CreateFPTrunc(src_value, irb_.GetJFloatTy());
- EmitStoreDalvikReg(dec_insn.vA, kFloat, kAccurate, result_value);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_IntArithm(unsigned dex_pc, const Instruction* insn,
- IntArithmKind arithm, JType op_jty,
- bool is_2addr) {
- DecodedInstruction dec_insn(insn);
-
- DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
-
- llvm::Value* src1_value;
- llvm::Value* src2_value;
-
- if (is_2addr) {
- src1_value = EmitLoadDalvikReg(dec_insn.vA, op_jty, kAccurate);
- src2_value = EmitLoadDalvikReg(dec_insn.vB, op_jty, kAccurate);
- } else {
- src1_value = EmitLoadDalvikReg(dec_insn.vB, op_jty, kAccurate);
- src2_value = EmitLoadDalvikReg(dec_insn.vC, op_jty, kAccurate);
- }
-
- llvm::Value* result_value =
- EmitIntArithmResultComputation(dex_pc, src1_value, src2_value,
- arithm, op_jty);
-
- EmitStoreDalvikReg(dec_insn.vA, op_jty, kAccurate, result_value);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_IntArithmImmediate(unsigned dex_pc,
- const Instruction* insn,
- IntArithmKind arithm) {
- DecodedInstruction dec_insn(insn);
-
- llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
-
- llvm::Value* imm_value = irb_.getInt32(dec_insn.vC);
-
- llvm::Value* result_value =
- EmitIntArithmResultComputation(dex_pc, src_value, imm_value, arithm, kInt);
-
- EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result_value);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_IntShiftArithm(unsigned dex_pc, const Instruction* insn,
- IntShiftArithmKind arithm, JType op_jty,
- bool is_2addr) {
- DecodedInstruction dec_insn(insn);
-
- DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
-
- llvm::Value* src1_value;
- llvm::Value* src2_value;
-
- // NOTE: The 2nd operand of the shift arithmetic instruction is
- // 32-bit integer regardless of the 1st operand.
- if (is_2addr) {
- src1_value = EmitLoadDalvikReg(dec_insn.vA, op_jty, kAccurate);
- src2_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
- } else {
- src1_value = EmitLoadDalvikReg(dec_insn.vB, op_jty, kAccurate);
- src2_value = EmitLoadDalvikReg(dec_insn.vC, kInt, kAccurate);
- }
-
- llvm::Value* result_value = EmitIntShiftArithmResultComputation(dex_pc,
- src1_value,
- src2_value,
- arithm,
- op_jty);
-
- EmitStoreDalvikReg(dec_insn.vA, op_jty, kAccurate, result_value);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_IntShiftArithmImmediate(unsigned dex_pc,
- const Instruction* insn,
- IntShiftArithmKind arithm) {
- DecodedInstruction dec_insn(insn);
-
- llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
-
- llvm::Value* imm_value = irb_.getInt32(dec_insn.vC);
-
- llvm::Value* result_value = EmitIntShiftArithmResultComputation(dex_pc,
- src_value,
- imm_value,
- arithm, kInt);
-
- EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result_value);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_RSubImmediate(unsigned dex_pc, const Instruction* insn) {
- DecodedInstruction dec_insn(insn);
-
- llvm::Value* src_value = EmitLoadDalvikReg(dec_insn.vB, kInt, kAccurate);
- llvm::Value* imm_value = irb_.getInt32(dec_insn.vC);
- llvm::Value* result_value = irb_.CreateSub(imm_value, src_value);
- EmitStoreDalvikReg(dec_insn.vA, kInt, kAccurate, result_value);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-void DexLang::EmitInsn_FPArithm(unsigned dex_pc, const Instruction* insn,
- FPArithmKind arithm, JType op_jty,
- bool is_2addr) {
- DecodedInstruction dec_insn(insn);
-
- DCHECK(op_jty == kFloat || op_jty == kDouble) << op_jty;
-
- llvm::Value* src1_value;
- llvm::Value* src2_value;
-
- if (is_2addr) {
- src1_value = EmitLoadDalvikReg(dec_insn.vA, op_jty, kAccurate);
- src2_value = EmitLoadDalvikReg(dec_insn.vB, op_jty, kAccurate);
- } else {
- src1_value = EmitLoadDalvikReg(dec_insn.vB, op_jty, kAccurate);
- src2_value = EmitLoadDalvikReg(dec_insn.vC, op_jty, kAccurate);
- }
-
- llvm::Value* result_value;
- switch (arithm) {
- case kFPArithm_Add: {
- result_value = irb_.CreateFAdd(src1_value, src2_value);
- break;
- }
- case kFPArithm_Sub: {
- result_value = irb_.CreateFSub(src1_value, src2_value);
- break;
- }
- case kFPArithm_Mul: {
- result_value = irb_.CreateFMul(src1_value, src2_value);
- break;
- }
- case kFPArithm_Div: {
- result_value = irb_.CreateFDiv(src1_value, src2_value);
- break;
- }
- case kFPArithm_Rem: {
- result_value = irb_.CreateFRem(src1_value, src2_value);
- break;
- }
- default: {
- LOG(FATAL) << "Unknown floating-point arithmetic kind: " << arithm;
- return;
- }
- }
-
- EmitStoreDalvikReg(dec_insn.vA, op_jty, kAccurate, result_value);
-
- irb_.CreateBr(GetNextBasicBlock(dex_pc));
- return;
-}
-
-bool DexLang::EmitInstructions() {
- unsigned dex_pc = 0;
- while (dex_pc < code_item_->insns_size_in_code_units_) {
- const Instruction* insn = Instruction::At(code_item_->insns_ + dex_pc);
- if (!EmitInstruction(dex_pc, insn)) {
- return false;
- }
- dex_pc += insn->SizeInCodeUnits();
- }
- return true;
-}
-
-bool DexLang::EmitInstruction(unsigned dex_pc, const Instruction* insn) {
- // Set the IRBuilder insertion point
- irb_.SetInsertPoint(GetBasicBlock(dex_pc));
-
-#define ARGS dex_pc, insn
-
- // Dispatch the instruction
- switch (insn->Opcode()) {
- case Instruction::NOP: {
- EmitInsn_Nop(ARGS);
- break;
- }
- case Instruction::MOVE:
- case Instruction::MOVE_FROM16:
- case Instruction::MOVE_16: {
- EmitInsn_Move(ARGS, kInt);
- break;
- }
- case Instruction::MOVE_WIDE:
- case Instruction::MOVE_WIDE_FROM16:
- case Instruction::MOVE_WIDE_16: {
- EmitInsn_Move(ARGS, kLong);
- break;
- }
- case Instruction::MOVE_OBJECT:
- case Instruction::MOVE_OBJECT_FROM16:
- case Instruction::MOVE_OBJECT_16: {
- EmitInsn_Move(ARGS, kObject);
- break;
- }
- case Instruction::MOVE_RESULT: {
- EmitInsn_MoveResult(ARGS, kInt);
- break;
- }
- case Instruction::MOVE_RESULT_WIDE: {
- EmitInsn_MoveResult(ARGS, kLong);
- break;
- }
- case Instruction::MOVE_RESULT_OBJECT: {
- EmitInsn_MoveResult(ARGS, kObject);
- break;
- }
- case Instruction::MOVE_EXCEPTION: {
- EmitInsn_MoveException(ARGS);
- break;
- }
- case Instruction::RETURN_VOID: {
- EmitInsn_ReturnVoid(ARGS);
- break;
- }
- case Instruction::RETURN:
- case Instruction::RETURN_WIDE:
- case Instruction::RETURN_OBJECT: {
- EmitInsn_Return(ARGS);
- break;
- }
- case Instruction::CONST_4:
- case Instruction::CONST_16:
- case Instruction::CONST:
- case Instruction::CONST_HIGH16: {
- EmitInsn_LoadConstant(ARGS, kInt);
- break;
- }
- case Instruction::CONST_WIDE_16:
- case Instruction::CONST_WIDE_32:
- case Instruction::CONST_WIDE:
- case Instruction::CONST_WIDE_HIGH16: {
- EmitInsn_LoadConstant(ARGS, kLong);
- break;
- }
- case Instruction::CONST_STRING:
- case Instruction::CONST_STRING_JUMBO: {
- EmitInsn_LoadConstantString(ARGS);
- break;
- }
- case Instruction::CONST_CLASS: {
- EmitInsn_LoadConstantClass(ARGS);
- break;
- }
- case Instruction::MONITOR_ENTER: {
- EmitInsn_MonitorEnter(ARGS);
- break;
- }
- case Instruction::MONITOR_EXIT: {
- EmitInsn_MonitorExit(ARGS);
- break;
- }
- case Instruction::CHECK_CAST: {
- EmitInsn_CheckCast(ARGS);
- break;
- }
- case Instruction::INSTANCE_OF: {
- EmitInsn_InstanceOf(ARGS);
- break;
- }
- case Instruction::ARRAY_LENGTH: {
- EmitInsn_ArrayLength(ARGS);
- break;
- }
- case Instruction::NEW_INSTANCE:
- EmitInsn_NewInstance(ARGS);
- break;
-
- case Instruction::NEW_ARRAY: {
- EmitInsn_NewArray(ARGS);
- break;
- }
- case Instruction::FILLED_NEW_ARRAY:
- EmitInsn_FilledNewArray(ARGS, /* is_range */false);
- break;
-
- case Instruction::FILLED_NEW_ARRAY_RANGE:
- EmitInsn_FilledNewArray(ARGS, /* is_range */true);
- break;
-
- case Instruction::FILL_ARRAY_DATA:
- EmitInsn_FillArrayData(ARGS);
- break;
-
- case Instruction::THROW: {
- EmitInsn_ThrowException(ARGS);
- break;
- }
- case Instruction::GOTO:
- case Instruction::GOTO_16:
- case Instruction::GOTO_32: {
- EmitInsn_UnconditionalBranch(ARGS);
- break;
- }
- case Instruction::PACKED_SWITCH: {
- EmitInsn_PackedSwitch(ARGS);
- break;
- }
- case Instruction::SPARSE_SWITCH: {
- EmitInsn_SparseSwitch(ARGS);
- break;
- }
- case Instruction::CMPL_FLOAT: {
- EmitInsn_FPCompare(ARGS, kFloat, false);
- break;
- }
- case Instruction::CMPG_FLOAT: {
- EmitInsn_FPCompare(ARGS, kFloat, true);
- break;
- }
- case Instruction::CMPL_DOUBLE: {
- EmitInsn_FPCompare(ARGS, kDouble, false);
- break;
- }
- case Instruction::CMPG_DOUBLE: {
- EmitInsn_FPCompare(ARGS, kDouble, true);
- break;
- }
- case Instruction::CMP_LONG: {
- EmitInsn_LongCompare(ARGS);
- break;
- }
- case Instruction::IF_EQ: {
- EmitInsn_BinaryConditionalBranch(ARGS, kCondBranch_EQ);
- break;
- }
- case Instruction::IF_NE: {
- EmitInsn_BinaryConditionalBranch(ARGS, kCondBranch_NE);
- break;
- }
- case Instruction::IF_LT: {
- EmitInsn_BinaryConditionalBranch(ARGS, kCondBranch_LT);
- break;
- }
- case Instruction::IF_GE: {
- EmitInsn_BinaryConditionalBranch(ARGS, kCondBranch_GE);
- break;
- }
- case Instruction::IF_GT: {
- EmitInsn_BinaryConditionalBranch(ARGS, kCondBranch_GT);
- break;
- }
- case Instruction::IF_LE: {
- EmitInsn_BinaryConditionalBranch(ARGS, kCondBranch_LE);
- break;
- }
- case Instruction::IF_EQZ: {
- EmitInsn_UnaryConditionalBranch(ARGS, kCondBranch_EQ);
- break;
- }
- case Instruction::IF_NEZ: {
- EmitInsn_UnaryConditionalBranch(ARGS, kCondBranch_NE);
- break;
- }
- case Instruction::IF_LTZ: {
- EmitInsn_UnaryConditionalBranch(ARGS, kCondBranch_LT);
- break;
- }
- case Instruction::IF_GEZ: {
- EmitInsn_UnaryConditionalBranch(ARGS, kCondBranch_GE);
- break;
- }
- case Instruction::IF_GTZ: {
- EmitInsn_UnaryConditionalBranch(ARGS, kCondBranch_GT);
- break;
- }
- case Instruction::IF_LEZ: {
- EmitInsn_UnaryConditionalBranch(ARGS, kCondBranch_LE);
- break;
- }
- case Instruction::AGET: {
- EmitInsn_AGet(ARGS, kInt);
- break;
- }
- case Instruction::AGET_WIDE: {
- EmitInsn_AGet(ARGS, kLong);
- break;
- }
- case Instruction::AGET_OBJECT: {
- EmitInsn_AGet(ARGS, kObject);
- break;
- }
- case Instruction::AGET_BOOLEAN: {
- EmitInsn_AGet(ARGS, kBoolean);
- break;
- }
- case Instruction::AGET_BYTE: {
- EmitInsn_AGet(ARGS, kByte);
- break;
- }
- case Instruction::AGET_CHAR: {
- EmitInsn_AGet(ARGS, kChar);
- break;
- }
- case Instruction::AGET_SHORT: {
- EmitInsn_AGet(ARGS, kShort);
- break;
- }
- case Instruction::APUT: {
- EmitInsn_APut(ARGS, kInt);
- break;
- }
- case Instruction::APUT_WIDE: {
- EmitInsn_APut(ARGS, kLong);
- break;
- }
- case Instruction::APUT_OBJECT: {
- EmitInsn_APut(ARGS, kObject);
- break;
- }
- case Instruction::APUT_BOOLEAN: {
- EmitInsn_APut(ARGS, kBoolean);
- break;
- }
- case Instruction::APUT_BYTE: {
- EmitInsn_APut(ARGS, kByte);
- break;
- }
- case Instruction::APUT_CHAR: {
- EmitInsn_APut(ARGS, kChar);
- break;
- }
- case Instruction::APUT_SHORT: {
- EmitInsn_APut(ARGS, kShort);
- break;
- }
- case Instruction::IGET: {
- EmitInsn_IGet(ARGS, kInt);
- break;
- }
- case Instruction::IGET_WIDE: {
- EmitInsn_IGet(ARGS, kLong);
- break;
- }
- case Instruction::IGET_OBJECT: {
- EmitInsn_IGet(ARGS, kObject);
- break;
- }
- case Instruction::IGET_BOOLEAN: {
- EmitInsn_IGet(ARGS, kBoolean);
- break;
- }
- case Instruction::IGET_BYTE: {
- EmitInsn_IGet(ARGS, kByte);
- break;
- }
- case Instruction::IGET_CHAR: {
- EmitInsn_IGet(ARGS, kChar);
- break;
- }
- case Instruction::IGET_SHORT: {
- EmitInsn_IGet(ARGS, kShort);
- break;
- }
- case Instruction::IPUT: {
- EmitInsn_IPut(ARGS, kInt);
- break;
- }
- case Instruction::IPUT_WIDE: {
- EmitInsn_IPut(ARGS, kLong);
- break;
- }
- case Instruction::IPUT_OBJECT: {
- EmitInsn_IPut(ARGS, kObject);
- break;
- }
- case Instruction::IPUT_BOOLEAN: {
- EmitInsn_IPut(ARGS, kBoolean);
- break;
- }
- case Instruction::IPUT_BYTE: {
- EmitInsn_IPut(ARGS, kByte);
- break;
- }
- case Instruction::IPUT_CHAR: {
- EmitInsn_IPut(ARGS, kChar);
- break;
- }
- case Instruction::IPUT_SHORT: {
- EmitInsn_IPut(ARGS, kShort);
- break;
- }
- case Instruction::SGET: {
- EmitInsn_SGet(ARGS, kInt);
- break;
- }
- case Instruction::SGET_WIDE: {
- EmitInsn_SGet(ARGS, kLong);
- break;
- }
- case Instruction::SGET_OBJECT: {
- EmitInsn_SGet(ARGS, kObject);
- break;
- }
- case Instruction::SGET_BOOLEAN: {
- EmitInsn_SGet(ARGS, kBoolean);
- break;
- }
- case Instruction::SGET_BYTE: {
- EmitInsn_SGet(ARGS, kByte);
- break;
- }
- case Instruction::SGET_CHAR: {
- EmitInsn_SGet(ARGS, kChar);
- break;
- }
- case Instruction::SGET_SHORT: {
- EmitInsn_SGet(ARGS, kShort);
- break;
- }
- case Instruction::SPUT: {
- EmitInsn_SPut(ARGS, kInt);
- break;
- }
- case Instruction::SPUT_WIDE: {
- EmitInsn_SPut(ARGS, kLong);
- break;
- }
- case Instruction::SPUT_OBJECT: {
- EmitInsn_SPut(ARGS, kObject);
- break;
- }
- case Instruction::SPUT_BOOLEAN: {
- EmitInsn_SPut(ARGS, kBoolean);
- break;
- }
- case Instruction::SPUT_BYTE: {
- EmitInsn_SPut(ARGS, kByte);
- break;
- }
- case Instruction::SPUT_CHAR: {
- EmitInsn_SPut(ARGS, kChar);
- break;
- }
- case Instruction::SPUT_SHORT: {
- EmitInsn_SPut(ARGS, kShort);
- break;
- }
- case Instruction::INVOKE_VIRTUAL: {
- EmitInsn_Invoke(ARGS, kVirtual, kArgReg);
- break;
- }
- case Instruction::INVOKE_SUPER: {
- EmitInsn_Invoke(ARGS, kSuper, kArgReg);
- break;
- }
- case Instruction::INVOKE_DIRECT: {
- EmitInsn_Invoke(ARGS, kDirect, kArgReg);
- break;
- }
- case Instruction::INVOKE_STATIC: {
- EmitInsn_Invoke(ARGS, kStatic, kArgReg);
- break;
- }
- case Instruction::INVOKE_INTERFACE: {
- EmitInsn_Invoke(ARGS, kInterface, kArgReg);
- break;
- }
- case Instruction::INVOKE_VIRTUAL_RANGE: {
- EmitInsn_Invoke(ARGS, kVirtual, kArgRange);
- break;
- }
- case Instruction::INVOKE_SUPER_RANGE: {
- EmitInsn_Invoke(ARGS, kSuper, kArgRange);
- break;
- }
- case Instruction::INVOKE_DIRECT_RANGE: {
- EmitInsn_Invoke(ARGS, kDirect, kArgRange);
- break;
- }
- case Instruction::INVOKE_STATIC_RANGE: {
- EmitInsn_Invoke(ARGS, kStatic, kArgRange);
- break;
- }
- case Instruction::INVOKE_INTERFACE_RANGE: {
- EmitInsn_Invoke(ARGS, kInterface, kArgRange);
- break;
- }
- case Instruction::NEG_INT: {
- EmitInsn_Neg(ARGS, kInt);
- break;
- }
- case Instruction::NOT_INT: {
- EmitInsn_Not(ARGS, kInt);
- break;
- }
- case Instruction::NEG_LONG: {
- EmitInsn_Neg(ARGS, kLong);
- break;
- }
- case Instruction::NOT_LONG: {
- EmitInsn_Not(ARGS, kLong);
- break;
- }
- case Instruction::NEG_FLOAT: {
- EmitInsn_FNeg(ARGS, kFloat);
- break;
- }
- case Instruction::NEG_DOUBLE: {
- EmitInsn_FNeg(ARGS, kDouble);
- break;
- }
- case Instruction::INT_TO_LONG: {
- EmitInsn_SExt(ARGS);
- break;
- }
- case Instruction::INT_TO_FLOAT: {
- EmitInsn_IntToFP(ARGS, kInt, kFloat);
- break;
- }
- case Instruction::INT_TO_DOUBLE: {
- EmitInsn_IntToFP(ARGS, kInt, kDouble);
- break;
- }
- case Instruction::LONG_TO_INT: {
- EmitInsn_Trunc(ARGS);
- break;
- }
- case Instruction::LONG_TO_FLOAT: {
- EmitInsn_IntToFP(ARGS, kLong, kFloat);
- break;
- }
- case Instruction::LONG_TO_DOUBLE: {
- EmitInsn_IntToFP(ARGS, kLong, kDouble);
- break;
- }
- case Instruction::FLOAT_TO_INT: {
- EmitInsn_FPToInt(ARGS, kFloat, kInt, IntrinsicHelper::F2I);
- break;
- }
- case Instruction::FLOAT_TO_LONG: {
- EmitInsn_FPToInt(ARGS, kFloat, kLong, IntrinsicHelper::F2L);
- break;
- }
- case Instruction::FLOAT_TO_DOUBLE: {
- EmitInsn_FExt(ARGS);
- break;
- }
- case Instruction::DOUBLE_TO_INT: {
- EmitInsn_FPToInt(ARGS, kDouble, kInt, IntrinsicHelper::D2I);
- break;
- }
- case Instruction::DOUBLE_TO_LONG: {
- EmitInsn_FPToInt(ARGS, kDouble, kLong, IntrinsicHelper::D2L);
- break;
- }
- case Instruction::DOUBLE_TO_FLOAT: {
- EmitInsn_FTrunc(ARGS);
- break;
- }
- case Instruction::INT_TO_BYTE: {
- EmitInsn_TruncAndSExt(ARGS, 8);
- break;
- }
- case Instruction::INT_TO_CHAR: {
- EmitInsn_TruncAndZExt(ARGS, 16);
- break;
- }
- case Instruction::INT_TO_SHORT: {
- EmitInsn_TruncAndSExt(ARGS, 16);
- break;
- }
- case Instruction::ADD_INT: {
- EmitInsn_IntArithm(ARGS, kIntArithm_Add, kInt, false);
- break;
- }
- case Instruction::SUB_INT: {
- EmitInsn_IntArithm(ARGS, kIntArithm_Sub, kInt, false);
- break;
- }
- case Instruction::MUL_INT: {
- EmitInsn_IntArithm(ARGS, kIntArithm_Mul, kInt, false);
- break;
- }
- case Instruction::DIV_INT: {
- EmitInsn_IntArithm(ARGS, kIntArithm_Div, kInt, false);
- break;
- }
- case Instruction::REM_INT: {
- EmitInsn_IntArithm(ARGS, kIntArithm_Rem, kInt, false);
- break;
- }
- case Instruction::AND_INT: {
- EmitInsn_IntArithm(ARGS, kIntArithm_And, kInt, false);
- break;
- }
- case Instruction::OR_INT: {
- EmitInsn_IntArithm(ARGS, kIntArithm_Or, kInt, false);
- break;
- }
- case Instruction::XOR_INT: {
- EmitInsn_IntArithm(ARGS, kIntArithm_Xor, kInt, false);
- break;
- }
- case Instruction::SHL_INT: {
- EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shl, kInt, false);
- break;
- }
- case Instruction::SHR_INT: {
- EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shr, kInt, false);
- break;
- }
- case Instruction::USHR_INT: {
- EmitInsn_IntShiftArithm(ARGS, kIntArithm_UShr, kInt, false);
- break;
- }
- case Instruction::ADD_LONG: {
- EmitInsn_IntArithm(ARGS, kIntArithm_Add, kLong, false);
- break;
- }
- case Instruction::SUB_LONG: {
- EmitInsn_IntArithm(ARGS, kIntArithm_Sub, kLong, false);
- break;
- }
- case Instruction::MUL_LONG: {
- EmitInsn_IntArithm(ARGS, kIntArithm_Mul, kLong, false);
- break;
- }
- case Instruction::DIV_LONG: {
- EmitInsn_IntArithm(ARGS, kIntArithm_Div, kLong, false);
- break;
- }
- case Instruction::REM_LONG: {
- EmitInsn_IntArithm(ARGS, kIntArithm_Rem, kLong, false);
- break;
- }
- case Instruction::AND_LONG: {
- EmitInsn_IntArithm(ARGS, kIntArithm_And, kLong, false);
- break;
- }
- case Instruction::OR_LONG: {
- EmitInsn_IntArithm(ARGS, kIntArithm_Or, kLong, false);
- break;
- }
- case Instruction::XOR_LONG: {
- EmitInsn_IntArithm(ARGS, kIntArithm_Xor, kLong, false);
- break;
- }
- case Instruction::SHL_LONG: {
- EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shl, kLong, false);
- break;
- }
- case Instruction::SHR_LONG: {
- EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shr, kLong, false);
- break;
- }
- case Instruction::USHR_LONG: {
- EmitInsn_IntShiftArithm(ARGS, kIntArithm_UShr, kLong, false);
- break;
- }
- case Instruction::ADD_FLOAT: {
- EmitInsn_FPArithm(ARGS, kFPArithm_Add, kFloat, false);
- break;
- }
- case Instruction::SUB_FLOAT: {
- EmitInsn_FPArithm(ARGS, kFPArithm_Sub, kFloat, false);
- break;
- }
- case Instruction::MUL_FLOAT: {
- EmitInsn_FPArithm(ARGS, kFPArithm_Mul, kFloat, false);
- break;
- }
- case Instruction::DIV_FLOAT: {
- EmitInsn_FPArithm(ARGS, kFPArithm_Div, kFloat, false);
- break;
- }
- case Instruction::REM_FLOAT: {
- EmitInsn_FPArithm(ARGS, kFPArithm_Rem, kFloat, false);
- break;
- }
- case Instruction::ADD_DOUBLE: {
- EmitInsn_FPArithm(ARGS, kFPArithm_Add, kDouble, false);
- break;
- }
- case Instruction::SUB_DOUBLE: {
- EmitInsn_FPArithm(ARGS, kFPArithm_Sub, kDouble, false);
- break;
- }
- case Instruction::MUL_DOUBLE: {
- EmitInsn_FPArithm(ARGS, kFPArithm_Mul, kDouble, false);
- break;
- }
- case Instruction::DIV_DOUBLE: {
- EmitInsn_FPArithm(ARGS, kFPArithm_Div, kDouble, false);
- break;
- }
- case Instruction::REM_DOUBLE: {
- EmitInsn_FPArithm(ARGS, kFPArithm_Rem, kDouble, false);
- break;
- }
- case Instruction::ADD_INT_2ADDR: {
- EmitInsn_IntArithm(ARGS, kIntArithm_Add, kInt, true);
- break;
- }
- case Instruction::SUB_INT_2ADDR: {
- EmitInsn_IntArithm(ARGS, kIntArithm_Sub, kInt, true);
- break;
- }
- case Instruction::MUL_INT_2ADDR: {
- EmitInsn_IntArithm(ARGS, kIntArithm_Mul, kInt, true);
- break;
- }
- case Instruction::DIV_INT_2ADDR: {
- EmitInsn_IntArithm(ARGS, kIntArithm_Div, kInt, true);
- break;
- }
- case Instruction::REM_INT_2ADDR: {
- EmitInsn_IntArithm(ARGS, kIntArithm_Rem, kInt, true);
- break;
- }
- case Instruction::AND_INT_2ADDR: {
- EmitInsn_IntArithm(ARGS, kIntArithm_And, kInt, true);
- break;
- }
- case Instruction::OR_INT_2ADDR: {
- EmitInsn_IntArithm(ARGS, kIntArithm_Or, kInt, true);
- break;
- }
- case Instruction::XOR_INT_2ADDR: {
- EmitInsn_IntArithm(ARGS, kIntArithm_Xor, kInt, true);
- break;
- }
- case Instruction::SHL_INT_2ADDR: {
- EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shl, kInt, true);
- break;
- }
- case Instruction::SHR_INT_2ADDR: {
- EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shr, kInt, true);
- break;
- }
- case Instruction::USHR_INT_2ADDR: {
- EmitInsn_IntShiftArithm(ARGS, kIntArithm_UShr, kInt, true);
- break;
- }
- case Instruction::ADD_LONG_2ADDR: {
- EmitInsn_IntArithm(ARGS, kIntArithm_Add, kLong, true);
- break;
- }
- case Instruction::SUB_LONG_2ADDR: {
- EmitInsn_IntArithm(ARGS, kIntArithm_Sub, kLong, true);
- break;
- }
- case Instruction::MUL_LONG_2ADDR: {
- EmitInsn_IntArithm(ARGS, kIntArithm_Mul, kLong, true);
- break;
- }
- case Instruction::DIV_LONG_2ADDR: {
- EmitInsn_IntArithm(ARGS, kIntArithm_Div, kLong, true);
- break;
- }
- case Instruction::REM_LONG_2ADDR: {
- EmitInsn_IntArithm(ARGS, kIntArithm_Rem, kLong, true);
- break;
- }
- case Instruction::AND_LONG_2ADDR: {
- EmitInsn_IntArithm(ARGS, kIntArithm_And, kLong, true);
- break;
- }
- case Instruction::OR_LONG_2ADDR: {
- EmitInsn_IntArithm(ARGS, kIntArithm_Or, kLong, true);
- break;
- }
- case Instruction::XOR_LONG_2ADDR: {
- EmitInsn_IntArithm(ARGS, kIntArithm_Xor, kLong, true);
- break;
- }
- case Instruction::SHL_LONG_2ADDR: {
- EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shl, kLong, true);
- break;
- }
- case Instruction::SHR_LONG_2ADDR: {
- EmitInsn_IntShiftArithm(ARGS, kIntArithm_Shr, kLong, true);
- break;
- }
- case Instruction::USHR_LONG_2ADDR: {
- EmitInsn_IntShiftArithm(ARGS, kIntArithm_UShr, kLong, true);
- break;
- }
- case Instruction::ADD_FLOAT_2ADDR: {
- EmitInsn_FPArithm(ARGS, kFPArithm_Add, kFloat, true);
- break;
- }
- case Instruction::SUB_FLOAT_2ADDR: {
- EmitInsn_FPArithm(ARGS, kFPArithm_Sub, kFloat, true);
- break;
- }
- case Instruction::MUL_FLOAT_2ADDR: {
- EmitInsn_FPArithm(ARGS, kFPArithm_Mul, kFloat, true);
- break;
- }
- case Instruction::DIV_FLOAT_2ADDR: {
- EmitInsn_FPArithm(ARGS, kFPArithm_Div, kFloat, true);
- break;
- }
- case Instruction::REM_FLOAT_2ADDR: {
- EmitInsn_FPArithm(ARGS, kFPArithm_Rem, kFloat, true);
- break;
- }
- case Instruction::ADD_DOUBLE_2ADDR: {
- EmitInsn_FPArithm(ARGS, kFPArithm_Add, kDouble, true);
- break;
- }
- case Instruction::SUB_DOUBLE_2ADDR: {
- EmitInsn_FPArithm(ARGS, kFPArithm_Sub, kDouble, true);
- break;
- }
- case Instruction::MUL_DOUBLE_2ADDR: {
- EmitInsn_FPArithm(ARGS, kFPArithm_Mul, kDouble, true);
- break;
- }
- case Instruction::DIV_DOUBLE_2ADDR: {
- EmitInsn_FPArithm(ARGS, kFPArithm_Div, kDouble, true);
- break;
- }
- case Instruction::REM_DOUBLE_2ADDR: {
- EmitInsn_FPArithm(ARGS, kFPArithm_Rem, kDouble, true);
- break;
- }
- case Instruction::ADD_INT_LIT16:
- case Instruction::ADD_INT_LIT8: {
- EmitInsn_IntArithmImmediate(ARGS, kIntArithm_Add);
- break;
- }
- case Instruction::RSUB_INT:
- case Instruction::RSUB_INT_LIT8: {
- EmitInsn_RSubImmediate(ARGS);
- break;
- }
- case Instruction::MUL_INT_LIT16:
- case Instruction::MUL_INT_LIT8: {
- EmitInsn_IntArithmImmediate(ARGS, kIntArithm_Mul);
- break;
- }
- case Instruction::DIV_INT_LIT16:
- case Instruction::DIV_INT_LIT8: {
- EmitInsn_IntArithmImmediate(ARGS, kIntArithm_Div);
- break;
- }
- case Instruction::REM_INT_LIT16:
- case Instruction::REM_INT_LIT8: {
- EmitInsn_IntArithmImmediate(ARGS, kIntArithm_Rem);
- break;
- }
- case Instruction::AND_INT_LIT16:
- case Instruction::AND_INT_LIT8: {
- EmitInsn_IntArithmImmediate(ARGS, kIntArithm_And);
- break;
- }
- case Instruction::OR_INT_LIT16:
- case Instruction::OR_INT_LIT8: {
- EmitInsn_IntArithmImmediate(ARGS, kIntArithm_Or);
- break;
- }
- case Instruction::XOR_INT_LIT16:
- case Instruction::XOR_INT_LIT8: {
- EmitInsn_IntArithmImmediate(ARGS, kIntArithm_Xor);
- break;
- }
- case Instruction::SHL_INT_LIT8: {
- EmitInsn_IntShiftArithmImmediate(ARGS, kIntArithm_Shl);
- break;
- }
- case Instruction::SHR_INT_LIT8: {
- EmitInsn_IntShiftArithmImmediate(ARGS, kIntArithm_Shr);
- break;
- }
- case Instruction::USHR_INT_LIT8: {
- EmitInsn_IntShiftArithmImmediate(ARGS, kIntArithm_UShr);
- break;
- }
-
- case Instruction::UNUSED_3E:
- case Instruction::UNUSED_3F:
- case Instruction::UNUSED_40:
- case Instruction::UNUSED_41:
- case Instruction::UNUSED_42:
- case Instruction::UNUSED_43:
- case Instruction::UNUSED_73:
- case Instruction::UNUSED_79:
- case Instruction::UNUSED_7A:
- case Instruction::UNUSED_E3:
- case Instruction::UNUSED_E4:
- case Instruction::UNUSED_E5:
- case Instruction::UNUSED_E6:
- case Instruction::UNUSED_E7:
- case Instruction::UNUSED_E8:
- case Instruction::UNUSED_E9:
- case Instruction::UNUSED_EA:
- case Instruction::UNUSED_EB:
- case Instruction::UNUSED_EC:
- case Instruction::UNUSED_ED:
- case Instruction::UNUSED_EE:
- case Instruction::UNUSED_EF:
- case Instruction::UNUSED_F0:
- case Instruction::UNUSED_F1:
- case Instruction::UNUSED_F2:
- case Instruction::UNUSED_F3:
- case Instruction::UNUSED_F4:
- case Instruction::UNUSED_F5:
- case Instruction::UNUSED_F6:
- case Instruction::UNUSED_F7:
- case Instruction::UNUSED_F8:
- case Instruction::UNUSED_F9:
- case Instruction::UNUSED_FA:
- case Instruction::UNUSED_FB:
- case Instruction::UNUSED_FC:
- case Instruction::UNUSED_FD:
- case Instruction::UNUSED_FE:
- case Instruction::UNUSED_FF: {
- LOG(FATAL) << "Dex file contains UNUSED bytecode: " << insn->Opcode();
- }
- }
-#undef ARGS
-
- return true;
-}
-
-
-bool DexLang::IsInstructionDirectToReturn(unsigned dex_pc) {
- for (int i = 0; i < 8; ++i) { // Trace at most 8 instructions.
- if (dex_pc >= code_item_->insns_size_in_code_units_) {
- return false;
- }
-
- Instruction const* insn = Instruction::At(code_item_->insns_ + dex_pc);
-
- if (insn->IsReturn()) {
- return true;
- }
-
- // Is throw, switch, invoke or conditional branch.
- if (insn->IsThrow() || insn->IsSwitch() || insn->IsInvoke() ||
- (insn->IsBranch() && !insn->IsUnconditional())) {
- return false;
- }
-
- switch (insn->Opcode()) {
- default:
- dex_pc += insn->SizeInCodeUnits();
- break;
-
- // This instruction will remove the exception. Consider as a side effect.
- case Instruction::MOVE_EXCEPTION:
- return false;
- break;
-
- case Instruction::GOTO:
- case Instruction::GOTO_16:
- case Instruction::GOTO_32:
- {
- DecodedInstruction dec_insn(insn);
- int32_t branch_offset = dec_insn.vA;
- dex_pc += branch_offset;
- }
- break;
- }
- }
- return false;
-}
-
-
-// TODO: Use high-level IR to do this
-void DexLang::ComputeMethodInfo() {
- // If this method is static, we set the "this" register index to -1. So we don't worry about this
- // method is static or not in the following comparison.
- int64_t this_reg_idx = (cunit_.IsStatic()) ?
- (-1) :
- (code_item_->registers_size_ - code_item_->ins_size_);
- bool has_invoke = false;
- bool may_have_loop = false;
- bool may_throw_exception = false;
- bool assume_this_non_null = false;
- std::vector<bool>& set_to_another_object = method_info_.set_to_another_object;
- set_to_another_object.resize(code_item_->registers_size_, false);
-
- Instruction const* insn;
- for (uint32_t dex_pc = 0;
- dex_pc < code_item_->insns_size_in_code_units_;
- dex_pc += insn->SizeInCodeUnits()) {
- insn = Instruction::At(code_item_->insns_ + dex_pc);
- DecodedInstruction dec_insn(insn);
-
- switch (insn->Opcode()) {
- case Instruction::NOP:
- break;
-
- case Instruction::MOVE:
- case Instruction::MOVE_FROM16:
- case Instruction::MOVE_16:
- case Instruction::MOVE_WIDE:
- case Instruction::MOVE_WIDE_FROM16:
- case Instruction::MOVE_WIDE_16:
- case Instruction::MOVE_RESULT:
- case Instruction::MOVE_RESULT_WIDE:
- break;
-
- case Instruction::MOVE_OBJECT:
- case Instruction::MOVE_OBJECT_FROM16:
- case Instruction::MOVE_OBJECT_16:
- case Instruction::MOVE_RESULT_OBJECT:
- case Instruction::MOVE_EXCEPTION:
- set_to_another_object[dec_insn.vA] = true;
- break;
-
- case Instruction::RETURN_VOID:
- case Instruction::RETURN:
- case Instruction::RETURN_WIDE:
- case Instruction::RETURN_OBJECT:
- break;
-
- case Instruction::CONST_4:
- case Instruction::CONST_16:
- case Instruction::CONST:
- case Instruction::CONST_HIGH16:
- set_to_another_object[dec_insn.vA] = true;
- break;
-
- case Instruction::CONST_WIDE_16:
- case Instruction::CONST_WIDE_32:
- case Instruction::CONST_WIDE:
- case Instruction::CONST_WIDE_HIGH16:
- break;
-
- case Instruction::CONST_STRING:
- case Instruction::CONST_STRING_JUMBO:
- // TODO: Will the ResolveString throw exception?
- if (!compiler_.CanAssumeStringIsPresentInDexCache(*dex_file_, dec_insn.vB)) {
- may_throw_exception = true;
- }
- set_to_another_object[dec_insn.vA] = true;
- break;
-
- case Instruction::CONST_CLASS:
- may_throw_exception = true;
- set_to_another_object[dec_insn.vA] = true;
- break;
-
- case Instruction::MONITOR_ENTER:
- case Instruction::MONITOR_EXIT:
- case Instruction::CHECK_CAST:
- may_throw_exception = true;
- break;
-
- case Instruction::ARRAY_LENGTH:
- may_throw_exception = true;
- break;
-
- case Instruction::INSTANCE_OF:
- case Instruction::NEW_INSTANCE:
- case Instruction::NEW_ARRAY:
- may_throw_exception = true;
- set_to_another_object[dec_insn.vA] = true;
- break;
-
- case Instruction::FILLED_NEW_ARRAY:
- case Instruction::FILLED_NEW_ARRAY_RANGE:
- case Instruction::FILL_ARRAY_DATA:
- case Instruction::THROW:
- may_throw_exception = true;
- break;
-
- case Instruction::GOTO:
- case Instruction::GOTO_16:
- case Instruction::GOTO_32:
- {
- int32_t branch_offset = dec_insn.vA;
- if (branch_offset <= 0 && !IsInstructionDirectToReturn(dex_pc + branch_offset)) {
- may_have_loop = true;
- }
- }
- break;
-
- case Instruction::PACKED_SWITCH:
- case Instruction::SPARSE_SWITCH:
- case Instruction::CMPL_FLOAT:
- case Instruction::CMPG_FLOAT:
- case Instruction::CMPL_DOUBLE:
- case Instruction::CMPG_DOUBLE:
- case Instruction::CMP_LONG:
- break;
-
- case Instruction::IF_EQ:
- case Instruction::IF_NE:
- case Instruction::IF_LT:
- case Instruction::IF_GE:
- case Instruction::IF_GT:
- case Instruction::IF_LE:
- {
- int32_t branch_offset = dec_insn.vC;
- if (branch_offset <= 0 && !IsInstructionDirectToReturn(dex_pc + branch_offset)) {
- may_have_loop = true;
- }
- }
- break;
-
- case Instruction::IF_EQZ:
- case Instruction::IF_NEZ:
- case Instruction::IF_LTZ:
- case Instruction::IF_GEZ:
- case Instruction::IF_GTZ:
- case Instruction::IF_LEZ:
- {
- int32_t branch_offset = dec_insn.vB;
- if (branch_offset <= 0 && !IsInstructionDirectToReturn(dex_pc + branch_offset)) {
- may_have_loop = true;
- }
- }
- break;
-
- case Instruction::AGET:
- case Instruction::AGET_WIDE:
- case Instruction::AGET_OBJECT:
- case Instruction::AGET_BOOLEAN:
- case Instruction::AGET_BYTE:
- case Instruction::AGET_CHAR:
- case Instruction::AGET_SHORT:
- may_throw_exception = true;
- if (insn->Opcode() == Instruction::AGET_OBJECT) {
- set_to_another_object[dec_insn.vA] = true;
- }
- break;
-
- case Instruction::APUT:
- case Instruction::APUT_WIDE:
- case Instruction::APUT_OBJECT:
- case Instruction::APUT_BOOLEAN:
- case Instruction::APUT_BYTE:
- case Instruction::APUT_CHAR:
- case Instruction::APUT_SHORT:
- may_throw_exception = true;
- break;
-
- case Instruction::IGET:
- case Instruction::IGET_WIDE:
- case Instruction::IGET_OBJECT:
- case Instruction::IGET_BOOLEAN:
- case Instruction::IGET_BYTE:
- case Instruction::IGET_CHAR:
- case Instruction::IGET_SHORT:
- {
- if (insn->Opcode() == Instruction::IGET_OBJECT) {
- set_to_another_object[dec_insn.vA] = true;
- }
- uint32_t reg_idx = dec_insn.vB;
- uint32_t field_idx = dec_insn.vC;
- int field_offset;
- bool is_volatile;
- bool is_fast_path = compiler_.ComputeInstanceFieldInfo(
- field_idx, &cunit_, field_offset, is_volatile, false);
- if (!is_fast_path) {
- may_throw_exception = true;
- } else {
- // Fast-path, may throw NullPointerException
- if (reg_idx == this_reg_idx) {
- // We assume "this" will not be null at first.
- assume_this_non_null = true;
- } else {
- may_throw_exception = true;
- }
- }
- }
- break;
-
- case Instruction::IPUT:
- case Instruction::IPUT_WIDE:
- case Instruction::IPUT_OBJECT:
- case Instruction::IPUT_BOOLEAN:
- case Instruction::IPUT_BYTE:
- case Instruction::IPUT_CHAR:
- case Instruction::IPUT_SHORT:
- {
- uint32_t reg_idx = dec_insn.vB;
- uint32_t field_idx = dec_insn.vC;
- int field_offset;
- bool is_volatile;
- bool is_fast_path = compiler_.ComputeInstanceFieldInfo(
- field_idx, &cunit_, field_offset, is_volatile, true);
- if (!is_fast_path) {
- may_throw_exception = true;
- } else {
- // Fast-path, may throw NullPointerException
- if (reg_idx == this_reg_idx) {
- // We assume "this" will not be null at first.
- assume_this_non_null = true;
- } else {
- may_throw_exception = true;
- }
- }
- }
- break;
-
- case Instruction::SGET:
- case Instruction::SGET_WIDE:
- case Instruction::SGET_OBJECT:
- case Instruction::SGET_BOOLEAN:
- case Instruction::SGET_BYTE:
- case Instruction::SGET_CHAR:
- case Instruction::SGET_SHORT:
- {
- if (insn->Opcode() == Instruction::AGET_OBJECT) {
- set_to_another_object[dec_insn.vA] = true;
- }
- uint32_t field_idx = dec_insn.vB;
-
- int field_offset;
- int ssb_index;
- bool is_referrers_class;
- bool is_volatile;
-
- bool is_fast_path = compiler_.ComputeStaticFieldInfo(
- field_idx, &cunit_, field_offset, ssb_index,
- is_referrers_class, is_volatile, false);
- if (!is_fast_path || !is_referrers_class) {
- may_throw_exception = true;
- }
- }
- break;
-
- case Instruction::SPUT:
- case Instruction::SPUT_WIDE:
- case Instruction::SPUT_OBJECT:
- case Instruction::SPUT_BOOLEAN:
- case Instruction::SPUT_BYTE:
- case Instruction::SPUT_CHAR:
- case Instruction::SPUT_SHORT:
- {
- uint32_t field_idx = dec_insn.vB;
-
- int field_offset;
- int ssb_index;
- bool is_referrers_class;
- bool is_volatile;
-
- bool is_fast_path = compiler_.ComputeStaticFieldInfo(
- field_idx, &cunit_, field_offset, ssb_index,
- is_referrers_class, is_volatile, true);
- if (!is_fast_path || !is_referrers_class) {
- may_throw_exception = true;
- }
- }
- break;
-
-
- case Instruction::INVOKE_VIRTUAL:
- case Instruction::INVOKE_SUPER:
- case Instruction::INVOKE_DIRECT:
- case Instruction::INVOKE_STATIC:
- case Instruction::INVOKE_INTERFACE:
- case Instruction::INVOKE_VIRTUAL_RANGE:
- case Instruction::INVOKE_SUPER_RANGE:
- case Instruction::INVOKE_DIRECT_RANGE:
- case Instruction::INVOKE_STATIC_RANGE:
- case Instruction::INVOKE_INTERFACE_RANGE:
- has_invoke = true;
- may_throw_exception = true;
- break;
-
- case Instruction::NEG_INT:
- case Instruction::NOT_INT:
- case Instruction::NEG_LONG:
- case Instruction::NOT_LONG:
- case Instruction::NEG_FLOAT:
- case Instruction::NEG_DOUBLE:
- case Instruction::INT_TO_LONG:
- case Instruction::INT_TO_FLOAT:
- case Instruction::INT_TO_DOUBLE:
- case Instruction::LONG_TO_INT:
- case Instruction::LONG_TO_FLOAT:
- case Instruction::LONG_TO_DOUBLE:
- case Instruction::FLOAT_TO_INT:
- case Instruction::FLOAT_TO_LONG:
- case Instruction::FLOAT_TO_DOUBLE:
- case Instruction::DOUBLE_TO_INT:
- case Instruction::DOUBLE_TO_LONG:
- case Instruction::DOUBLE_TO_FLOAT:
- case Instruction::INT_TO_BYTE:
- case Instruction::INT_TO_CHAR:
- case Instruction::INT_TO_SHORT:
- case Instruction::ADD_INT:
- case Instruction::SUB_INT:
- case Instruction::MUL_INT:
- case Instruction::AND_INT:
- case Instruction::OR_INT:
- case Instruction::XOR_INT:
- case Instruction::SHL_INT:
- case Instruction::SHR_INT:
- case Instruction::USHR_INT:
- case Instruction::ADD_LONG:
- case Instruction::SUB_LONG:
- case Instruction::MUL_LONG:
- case Instruction::AND_LONG:
- case Instruction::OR_LONG:
- case Instruction::XOR_LONG:
- case Instruction::SHL_LONG:
- case Instruction::SHR_LONG:
- case Instruction::USHR_LONG:
- case Instruction::ADD_INT_2ADDR:
- case Instruction::SUB_INT_2ADDR:
- case Instruction::MUL_INT_2ADDR:
- case Instruction::AND_INT_2ADDR:
- case Instruction::OR_INT_2ADDR:
- case Instruction::XOR_INT_2ADDR:
- case Instruction::SHL_INT_2ADDR:
- case Instruction::SHR_INT_2ADDR:
- case Instruction::USHR_INT_2ADDR:
- case Instruction::ADD_LONG_2ADDR:
- case Instruction::SUB_LONG_2ADDR:
- case Instruction::MUL_LONG_2ADDR:
- case Instruction::AND_LONG_2ADDR:
- case Instruction::OR_LONG_2ADDR:
- case Instruction::XOR_LONG_2ADDR:
- case Instruction::SHL_LONG_2ADDR:
- case Instruction::SHR_LONG_2ADDR:
- case Instruction::USHR_LONG_2ADDR:
- break;
-
- case Instruction::DIV_INT:
- case Instruction::REM_INT:
- case Instruction::DIV_LONG:
- case Instruction::REM_LONG:
- case Instruction::DIV_INT_2ADDR:
- case Instruction::REM_INT_2ADDR:
- case Instruction::DIV_LONG_2ADDR:
- case Instruction::REM_LONG_2ADDR:
- may_throw_exception = true;
- break;
-
- case Instruction::ADD_FLOAT:
- case Instruction::SUB_FLOAT:
- case Instruction::MUL_FLOAT:
- case Instruction::DIV_FLOAT:
- case Instruction::REM_FLOAT:
- case Instruction::ADD_DOUBLE:
- case Instruction::SUB_DOUBLE:
- case Instruction::MUL_DOUBLE:
- case Instruction::DIV_DOUBLE:
- case Instruction::REM_DOUBLE:
- case Instruction::ADD_FLOAT_2ADDR:
- case Instruction::SUB_FLOAT_2ADDR:
- case Instruction::MUL_FLOAT_2ADDR:
- case Instruction::DIV_FLOAT_2ADDR:
- case Instruction::REM_FLOAT_2ADDR:
- case Instruction::ADD_DOUBLE_2ADDR:
- case Instruction::SUB_DOUBLE_2ADDR:
- case Instruction::MUL_DOUBLE_2ADDR:
- case Instruction::DIV_DOUBLE_2ADDR:
- case Instruction::REM_DOUBLE_2ADDR:
- break;
-
- case Instruction::ADD_INT_LIT16:
- case Instruction::ADD_INT_LIT8:
- case Instruction::RSUB_INT:
- case Instruction::RSUB_INT_LIT8:
- case Instruction::MUL_INT_LIT16:
- case Instruction::MUL_INT_LIT8:
- case Instruction::AND_INT_LIT16:
- case Instruction::AND_INT_LIT8:
- case Instruction::OR_INT_LIT16:
- case Instruction::OR_INT_LIT8:
- case Instruction::XOR_INT_LIT16:
- case Instruction::XOR_INT_LIT8:
- case Instruction::SHL_INT_LIT8:
- case Instruction::SHR_INT_LIT8:
- case Instruction::USHR_INT_LIT8:
- break;
-
- case Instruction::DIV_INT_LIT16:
- case Instruction::DIV_INT_LIT8:
- case Instruction::REM_INT_LIT16:
- case Instruction::REM_INT_LIT8:
- if (dec_insn.vC == 0) {
- may_throw_exception = true;
- }
- break;
-
- case Instruction::UNUSED_3E:
- case Instruction::UNUSED_3F:
- case Instruction::UNUSED_40:
- case Instruction::UNUSED_41:
- case Instruction::UNUSED_42:
- case Instruction::UNUSED_43:
- case Instruction::UNUSED_73:
- case Instruction::UNUSED_79:
- case Instruction::UNUSED_7A:
- case Instruction::UNUSED_E3:
- case Instruction::UNUSED_E4:
- case Instruction::UNUSED_E5:
- case Instruction::UNUSED_E6:
- case Instruction::UNUSED_E7:
- case Instruction::UNUSED_E8:
- case Instruction::UNUSED_E9:
- case Instruction::UNUSED_EA:
- case Instruction::UNUSED_EB:
- case Instruction::UNUSED_EC:
- case Instruction::UNUSED_ED:
- case Instruction::UNUSED_EE:
- case Instruction::UNUSED_EF:
- case Instruction::UNUSED_F0:
- case Instruction::UNUSED_F1:
- case Instruction::UNUSED_F2:
- case Instruction::UNUSED_F3:
- case Instruction::UNUSED_F4:
- case Instruction::UNUSED_F5:
- case Instruction::UNUSED_F6:
- case Instruction::UNUSED_F7:
- case Instruction::UNUSED_F8:
- case Instruction::UNUSED_F9:
- case Instruction::UNUSED_FA:
- case Instruction::UNUSED_FB:
- case Instruction::UNUSED_FC:
- case Instruction::UNUSED_FD:
- case Instruction::UNUSED_FE:
- case Instruction::UNUSED_FF:
- LOG(FATAL) << "Dex file contains UNUSED bytecode: " << insn->Opcode();
- break;
- }
- }
-
- method_info_.this_reg_idx = this_reg_idx;
- // According to the statistics, there are few methods that modify the "this" pointer. So this is a
- // simple way to avoid data flow analysis. After we have a high-level IR before IRBuilder, we
- // should remove this trick.
- method_info_.this_will_not_be_null =
- (cunit_.IsStatic()) ? (true) : (!set_to_another_object[this_reg_idx]);
- method_info_.has_invoke = has_invoke;
- // If this method has loop or invoke instruction, it may suspend. Thus we need a shadow frame entry
- // for GC.
- method_info_.need_shadow_frame_entry = has_invoke || may_have_loop;
- // If this method may throw an exception, we need a shadow frame for stack trace (dexpc).
- method_info_.need_shadow_frame = method_info_.need_shadow_frame_entry || may_throw_exception ||
- (assume_this_non_null && !method_info_.this_will_not_be_null);
- // If can only throw exception, but can't suspend check (no loop, no invoke),
- // then there is no shadow frame entry. Only Shadow frame is needed.
- method_info_.lazy_push_shadow_frame =
- method_info_.need_shadow_frame && !method_info_.need_shadow_frame_entry;
-}
-
-} // namespace greenland
-} // namespace art
diff --git a/src/greenland/dex_lang.h b/src/greenland/dex_lang.h
deleted file mode 100644
index 70ad5bf..0000000
--- a/src/greenland/dex_lang.h
+++ /dev/null
@@ -1,505 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#ifndef ART_SRC_GREENLAND_DEX_LANG_H_
-#define ART_SRC_GREENLAND_DEX_LANG_H_
-
-#include "backend_types.h"
-#include "dalvik_reg.h"
-#include "ir_builder.h"
-
-#include "dex_file.h"
-#include "dex_instruction.h"
-#include "invoke_type.h"
-#include "macros.h"
-
-#include <vector>
-
-#include <llvm/Module.h>
-#include <llvm/ADT/ArrayRef.h>
-
-namespace llvm {
- class BasicBlock;
- class Function;
- class LLVMContext;
- class Type;
-}
-
-namespace art {
- class Compiler;
- class OatCompilationUnit;
-}
-
-namespace art {
-namespace greenland {
-
-class DalvikReg;
-class InferredRegCategoryMap;
-class IntrinsicHelper;
-
-class DexLang {
- public:
- class Context {
- private:
- llvm::Module& module_;
- IntrinsicHelper* intrinsic_helper_;
-
- public:
- Context(llvm::Module& module);
- ~Context();
-
- inline llvm::LLVMContext& GetLLVMContext()
- { return module_.getContext(); }
-
- inline llvm::Module& GetOutputModule()
- { return module_; }
-
- inline IntrinsicHelper& GetIntrinsicHelper()
- { return *intrinsic_helper_; }
- inline const IntrinsicHelper& GetIntrinsicHelper() const
- { return *intrinsic_helper_; }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Context);
- };
-
- public:
- DexLang(Context& context, Compiler& compiler, OatCompilationUnit& cunit);
-
- ~DexLang();
-
- llvm::Function* Build();
-
- inline IRBuilder& GetIRBuilder() {
- return irb_;
- }
- llvm::Value* AllocateDalvikReg(RegCategory cat, unsigned reg_idx);
-
- private:
- Context& dex_lang_ctx_;
- Compiler& compiler_;
- OatCompilationUnit& cunit_;
-
- const DexFile* dex_file_;
- const DexFile::CodeItem* code_item_;
- uint32_t method_idx_;
-
- llvm::LLVMContext& context_;
- llvm::Module& module_;
- IntrinsicHelper& intrinsic_helper_;
-
- IRBuilder irb_;
- llvm::Function* func_;
-
- private:
- //----------------------------------------------------------------------------
- // Basic Block Helper Functions
- //----------------------------------------------------------------------------
- llvm::BasicBlock* reg_alloc_bb_;
- llvm::BasicBlock* arg_reg_init_bb_;
-
- std::vector<llvm::BasicBlock*> basic_blocks_;
-
- llvm::BasicBlock* GetBasicBlock(unsigned dex_pc);
- llvm::BasicBlock* CreateBasicBlockWithDexPC(unsigned dex_pc,
- char const* postfix = NULL);
- llvm::BasicBlock* GetNextBasicBlock(unsigned dex_pc);
-
- private:
- //----------------------------------------------------------------------------
- // Register Helper Functions
- //----------------------------------------------------------------------------
- std::vector<DalvikReg*> regs_;
-
- llvm::Value* EmitLoadDalvikReg(unsigned reg_idx, JType jty, JTypeSpace space);
-
- llvm::Value* EmitLoadDalvikReg(unsigned reg_idx, char shorty, JTypeSpace space);
-
- void EmitStoreDalvikReg(unsigned reg_idx, JType jty,
- JTypeSpace space, llvm::Value* new_value);
-
- void EmitStoreDalvikReg(unsigned reg_idx, char shorty,
- JTypeSpace space, llvm::Value* new_value);
-
- private:
- //----------------------------------------------------------------------------
- // Return Value Related
- //----------------------------------------------------------------------------
- // Hold the return value returned from the lastest invoke-* instruction
- DalvikReg* retval_reg_;
-
- llvm::Value* EmitLoadDalvikRetValReg(JType jty, JTypeSpace space);
-
- llvm::Value* EmitLoadDalvikRetValReg(char shorty, JTypeSpace space);
-
- void EmitStoreDalvikRetValReg(JType jty, JTypeSpace space, llvm::Value* new_value);
-
- void EmitStoreDalvikRetValReg(char shorty, JTypeSpace space, llvm::Value* new_value);
-
- private:
- //----------------------------------------------------------------------------
- // Shadow Frame
- //----------------------------------------------------------------------------
- unsigned num_shadow_frame_entries_;
- std::vector<int32_t> reg_to_shadow_frame_index_;
-
- void EmitUpdateDexPC(unsigned dex_pc);
-
- void EmitPopShadowFrame();
-
- private:
- //----------------------------------------------------------------------------
- // RegCategory
- //----------------------------------------------------------------------------
- RegCategory GetInferredRegCategory(unsigned dex_pc, unsigned reg_idx);
-
- InferredRegCategoryMap const* GetInferredRegCategoryMap();
-
- bool IsRegCanBeObject(unsigned reg_idx);
-
- private:
- //----------------------------------------------------------------------------
- // Exception Handling
- //----------------------------------------------------------------------------
- std::vector<llvm::BasicBlock*> landing_pads_bb_;
- llvm::BasicBlock* exception_unwind_bb_;
-
- // cur_try_item_offset caches the latest try item offset such that we don't
- // have to call DexFile::FindCatchHandlerOffset(...) (using binary search) for
- // every query of the try item for the given dex_pc.
- int32_t cur_try_item_offset;
-
- int32_t GetTryItemOffset(unsigned dex_pc);
-
- llvm::BasicBlock* GetLandingPadBasicBlock(unsigned dex_pc);
-
- llvm::BasicBlock* GetUnwindBasicBlock();
-
- void EmitBranchExceptionLandingPad(unsigned dex_pc);
-
- void EmitGuard_DivZeroException(unsigned dex_pc,
- llvm::Value* denominator,
- JType op_jty);
-
- void EmitGuard_NullPointerException(unsigned dex_pc, llvm::Value* object);
-
- void EmitGuard_ArrayIndexOutOfBoundsException(unsigned dex_pc,
- llvm::Value* array,
- llvm::Value* index);
-
- void EmitGuard_ArrayException(unsigned dex_pc,
- llvm::Value* array,
- llvm::Value* index);
-
- void EmitGuard_ExceptionLandingPad(unsigned dex_pc, bool can_skip_unwind);
-
- private:
- //----------------------------------------------------------------------------
- // Garbage Collection Safe Point
- //----------------------------------------------------------------------------
- void EmitGuard_GarbageCollectionSuspend();
-
- private:
- //----------------------------------------------------------------------------
- // Code Generation
- //----------------------------------------------------------------------------
- bool CreateFunction();
- llvm::FunctionType* GetFunctionType();
-
- bool EmitPrologue();
- bool EmitPrologueAssignArgRegister();
- bool EmitPrologueAllcaShadowFrame();
- bool EmitPrologueLinkBasicBlocks();
- bool PrettyLayoutExceptionBasicBlocks();
- bool VerifyFunction();
- bool OptimizeFunction();
- // Our optimization passes
- bool RemoveRedundantPendingExceptionChecks();
-
- //----------------------------------------------------------------------------
- // Emit* Helper Functions
- //----------------------------------------------------------------------------
- enum CondBranchKind {
- kCondBranch_EQ,
- kCondBranch_NE,
- kCondBranch_LT,
- kCondBranch_GE,
- kCondBranch_GT,
- kCondBranch_LE,
- };
-
- enum IntArithmKind {
- kIntArithm_Add,
- kIntArithm_Sub,
- kIntArithm_Mul,
- kIntArithm_Div,
- kIntArithm_Rem,
- kIntArithm_And,
- kIntArithm_Or,
- kIntArithm_Xor,
- };
-
- enum IntShiftArithmKind {
- kIntArithm_Shl,
- kIntArithm_Shr,
- kIntArithm_UShr,
- };
-
- enum FPArithmKind {
- kFPArithm_Add,
- kFPArithm_Sub,
- kFPArithm_Mul,
- kFPArithm_Div,
- kFPArithm_Rem,
- };
-
- enum InvokeArgFmt {
- kArgReg,
- kArgRange,
- };
-
- llvm::Value* EmitLoadMethodObjectAddr();
-
- llvm::Value* EmitGetCurrentThread();
-
- void EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr);
-
- llvm::Value* EmitInvokeIntrinsicNoThrow(IntrinsicHelper::IntrinsicId intr_id,
- llvm::ArrayRef<llvm::Value*> args
- = llvm::ArrayRef<llvm::Value*>());
- llvm::Value* EmitInvokeIntrinsic2NoThrow(IntrinsicHelper::IntrinsicId intr_id,
- llvm::Value* arg1,
- llvm::Value* arg2) {
- llvm::Value* args[] = { arg1, arg2 };
- return EmitInvokeIntrinsicNoThrow(intr_id, args);
- }
- llvm::Value* EmitInvokeIntrinsic3NoThrow(IntrinsicHelper::IntrinsicId intr_id,
- llvm::Value* arg1,
- llvm::Value* arg2,
- llvm::Value* arg3) {
- llvm::Value* args[] = { arg1, arg2, arg3 };
- return EmitInvokeIntrinsicNoThrow(intr_id, args);
- }
- llvm::Value* EmitInvokeIntrinsic4NoThrow(IntrinsicHelper::IntrinsicId intr_id,
- llvm::Value* arg1,
- llvm::Value* arg2,
- llvm::Value* arg3,
- llvm::Value* arg4) {
- llvm::Value* args[] = { arg1, arg2, arg3, arg4 };
- return EmitInvokeIntrinsicNoThrow(intr_id, args);
- }
-
- llvm::Value* EmitInvokeIntrinsic(unsigned dex_pc, bool can_skip_unwind,
- IntrinsicHelper::IntrinsicId intr_id,
- llvm::ArrayRef<llvm::Value*> args
- = llvm::ArrayRef<llvm::Value*>());
- llvm::Value* EmitInvokeIntrinsic2(unsigned dex_pc, bool can_skip_unwind,
- IntrinsicHelper::IntrinsicId intr_id,
- llvm::Value* arg1,
- llvm::Value* arg2) {
- llvm::Value* args[] = { arg1, arg2 };
- return EmitInvokeIntrinsic(dex_pc, can_skip_unwind, intr_id, args);
- }
- llvm::Value* EmitInvokeIntrinsic3(unsigned dex_pc, bool can_skip_unwind,
- IntrinsicHelper::IntrinsicId intr_id,
- llvm::Value* arg1,
- llvm::Value* arg2,
- llvm::Value* arg3) {
- llvm::Value* args[] = { arg1, arg2, arg3 };
- return EmitInvokeIntrinsic(dex_pc, can_skip_unwind, intr_id, args);
- }
- llvm::Value* EmitInvokeIntrinsic4(unsigned dex_pc, bool can_skip_unwind,
- IntrinsicHelper::IntrinsicId intr_id,
- llvm::Value* arg1,
- llvm::Value* arg2,
- llvm::Value* arg3,
- llvm::Value* arg4) {
- llvm::Value* args[] = { arg1, arg2, arg3, arg4 };
- return EmitInvokeIntrinsic(dex_pc, can_skip_unwind, intr_id, args);
- }
- llvm::Value* EmitInvokeIntrinsic5(unsigned dex_pc, bool can_skip_unwind,
- IntrinsicHelper::IntrinsicId intr_id,
- llvm::Value* arg1,
- llvm::Value* arg2,
- llvm::Value* arg3,
- llvm::Value* arg4,
- llvm::Value* arg5) {
- llvm::Value* args[] = { arg1, arg2, arg3, arg4, arg5 };
- return EmitInvokeIntrinsic(dex_pc, can_skip_unwind, intr_id, args);
- }
-
- llvm::Value* EmitLoadConstantClass(unsigned dex_pc, uint32_t type_idx);
-
- llvm::Value* EmitLoadArrayLength(llvm::Value* array);
-
- llvm::Value* EmitAllocNewArray(unsigned dex_pc, int32_t length,
- uint32_t type_idx, bool is_filled_new_array);
-
- llvm::Value* EmitCompareResultSelection(llvm::Value* cmp_eq,
- llvm::Value* cmp_lt);
-
- llvm::Value* EmitLoadStaticStorage(unsigned dex_pc, unsigned type_idx);
-
- llvm::Value* EmitConditionResult(llvm::Value* lhs, llvm::Value* rhs,
- CondBranchKind cond);
-
- llvm::Value* EmitIntArithmResultComputation(unsigned dex_pc,
- llvm::Value* lhs,
- llvm::Value* rhs,
- IntArithmKind arithm,
- JType op_jty);
-
- llvm::Value* EmitIntShiftArithmResultComputation(uint32_t dex_pc,
- llvm::Value* lhs,
- llvm::Value* rhs,
- IntShiftArithmKind arithm,
- JType op_jty);
-
- llvm::Value* EmitIntDivRemResultComputation(unsigned dex_pc,
- llvm::Value* dividend,
- llvm::Value* divisor,
- IntArithmKind arithm,
- JType op_jty);
-
-#define GEN_INSN_ARGS unsigned dex_pc, const Instruction* insn
- // NOP, PAYLOAD (unreachable) instructions
- void EmitInsn_Nop(GEN_INSN_ARGS);
-
- // MOVE, MOVE_RESULT instructions
- void EmitInsn_Move(GEN_INSN_ARGS, JType jty);
- void EmitInsn_MoveResult(GEN_INSN_ARGS, JType jty);
-
- // MOVE_EXCEPTION, THROW instructions
- void EmitInsn_MoveException(GEN_INSN_ARGS);
- void EmitInsn_ThrowException(GEN_INSN_ARGS);
-
- // RETURN instructions
- void EmitInsn_ReturnVoid(GEN_INSN_ARGS);
- void EmitInsn_Return(GEN_INSN_ARGS);
-
- // CONST, CONST_CLASS, CONST_STRING instructions
- void EmitInsn_LoadConstant(GEN_INSN_ARGS, JType imm_jty);
- void EmitInsn_LoadConstantString(GEN_INSN_ARGS);
- void EmitInsn_LoadConstantClass(GEN_INSN_ARGS);
-
- // MONITOR_ENTER, MONITOR_EXIT instructions
- void EmitInsn_MonitorEnter(GEN_INSN_ARGS);
- void EmitInsn_MonitorExit(GEN_INSN_ARGS);
-
- // CHECK_CAST, INSTANCE_OF instructions
- void EmitInsn_CheckCast(GEN_INSN_ARGS);
- void EmitInsn_InstanceOf(GEN_INSN_ARGS);
-
- // NEW_INSTANCE instructions
- void EmitInsn_NewInstance(GEN_INSN_ARGS);
-
- // ARRAY_LEN, NEW_ARRAY, FILLED_NEW_ARRAY, FILL_ARRAY_DATA instructions
- void EmitInsn_ArrayLength(GEN_INSN_ARGS);
- void EmitInsn_NewArray(GEN_INSN_ARGS);
- void EmitInsn_FilledNewArray(GEN_INSN_ARGS, bool is_range);
- void EmitInsn_FillArrayData(GEN_INSN_ARGS);
-
- // GOTO, IF_TEST, IF_TESTZ instructions
- void EmitInsn_UnconditionalBranch(GEN_INSN_ARGS);
- void EmitInsn_UnaryConditionalBranch(GEN_INSN_ARGS, CondBranchKind cond);
- void EmitInsn_BinaryConditionalBranch(GEN_INSN_ARGS, CondBranchKind cond);
-
- // PACKED_SWITCH, SPARSE_SWITCH instrutions
- void EmitInsn_PackedSwitch(GEN_INSN_ARGS);
- void EmitInsn_SparseSwitch(GEN_INSN_ARGS);
-
- // CMPX_FLOAT, CMPX_DOUBLE, CMP_LONG instructions
- void EmitInsn_FPCompare(GEN_INSN_ARGS, JType fp_jty, bool gt_bias);
- void EmitInsn_LongCompare(GEN_INSN_ARGS);
-
- // AGET, APUT instrutions
- void EmitInsn_AGet(GEN_INSN_ARGS, JType elem_jty);
- void EmitInsn_APut(GEN_INSN_ARGS, JType elem_jty);
-
- // IGET, IPUT instructions
- void EmitInsn_IGet(GEN_INSN_ARGS, JType field_jty);
- void EmitInsn_IPut(GEN_INSN_ARGS, JType field_jty);
-
- // SGET, SPUT instructions
- void EmitInsn_SGet(GEN_INSN_ARGS, JType field_jty);
- void EmitInsn_SPut(GEN_INSN_ARGS, JType field_jty);
-
- void EmitInsn_Invoke(GEN_INSN_ARGS,
- InvokeType invoke_type,
- InvokeArgFmt arg_fmt);
-
- // Unary instructions
- void EmitInsn_Neg(GEN_INSN_ARGS, JType op_jty);
- void EmitInsn_Not(GEN_INSN_ARGS, JType op_jty);
- void EmitInsn_SExt(GEN_INSN_ARGS);
- void EmitInsn_Trunc(GEN_INSN_ARGS);
- void EmitInsn_TruncAndSExt(GEN_INSN_ARGS, unsigned N);
- void EmitInsn_TruncAndZExt(GEN_INSN_ARGS, unsigned N);
-
- void EmitInsn_FNeg(GEN_INSN_ARGS, JType op_jty);
- void EmitInsn_IntToFP(GEN_INSN_ARGS, JType src_jty, JType dest_jty);
- void EmitInsn_FPToInt(GEN_INSN_ARGS, JType src_jty, JType dest_jty,
- IntrinsicHelper::IntrinsicId intr_id);
- void EmitInsn_FExt(GEN_INSN_ARGS);
- void EmitInsn_FTrunc(GEN_INSN_ARGS);
-
- // Integer binary arithmetic instructions
- void EmitInsn_IntArithm(GEN_INSN_ARGS, IntArithmKind arithm,
- JType op_jty, bool is_2addr);
-
- void EmitInsn_IntArithmImmediate(GEN_INSN_ARGS, IntArithmKind arithm);
-
- void EmitInsn_IntShiftArithm(GEN_INSN_ARGS, IntShiftArithmKind arithm,
- JType op_jty, bool is_2addr);
-
- void EmitInsn_IntShiftArithmImmediate(GEN_INSN_ARGS,
- IntShiftArithmKind arithm);
-
- void EmitInsn_RSubImmediate(GEN_INSN_ARGS);
-
- // Floating-point binary arithmetic instructions
- void EmitInsn_FPArithm(GEN_INSN_ARGS, FPArithmKind arithm,
- JType op_jty, bool is_2addr);
-#undef GEN_INSN_ARGS
-
-
- bool EmitInstructions();
- bool EmitInstruction(unsigned dex_pc, const Instruction* insn);
-
-
- // TODO: Use high-level IR to do this
- bool IsInstructionDirectToReturn(uint32_t dex_pc);
-
- struct MethodInfo {
- int64_t this_reg_idx;
- bool this_will_not_be_null;
- bool has_invoke;
- bool need_shadow_frame_entry;
- bool need_shadow_frame;
- bool lazy_push_shadow_frame;
- std::vector<bool> set_to_another_object;
- };
- MethodInfo method_info_;
-
- void ComputeMethodInfo();
-
- DISALLOW_COPY_AND_ASSIGN(DexLang);
-};
-
-} // namespace greenland
-} // namespace art
-
-#endif // ART_SRC_GREENLAND_DEX_LANG_H_
diff --git a/src/greenland/gbc_context.cc b/src/greenland/gbc_context.cc
deleted file mode 100644
index ec86bfb..0000000
--- a/src/greenland/gbc_context.cc
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2012 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 "gbc_context.h"
-
-#include "atomic.h"
-
-namespace art {
-namespace greenland {
-
-GBCContext::GBCContext()
- : context_(), module_(NULL), ref_count_(1), mem_usage_(0) {
- module_ = new llvm::Module("art", context_);
-
- // Initialize the contents of an empty module
- // Type of "JavaObject"
- llvm::StructType::create(context_, "JavaObject");
- // Type of "Method"
- llvm::StructType::create(context_, "Method");
- // Type of "Thread"
- llvm::StructType::create(context_, "Thread");
-
- dex_lang_ctx_ = new DexLang::Context(*module_);
- return;
-}
-
-GBCContext::~GBCContext() {
- delete dex_lang_ctx_;
- return;
-}
-
-GBCContext& GBCContext::IncRef() {
- android_atomic_inc(&ref_count_);
- return *this;
-}
-
-const GBCContext& GBCContext::IncRef() const {
- android_atomic_inc(&ref_count_);
- return *this;
-}
-
-void GBCContext::DecRef() const {
- int32_t old_ref_count = android_atomic_dec(&ref_count_);
- if (old_ref_count <= 1) {
- delete this;
- }
- return;
-}
-
-void GBCContext::AddMemUsageApproximation(size_t usage) {
- android_atomic_add(static_cast<int32_t>(usage), &mem_usage_);
- return;
-}
-
-} // namespace greenland
-} // namespace art
diff --git a/src/greenland/gbc_context.h b/src/greenland/gbc_context.h
deleted file mode 100644
index 7c31816..0000000
--- a/src/greenland/gbc_context.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#ifndef ART_SRC_GREENLAND_GBC_CONTEXT_H_
-#define ART_SRC_GREENLAND_GBC_CONTEXT_H_
-
-#include "dex_lang.h"
-
-#include "macros.h"
-
-#include <llvm/LLVMContext.h>
-
-namespace llvm {
- class Module;
-} // namespace llvm
-
-namespace art {
-namespace greenland {
-
-class IntrinsicHelper;
-
-class GBCContext {
- private:
- llvm::LLVMContext context_;
- llvm::Module* module_;
- DexLang::Context* dex_lang_ctx_;
-
- mutable volatile int32_t ref_count_;
- volatile int32_t mem_usage_;
-
- ~GBCContext();
-
- public:
- GBCContext();
-
- inline llvm::LLVMContext& GetLLVMContext()
- { return context_; }
- inline llvm::Module& GetOutputModule()
- { return *module_; }
-
- inline IntrinsicHelper& GetIntrinsicHelper()
- { return dex_lang_ctx_->GetIntrinsicHelper(); }
- inline const IntrinsicHelper& GetIntrinsicHelper() const
- { return dex_lang_ctx_->GetIntrinsicHelper(); }
-
- inline DexLang::Context& GetDexLangContext()
- { return *dex_lang_ctx_; }
- inline const DexLang::Context& GetDexLangContext() const
- { return *dex_lang_ctx_; }
-
- GBCContext& IncRef();
- const GBCContext& IncRef() const;
- void DecRef() const;
-
- void AddMemUsageApproximation(size_t usage);
- inline bool IsMemUsageThresholdReached() const {
- return (mem_usage_ > (30 << 20)); // (threshold: 30MiB)
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(GBCContext);
-};
-
-} // namespace greenland
-} // namespace art
-
-#endif // ART_SRC_GREENLAND_GBC_CONTEXT_H_
diff --git a/src/greenland/gbc_function.h b/src/greenland/gbc_function.h
deleted file mode 100644
index b7cbea6..0000000
--- a/src/greenland/gbc_function.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#ifndef ART_SRC_GREENLAND_GBC_FUNCTION_H_
-#define ART_SRC_GREENLAND_GBC_FUNCTION_H_
-
-#include "gbc_context.h"
-
-namespace llvm {
- class Function;
-} // namespace llvm
-
-namespace art {
- class OatCompilationUnit;
-} // namespace art
-
-namespace art {
-namespace greenland {
-
-class GBCContext;
-
-class GBCFunction {
- private:
- // The GBCContext associated with this GBCFunction
- GBCContext& context_;
-
- // The LLVM Function in Greenland bitcode
- llvm::Function& func_;
-
- // The associated OatCompilationUnit
- const OatCompilationUnit& cunit_;
-
- public:
- GBCFunction(GBCContext& context, llvm::Function& func,
- const OatCompilationUnit& cunit)
- : context_(context.IncRef()), func_(func), cunit_(cunit) { }
-
- ~GBCFunction() {
- context_.DecRef();
- return;
- }
-
- IntrinsicHelper& GetIntrinsicHelper() {
- return context_.GetIntrinsicHelper();
- }
- const IntrinsicHelper& GetIntrinsicHelper() const {
- return context_.GetIntrinsicHelper();
- }
-
- llvm::Function& GetBitcode() {
- return func_;
- }
- const llvm::Function& GetBitcode() const {
- return func_;
- }
-
- const OatCompilationUnit& GetOatCompilationUnit() const {
- return cunit_;
- }
-};
-
-} // namespace greenland
-} // namespace art
-
-#endif // ART_SRC_GREENLAND_GBC_FUNCTION_H_
diff --git a/src/greenland/greenland.cc b/src/greenland/greenland.cc
deleted file mode 100644
index 469f7d5..0000000
--- a/src/greenland/greenland.cc
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright (C) 2012 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 "greenland.h"
-
-#include "gbc_context.h"
-#include "gbc_function.h"
-#include "target_codegen_machine.h"
-#include "target_registry.h"
-
-#include "class_linker.h"
-#include "compiler.h"
-#include "oat_compilation_unit.h"
-#include "stl_util.h"
-#include "utils.h"
-
-#include <vector>
-
-#include <llvm/InitializePasses.h>
-#include <llvm/Module.h>
-#include <llvm/PassRegistry.h>
-#include <llvm/Support/Threading.h>
-
-namespace art {
-namespace greenland {
-
-// Forward declarations
-#define LLVM_TARGET(TargetName) void Initialize##TargetName##CodeGenMachine();
-#include <llvm/Config/Targets.def>
-
-#define LLVM_TARGET(TargetName) \
- void Initialize##TargetName##InvokeStubCompiler();
-#include <llvm/Config/Targets.def>
-
-} // namespace greeland
-} // namespace art
-
-namespace {
-
-pthread_once_t greenland_initialized = PTHREAD_ONCE_INIT;
-
-void InitializeAllCodeGenMachines() {
-#define LLVM_TARGET(TargetName) \
- art::greenland::Initialize##TargetName##CodeGenMachine();
-#include <llvm/Config/Targets.def>
-}
-
-void InitializeAllInvokeStubCompilers() {
-#define LLVM_TARGET(TargetName) \
- art::greenland::Initialize##TargetName##InvokeStubCompiler();
-#include <llvm/Config/Targets.def>
-}
-
-void InitializeGreenland() {
- // Initialize LLVM internal data structure for multithreading
- llvm::llvm_start_multithreaded();
-
- // Initialize passes
- llvm::PassRegistry ®istry = *llvm::PassRegistry::getPassRegistry();
-
- llvm::initializeCore(registry);
- llvm::initializeScalarOpts(registry);
-
- // Run vectorization passes when our backend supports vector type
- //llvm::initializeVectorization(registry);
-
- // DexLang operates on an llvm::Function and never runs IPO and IPA
- //llvm::initializeIPO(registry);
- //llvm::initializeIPA(registry);
-
- llvm::initializeAnalysis(registry);
- llvm::initializeTransformUtils(registry);
- llvm::initializeInstCombine(registry);
-
- InitializeAllCodeGenMachines();
- InitializeAllInvokeStubCompilers();
-
- return;
-}
-
-} // anonymous namespace
-
-namespace art {
-namespace greenland {
-
-Greenland::Greenland(art::Compiler& compiler)
- : compiler_(compiler), codegen_machine_(NULL),
- lock_("greenland_compiler_lock"), cur_gbc_ctx_(NULL) {
- // Initialize Greenland
- pthread_once(&greenland_initialized, InitializeGreenland);
-
- codegen_machine_ =
- TargetCodeGenMachine::Create(compiler_.GetInstructionSet());
- DCHECK(codegen_machine_ != NULL);
- return;
-}
-
-Greenland::~Greenland() {
- cur_gbc_ctx_->DecRef();
- delete codegen_machine_;
-}
-
-CompiledMethod* Greenland::Compile(OatCompilationUnit& cunit) {
- MutexLock GUARD(lock_);
-
- // Dex to LLVM IR
- GBCContext& gbc_ctx = GetGBCContext();
-
- UniquePtr<DexLang> dex_lang(new DexLang(gbc_ctx.GetDexLangContext(),
- compiler_, cunit));
-
- llvm::Function* func = dex_lang->Build();
-
- if (func == NULL) {
- LOG(FATAL) << "Failed to run dexlang on "
- << PrettyMethod(cunit.GetDexMethodIndex(), *cunit.GetDexFile());
- return NULL;
- }
-
- func->dump();
-
- // NOTE: From statistic, the bitcode size is 4.5 times bigger than the
- // Dex file. Besides, we have to convert the code unit into bytes.
- // Thus, we got our magic number 9.
- gbc_ctx.AddMemUsageApproximation(
- cunit.GetCodeItem()->insns_size_in_code_units_ * 900);
-
- GBCFunction gbc_func(gbc_ctx, *func, cunit);
-
- UniquePtr<CompiledMethod> result(codegen_machine_->Run(compiler_, gbc_func));
-
- // gbc_ctx was no longer needed
- gbc_ctx.DecRef();
-
- return result.release();
-}
-
-GBCContext& Greenland::GetGBCContext() {
- //MutexLock GUARD(lock_);
-
- ResetGBCContextIfThresholdReached();
-
- if (cur_gbc_ctx_ == NULL) {
- cur_gbc_ctx_ = new GBCContext();
- }
- CHECK(cur_gbc_ctx_ != NULL);
-
- return cur_gbc_ctx_->IncRef();
-}
-
-void Greenland::ResetGBCContextIfThresholdReached() {
- lock_.AssertHeld();
-
- if (cur_gbc_ctx_ == NULL) {
- return;
- }
-
- if (cur_gbc_ctx_->IsMemUsageThresholdReached()) {
- cur_gbc_ctx_->DecRef();
- cur_gbc_ctx_ = NULL;
- }
- return;
-}
-
-} // namespace greenland
-} // namespace art
-
-inline static art::greenland::Greenland* ContextOf(art::Compiler& compiler) {
- void *compiler_context = compiler.GetCompilerContext();
- CHECK(compiler_context != NULL);
- return reinterpret_cast<art::greenland::Greenland*>(compiler_context);
-}
-
-extern "C" void ArtInitCompilerContext(art::Compiler& compiler) {
- CHECK(compiler.GetCompilerContext() == NULL);
- compiler.SetCompilerContext(new art::greenland::Greenland(compiler));
- return;
-}
-
-extern "C" art::CompiledMethod* ArtCompileMethod(art::Compiler& compiler,
- const art::DexFile::CodeItem* code_item,
- uint32_t access_flags, uint32_t method_idx,
- const art::ClassLoader* class_loader,
- const art::DexFile& dex_file)
-{
- art::ClassLinker *class_linker = art::Runtime::Current()->GetClassLinker();
- art::DexCache *dex_cache = class_linker->FindDexCache(dex_file);
-
- art::OatCompilationUnit cunit(
- class_loader, class_linker, dex_file, *dex_cache, code_item,
- method_idx, access_flags);
-
- return ContextOf(compiler)->Compile(cunit);
-}
-
-extern "C" art::CompiledInvokeStub* ArtCreateInvokeStub(art::Compiler& compiler,
- bool is_static,
- const char* shorty,
- uint32_t shorty_len) {
- art::greenland::TargetRegistry::CreateInvokeStubFn compiler_fn =
- art::greenland::TargetRegistry::GetInvokeStubCompiler(compiler.GetInstructionSet());
- CHECK(compiler_fn != NULL);
- return (*compiler_fn)(compiler, is_static, shorty, shorty_len);
-}
diff --git a/src/greenland/greenland.h b/src/greenland/greenland.h
deleted file mode 100644
index 1d6f8e5..0000000
--- a/src/greenland/greenland.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#ifndef ART_SRC_GREENLAND_GREENLAND_H_
-#define ART_SRC_GREENLAND_GREENLAND_H_
-
-#include "macros.h"
-#include "object.h"
-
-namespace art {
- class CompiledMethod;
- class Compiler;
- class OatCompilationUnit;
-}
-
-namespace art {
-namespace greenland {
-
-class GBCContext;
-class TargetCodeGenMachine;
-
-class Greenland {
- public:
- Greenland(art::Compiler& compiler);
- ~Greenland();
-
- CompiledMethod* Compile(OatCompilationUnit& cunit);
-
- const Compiler& GetCompiler() const {
- return compiler_;
- }
- Compiler& GetCompiler() {
- return compiler_;
- }
-
- private:
- Compiler& compiler_;
-
- TargetCodeGenMachine* codegen_machine_;
-
- Mutex lock_;
-
- // NOTE: Ensure that the lock_ is held before altering cur_gbc_ctx
- GBCContext *cur_gbc_ctx_;
-
- GBCContext& GetGBCContext();
- void ResetGBCContextIfThresholdReached();
-
- DISALLOW_COPY_AND_ASSIGN(Greenland);
-};
-
-} // namespace greenland
-} // namespace art
-
-#endif // ART_SRC_GREENLAND_GREENLAND_H_
diff --git a/src/greenland/mips/mips_codegen_machine.cc b/src/greenland/mips/mips_codegen_machine.cc
deleted file mode 100644
index c63718b..0000000
--- a/src/greenland/mips/mips_codegen_machine.cc
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2012 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 "mips_codegen_machine.h"
-
-#include "greenland/target_registry.h"
-
-namespace art {
-namespace greenland {
-
-MipsCodeGenMachine::MipsCodeGenMachine() {
-}
-
-MipsCodeGenMachine::~MipsCodeGenMachine() {
-}
-
-void InitializeMipsCodeGenMachine() {
- RegisterTargetCodeGenMachine<MipsCodeGenMachine> X(kMips);
-}
-
-} // namespace greenland
-} // namespace art
diff --git a/src/greenland/mips/mips_codegen_machine.h b/src/greenland/mips/mips_codegen_machine.h
deleted file mode 100644
index c9f0abf..0000000
--- a/src/greenland/mips/mips_codegen_machine.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#ifndef ART_SRC_GREENLAND_MIPS_CODEGEN_MACHINE_H_
-#define ART_SRC_GREENLAND_MIPS_CODEGEN_MACHINE_H_
-
-#include "greenland/target_codegen_machine.h"
-
-namespace art {
-namespace greenland {
-
-class MipsCodeGenMachine : public TargetCodeGenMachine {
- private:
-
- public:
- MipsCodeGenMachine();
- virtual ~MipsCodeGenMachine();
-
- virtual TargetLIREmitter* CreateLIREmitter() {
- return NULL;
- }
-
- virtual const TargetDataLayout* GetDataLayout() const {
- return NULL;
- }
-
- virtual const TargetLIRInfo* GetLIRInfo() const {
- return NULL;
- }
-
- virtual const TargetRegisterInfo* GetRegisterInfo() const {
- return NULL;
- }
-
- virtual const char* GetConditionCodeName(unsigned cond) const {
- return NULL;
- }
-
- virtual TargetLIRBuilder* CreateLIRBuilder() {
- return NULL;
- }
-
- virtual RegisterAllocator* GetRegisterAllocator() {
- return NULL;
- }
-
- virtual TargetAssembler* GetAssembler() {
- return NULL;
- }
-
- virtual std::string PrettyTargeteLIR(const LIR& lir) const {
- return "";
- }
-};
-
-} // namespace greenland
-} // namespace art
-
-#endif // ART_SRC_GREENLAND_MIPS_CODEGEN_MACHINE_H_
diff --git a/src/greenland/mips/mips_invoke_stub_compiler.cc b/src/greenland/mips/mips_invoke_stub_compiler.cc
deleted file mode 100644
index e7aa662..0000000
--- a/src/greenland/mips/mips_invoke_stub_compiler.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2011 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 "greenland/target_registry.h"
-
-#include "logging.h"
-
-namespace art {
- class Compiler;
- class CompiledInvokeStub;
-}
-
-namespace {
-
-art::CompiledInvokeStub* MipsInvokeStubCompiler(art::Compiler& /*compiler*/,
- bool is_static,
- const char* shorty,
- uint32_t shorty_len) {
- UNIMPLEMENTED(FATAL);
- return NULL;
-}
-
-} // anonymous namespace
-
-namespace art {
-namespace greenland {
-
-void InitializeMipsInvokeStubCompiler() {
- TargetRegistry::RegisterInvokeStubCompiler(kMips, MipsInvokeStubCompiler);
-}
-
-} // namespace greenland
-} // namespace art
diff --git a/src/greenland/mips/mips_lir.def b/src/greenland/mips/mips_lir.def
deleted file mode 100644
index 0741f1b..0000000
--- a/src/greenland/mips/mips_lir.def
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 2012 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 "greenland/target_lir.def"
-#include "greenland/clear_target_lir.def"
diff --git a/src/greenland/register_allocator.cc b/src/greenland/register_allocator.cc
deleted file mode 100644
index b19f111..0000000
--- a/src/greenland/register_allocator.cc
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * Copyright (C) 2012 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 "register_allocator.h"
-#include "lir_function.h"
-#include "lir_frame_info.h"
-#include "lir_reg.h"
-
-#include "target_register_info.h"
-
-#include "logging.h"
-#include "stl_util.h"
-
-namespace art {
-namespace greenland {
-
-void RegisterAllocator::BuildKillInfo(LIRFunction& lir_func) {
- //TODO: Build Register KillInfo
-}
-
-static LIRBasicBlock::iterator
-GetSourceIterator(LIRBasicBlock& sourceBB, LIRBasicBlock& targetBB) {
- LIRBasicBlock::iterator it;
- for (it = sourceBB.back(); it != sourceBB.begin(); --it) {
- if (it->IsBranch() && (it->GetOperand(0).GetLabelTarget() == &targetBB))
- break;
- }
- return it;
-}
-
-void RegisterAllocator::PHIElimination(LIRFunction& lir_func) {
- for (LIRFunction::iterator bb = lir_func.begin(); bb != lir_func.end(); ++bb) {
- if (bb->IsEmpty() || !bb->front().IsPHI())
- continue;
-
- LIRBasicBlock::iterator it; // current LIR
- LIRBasicBlock::iterator next_it; // next LIR
- for(it = bb->begin(); it != bb->end(); it = next_it) {
- next_it = it; ++next_it;
- if (!it->IsPHI())
- break;
-
- for (unsigned i = 1; i < it->GetNumOperands(); i+=2) {
- const LIROperand& dst = it->GetOperand(0);
- const LIROperand& src = it->GetOperand(i);
- LIRBasicBlock* sourceBB =
- const_cast<LIRBasicBlock*> (it->GetOperand(i + 1).GetLabelTarget());
-
- LIR* lir = reg_info_.CreateCopy(lir_func, dst.GetReg(), src);
- LOG(INFO) << "PHIElimination: Insert COPY into BB: " << sourceBB->GetName();
- sourceBB->insert(GetSourceIterator(*sourceBB, *bb), lir);
- }
-
- bb->erase(it);
- }
- }
-}
-
-RegisterAllocator::Storage
-RegisterAllocator::AllocateStorage(LIRFunction &lir_func, unsigned vreg_idx) {
- // The virtual register is allocated, return it.
- if (allocated_map_.find(vreg_idx) != allocated_map_.end()) {
- return allocated_map_[vreg_idx];
- }
-
- Storage s;
- // Have free register(s).
- if (!allocatable_list_.empty()) {
- s.regTag = kPhyRegType;
- s.index = allocatable_list_.front();
- allocatable_list_.pop_front();
- }
- else {
- s.regTag = kFrameType;
- if (stackstorage_list_.empty()) {
- // FIXME: Get register subword
- s.index = lir_func.GetFrameInfo().AllocateStackObject(4);
- }
- else {
- s.index = stackstorage_list_.front();
- stackstorage_list_.pop_front();
- }
- }
- allocated_map_[vreg_idx] = s;
- return s;
-}
-
-void RegisterAllocator::KeepStorage(const LIR& lir) {
- unsigned reg_value = lir.GetOperand(0).GetReg();
- int frame_idx = lir.GetOperand(1).GetFrameIndex();
-
- if (!LIRReg::IsVirtualReg(reg_value))
- return;
-
- unsigned vreg_idx = LIRReg::GetRegNo(reg_value);
-
- LOG(INFO) << "VIRTUAL REG " << vreg_idx << " Keep in Stack Frame [" << frame_idx << "];";
-
- Storage s;
- s.regTag = kInStackType;
- s.index = frame_idx;
- allocated_map_[vreg_idx] = s;
-}
-
-void RegisterAllocator::FreeStorage(unsigned vreg_idx) {
- //TODO: Check vreg_idx must be allocated
- Storage s = allocated_map_[vreg_idx];
-
- if (s.regTag == kInStackType)
- return;
-
- if (s.regTag == kPhyRegType)
- allocatable_list_.push_front(s.index);
- else
- stackstorage_list_.push_front(s.index);
-
- allocated_map_.erase(vreg_idx);
-}
-
-void RegisterAllocator::InitializeAllocation(LIRFunction &lir_func) {
- allocatable_list_ = reg_info_.GetAllocatableList();
- stackstorage_list_.clear();
- allocated_map_.clear();
-}
-
-void RegisterAllocator::PreRegisterAllocation(LIRFunction &lir_func) {
- PHIElimination(lir_func);
-}
-
-void
-RegisterAllocator::HandleInsnCopy(LIRBasicBlock &bb,
- LIRBasicBlock::iterator it,
- LIRBasicBlock::iterator next_it) {
- unsigned reg_dst = it->GetOperand(0).GetReg();
- unsigned reg_src = it->GetOperand(1).GetReg();
-
- Storage stor_dst = {-1, kNoneType};
- Storage stor_src = {-1, kNoneType};
- unsigned vidx_dst = 0, vidx_src = 0;
-
- if (LIRReg::IsVirtualReg(reg_dst)) {
- vidx_dst = LIRReg::GetRegNo(reg_dst);
- LOG(INFO) << "VIRTUAL REG " << vidx_dst << " in COPY need allocated !!";
- stor_dst = AllocateStorage(bb.GetParent(), vidx_dst);
- }
-
- if (LIRReg::IsVirtualReg(reg_src)) {
- vidx_src = LIRReg::GetRegNo(reg_src);
- LOG(INFO) << "VIRTUAL REG " << vidx_src << " in COPY need allocated !!";
- stor_src = AllocateStorage(bb.GetParent(), vidx_src);
- }
-
- if ((LIRReg::IsPhysicalReg(reg_dst) || (stor_dst.regTag == kPhyRegType))
- && (LIRReg::IsPhysicalReg(reg_src) || (stor_src.regTag == kPhyRegType))) {
- // MovRR
- unsigned idx_dst = (LIRReg::IsPhysicalReg(reg_dst)) ?
- LIRReg::GetRegNo(reg_dst) : stor_dst.index;
- unsigned idx_src = (LIRReg::IsPhysicalReg(reg_src)) ?
- LIRReg::GetRegNo(reg_src) : stor_src.index;
- LOG(INFO) << "\t [COPY] create MOVE: move " << idx_dst << ", "<< idx_src;
- LIR* lir = reg_info_.CreateMoveReg(bb.GetParent(), idx_dst, idx_src);
- bb.insert(next_it, lir);
- bb.erase(it);
-
- if(LIRReg::IsVirtualReg(reg_src)) {
- FreeStorage(vidx_src);
- }
- return;
- }
-
- if ((stor_dst.regTag == stor_src.regTag) && (stor_dst.index == stor_src.index)) {
- // Redundant move
- FreeStorage(vidx_dst);
- FreeStorage(vidx_src);
- bb.erase(it);
- return;
- }
-
- if (stor_dst.regTag != kPhyRegType && stor_src.regTag != kPhyRegType) {
- unsigned idx = reg_info_.GetTempRegsiter(0);
- LIR* lir = reg_info_.CreateLoadStack(bb.GetParent(), idx, stor_src.index);
- bb.insert(it, lir);
- lir = reg_info_.CreateStoreStack(bb.GetParent(), idx, stor_dst.index);
- bb.insert(next_it, lir);
- bb.erase(it);
- return;
- }
-
- if (stor_dst.regTag != kPhyRegType) {
- unsigned idx = (LIRReg::IsPhysicalReg(reg_src)) ?
- LIRReg::GetRegNo(reg_src) : stor_src.index;
- LOG(INFO) << "\t [COPY] create StoreStack: move " << idx << ", "<< stor_dst.index;
- LIR* lir = reg_info_.CreateStoreStack(bb.GetParent(), idx, stor_dst.index);
- bb.insert(next_it, lir);
- bb.erase(it);
- return;
- }
-
- if (stor_src.regTag != kPhyRegType) {
- unsigned idx = (LIRReg::IsPhysicalReg(reg_dst)) ?
- LIRReg::GetRegNo(reg_dst) : stor_dst.index;
- LOG(INFO) << "\t [COPY] create LoadStack: move " << idx << ", "<< stor_src.index;
- LIR* lir = reg_info_.CreateLoadStack(bb.GetParent(), idx, stor_src.index);
- bb.insert(next_it, lir);
- bb.erase(it);
- return;
- }
-}
-
-void RegisterAllocator::FunctionRegisterAllocation(LIRFunction &lir_func) {
- for (LIRFunction::iterator bb = lir_func.begin(); bb != lir_func.end(); ++bb) {
- LIRBasicBlock::iterator it; // current LIR
- LIRBasicBlock::iterator next_it; // next LIR
- for (LIRBasicBlock::iterator it = bb->begin(); it != bb->end(); it = next_it) {
- next_it = it; ++next_it;
-
- // Handle Incoming Args
- if (reg_info_.IsLoadIncomingArgs(it)) {
- KeepStorage(*it);
- bb->erase(it);
- continue;
- }
-
- // Handle Copy
- if (it->GetOpcode() == opcode::kCOPY) {
- HandleInsnCopy(*bb, *it, *next_it);
- continue;
- }
-
- std::vector<unsigned> free_list;
- //for (LIR::op_iterator opi = i->operands_begin(); opi != i->operands_end(); ++opi) {
- for (unsigned i = 0 ; i < it->GetNumOperands(); i++) {
- LIROperand& lir_opd = it->GetOperand(i);
- unsigned temp_count = 0;
-
- if (!lir_opd.IsReg())
- continue;
-
- unsigned reg_value = lir_opd.GetReg();
- if (!LIRReg::IsVirtualReg(reg_value))
- continue;
- unsigned vreg_idx = LIRReg::GetRegNo(reg_value);
- LOG(INFO) << "\t" << "VIRTUAL REG " << vreg_idx << " need allocated !!";
- Storage s = AllocateStorage(lir_func, vreg_idx);
- if (!s.regTag) {
- LOG(INFO) << "\t" << "VIRTUAL REG " << vreg_idx << " is map to REG[" << s.index << "]!!";
- lir_opd.SetReg(s.index);
- } else {
- unsigned temp_idx = reg_info_.GetTempRegsiter(temp_count++);
- if ( lir_opd.IsDef() ) {
- LIR* lir = reg_info_.CreateStoreStack(lir_func, temp_idx, s.index);
- bb->insert(next_it, lir);
- lir_opd.SetReg(temp_idx);
- } else {
- LIR* lir = reg_info_.CreateLoadStack(lir_func, temp_idx, s.index);
- bb->insert(it, lir);
- lir_opd.SetReg(temp_idx);
- }
-
- LOG(INFO) << "\t" << "VIRTUAL REG " << vreg_idx << " is map to Frame[" << s.index << "]!!";
- }
-
- if (lir_opd.IsKill()) {
- free_list.push_back(vreg_idx);
- LOG(INFO) << "\t" << "VIRTUAL REG " << vreg_idx << " is mark kill!!";
- }
- }
-
- for (size_t i = 0 ; i < free_list.size(); i++) {
- LOG(INFO) << "\t" << "VIRTUAL REG " << free_list[i] << " is kill!!";
- FreeStorage(free_list[i]);
- }
- }
- }
-}
-
-} // namespace greenland
-} // namespace art
diff --git a/src/greenland/register_allocator.h b/src/greenland/register_allocator.h
deleted file mode 100644
index ffe0914..0000000
--- a/src/greenland/register_allocator.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#ifndef ART_SRC_GREENLAND_REGISTER_ALLOCATOR_H_
-#define ART_SRC_GREENLAND_REGISTER_ALLOCATOR_H_
-
-#include "backend_types.h"
-
-#include "lir_basic_block.h"
-
-#include <stdint.h>
-#include <list>
-#include <map>
-
-namespace art {
-namespace greenland {
-
-class LIR;
-class LIRFunction;
-class TargetRegisterInfo;
-
-class RegisterAllocator {
- private:
- enum RegTypeTag {
- kPhyRegType = 0, kFrameType, kInStackType, kNoneType = -1
- };
-
- struct Storage {
- int index;
- RegTypeTag regTag;
- };
-
- // Storage Allocation
- Storage AllocateStorage(LIRFunction &lir_func, unsigned vreg_idx);
- void KeepStorage(const LIR& lir);
- void FreeStorage(unsigned vreg_idx);
- void HandleInsnCopy(LIRBasicBlock& bb,
- LIRBasicBlock::iterator it,
- LIRBasicBlock::iterator next_lir);
-
- // Pre-RA
- void BuildKillInfo(LIRFunction& lir_func);
- void PHIElimination(LIRFunction& lir_func);
-
- void InitializeAllocation(LIRFunction& lir_func);
- void PreRegisterAllocation(LIRFunction& lir_func);
- void FunctionRegisterAllocation(LIRFunction& lir_func);
- public:
- RegisterAllocator(const TargetRegisterInfo& info) : reg_info_(info) { }
- ~RegisterAllocator() { }
-
- void AllocateRegisters(LIRFunction& lir_func) {
- InitializeAllocation(lir_func);
- PreRegisterAllocation(lir_func);
- FunctionRegisterAllocation(lir_func);
- }
-
- private:
- std::list<unsigned> allocatable_list_;
- std::list<unsigned> stackstorage_list_;
- std::map<unsigned, Storage> allocated_map_;
- const TargetRegisterInfo& reg_info_;
- DISALLOW_COPY_AND_ASSIGN(RegisterAllocator);
-};
-
-} // namespace greenland
-} // namespace art
-
-#endif // ART_SRC_GREENLAND_REGISTER_ALLOCATOR_H_
diff --git a/src/greenland/runtime/runtime_utils.h b/src/greenland/runtime/runtime_utils.h
deleted file mode 100644
index cbdfcc6..0000000
--- a/src/greenland/runtime/runtime_utils.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#ifndef ART_SRC_GREENLAND_RUNTIME_UTILS_H_
-#define ART_SRC_GREENLAND_RUNTIME_UTILS_H_
-
-#include "asm_support.h"
-#include "thread.h"
-
-namespace art {
-namespace greenland {
-
-static inline Thread* art_get_current_thread() {
-#if defined(__i386__)
- Thread* ptr;
- __asm__ __volatile__("movl %%fs:(%1), %0"
- : "=r"(ptr) // output
- : "r"(THREAD_SELF_OFFSET) // input
- :); // clobber
- return ptr;
-#else
- return Thread::Current();
-#endif
-}
-
-} // namespace greenland
-} // namespace art
-
-#endif // ART_SRC_GREENLAND_RUNTIME_UTILS_H_
diff --git a/src/greenland/runtime/support_alloc.cc b/src/greenland/runtime/support_alloc.cc
deleted file mode 100644
index dd7850d..0000000
--- a/src/greenland/runtime/support_alloc.cc
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2012 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 "greenland/runtime_entry_points.h"
-
-#include "runtime_utils.h"
-#include "runtime_support.h"
-
-using namespace art;
-using namespace art::greenland;
-
-namespace {
-
-Object* art_alloc_array_from_code(uint32_t type_idx,
- AbstractMethod* referrer,
- uint32_t length,
- Thread* thread) {
- return AllocArrayFromCode(type_idx, referrer, length, thread, false);
-}
-
-Object* art_alloc_array_from_code_with_access_check(uint32_t type_idx,
- AbstractMethod* referrer,
- uint32_t length,
- Thread* thread) {
- return AllocArrayFromCode(type_idx, referrer, length, thread, true);
-}
-
-Object* art_check_and_alloc_array_from_code(uint32_t type_idx,
- AbstractMethod* referrer,
- uint32_t length,
- Thread* thread) {
- return CheckAndAllocArrayFromCode(type_idx, referrer, length, thread, false);
-}
-
-Object* art_check_and_alloc_array_from_code_with_access_check(uint32_t type_idx,
- AbstractMethod* referrer,
- uint32_t length,
- Thread* thread) {
- return CheckAndAllocArrayFromCode(type_idx, referrer, length, thread, true);
-}
-
-} // anonymous namespace
-
-namespace art {
-namespace greenland {
-
-void InitAllocRuntimes(RuntimeEntryPoints* entry_points) {
- entry_points->AllocArray = art_alloc_array_from_code;
- entry_points->AllocArrayWithAccessCheck = art_alloc_array_from_code_with_access_check;
- entry_points->CheckAndAllocArray = art_check_and_alloc_array_from_code;
- entry_points->CheckAndAllocArrayWithAccessCheck = art_check_and_alloc_array_from_code_with_access_check;
- return;
-}
-
-} // namespace greenland
-} // namespace art
diff --git a/src/greenland/runtime/support_cast.cc b/src/greenland/runtime/support_cast.cc
deleted file mode 100644
index d74dbe7..0000000
--- a/src/greenland/runtime/support_cast.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2012 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 "greenland/runtime_entry_points.h"
-
-#include "runtime_utils.h"
-#include "runtime_support.h"
-
-using namespace art;
-using namespace art::greenland;
-
-namespace {
-
-void art_check_put_array_element_from_code(const Object* element,
- const Object* array) {
- if (element == NULL) {
- return;
- }
- DCHECK(array != NULL);
- Class* array_class = array->GetClass();
- DCHECK(array_class != NULL);
- Class* component_type = array_class->GetComponentType();
- Class* element_class = element->GetClass();
- if (UNLIKELY(!component_type->IsAssignableFrom(element_class))) {
- Thread* thread = art_get_current_thread();
- thread->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
- "%s cannot be stored in an array of type %s",
- PrettyDescriptor(element_class).c_str(),
- PrettyDescriptor(array_class).c_str());
- }
- return;
-}
-
-} // anonymous namespace
-
-namespace art {
-namespace greenland {
-
-void InitCastRuntimes(RuntimeEntryPoints* entry_points) {
- entry_points->CheckPutArrayElement = art_check_put_array_element_from_code;
-}
-
-} // namespace greenland
-} // namespace art
diff --git a/src/greenland/runtime/support_dexcache.cc b/src/greenland/runtime/support_dexcache.cc
deleted file mode 100644
index 9d36aad..0000000
--- a/src/greenland/runtime/support_dexcache.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2012 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 "greenland/runtime_entry_points.h"
-
-#include "runtime_utils.h"
-#include "runtime_support.h"
-
-using namespace art;
-using namespace art::greenland;
-
-namespace {
-
-Object* art_resolve_string(AbstractMethod* referrer, uint32_t string_idx) {
- return ResolveStringFromCode(referrer, string_idx);
-}
-
-} // anonymous namespace
-
-namespace art {
-namespace greenland {
-
-void InitDexCacheRuntimes(RuntimeEntryPoints* entry_points) {
- entry_points->ResolveString = art_resolve_string;
-}
-
-} // namespace greenland
-} // namespace art
diff --git a/src/greenland/runtime/support_exception.cc b/src/greenland/runtime/support_exception.cc
deleted file mode 100644
index 4bc910a..0000000
--- a/src/greenland/runtime/support_exception.cc
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2012 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 "greenland/runtime_entry_points.h"
-
-#include "nth_caller_visitor.h"
-#include "runtime_utils.h"
-#include "runtime_support.h"
-
-using namespace art;
-using namespace art::greenland;
-
-namespace {
-
-int32_t art_find_catch_block(AbstractMethod* current_method, uint32_t ti_offset) {
- Thread* thread = art_get_current_thread();
- Class* exception_type = thread->GetException()->GetClass();
- MethodHelper mh(current_method);
- const DexFile::CodeItem* code_item = mh.GetCodeItem();
- DCHECK_LT(ti_offset, code_item->tries_size_);
- const DexFile::TryItem* try_item = DexFile::GetTryItems(*code_item, ti_offset);
-
- int iter_index = 0;
- // Iterate over the catch handlers associated with dex_pc
- for (CatchHandlerIterator it(*code_item, *try_item); it.HasNext(); it.Next()) {
- uint16_t iter_type_idx = it.GetHandlerTypeIndex();
- // Catch all case
- if (iter_type_idx == DexFile::kDexNoIndex16) {
- return iter_index;
- }
- // Does this catch exception type apply?
- Class* iter_exception_type = mh.GetDexCacheResolvedType(iter_type_idx);
- if (iter_exception_type == NULL) {
- // The verifier should take care of resolving all exception classes early
- LOG(WARNING) << "Unresolved exception class when finding catch block: "
- << mh.GetTypeDescriptorFromTypeIdx(iter_type_idx);
- } else if (iter_exception_type->IsAssignableFrom(exception_type)) {
- return iter_index;
- }
- ++iter_index;
- }
- // Handler not found
- return -1;
-}
-
-void art_throw_array_bounds(int32_t length, int32_t index) {
- Thread* thread = art_get_current_thread();
- thread->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
- "length=%d; index=%d", length, index);
-}
-
-void art_throw_null_pointer_exception(uint32_t dex_pc) {
- Thread* thread = art_get_current_thread();
- NthCallerVisitor visitor(0);
- thread->WalkStack(&visitor);
- AbstractMethod* throw_method = visitor.caller;
- ThrowNullPointerExceptionFromDexPC(thread, throw_method, dex_pc);
-}
-
-} // anonymous namespace
-
-namespace art {
-namespace greenland {
-
-void InitExceptionRuntimes(RuntimeEntryPoints* entry_points) {
- entry_points->FindCatchBlock = art_find_catch_block;
- entry_points->ThrowIndexOutOfBounds = art_throw_array_bounds;
- entry_points->ThrowNullPointerException = art_throw_null_pointer_exception;
-}
-
-} // namespace greenland
-} // namespace art
diff --git a/src/greenland/runtime/support_field.cc b/src/greenland/runtime/support_field.cc
deleted file mode 100644
index e5fa814..0000000
--- a/src/greenland/runtime/support_field.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2012 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 "greenland/runtime_entry_points.h"
-
-#include "runtime_utils.h"
-#include "runtime_support.h"
-
-using namespace art;
-using namespace art::greenland;
-
-namespace {
-
-Object* art_get_obj_static_from_code(uint32_t field_idx, AbstractMethod* referrer) {
- Field* field = FindFieldFast(field_idx, referrer, false, false, sizeof(Object*));
- if (LIKELY(field != NULL)) {
- return field->GetObj(NULL);
- }
- field = FindFieldFromCode(field_idx, referrer, art_get_current_thread(),
- true, false, false, sizeof(Object*));
- if (LIKELY(field != NULL)) {
- return field->GetObj(NULL);
- }
- return 0;
-}
-
-} // anonymous namespace
-
-namespace art {
-namespace greenland {
-
-void InitFieldRuntimes(RuntimeEntryPoints* entry_points) {
- entry_points->GetObjectStatic = art_get_obj_static_from_code;
-}
-
-} // namespace greenland
-} // namespace art
diff --git a/src/greenland/runtime/support_thread.cc b/src/greenland/runtime/support_thread.cc
deleted file mode 100644
index 25fb698..0000000
--- a/src/greenland/runtime/support_thread.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2012 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 "greenland/runtime_entry_points.h"
-
-#include "runtime_utils.h"
-#include "runtime_support.h"
-#include "thread_list.h"
-
-using namespace art;
-using namespace art::greenland;
-
-namespace {
-
-void art_test_suspend(Thread* thread) {
- Runtime::Current()->GetThreadList()->FullSuspendCheck(thread);
-}
-
-} // anonymous namespace
-
-namespace art {
-namespace greenland {
-
-void InitThreadRuntimes(RuntimeEntryPoints* entry_points) {
- entry_points->TestSuspend = art_test_suspend;
-}
-
-} // namespace greenland
-} // namespace art
diff --git a/src/greenland/runtime_entry_points.cc b/src/greenland/runtime_entry_points.cc
deleted file mode 100644
index a9b1edc..0000000
--- a/src/greenland/runtime_entry_points.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2012 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 "runtime_entry_points.h"
-
-namespace art {
-
-// Forward Declarations
-namespace greenland {
-
-void InitThreadRuntimes(RuntimeEntryPoints* entry_points);
-void InitExceptionRuntimes(RuntimeEntryPoints* entry_points);
-void InitAllocRuntimes(RuntimeEntryPoints* entry_points);
-void InitDexCacheRuntimes(RuntimeEntryPoints* entry_points);
-void InitFieldRuntimes(RuntimeEntryPoints* entry_points);
-void InitCastRuntimes(RuntimeEntryPoints* entry_points);
-
-} // namespace greenland
-
-void InitRuntimeEntryPoints(RuntimeEntryPoints* entry_points) {
- // Defined in runtime/support_thread.cc
- greenland::InitThreadRuntimes(entry_points);
- // Defined in runtime/support_exception.cc
- greenland::InitExceptionRuntimes(entry_points);
- // Defined in runtime/support_alloc.cc
- greenland::InitAllocRuntimes(entry_points);
- // Defined in runtime/support_dexcache.cc
- greenland::InitDexCacheRuntimes(entry_points);
- // Defined in runtime/support_field.cc
- greenland::InitFieldRuntimes(entry_points);
- // Defined in runtime/support_case.cc
- greenland::InitCastRuntimes(entry_points);
- return;
-}
-
-} // namespace art
diff --git a/src/greenland/runtime_entry_points.h b/src/greenland/runtime_entry_points.h
deleted file mode 100644
index 9ee053e..0000000
--- a/src/greenland/runtime_entry_points.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#ifndef ART_SRC_GREENLAND_RUNTIME_ENTRY_POINTS_H_
-#define ART_SRC_GREENLAND_RUNTIME_ENTRY_POINTS_H_
-
-#include "macros.h"
-
-#include <stdint.h>
-
-#define RUNTIME_ENTRYPOINT(x) \
- (static_cast<uintptr_t>(OFFSETOF_MEMBER(Thread, runtime_entry_points_)) + \
- static_cast<uintptr_t>(OFFSETOF_MEMBER(RuntimeEntryPoints, x)))
-
-namespace art {
-
-class AbstractMethod;
-class Object;
-class Thread;
-
-struct PACKED RuntimeEntryPoints {
- //----------------------------------------------------------------------------
- // Thread
- //----------------------------------------------------------------------------
- void (*TestSuspend)(Thread* thread);
-
- //----------------------------------------------------------------------------
- // Exception
- //----------------------------------------------------------------------------
- int32_t (*FindCatchBlock)(AbstractMethod* current_method, uint32_t ti_offset);
- void (*ThrowIndexOutOfBounds)(int32_t length, int32_t index);
- void (*ThrowNullPointerException)(unsigned dex_pc);
-
- //----------------------------------------------------------------------------
- // Alloc
- //----------------------------------------------------------------------------
- Object* (*AllocArray)(uint32_t type_idx, AbstractMethod* referrer,
- uint32_t length, Thread* thread);
-
- Object* (*AllocArrayWithAccessCheck)(uint32_t type_idx, AbstractMethod* referrer,
- uint32_t length, Thread* thread);
-
- Object* (*CheckAndAllocArray)(uint32_t type_idx, AbstractMethod* referrer,
- uint32_t length, Thread* thread);
-
- Object* (*CheckAndAllocArrayWithAccessCheck)(uint32_t type_idx,
- AbstractMethod* referrer,
- uint32_t length,
- Thread* thread);
-
- //----------------------------------------------------------------------------
- // DexCache
- //----------------------------------------------------------------------------
- Object* (*ResolveString)(AbstractMethod* referrer, uint32_t string_idx);
-
- //----------------------------------------------------------------------------
- // Field
- //----------------------------------------------------------------------------
- Object* (*GetObjectStatic)(uint32_t field_idx, AbstractMethod* referrer);
-
- //----------------------------------------------------------------------------
- // Cast
- //----------------------------------------------------------------------------
- void (*CheckPutArrayElement)(const Object* element, const Object* array);
-
- //----------------------------------------------------------------------------
- // JNI
- //----------------------------------------------------------------------------
-};
-
-// Initialize an entry point data structure.
-void InitRuntimeEntryPoints(RuntimeEntryPoints* entry_points);
-
-} // namespace art
-
-#endif // ART_SRC_GREENLAND_RUNTIME_ENTRY_POINTS_H_
diff --git a/src/greenland/target_codegen_machine.cc b/src/greenland/target_codegen_machine.cc
deleted file mode 100644
index 3c65a68..0000000
--- a/src/greenland/target_codegen_machine.cc
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2012 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 "target_codegen_machine.h"
-
-#include "lir_function.h"
-#include "lir_pass_manager.h"
-#include "target_lir_emitter.h"
-#include "target_lir_opcodes.h"
-#include "target_registry.h"
-
-#include "compiled_method.h"
-#include "compiler.h"
-#include "oat_compilation_unit.h"
-#include "utils.h"
-
-#include <UniquePtr.h>
-
-namespace art {
-namespace greenland {
-
-TargetCodeGenMachine* TargetCodeGenMachine::Create(InstructionSet insn_set) {
- TargetRegistry::TargetCodeGenMachineCtorTy ctor =
- TargetRegistry::GetTargetCodeGenMachineCtor(insn_set);
-
- if (ctor == NULL) {
- return NULL;
- }
-
- return (*ctor)();
-}
-
-CompiledMethod* TargetCodeGenMachine::Run(const Compiler& compiler,
- const GBCFunction& gbc_func) {
- LIRPassManager lir_pm;
-
- lir_pm.Add(CreateLIREmitter());
-
- LIRFunction lir_func(*this, gbc_func);
-
- if (!lir_pm.Run(lir_func)) {
- return NULL;
- }
-
- lir_func.Dump();
-
- // 0x90 is the NOP in x86
- std::vector<uint8_t> code(10, 0x90);
-
- return new CompiledMethod(compiler.GetInstructionSet(), code,
- /* frame_size_in_bytes */0,
- /* core_spill_mask */0,
- /* fp_spill_mask */0);
-}
-
-} // namespace greenland
-} // namespace art
diff --git a/src/greenland/target_codegen_machine.h b/src/greenland/target_codegen_machine.h
deleted file mode 100644
index 8cae791..0000000
--- a/src/greenland/target_codegen_machine.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#ifndef ART_SRC_GREENLAND_TARGET_CODEGEN_MACHINE_H_
-#define ART_SRC_GREENLAND_TARGET_CODEGEN_MACHINE_H_
-
-#include "instruction_set.h"
-
-#include <string>
-
-namespace art {
- class CompiledMethod;
- class Compiler;
-}
-
-namespace art {
-namespace greenland {
-
-class GBCFunction;
-class LIR;
-class RegisterAllocator;
-class TargetAssembler;
-class TargetDataLayout;
-class TargetLIRBuilder;
-class TargetLIREmitter;
-class TargetLIRInfo;
-class TargetRegisterInfo;
-
-class TargetCodeGenMachine {
- protected:
- TargetCodeGenMachine() { }
-
- public:
- virtual ~TargetCodeGenMachine() { }
-
- virtual TargetLIREmitter* CreateLIREmitter() = 0;
-
- virtual const TargetDataLayout* GetDataLayout() const = 0;
-
- virtual const TargetLIRInfo* GetLIRInfo() const = 0;
-
- virtual const TargetRegisterInfo* GetRegisterInfo() const = 0;
-
- virtual const char* GetConditionCodeName(unsigned cond) const = 0;
-
- virtual TargetLIRBuilder* CreateLIRBuilder() = 0;
-
- virtual RegisterAllocator* GetRegisterAllocator() = 0;
-
- virtual TargetAssembler* GetAssembler() = 0;
-
- static TargetCodeGenMachine* Create(InstructionSet insn_set);
-
- public:
- CompiledMethod* Run(const Compiler& compiler, const GBCFunction& gbc_func);
-};
-
-} // namespace greenland
-} // namespace art
-
-#endif // ART_SRC_GREENLAND_TARGET_CODEGEN_MACHINE_H_
diff --git a/src/greenland/target_data_layout.h b/src/greenland/target_data_layout.h
deleted file mode 100644
index 7b634cf..0000000
--- a/src/greenland/target_data_layout.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#ifndef ART_SRC_GREENLAND_TARGET_DATA_LAYOUT_H_
-#define ART_SRC_GREENLAND_TARGET_DATA_LAYOUT_H_
-
-#include "lir.h"
-
-#include "logging.h"
-
-namespace art {
-namespace greenland {
-
-class TargetDataLayout {
- private:
- // Size of pointer in bytes
- unsigned pointer_size_;
-
- // Stack alignment in bytes
- unsigned stack_alignment_;
-
- public:
- TargetDataLayout(unsigned pointer_size, unsigned stack_alignment)
- : pointer_size_(pointer_size), stack_alignment_(stack_alignment) { }
-
- unsigned GetPointerSize() const {
- return pointer_size_;
- }
- unsigned GetPointerSizeInBits() const {
- return (pointer_size_ << 3);
- }
-
- unsigned GetStackAlignment() const {
- return stack_alignment_;
- }
-
- unsigned GetOpTypeSize(LIR::OperationType op_type) const {
- switch (op_type) {
- case LIR::kUInt8TypeOp: return 1; break;
- case LIR::kSInt8TypeOp: return 1; break;
- case LIR::kUInt16TypeOp: return 2; break;
- case LIR::kSInt16TypeOp: return 2; break;
- case LIR::kInt32TypeOp: return 4; break;
- case LIR::kInt64TypeOp: return 8; break;
- case LIR::kFloatTypeOp: return 4; break;
- case LIR::kDoubleTypeOp: return 8; break;
- case LIR::kPointerTypeOp: return pointer_size_; break;
- case LIR::kUnknownTypeOp:
- default: {
- LOG(FATAL) << "Unknown operation type: " << op_type;
- return 0;
- }
- }
- // unreachable
- }
-};
-
-} // namespace greenland
-} // namespace art
-
-#endif // ART_SRC_GREENLAND_TARGET_DATA_LAYOUT_H_
diff --git a/src/greenland/target_register_info.h b/src/greenland/target_register_info.h
deleted file mode 100644
index 41d69e1..0000000
--- a/src/greenland/target_register_info.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#ifndef ART_SRC_GREENLAND_TARGET_REGISTER_INFO_H_
-#define ART_SRC_GREENLAND_TARGET_REGISTER_INFO_H_
-
-#include "lir_function.h"
-#include "lir_reg.h"
-
-#include "target_lir_builder.h"
-#include "target_lir_info.h"
-
-#include <string>
-
-namespace art {
-namespace greenland {
-
-class TargetRegisterInfo {
- protected:
- const TargetLIRInfo& lir_info_;
- TargetRegisterInfo(const TargetLIRInfo& info) :lir_info_(info) { }
-
- public:
- virtual const char* GetPhyRegName(unsigned reg) const = 0;
-
- std::string GetRegName(unsigned reg) const {
- if (LIRReg::IsVirtualReg(reg)) {
- return LIRReg::GetVirtualRegName(reg);
- } else {
- return GetPhyRegName(reg);
- }
- }
-
- virtual LIR*
- CreateLoadStack(LIRFunction& lir_func,
- unsigned reg,
- int frame_idx) const = 0;
-
- virtual LIR*
- CreateStoreStack(LIRFunction& lir_func,
- unsigned reg,
- int frame_idx) const = 0;
-
- virtual LIR*
- CreateMoveReg(LIRFunction& lir_func,
- unsigned dst,
- unsigned src) const = 0;
-
- virtual bool
- IsLoadIncomingArgs(const LIR* lir) const = 0;
-
- virtual LIR*
- CreateCopy(LIRFunction& lir_func,
- unsigned dst,
- const LIROperand& src) const = 0;
-
- virtual std::list<unsigned> GetAllocatableList() const = 0;
- virtual unsigned GetTempRegsiter(unsigned idx) const = 0;
-
- virtual ~TargetRegisterInfo() { }
-};
-
-} // namespace greenland
-} // namespace art
-
-#endif // ART_SRC_GREENLAND_TARGET_REGISTER_INFO_H_
diff --git a/src/greenland/target_registry.cc b/src/greenland/target_registry.cc
deleted file mode 100644
index e4a1840..0000000
--- a/src/greenland/target_registry.cc
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2012 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 "target_registry.h"
-
-#include "logging.h"
-
-namespace {
-
-// The following arrays contain the real registry data store by Register*()
-// methods in TargetRegistry. Should keep sync with enum InstructionSet.
-art::greenland::TargetRegistry::TargetCodeGenMachineCtorTy
-RegisteredTargetCodeGenMachineCtor[] = {
- NULL, /* kNone */
- NULL, /* kArm */
- NULL, /* kThumb2 */
- NULL, /* kX86 */
- NULL, /* kMips */
-};
-
-art::greenland::TargetRegistry::CreateInvokeStubFn
-RegisteredInvokeStubCompiler[] = {
- NULL, /* kNone */
- NULL, /* kArm */
- NULL, /* kThumb2 */
- NULL, /* kX86 */
- NULL, /* kMips */
-};
-
-} // anonymous namespace
-
-namespace art {
-namespace greenland {
-
-void TargetRegistry::RegisterTargetCodeGenMachine(InstructionSet insn_set,
- TargetCodeGenMachineCtorTy ctor) {
- CHECK(static_cast<unsigned>(insn_set) <
- (sizeof(RegisteredTargetCodeGenMachineCtor) / sizeof(RegisteredTargetCodeGenMachineCtor[0])));
- RegisteredTargetCodeGenMachineCtor[static_cast<unsigned>(insn_set)] = ctor;
- return;
-}
-
-TargetRegistry::TargetCodeGenMachineCtorTy
-TargetRegistry::GetTargetCodeGenMachineCtor(InstructionSet insn_set) {
- CHECK(static_cast<unsigned>(insn_set) <
- (sizeof(RegisteredTargetCodeGenMachineCtor) / sizeof(RegisteredTargetCodeGenMachineCtor[0])));
- return RegisteredTargetCodeGenMachineCtor[static_cast<unsigned>(insn_set)];
-}
-
-void
-TargetRegistry::RegisterInvokeStubCompiler(InstructionSet insn_set,
- CreateInvokeStubFn compiler_fn) {
- CHECK(static_cast<unsigned>(insn_set) <
- (sizeof(RegisteredInvokeStubCompiler) / sizeof(RegisteredInvokeStubCompiler[0])));
- RegisteredInvokeStubCompiler[static_cast<unsigned>(insn_set)] = compiler_fn;
- return;
-}
-
-TargetRegistry::CreateInvokeStubFn
-TargetRegistry::GetInvokeStubCompiler(InstructionSet insn_set) {
- CHECK(static_cast<unsigned>(insn_set) <
- (sizeof(RegisteredInvokeStubCompiler) / sizeof(RegisteredInvokeStubCompiler[0])));
- return RegisteredInvokeStubCompiler[static_cast<unsigned>(insn_set)];
-}
-
-} // namespace greenland
-} // namespace art
diff --git a/src/greenland/target_registry.h b/src/greenland/target_registry.h
deleted file mode 100644
index 0f490e0..0000000
--- a/src/greenland/target_registry.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#ifndef ART_SRC_GREENLAND_TARGET_REGISTRY_H_
-#define ART_SRC_GREENLAND_TARGET_REGISTRY_H_
-
-#include "instruction_set.h"
-
-#include <stdint.h>
-
-namespace art {
- class Compiler;
- class CompiledInvokeStub;
-}
-
-namespace art {
-namespace greenland {
-
-class TargetCodeGenMachine;
-
-class TargetRegistry {
- public:
- typedef TargetCodeGenMachine* (*TargetCodeGenMachineCtorTy)();
- typedef CompiledInvokeStub* (*CreateInvokeStubFn)(Compiler& compiler,
- bool is_static,
- const char* shorty,
- uint32_t shorty_len);
-
- static void RegisterTargetCodeGenMachine(InstructionSet insn_set,
- TargetCodeGenMachineCtorTy ctor);
- static TargetCodeGenMachineCtorTy GetTargetCodeGenMachineCtor(InstructionSet insn_set);
-
- static void RegisterInvokeStubCompiler(InstructionSet insn_set,
- CreateInvokeStubFn compiler_fn);
- static CreateInvokeStubFn GetInvokeStubCompiler(InstructionSet insn_set);
-};
-
-template<class TargetCodeGenMachineImpl>
-class RegisterTargetCodeGenMachine {
- private:
- static TargetCodeGenMachine* Allocator() {
- return new TargetCodeGenMachineImpl();
- }
-
- public:
- RegisterTargetCodeGenMachine(InstructionSet insn_set) {
- TargetRegistry::RegisterTargetCodeGenMachine(insn_set, &Allocator);
- }
-};
-
-
-} // namespace greenland
-} // namespace art
-
-#endif // ART_SRC_GREENLAND_TARGET_REGISTRY_H_
diff --git a/src/greenland/tools/target_lir_builder_generator.cc b/src/greenland/tools/target_lir_builder_generator.cc
deleted file mode 100644
index 2a48136..0000000
--- a/src/greenland/tools/target_lir_builder_generator.cc
+++ /dev/null
@@ -1,574 +0,0 @@
-/*
- * Copyright (C) 2012 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 <cassert>
-#include <cctype>
-#include <cstring>
-#include <iostream>
-#include <string>
-
-// Should be synced with the one in lir_desc.h
-#define MAX_LIR_OPERANDS 6
-
-//----------------------------------------------------------------------------
-// Operand Info
-//----------------------------------------------------------------------------
-class LIROperand {
- public:
- enum Type {
- UnknownType,
- RegisterType,
- ImmediateType,
- LabelType,
- FrameIndexType,
- };
-};
-
-// Copy from lir_desc.h
-class LIRDescFlag {
- public:
- enum Flag {
- kNone,
- kPseudo,
- kVariadic,
-
- kIsLoad,
- kIsStore,
- kIsBranch,
-
- kDefReg0,
- kDefReg1,
-
- kUseReg0,
- kUseReg1,
- kUseReg2,
- kUseReg3,
- kUseReg4,
- kUseReg5,
-
- kSetCCodes,
- kUseCCodes,
-
- kNeedRelax,
- };
-};
-
-class LIROperandInfo {
- public:
- class TypeStrings {
- public:
- // Take RegisterType as example:
- // type_string_ is "unsigned"
- // var_string_ is "reg"
- // set_method_ is "SetReg"
- const char* type_string_;
- const char* var_string_;
- const char* set_method_;
- };
-
- LIROperand::Type GetOperandType(unsigned i) const {
- assert((i < num_operands_) && "Invalid operand index!");
- return info_[i].type_;
- }
-
- const TypeStrings& GetOperandTypeStrings(unsigned i) const {
- return OperandTypeStrings[GetOperandType(i)];
- }
-
- private:
- static const TypeStrings OperandTypeStrings[];
-
- public:
- const char* name_;
- unsigned num_operands_;
- struct {
- enum LIROperand::Type type_;
- } info_[MAX_LIR_OPERANDS];
-};
-
-const LIROperandInfo::TypeStrings LIROperandInfo::OperandTypeStrings[] = {
- /* UnknownType */ { "void", "", "", },
- /* RegisterType */ { "unsigned", "reg", "SetReg" },
- /* ImmediateType */ { "int32_t" , "imm_val", "SetImm" },
- /* LabelType */ { "LIRBasicBlock*", "target", "SetLabelTarget" },
- /* FrameIndexType */ { "int", "frame_index", "SetFrameIndex" }
-};
-
-#define DEF_LIR_OPERAND_INFO(INFO_ID, NUM_OPS, INFO_DEF) \
-static const LIROperandInfo OpInfo ## INFO_ID = \
- { #INFO_ID, NUM_OPS, INFO_DEF };
-#include "greenland/target_lir.def"
-#include "greenland/clear_target_lir.def"
-
-static const LIROperandInfo* const OpInfos[] = {
-#define DEF_LIR_OPERAND_INFO(INFO_ID, NUM_OPS, INFO_DEF) \
- &OpInfo ## INFO_ID,
-#include "greenland/target_lir.def"
-#include "greenland/clear_target_lir.def"
-};
-
-static const unsigned NumObInfos = sizeof(OpInfos) / sizeof(OpInfos[0]);
-
-//----------------------------------------------------------------------------
-// Data structure of LIRDesc to load {target}_lir.def
-//----------------------------------------------------------------------------
-
-class LIRDesc {
- public:
- const char* opcode_name_;
- const char* name_;
- const char* format_;
- unsigned flags;
- const LIROperandInfo& operand_info_;
-
- bool IsPseudo() const {
- return (flags & (1 << LIRDescFlag::kPseudo));
- }
-};
-
-//----------------------------------------------------------------------------
-// Target-independent LIR Enumeration
-//----------------------------------------------------------------------------
-// This is here to get the number of target-independent LIRs
-// (i.e., kNumTargetIndependentLIR)
-enum {
-#define DEF_LIR_DESC(OPCODE, ...) OPCODE,
-#include "greenland/target_lir.def"
-#include "greenland/clear_target_lir.def"
-
- kNumTargetIndependentLIR
-};
-
-//----------------------------------------------------------------------------
-// ARM
-//----------------------------------------------------------------------------
-static const LIRDesc ARMLIR[] = {
-#define DEF_LIR_DESC(OPCODE, KIND, FLAGS, NAME, FORMAT, OPS_INFO) \
- { #OPCODE, NAME, FORMAT, FLAGS, OpInfo ## OPS_INFO },
-#include "greenland/arm/arm_lir.def"
-};
-
-//----------------------------------------------------------------------------
-// Mips
-//----------------------------------------------------------------------------
-static const LIRDesc MipsLIR[] = {
-#define DEF_LIR_DESC(OPCODE, KIND, FLAGS, NAME, FORMAT, OPS_INFO) \
- { #OPCODE, NAME, FORMAT, FLAGS, OpInfo ## OPS_INFO },
-#include "greenland/mips/mips_lir.def"
-};
-
-//----------------------------------------------------------------------------
-// X86
-//----------------------------------------------------------------------------
-static const LIRDesc X86LIR[] = {
-#define DEF_LIR_DESC(OPCODE, KIND, FLAGS, NAME, FORMAT, OPS_INFO) \
- { #OPCODE, NAME, FORMAT, FLAGS, OpInfo ## OPS_INFO },
-#include "greenland/x86/x86_lir.def"
-};
-
-class Context {
- private:
- std::ostream& out_;
- unsigned indent_;
-
- public:
- Context(std::ostream& out) : out_(out), indent_(0) { }
-
- void IncIndent() {
- indent_ += 2;
- return;
- }
-
- void DecIndent() {
- indent_ -= 2;
- }
-
- std::ostream& Indent() {
- for (unsigned i = 0; i < indent_; i += 2) {
- out_.write(" ", 2);
- }
- return out_;
- }
-
- std::ostream& Newline() {
- return out_ << std::endl;
- }
-
- std::ostream& Out() {
- return out_;
- }
-
- const LIRDesc* target_lirs_;
- unsigned num_target_lirs_;
-
- std::string lowercase_target_string_;
- std::string uppercase_target_string_;
- std::string class_name_;
-};
-
-class GenPrototype {
- const LIROperandInfo& op_info_;
- const char* preface_;
- public:
- GenPrototype(const LIROperandInfo& op_info, const char* preface = NULL)
- : op_info_(op_info), preface_(preface) { }
-
- friend std::ostream& operator<<(std::ostream& out, const GenPrototype& obj);
-};
-
-std::ostream& operator<<(std::ostream& out, const GenPrototype& obj) {
- out << "(";
-
- unsigned num_ops = obj.op_info_.num_operands_;
- if (obj.preface_ != NULL) {
- out << obj.preface_;
- if (num_ops > 0) {
- out << ", ";
- }
- }
-
- for (unsigned i = 0; i < num_ops; i++) {
- const LIROperandInfo::TypeStrings& type_strings =
- obj.op_info_.GetOperandTypeStrings(i);
-
- out << type_strings.type_string_ << " " << type_strings.var_string_ << i;
-
- if (i != (num_ops - 1)) {
- // Append "," if not the last one
- out << ", ";
- }
- }
-
- out << ")";
- return out;
-}
-
-//----------------------------------------------------------------------------
-
-// Forward Declarations
-static void GenBeginNamespace(Context& C);
-static void GenCreateTargetLIR(Context& C, const LIRDesc& lir, bool proto_only);
-static void GenCallSetOperands(Context& C, const LIROperandInfo& operand_info);
-static void GenEndNamespace(Context& C);
-
-static void GenLicenseNote(Context& C) {
- C.Indent() << "/*" << std::endl;
- C.Indent() << " * Copyright (C) 2012 The Android Open Source Project" << std::endl;
- C.Indent() << " *" << std::endl;
- C.Indent() << " * Licensed under the Apache License, Version 2.0 (the \"License\"" << std::endl;
- C.Indent() << " * you may not use this file except in compliance with the License." << std::endl;
- C.Indent() << " * You may obtain a copy of the License at" << std::endl;
- C.Indent() << " *" << std::endl;
- C.Indent() << " * http://www.apache.org/licenses/LICENSE-2.0" << std::endl;
- C.Indent() << " *" << std::endl;
- C.Indent() << " * Unless required by applicable law or agreed to in writing, software" << std::endl;
- C.Indent() << " * distributed under the License is distributed on an \"AS IS\" BASIS," << std::endl;
- C.Indent() << " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied." << std::endl;
- C.Indent() << " * See the License for the specific language governing permissions and" << std::endl;
- C.Indent() << " * limitations under the License." << std::endl;
- C.Indent() << " */" << std::endl;
- C.Newline();
- return;
-}
-
-//----------------------------------------------------------------------------
-
-static void GenTargetLIRBuilderHeader(Context& C) {
- C.Indent() << "#ifdef GET_" << C.uppercase_target_string_ << "_LIR_BUILDER_HEADER";
- C.Newline();
-
- //----------------------------------------------------------------------------
- // Include Files
- //----------------------------------------------------------------------------
- C.Indent() << "#include \"greenland/target_lir_builder.h\"" << std::endl;;
- C.Indent() << "#include \"greenland/target_lir_info.h\"" << std::endl;
- C.Newline();
-
- GenBeginNamespace(C);
-
- //----------------------------------------------------------------------------
- // Forward Declarations
- //----------------------------------------------------------------------------
- C.Indent() << "class TargetLIRInfo;" << std::endl;
- C.Newline();
-
- C.Indent() << "class " << C.class_name_ << " : public TargetLIRBuilder {"
- << std::endl;
-
- //----------------------------------------------------------------------------
- // Members
- //----------------------------------------------------------------------------
- C.Indent() << " private:" << std::endl;
- C.IncIndent();
- C.Indent() << "const TargetLIRInfo& info_;" << std::endl;
- C.DecIndent();
- C.Newline();
-
- //----------------------------------------------------------------------------
- // APIs
- //----------------------------------------------------------------------------
- C.Indent() << " public:" << std::endl;
-
- C.IncIndent();
-
- //----------------------------------------------------------------------------
- // Constructor
- //----------------------------------------------------------------------------
- C.Indent() << C.class_name_ << "(const TargetLIRInfo& info) "
- ": TargetLIRBuilder(), info_(info) { }"
- << std::endl;
- C.Newline();
-
- //----------------------------------------------------------------------------
- // LIR* Create(unsigned opcode)
- //----------------------------------------------------------------------------
- C.Indent() << "LIR* Create(unsigned opcode) {" << std::endl;
- C.IncIndent();
-
- C.Indent() << "return bb_->GetParent().CreateLIR(*bb_, info_.GetLIRDesc(opcode));" << std::endl;
-
- C.DecIndent();
- C.Indent() << "}" << std::endl;
- C.Newline();
-
- //----------------------------------------------------------------------------
- // LIR* Create(LIRDesc& desc)
- //----------------------------------------------------------------------------
- C.Indent() << "LIR* Create(const LIRDesc& desc) {" << std::endl;
- C.IncIndent();
-
- C.Indent() << "return bb_->GetParent().CreateLIR(*bb_, desc);" << std::endl;
-
- C.DecIndent();
- C.Indent() << "}" << std::endl;
- C.Newline();
-
- //----------------------------------------------------------------------------
- // LIR* Create_*([operand...])
- //----------------------------------------------------------------------------
- for (unsigned i = 0; i < C.num_target_lirs_; i++) {
- const LIRDesc& lir = C.target_lirs_[i];
- if (!lir.IsPseudo() || (i > kNumTargetIndependentLIR)) {
- GenCreateTargetLIR(C, lir, /* proto_only */true);
- }
- }
-
- C.DecIndent();
-
- C.Indent() << "};" << std::endl;
- C.Newline();
-
- GenEndNamespace(C);
-
- C.Indent() << "#undef GET_" << C.uppercase_target_string_ << "_LIR_BUILDER_HEADER" << std::endl;
- C.Indent() << "#endif // GET_" << C.uppercase_target_string_ << "_LIR_BUILDER_HEADER" << std::endl;
- return;
-}
-
-static void GenTargetLIRBuilderImpl(Context& C) {
- C.Indent() << "#ifdef GET_" << C.uppercase_target_string_ << "_LIR_BUILDER_IMPL";
- C.Newline();
-
- //----------------------------------------------------------------------------
- // Include Files
- //----------------------------------------------------------------------------
- C.Indent() << "#include \"greenland/lir_desc.h\"" << std::endl;
- C.Indent() << "#include \"greenland/lir_function.h\"" << std::endl;
- C.Indent() << "#include \"greenland/" << C.lowercase_target_string_
- << "/" << C.lowercase_target_string_ << "_lir_opcodes.h\""
- << std::endl;
- C.Newline();
-
- GenBeginNamespace(C);
-
- for (unsigned i = 0; i < C.num_target_lirs_; i++) {
- const LIRDesc& lir = C.target_lirs_[i];
- if (!lir.IsPseudo() || (i > kNumTargetIndependentLIR)) {
- GenCreateTargetLIR(C, lir, /* proto_only */false);
- }
- }
-
- C.Newline();
-
- GenEndNamespace(C);
-
- C.Indent() << "#undef GET_" << C.uppercase_target_string_ << "_LIR_BUILDER_IMPL" << std::endl;
- C.Indent() << "#endif // GET_" << C.uppercase_target_string_ << "_LIR_BUILDER_IMPL" << std::endl;
- C.Newline();
- return;
-}
-
-//----------------------------------------------------------------------------
-
-static void GenBeginNamespace(Context& C) {
- C.Indent() << "namespace art {" << std::endl;
- C.Indent() << "namespace greenland {" << std::endl;
- C.Newline();
- return;
-}
-
-static void GenCreateTargetLIR(Context& C, const LIRDesc& lir, bool proto_only){
- C.Indent() << "// " << lir.name_ << " " << lir.format_ << std::endl;
-
- if (proto_only) {
- C.Indent() << "LIR* Create_" << &lir.opcode_name_[1] /* hack: skip 'k' */
- << GenPrototype(lir.operand_info_) << ";" << std::endl;
- return;
- } else {
- C.Indent() << "LIR* " << C.class_name_ << "::Create_"
- << &lir.opcode_name_[1] /* hack: skip 'k' */
- << GenPrototype(lir.operand_info_) << " {" << std::endl;
- }
-
- C.IncIndent();
- C.Indent() << "LIR* lir = Create("
- << C.lowercase_target_string_ << "::" << lir.opcode_name_<< ");"
- << std::endl;
- GenCallSetOperands(C, lir.operand_info_);
- C.Indent() << "return lir;" << std::endl;
- C.DecIndent();
-
- C.Indent() << "}" << std::endl;
- C.Newline();
- return;
-}
-
-static void
-GenCallSetOperands(Context& C, const LIROperandInfo& operand_info) {
- if (operand_info.num_operands_ > 0) {
- C.Indent() << "Set" << operand_info.name_ << "Operands(*lir, ";
-
- for (unsigned i = 0; i < operand_info.num_operands_; i++) {
- const LIROperandInfo::TypeStrings& type_strings =
- operand_info.GetOperandTypeStrings(i);
-
- C.Out() << type_strings.var_string_ << i;
-
- if (i != (operand_info.num_operands_ - 1)) {
- // Append "," if not the last one
- C.Out() << ", ";
- }
- }
-
- C.Out() << ");" << std::endl;
- }
- return;
-}
-
-static void GenEndNamespace(Context& C) {
- C.Newline();
- C.Indent() << "} // namespace greenland" << std::endl;
- C.Indent() << "} // namespace art" << std::endl;
- C.Newline();
- return;
-}
-
-//----------------------------------------------------------------------------
-// Special functionality to generate Set*Operands in TargetLIRBuilder
-//----------------------------------------------------------------------------
-static void GenSetOperandsImpl(Context& C, const LIROperandInfo& operand_info);
-
-static void GenSetOperands(Context& C) {
- for (unsigned i = 0; i < NumObInfos; i++) {
- const LIROperandInfo& op_info = *OpInfos[i];
- C.Indent() << "static inline void Set" << op_info.name_
- << "Operands" << GenPrototype(op_info, /* preface */"LIR& lir")
- << " {" << std::endl;
- C.IncIndent();
- GenSetOperandsImpl(C, op_info);
- C.DecIndent();
- C.Indent() << "}" << std::endl;
- C.Newline();
- }
-
- return;
-}
-
-static void GenSetOperandsImpl(Context& C, const LIROperandInfo& operand_info) {
- if (operand_info.num_operands_ <= 0) {
- return;
- }
-
- C.Indent() << "lir";
- for (unsigned i = 0; i < operand_info.num_operands_; i++) {
- const LIROperandInfo::TypeStrings& type_strings =
- operand_info.GetOperandTypeStrings(i);
-
- if (i != 0) {
- C.Indent() << " ";
- }
-
- C.Out() << "." << type_strings.set_method_ << "(" << i << ", "
- << type_strings.var_string_ << i
- << ")";
- if (i == (operand_info.num_operands_ - 1)) {
- // Append ";" if not the last one
- C.Out() << ";";
- }
- C.Out() << std::endl;
- }
-
- C.Indent() << "return;" << std::endl;
-
- return;
-}
-
-int main(int argc, char** argv) {
- if (argc < 2) {
- std::cerr << "usage: " << argv[0] << " [target]" << std::endl;
- return 1;
- }
-
- Context C(std::cout);
-
- C.lowercase_target_string_ = argv[1];
- for (size_t i = 0, e = C.lowercase_target_string_.length(); i != e; i++) {
- C.lowercase_target_string_[i] = ::tolower(C.lowercase_target_string_[i]);
- }
-
- // Special function to generate TargetLIRBuilder::Set*Operands(...).
- if (C.lowercase_target_string_ == "gen_set_operands") {
- GenSetOperands(C);
- return 0;
- }
-
- // Setup the context according to the target supplied
- if (C.lowercase_target_string_ == "arm") {
- C.target_lirs_ = ARMLIR;
- C.num_target_lirs_ = sizeof(ARMLIR) / sizeof(ARMLIR[0]);
- C.uppercase_target_string_ = "ARM";
- C.class_name_ = "ARMLIRBuilderBase";
- } else if (C.lowercase_target_string_ == "mips") {
- C.target_lirs_ = MipsLIR;
- C.num_target_lirs_ = sizeof(MipsLIR) / sizeof(MipsLIR[0]);
- C.uppercase_target_string_ = "MIPS";
- C.class_name_ = "MipsLIRBuilderBase";
- } else if (C.lowercase_target_string_ == "x86") {
- C.target_lirs_ = X86LIR;
- C.num_target_lirs_ = sizeof(X86LIR) / sizeof(X86LIR[0]);
- C.uppercase_target_string_ = "X86";
- C.class_name_ = "X86LIRBuilderBase";
- } else {
- std::cerr << "unknown target `" << argv[1] << "'!" << std::endl;
- return 1;
- }
-
- GenLicenseNote(C);
- GenTargetLIRBuilderHeader(C);
- GenTargetLIRBuilderImpl(C);
-
- return 0;
-}
diff --git a/src/greenland/x86/x86_codegen_machine.cc b/src/greenland/x86/x86_codegen_machine.cc
deleted file mode 100644
index fe4bd83..0000000
--- a/src/greenland/x86/x86_codegen_machine.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2012 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 "x86_codegen_machine.h"
-
-#include "x86_lir_emitter.h"
-
-#include "greenland/target_registry.h"
-
-namespace art {
-namespace greenland {
-
-void InitializeX86CodeGenMachine() {
- RegisterTargetCodeGenMachine<X86CodeGenMachine> X(kX86);
-}
-
-X86CodeGenMachine::X86CodeGenMachine() : lir_info_() {
-}
-
-X86CodeGenMachine::~X86CodeGenMachine() {
-}
-
-TargetLIREmitter*
-X86CodeGenMachine::CreateLIREmitter(const llvm::Function& func,
- const OatCompilationUnit& cunit,
- DexLang::Context& dex_lang_ctx) {
- return new X86LIREmitter(func, cunit, dex_lang_ctx, lir_info_);
-}
-
-} // namespace greenland
-} // namespace art
diff --git a/src/greenland/x86/x86_codegen_machine.h b/src/greenland/x86/x86_codegen_machine.h
deleted file mode 100644
index 1b9ac4d..0000000
--- a/src/greenland/x86/x86_codegen_machine.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#ifndef ART_SRC_GREENLAND_X86_CODEGEN_MACHINE_H_
-#define ART_SRC_GREENLAND_X86_CODEGEN_MACHINE_H_
-
-#include "greenland/target_codegen_machine.h"
-
-#include "x86_lir_info.h"
-
-namespace art {
-namespace greenland {
-
-class X86CodeGenMachine : public TargetCodeGenMachine {
- private:
- X86LIRInfo lir_info_;
-
- public:
- X86CodeGenMachine();
-
- virtual ~X86CodeGenMachine();
-
- virtual TargetLIREmitter* CreateLIREmitter(const llvm::Function& func,
- const OatCompilationUnit& cunit,
- DexLang::Context& dex_lang_ctx);
-
- virtual RegisterAllocator* GetRegisterAllocator() {
- return NULL;
- }
-
- virtual TargetAssembler* GetAssembler() {
- return NULL;
- }
-};
-
-} // namespace greenland
-} // namespace art
-
-#endif // ART_SRC_GREENLAND_X86_CODEGEN_MACHINE_H_
diff --git a/src/greenland/x86/x86_invoke_stub_compiler.cc b/src/greenland/x86/x86_invoke_stub_compiler.cc
deleted file mode 100644
index 872a9da..0000000
--- a/src/greenland/x86/x86_invoke_stub_compiler.cc
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (C) 2011 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 "compiled_method.h"
-#include "compiler.h"
-#include "greenland/target_registry.h"
-#include "oat/utils/assembler.h"
-#include "oat/utils/x86/assembler_x86.h"
-#include "object.h"
-
-using namespace art;
-using namespace art::x86;
-
-namespace {
-
-// Creates a function which invokes a managed method with an array of
-// arguments.
-//
-// Immediately after the call on X86, the environment looks like this:
-//
-// [SP+0 ] = Return address
-// [SP+4 ] = method pointer
-// [SP+8 ] = receiver pointer or NULL for static methods
-// [SP+12] = (managed) thread pointer
-// [SP+16] = argument array or NULL for no argument methods
-// [SP+20] = JValue* result or NULL for void returns
-//
-// As the JNI call has already transitioned the thread into the
-// "running" state the remaining responsibilities of this routine are
-// to save the native registers and set up the managed registers. On
-// return, the return value must be store into the result JValue.
-CompiledInvokeStub* CreateInvokeStub(bool is_static, const char* shorty, uint32_t shorty_len) {
- UniquePtr<X86Assembler> assembler(down_cast<X86Assembler*>(Assembler::Create(kX86)));
-#define __ assembler->
- size_t num_arg_array_bytes = NumArgArrayBytes(shorty, shorty_len);
- // Size of frame = return address + saved EBX + Method* + possible receiver + arg array size
- // Note, space is left in the frame to flush arguments in registers back to out locations.
- size_t frame_size = 3 * kPointerSize + (is_static ? 0 : kPointerSize) + num_arg_array_bytes;
- size_t pad_size = RoundUp(frame_size, kStackAlignment) - frame_size;
-
- Register rMethod = EAX;
- __ movl(rMethod, Address(ESP, 4)); // EAX = method
- Register rReceiver = ECX;
- if (!is_static) {
- __ movl(rReceiver, Address(ESP, 8)); // ECX = receiver
- }
- // Save EBX
- __ pushl(EBX);
- Register rArgArray = EBX;
- __ movl(rArgArray, Address(ESP, 20)); // EBX = arg array
-
- // TODO: optimize the frame set up to avoid excessive SP math
- // Push padding
- if (pad_size != 0) {
- __ subl(ESP, Immediate(pad_size));
- }
- // Push/copy arguments.
- size_t arg_count = (shorty_len - 1);
- size_t dst_offset = num_arg_array_bytes;
- size_t src_offset = arg_count * sizeof(JValue);
- for (size_t i = shorty_len - 1; i > 0; --i) {
- switch (shorty[i]) {
- case 'D':
- case 'J':
- // Move both pointers 64 bits.
- dst_offset -= kPointerSize;
- src_offset -= sizeof(JValue) / 2;
- __ pushl(Address(rArgArray, src_offset));
- dst_offset -= kPointerSize;
- src_offset -= sizeof(JValue) / 2;
- __ pushl(Address(rArgArray, src_offset));
- break;
- default:
- // Move the source pointer sizeof(JValue) and the destination pointer 32 bits.
- dst_offset -= kPointerSize;
- src_offset -= sizeof(JValue);
- __ pushl(Address(rArgArray, src_offset));
- break;
- }
- }
-
- // Backing space for receiver.
- if (!is_static) {
- __ pushl(Immediate(0));
- }
- // Push 0 as NULL Method* thereby terminating managed stack crawls.
- __ pushl(Immediate(0));
- if (!is_static) {
- if (shorty_len > 1) {
- // Receiver already in ECX, pass remaining 2 args in EDX and EBX.
- __ movl(EDX, Address(rArgArray, 0));
- if (shorty[1] == 'D' || shorty[1] == 'J') {
- __ movl(EBX, Address(rArgArray, sizeof(JValue) / 2));
- } else if (shorty_len > 2) {
- __ movl(EBX, Address(rArgArray, sizeof(JValue)));
- }
- }
- } else {
- if (shorty_len > 1) {
- // Pass remaining 3 args in ECX, EDX and EBX.
- __ movl(ECX, Address(rArgArray, 0));
- if (shorty[1] == 'D' || shorty[1] == 'J') {
- __ movl(EDX, Address(rArgArray, sizeof(JValue) / 2));
- if (shorty_len > 2) {
- __ movl(EBX, Address(rArgArray, sizeof(JValue)));
- }
- } else if (shorty_len > 2) {
- __ movl(EDX, Address(rArgArray, sizeof(JValue)));
- if (shorty[2] == 'D' || shorty[2] == 'J') {
- __ movl(EBX, Address(rArgArray, sizeof(JValue) + (sizeof(JValue) / 2)));
- } else {
- __ movl(EBX, Address(rArgArray, sizeof(JValue) + sizeof(JValue)));
- }
- }
- }
- }
-
- __ call(Address(EAX, AbstractMethod::GetCodeOffset())); // Call code off of method
-
- // Pop arguments up to EBX and the return address.
- __ addl(ESP, Immediate(frame_size + pad_size - (2 * kPointerSize)));
- // Restore EBX.
- __ popl(EBX);
- char ch = shorty[0];
- if (ch != 'V') {
- // Load the result JValue pointer.
- __ movl(ECX, Address(ESP, 20));
- switch (ch) {
- case 'D':
- __ movsd(Address(ECX, 0), XMM0);
- break;
- case 'F':
- __ movss(Address(ECX, 0), XMM0);
- break;
- case 'J':
- __ movl(Address(ECX, 0), EAX);
- __ movl(Address(ECX, 4), EDX);
- break;
- default:
- __ movl(Address(ECX, 0), EAX);
- break;
- }
- }
- __ ret();
- // TODO: store native_entry in the stub table
- std::vector<uint8_t> code(assembler->CodeSize());
- MemoryRegion region(&code[0], code.size());
- assembler->FinalizeInstructions(region);
- return new CompiledInvokeStub(code);
-#undef __
-}
-
-CompiledInvokeStub* X86InvokeStubCompiler(art::Compiler& /*compiler*/,
- bool is_static,
- const char* shorty,
- uint32_t shorty_len) {
- return CreateInvokeStub(is_static, shorty, shorty_len);
-}
-
-} // anonymous namespace
-
-namespace art {
-namespace greenland {
-
-void InitializeX86InvokeStubCompiler() {
- TargetRegistry::RegisterInvokeStubCompiler(kX86, X86InvokeStubCompiler);
-}
-
-} // namespace greenland
-} // namespace art
diff --git a/src/greenland/x86/x86_lir.def b/src/greenland/x86/x86_lir.def
deleted file mode 100644
index bf96b42..0000000
--- a/src/greenland/x86/x86_lir.def
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (C) 2012 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 "greenland/target_lir.def"
diff --git a/src/greenland/x86/x86_lir_emitter.cc b/src/greenland/x86/x86_lir_emitter.cc
deleted file mode 100644
index 7b56a9f..0000000
--- a/src/greenland/x86/x86_lir_emitter.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2012 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 "x86_lir_emitter.h"
-
-namespace art {
-namespace greenland {
-
-X86LIREmitter::X86LIREmitter(const llvm::Function& func,
- const OatCompilationUnit& cunit,
- DexLang::Context& dex_lang_ctx,
- TargetLIRInfo& target_lir_info)
- : TargetLIREmitter(func, cunit, dex_lang_ctx, target_lir_info) {
- return;
-}
-
-} // namespace greenland
-} // namespace art
diff --git a/src/greenland/x86/x86_lir_emitter.h b/src/greenland/x86/x86_lir_emitter.h
deleted file mode 100644
index ab2d7c7..0000000
--- a/src/greenland/x86/x86_lir_emitter.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#ifndef ART_SRC_GREENLAND_X86_LIR_EMITTER_H_
-#define ART_SRC_GREENLAND_X86_LIR_EMITTER_H_
-
-#include "greenland/target_lir_emitter.h"
-
-namespace art {
-namespace greenland {
-
-class TargetLIRInfo;
-
-class X86LIREmitter : public TargetLIREmitter {
- private:
-
-
- public:
- X86LIREmitter(const llvm::Function& func,
- const OatCompilationUnit& cunit,
- DexLang::Context& dex_lang_ctx,
- TargetLIRInfo& target_lir_info);
-};
-
-} // namespace greenland
-} // namespace art
-
-#endif // ART_SRC_GREENLAND_X86_LIR_EMITTER_H_
diff --git a/src/greenland/x86/x86_lir_info.cc b/src/greenland/x86/x86_lir_info.cc
deleted file mode 100644
index 2f29c97..0000000
--- a/src/greenland/x86/x86_lir_info.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2012 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 "x86_lir_info.h"
-#include "x86_lir_opcodes.h"
-
-namespace {
-
-const art::greenland::LIRDesc X86LIR[] = {
-#define DEF_LIR_DESC(OPCODE, NUM_OPS) { art::greenland::x86::OPCODE, NUM_OPS },
-#include "x86_lir.def"
-#undef DEF_LIR_DESC
-};
-
-} // anonymous namespace
-
-namespace art {
-namespace greenland {
-
-X86LIRInfo::X86LIRInfo()
- : TargetLIRInfo(X86LIR, sizeof(X86LIR) / sizeof(X86LIR[0])) {
-}
-
-} // namespace greenland
-} // namespace art
diff --git a/src/greenland/x86/x86_lir_info.h b/src/greenland/x86/x86_lir_info.h
deleted file mode 100644
index 92e4bae..0000000
--- a/src/greenland/x86/x86_lir_info.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#ifndef ART_SRC_GREENLAND_X86_LIR_INFO_H_
-#define ART_SRC_GREENLAND_X86_LIR_INFO_H_
-
-#include "greenland/target_lir_info.h"
-
-namespace art {
-namespace greenland {
-
-class X86LIRInfo : public TargetLIRInfo {
- private:
-
- public:
- X86LIRInfo();
-};
-
-} // namespace greenland
-} // namespace art
-
-#endif // ART_SRC_GREENLAND_X86_LIR_INFO_H_
diff --git a/src/greenland/x86/x86_lir_opcodes.h b/src/greenland/x86/x86_lir_opcodes.h
deleted file mode 100644
index 487b609..0000000
--- a/src/greenland/x86/x86_lir_opcodes.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#ifndef ART_SRC_GREENLAND_X86_LIR_OPCODES_H_
-#define ART_SRC_GREENLAND_X86_LIR_OPCODES_H_
-
-namespace art {
-namespace greenland {
-namespace x86 {
-
-enum {
-#define DEF_LIR_DESC(OPCODE, ...) OPCODE,
-#include "x86_lir.def"
-#undef DEF_LIR_DESC
-};
-
-} // namespace x86
-} // namespace greenland
-} // namespace art
-
-#endif // ART_SRC_GREENLAND_X86_LIR_OPCODES_H_