blob: e3f664b1ce75a32a97b9d4c67b1242f458f101ac [file] [log] [blame]
//===-- VMMethod.cpp - Compiler representation of a Java method -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the implementation of the Method class that represents a
// compile time representation of a Java class method (java.lang.Method).
//
//===----------------------------------------------------------------------===//
#include "VMMethod.h"
#include "Resolver.h"
#include "VMClass.h"
#include <llvm/Constants.h>
#include <llvm/DerivedTypes.h>
#include <llvm/Function.h>
#include <llvm/Instructions.h>
#include <llvm/ADT/STLExtras.h>
using namespace llvm;
using namespace llvm::Java;
void VMMethod::init()
{
const std::string& methodName = method_->getName()->str();
const std::string& methodDescriptor = method_->getDescriptor()->str();
const std::string& functionName =
parent_->getName() + '/' + methodName + methodDescriptor;
Resolver* resolver = parent_->getResolver();
// FIXME: This type should be taken from the owning class's constant
// pool (parsed only once per class). This means the
// Resolver::getType() should be moved in VMClass and its return
// value should be cached in the constant pool along with the
// others.
const FunctionType* functionType = cast<FunctionType>(
resolver->getType(methodDescriptor, !method_->isStatic()));
Module* module = resolver->getModule();
function_ = module->getOrInsertFunction(functionName, functionType);
std::vector<const Type*> argTypes;
argTypes.reserve(2);
argTypes.push_back(resolver->getObjectBaseType());
argTypes.push_back(PointerType::get(Type::SByteTy));
const FunctionType* bridgeFunctionType =
FunctionType::get(functionType->getReturnType(), argTypes, false);
bridgeFunction_ = module->getOrInsertFunction("bridge_to_" + functionName,
bridgeFunctionType);
BasicBlock* bb = new BasicBlock("entry", bridgeFunction_);
std::vector<Value*> params;
params.reserve(functionType->getNumParams());
Value* objectArg = bridgeFunction_->arg_begin();
Value* vaList = next(bridgeFunction_->arg_begin());
if (!method_->isStatic())
params.push_back(objectArg);
for (unsigned i = !method_->isStatic(), e = functionType->getNumParams();
i != e; ++i) {
const Type* paramType = functionType->getParamType(i);
const Type* argType = paramType->getVAArgsPromotedType();
Value* arg = new VAArgInst(vaList, argType, "tmp", bb);
vaList = new VANextInst(vaList, argType, "", bb);
if (paramType != argType)
arg = new CastInst(arg, paramType, "tmp", bb);
params.push_back(arg);
}
if (functionType->getReturnType() == Type::VoidTy) {
new CallInst(function_, params, "", bb);
new ReturnInst(bb);
}
else {
Value* result = new CallInst(function_, params, "result", bb);
new ReturnInst(result, bb);
}
}
VMMethod::VMMethod(const VMClass* parent, const Method* method)
: parent_(parent),
method_(method),
index_(-1)
{
assert(isStaticallyBound() && "This should be a statically bound method!");
init();
}
VMMethod::VMMethod(const VMClass* parent, const Method* method, int index)
: parent_(parent),
method_(method),
index_(index)
{
assert(isDynamicallyBound() && "This should be a dynamically bound method!");
init();
}
llvm::Constant* VMMethod::buildMethodDescriptor() const
{
llvm::Constant* fd = ConstantArray::get(getName() + getDescriptor());
return ConstantExpr::getPtrPtrFromArrayPtr(
new GlobalVariable(
fd->getType(),
true,
GlobalVariable::ExternalLinkage,
fd,
getName() + getDescriptor(),
parent_->getResolver()->getModule()));
}
llvm::Constant* VMMethod::getBridgeFunction() const
{
return bridgeFunction_;
}