Implement sget* instructions.
Change-Id: I53f655c23bf78c05d214d721496380474ea3e238
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index 4c03813..c45aa22 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -2295,10 +2295,182 @@
}
+Field* MethodCompiler::ResolveField(uint32_t field_idx) {
+ Thread* thread = Thread::Current();
+
+ // Save the exception state
+ Throwable* old_exception = NULL;
+ if (thread->IsExceptionPending()) {
+ old_exception = thread->GetException();
+ thread->ClearException();
+ }
+
+ // Resolve the fields through the class linker
+ Field* field = class_linker_->ResolveField(*dex_file_, field_idx,
+ dex_cache_, class_loader_,
+ /* is_static= */ true);
+
+ if (field == NULL) {
+ // Ignore the exception raised during the field resolution
+ thread->ClearException();
+ }
+
+ // Restore the exception state
+ if (old_exception != NULL) {
+ thread->SetException(old_exception);
+ }
+
+ return field;
+}
+
+
+Field* MethodCompiler::
+FindFieldAndDeclaringTypeIdx(uint32_t field_idx,
+ uint32_t &resolved_type_idx) {
+
+ // Resolve the field through the class linker
+ Field* field = ResolveField(field_idx);
+ if (field == NULL) {
+ return NULL;
+ }
+
+ DexFile::FieldId const& field_id = dex_file_->GetFieldId(field_idx);
+
+ // Search for the type_idx of the declaring class
+ uint16_t type_idx = field_id.class_idx_;
+ Class* klass = dex_cache_->GetResolvedTypes()->Get(type_idx);
+
+ // Test: Is referring_class equal to declaring_class?
+
+ // If true, then return the type_idx; otherwise, this field must be declared
+ // in super class or interfaces, we have to search for declaring class.
+
+ if (field->GetDeclaringClass() == klass) {
+ resolved_type_idx = type_idx;
+ return field;
+ }
+
+ // Search for the type_idx of the super class or interfaces
+ std::string desc(FieldHelper(field).GetDeclaringClassDescriptor());
+
+ DexFile::StringId const* string_id = dex_file_->FindStringId(desc);
+
+ if (string_id == NULL) {
+ return NULL;
+ }
+
+ DexFile::TypeId const* type_id =
+ dex_file_->FindTypeId(dex_file_->GetIndexForStringId(*string_id));
+
+ if (type_id == NULL) {
+ return NULL;
+ }
+
+ resolved_type_idx = dex_file_->GetIndexForTypeId(*type_id);
+ return field;
+}
+
+
+llvm::Value* MethodCompiler::EmitLoadStaticStorage(uint32_t dex_pc,
+ uint32_t type_idx) {
+ llvm::BasicBlock* block_load_static =
+ CreateBasicBlockWithDexPC(dex_pc, "load_static");
+
+ llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
+
+ // Load static storage from dex cache
+ llvm::Value* storage_field_addr =
+ EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
+
+ llvm::Value* storage_object_addr = irb_.CreateLoad(storage_field_addr);
+
+ 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::Function* runtime_func =
+ irb_.GetRuntime(InitializeStaticStorage);
+
+ llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
+
+ llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+ llvm::Value* loaded_storage_object_addr =
+ irb_.CreateCall2(runtime_func, type_idx_value, method_object_addr);
+
+ EmitGuard_ExceptionLandingPad(dex_pc);
+
+ 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;
+}
+
+
void MethodCompiler::EmitInsn_SGet(uint32_t dex_pc,
Instruction const* insn,
JType field_jty) {
- // UNIMPLEMENTED(WARNING);
+
+ Instruction::DecodedInstruction dec_insn(insn);
+
+ uint32_t declaring_type_idx = DexFile::kDexNoIndex;
+
+ Field* field = FindFieldAndDeclaringTypeIdx(dec_insn.vB_, declaring_type_idx);
+
+ llvm::Value* static_field_value;
+
+ if (field == NULL) {
+ llvm::Function* runtime_func;
+
+ if (field_jty == kObject) {
+ runtime_func = irb_.GetRuntime(GetObjectStatic);
+ } else if (field_jty == kLong || field_jty == kDouble) {
+ runtime_func = irb_.GetRuntime(Get64Static);
+ } else {
+ runtime_func = irb_.GetRuntime(Get32Static);
+ }
+
+ llvm::Constant* field_idx_value = irb_.getInt32(dec_insn.vB_);
+
+ llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+ static_field_value =
+ irb_.CreateCall2(runtime_func, field_idx_value, method_object_addr);
+
+ EmitGuard_ExceptionLandingPad(dex_pc);
+
+ } else {
+ llvm::Value* static_storage_addr =
+ EmitLoadStaticStorage(dex_pc, declaring_type_idx);
+
+ llvm::Value* static_field_offset_value =
+ irb_.getPtrEquivInt(field->GetOffset().Int32Value());
+
+ llvm::Value* static_field_addr =
+ irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
+ irb_.getJType(field_jty, kField)->getPointerTo());
+
+ static_field_value = irb_.CreateLoad(static_field_addr);
+ }
+
+ EmitStoreDalvikReg(dec_insn.vA_, field_jty, kField, static_field_value);
+
irb_.CreateBr(GetNextBasicBlock(dex_pc));
}
diff --git a/src/compiler_llvm/method_compiler.h b/src/compiler_llvm/method_compiler.h
index df381ee..36f90e5 100644
--- a/src/compiler_llvm/method_compiler.h
+++ b/src/compiler_llvm/method_compiler.h
@@ -37,6 +37,7 @@
class CompiledMethod;
class Compiler;
class DexCache;
+ class Field;
}
@@ -322,6 +323,8 @@
llvm::Value* EmitLoadConstantClass(uint32_t dex_pc, uint32_t type_idx);
+ llvm::Value* EmitLoadStaticStorage(uint32_t dex_pc, uint32_t type_idx);
+
void EmitGuard_DivZeroException(uint32_t dex_pc,
llvm::Value* denominator,
JType op_jty);
@@ -339,6 +342,11 @@
RegCategory GetInferredRegCategory(uint32_t dex_pc, uint16_t reg);
+ Field* ResolveField(uint32_t field_idx);
+
+ Field* FindFieldAndDeclaringTypeIdx(uint32_t field_idx,
+ uint32_t &resolved_type_idx);
+
// Diagnostics helper function
void PrintUnresolvedFieldWarning(int32_t field_idx);