[llvm-commits] CVS: llvm-java/lib/Compiler/Compiler.cpp
Alkis Evlogimenos
alkis at cs.uiuc.edu
Wed Nov 17 02:32:51 PST 2004
Changes in directory llvm-java/lib/Compiler:
Compiler.cpp updated: 1.144 -> 1.145
---
Log message:
Add stubs to JNI calls when codegening a natively implemented java
method.
---
Diffs of the changes: (+106 -2)
Index: llvm-java/lib/Compiler/Compiler.cpp
diff -u llvm-java/lib/Compiler/Compiler.cpp:1.144 llvm-java/lib/Compiler/Compiler.cpp:1.145
--- llvm-java/lib/Compiler/Compiler.cpp:1.144 Mon Nov 15 14:24:03 2004
+++ llvm-java/lib/Compiler/Compiler.cpp Wed Nov 17 04:32:39 2004
@@ -70,6 +70,7 @@
class Compiler : public BytecodeParser<Compiler> {
Module& module_;
+ GlobalVariable* JNIEnvPtr_;
ClassFile* cf_;
std::auto_ptr<BasicBlockBuilder> bbBuilder_;
std::list<BasicBlock*> bbWorkList_;
@@ -123,6 +124,14 @@
public:
Compiler(Module& m)
: module_(m) {
+ Type* JNIEnvTy = OpaqueType::get();
+ module_.addTypeName("JNIEnv", JNIEnvTy);
+ JNIEnvPtr_ = new GlobalVariable(JNIEnvTy,
+ true,
+ GlobalVariable::ExternalLinkage,
+ NULL,
+ "llvm_java_JNIEnv",
+ &module_);
}
private:
@@ -216,6 +225,64 @@
}
}
+ /// Returns the type of the Java string descriptor for JNI. If the
+ /// Type* self is not NULL then that type is used as the first
+ /// type in function types
+ Type* getJNIType(ConstantUtf8* descr, Type* self = NULL) {
+ unsigned i = 0;
+ return getJNITypeHelper(descr->str(), i, self);
+ }
+
+ Type* getJNITypeHelper(const std::string& descr, unsigned& i, Type* self) {
+ assert(i < descr.size());
+ switch (descr[i++]) {
+ case 'B': return Type::SByteTy;
+ case 'C': return Type::UShortTy;
+ case 'D': return Type::DoubleTy;
+ case 'F': return Type::FloatTy;
+ case 'I': return Type::IntTy;
+ case 'J': return Type::LongTy;
+ case 'S': return Type::ShortTy;
+ case 'Z': return Type::BoolTy;
+ case 'V': return Type::VoidTy;
+ case 'L': {
+ unsigned e = descr.find(';', i);
+ std::string className = descr.substr(i, e - i);
+ i = e + 1;
+ return PointerType::get(Type::VoidTy);
+ }
+ case '[':
+ if (descr[i] == '[') {
+ do { ++i; } while (descr[i] == '[');
+ getTypeHelper(descr, i, NULL);
+ return PointerType::get(Type::VoidTy);
+ }
+ else if (descr[i] == 'L') {
+ getTypeHelper(descr, i, NULL);
+ return PointerType::get(Type::VoidTy);
+ }
+ else {
+ return PointerType::get(
+ getPrimitiveArrayInfo(getTypeHelper(descr, i, NULL)).type);
+ }
+ break;
+ case '(': {
+ std::vector<const Type*> params;
+ // JNIEnv*
+ params.push_back(JNIEnvPtr_->getType());
+
+ assert(self && "first argument after JNIEnv* must be that of a "
+ "class or an object pointer");
+ params.push_back(PointerType::get(self));
+ while (descr[i] != ')')
+ params.push_back(getTypeHelper(descr, i, NULL));
+ return FunctionType::get(getTypeHelper(descr, ++i, NULL),params, false);
+ }
+ // FIXME: Throw something
+ default: return NULL;
+ }
+ }
+
/// Initializes the class info map; in other words it adds the
/// class info of java.lang.Object.
bool initializeClassInfoMap() {
@@ -1100,8 +1167,45 @@
assert(function->empty() && "Compiling an already compiled method!");
if (method->isNative()) {
- DEBUG(std::cerr << "Ignoring native method: ";
- std::cerr << classMethodDesc << '\n');
+ DEBUG(std::cerr << "Adding stub for natively implemented method: "
+ << classMethodDesc << '\n');
+ FunctionType* funcTy = cast<FunctionType>(
+ getJNIType(method->getDescriptor(), Type::VoidTy));
+
+ std::string funcName = "Java_";
+ const std::string& className = cf_->getThisClass()->getName()->str();
+ for (unsigned i = 0, e = className.size(); i != e; ++i) {
+ if (className[i] == '/')
+ funcName += '_';
+ else
+ funcName += className[i];
+ }
+ funcName += '_';
+
+ const std::string& methodName = method->getName()->str();
+ funcName += methodName;
+
+ Function* jniFunction = module_.getOrInsertFunction(funcName, funcTy);
+ jniFunction->setLinkage(method->isPrivate() ?
+ Function::InternalLinkage :
+ Function::ExternalLinkage);
+
+ BasicBlock* bb = new BasicBlock("entry", function);
+ std::vector<Value*> params;
+ params.push_back(JNIEnvPtr_);
+ if (method->isStatic())
+ params.push_back(llvm::Constant::getNullValue(
+ PointerType::get(Type::VoidTy)));
+ for (Function::aiterator A = function->abegin(), E = function->aend();
+ A != E; ++A) {
+ params.push_back(&*A);
+ }
+ Value* r = new CallInst(jniFunction, params, "", bb);
+ if (r->getType() == Type::VoidTy)
+ new ReturnInst(NULL, bb);
+ else
+ new ReturnInst(r, bb);
+
return function;
}
else if (method->isAbstract()) {
More information about the llvm-commits
mailing list