Ejemplo n.º 1
0
void GCOVProfiler::insertIndirectCounterIncrement() {
  Function *Fn =
    cast<Function>(GCOVProfiler::getIncrementIndirectCounterFunc());
  Fn->setUnnamedAddr(true);
  Fn->setLinkage(GlobalValue::InternalLinkage);
  Fn->addFnAttr(Attributes::NoInline);
  if (NoRedZone)
    Fn->addFnAttr(Attributes::NoRedZone);

  Type *Int32Ty = Type::getInt32Ty(*Ctx);
  Type *Int64Ty = Type::getInt64Ty(*Ctx);
  Constant *NegOne = ConstantInt::get(Int32Ty, 0xffffffff);

  // Create basic blocks for function.
  BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", Fn);
  IRBuilder<> Builder(BB);

  BasicBlock *PredNotNegOne = BasicBlock::Create(*Ctx, "", Fn);
  BasicBlock *CounterEnd = BasicBlock::Create(*Ctx, "", Fn);
  BasicBlock *Exit = BasicBlock::Create(*Ctx, "exit", Fn);

  // uint32_t pred = *predecessor;
  // if (pred == 0xffffffff) return;
  Argument *Arg = Fn->arg_begin();
  Arg->setName("predecessor");
  Value *Pred = Builder.CreateLoad(Arg, "pred");
  Value *Cond = Builder.CreateICmpEQ(Pred, NegOne);
  BranchInst::Create(Exit, PredNotNegOne, Cond, BB);

  Builder.SetInsertPoint(PredNotNegOne);

  // uint64_t *counter = counters[pred];
  // if (!counter) return;
  Value *ZExtPred = Builder.CreateZExt(Pred, Int64Ty);
  Arg = llvm::next(Fn->arg_begin());
  Arg->setName("counters");
  Value *GEP = Builder.CreateGEP(Arg, ZExtPred);
  Value *Counter = Builder.CreateLoad(GEP, "counter");
  Cond = Builder.CreateICmpEQ(Counter,
                              Constant::getNullValue(Int64Ty->getPointerTo()));
  Builder.CreateCondBr(Cond, Exit, CounterEnd);

  // ++*counter;
  Builder.SetInsertPoint(CounterEnd);
  Value *Add = Builder.CreateAdd(Builder.CreateLoad(Counter),
                                 ConstantInt::get(Int64Ty, 1));
  Builder.CreateStore(Add, Counter);
  Builder.CreateBr(Exit);

  // Fill in the exit block.
  Builder.SetInsertPoint(Exit);
  Builder.CreateRetVoid();
}
Ejemplo n.º 2
0
static Function* createAdd1(Module *M) {
  // Create the add1 function entry and insert this entry into module M.  The
  // function will have a return type of "int" and take an argument of "int".
  // The '0' terminates the list of argument types.
  Function *Add1F =
    cast<Function>(M->getOrInsertFunction("add1", Type::Int32Ty, Type::Int32Ty,
                                          (Type *)0));

  // Add a basic block to the function. As before, it automatically inserts
  // because of the last argument.
  BasicBlock *BB = BasicBlock::Create("EntryBlock", Add1F);

  // Get pointers to the constant `1'.
  Value *One = ConstantInt::get(Type::Int32Ty, 1);

  // Get pointers to the integer argument of the add1 function...
  assert(Add1F->arg_begin() != Add1F->arg_end()); // Make sure there's an arg
  Argument *ArgX = Add1F->arg_begin();  // Get the arg
  ArgX->setName("AnArg");            // Give it a nice symbolic name for fun.

  // Create the add instruction, inserting it into the end of BB.
  Instruction *Add = BinaryOperator::CreateAdd(One, ArgX, "addresult", BB);

  // Create the return instruction and add it to the basic block
  ReturnInst::Create(Add, BB);

  // Now, function add1 is ready.
  return Add1F;
}
Ejemplo n.º 3
0
        virtual void visit(Function *type)
        {
            Function *funTy = control()->newFunction(0, 0);
            funTy->copy(type);
            funTy->setConst(type->isConst());
            funTy->setVolatile(type->isVolatile());

            funTy->setName(rewrite->rewriteName(type->name()));

            funTy->setReturnType(rewrite->rewriteType(type->returnType()));

            for (unsigned i = 0, argc = type->argumentCount(); i < argc; ++i) {
                Symbol *arg = type->argumentAt(i);

                Argument *newArg = control()->newArgument(0, 0);
                newArg->copy(arg);
                newArg->setName(rewrite->rewriteName(arg->name()));
                newArg->setType(rewrite->rewriteType(arg->type()));

                // the copy() call above set the scope to 'type'
                // reset it to 0 before adding addMember to avoid assert
                newArg->resetEnclosingScope();
                funTy->addMember(newArg);
            }

            temps.append(funTy);
        }
Ejemplo n.º 4
0
Argument *Engine::newArgument(Function *function, const QString &name, const Type *type)
{
    Argument *a = new Argument(function);
    a->setName(name);
    a->setType(type);
    _symbols.append(a);
    return a;
}
Ejemplo n.º 5
0
static Function *CreateFibFunction(Module *M, LLVMContext &Context) {
  // Create the fib function and insert it into module M.  This function is said
  // to return an int and take an int parameter.
  Function *FibF =
    cast<Function>(M->getOrInsertFunction("fib", Type::getInt32Ty(Context), 
                                          Type::getInt32Ty(Context),
                                          (Type *)0));

  // Add a basic block to the function.
  BasicBlock *BB = BasicBlock::Create(Context, "EntryBlock", FibF);

  // Get pointers to the constants.
  Value *One = ConstantInt::get(Type::getInt32Ty(Context), 1);
  Value *Two = ConstantInt::get(Type::getInt32Ty(Context), 2);

  // Get pointer to the integer argument of the add1 function...
  Argument *ArgX = FibF->arg_begin();   // Get the arg.
  ArgX->setName("AnArg");            // Give it a nice symbolic name for fun.

  // Create the true_block.
  BasicBlock *RetBB = BasicBlock::Create(Context, "return", FibF);
  // Create an exit block.
  BasicBlock* RecurseBB = BasicBlock::Create(Context, "recurse", FibF);

  // Create the "if (arg <= 2) goto exitbb"
  Value *CondInst = new ICmpInst(*BB, ICmpInst::ICMP_SLE, ArgX, Two, "cond");
  BranchInst::Create(RetBB, RecurseBB, CondInst, BB);

  // Create: ret int 1
  ReturnInst::Create(Context, One, RetBB);

  // create fib(x-1)
  Value *Sub = BinaryOperator::CreateSub(ArgX, One, "arg", RecurseBB);
  CallInst *CallFibX1 = CallInst::Create(FibF, Sub, "fibx1", RecurseBB);
  CallFibX1->setTailCall();

  // create fib(x-2)
  Sub = BinaryOperator::CreateSub(ArgX, Two, "arg", RecurseBB);
  CallInst *CallFibX2 = CallInst::Create(FibF, Sub, "fibx2", RecurseBB);
  CallFibX2->setTailCall();


  // fib(x-1)+fib(x-2)
  Value *Sum = BinaryOperator::CreateAdd(CallFibX1, CallFibX2,
                                         "addresult", RecurseBB);

  // Create the return instruction and add it to the basic block
  ReturnInst::Create(Context, Sum, RecurseBB);

  return FibF;
}
void ActionRequest::initArgumentList() {
  Node *actNode = getActionNode();
  if (actNode == NULL)
    return;
  int nArgNodes = actNode->getNNodes();
  argumentList.clear();
  for (int n = 0; n < nArgNodes; n++) {
    Argument *arg = new Argument();
    Node *argNode = actNode->getNode(n);
    arg->setName(argNode->getName());
    arg->setValue(argNode->getValue());
    argumentList.add(arg);
  }
}
Ejemplo n.º 7
0
int main() {
  
  InitializeNativeTarget();

  LLVMContext Context;
  
  // Create some module to put our function into it.
  Module *M = new Module("test", Context);

  // Create the add1 function entry and insert this entry into module M.  The
  // function will have a return type of "int" and take an argument of "int".
  // The '0' terminates the list of argument types.
  Function *Add1F =
    cast<Function>(M->getOrInsertFunction("add1", Type::getInt32Ty(Context),
                                          Type::getInt32Ty(Context),
                                          (Type *)0));

  // Add a basic block to the function. As before, it automatically inserts
  // because of the last argument.
  BasicBlock *BB = BasicBlock::Create(Context, "EntryBlock", Add1F);

  // Create a basic block builder with default parameters.  The builder will
  // automatically append instructions to the basic block `BB'.
  IRBuilder<> builder(BB);

  // Get pointers to the constant `1'.
  Value *One = builder.getInt32(1);

  // Get pointers to the integer argument of the add1 function...
  assert(Add1F->arg_begin() != Add1F->arg_end()); // Make sure there's an arg
  Argument *ArgX = Add1F->arg_begin();  // Get the arg
  ArgX->setName("AnArg");            // Give it a nice symbolic name for fun.

  // Create the add instruction, inserting it into the end of BB.
  Value *Add = builder.CreateAdd(One, ArgX);

  // Create the return instruction and add it to the basic block
  builder.CreateRet(Add);

  // Now, function add1 is ready.


  // Now we're going to create function `foo', which returns an int and takes no
  // arguments.
  Function *FooF =
    cast<Function>(M->getOrInsertFunction("foo", Type::getInt32Ty(Context),
                                          (Type *)0));

  // Add a basic block to the FooF function.
  BB = BasicBlock::Create(Context, "EntryBlock", FooF);

  // Tell the basic block builder to attach itself to the new basic block
  builder.SetInsertPoint(BB);

  // Get pointer to the constant `10'.
  Value *Ten = builder.getInt32(10);

  // Pass Ten to the call to Add1F
  CallInst *Add1CallRes = builder.CreateCall(Add1F, Ten);
  Add1CallRes->setTailCall(true);

  // Create the return instruction and add it to the basic block.
  builder.CreateRet(Add1CallRes);

  // Now we create the JIT.
  ExecutionEngine* EE = EngineBuilder(M).create();

  outs() << "We just constructed this LLVM module:\n\n" << *M;
  outs() << "\n\nRunning foo: ";
  outs().flush();

  // Call the `foo' function with no arguments:
  std::vector<GenericValue> noargs;
  GenericValue gv = EE->runFunction(FooF, noargs);

  // Import result of execution:
  outs() << "Result: " << gv.IntVal << "\n";
  EE->freeMachineCodeForFunction(FooF);
  delete EE;
  llvm_shutdown();
  return 0;
}
Ejemplo n.º 8
0
int main() {
  // Create some module to put our function into it.
  Module *M = new Module("test");

  // Create the add1 function entry and insert this entry into module M.  The
  // function will have a return type of "int" and take an argument of "int".
  // The '0' terminates the list of argument types.
  Function *Add1F =
    cast<Function>(M->getOrInsertFunction("add1", Type::Int32Ty, Type::Int32Ty,
                                          (Type *)0));

  // Add a basic block to the function. As before, it automatically inserts
  // because of the last argument.
  BasicBlock *BB = BasicBlock::Create("EntryBlock", Add1F);

  // Get pointers to the constant `1'.
  Value *One = ConstantInt::get(Type::Int32Ty, 1);

  // Get pointers to the integer argument of the add1 function...
  assert(Add1F->arg_begin() != Add1F->arg_end()); // Make sure there's an arg
  Argument *ArgX = Add1F->arg_begin();  // Get the arg
  ArgX->setName("AnArg");            // Give it a nice symbolic name for fun.

  // Create the add instruction, inserting it into the end of BB.
  Instruction *Add = BinaryOperator::CreateAdd(One, ArgX, "addresult", BB);

  // Create the return instruction and add it to the basic block
  ReturnInst::Create(Add, BB);

  // Now, function add1 is ready.


  // Now we going to create function `foo', which returns an int and takes no
  // arguments.
  Function *FooF =
    cast<Function>(M->getOrInsertFunction("foo", Type::Int32Ty, (Type *)0));

  // Add a basic block to the FooF function.
  BB = BasicBlock::Create("EntryBlock", FooF);

  // Get pointers to the constant `10'.
  Value *Ten = ConstantInt::get(Type::Int32Ty, 10);

  // Pass Ten to the call call:
  CallInst *Add1CallRes = CallInst::Create(Add1F, Ten, "add1", BB);
  Add1CallRes->setTailCall(true);

  // Create the return instruction and add it to the basic block.
  ReturnInst::Create(Add1CallRes, BB);

  // Now we create the JIT.
  ExistingModuleProvider* MP = new ExistingModuleProvider(M);
  ExecutionEngine* EE = ExecutionEngine::create(MP, false);

  outs() << "We just constructed this LLVM module:\n\n" << *M;
  outs() << "\n\nRunning foo: ";
  outs().flush();

  // Call the `foo' function with no arguments:
  std::vector<GenericValue> noargs;
  GenericValue gv = EE->runFunction(FooF, noargs);

  // Import result of execution:
  outs() << "Result: " << gv.IntVal << "\n";
  return 0;
}
Ejemplo n.º 9
0
void SharkFunction::initialize(const char *name) {
  // Create the function
  _function = Function::Create(
    entry_point_type(),
    GlobalVariable::InternalLinkage,
    name);

  // Get our arguments
  Function::arg_iterator ai = function()->arg_begin();
  Argument *method = ai++;
  method->setName("method");
  Argument *osr_buf = NULL;
  if (is_osr()) {
    osr_buf = ai++;
    osr_buf->setName("osr_buf");
  }
  Argument *base_pc = ai++;
  base_pc->setName("base_pc");
  code_buffer()->set_base_pc(base_pc);
  Argument *thread = ai++;
  thread->setName("thread");
  set_thread(thread);

  // Create the list of blocks
  set_block_insertion_point(NULL);
  _blocks = NEW_RESOURCE_ARRAY(SharkTopLevelBlock*, block_count());
  for (int i = 0; i < block_count(); i++) {
    ciTypeFlow::Block *b = flow()->pre_order_at(i);

    // Work around a bug in pre_order_at() that does not return
    // the correct pre-ordering.  If pre_order_at() were correct
    // this line could simply be:
    // _blocks[i] = new SharkTopLevelBlock(this, b);
    _blocks[b->pre_order()] = new SharkTopLevelBlock(this, b);
  }

  // Walk the tree from the start block to determine which
  // blocks are entered and which blocks require phis
  SharkTopLevelBlock *start_block = block(flow()->start_block_num());
  assert(start_block->start() == flow()->start_bci(), "blocks out of order");
  start_block->enter();

  // Initialize all entered blocks
  for (int i = 0; i < block_count(); i++) {
    if (block(i)->entered())
      block(i)->initialize();
  }

  // Create and push our stack frame
  set_block_insertion_point(&function()->front());
  builder()->SetInsertPoint(CreateBlock());
  _stack = SharkStack::CreateBuildAndPushFrame(this, method);

  // Create the entry state
  SharkState *entry_state;
  if (is_osr()) {
    entry_state = new SharkOSREntryState(start_block, method, osr_buf);

    // Free the OSR buffer
    builder()->CreateCall(builder()->osr_migration_end(), osr_buf);
  }
  else {
    entry_state = new SharkNormalEntryState(start_block, method);

    // Lock if necessary
    if (is_synchronized()) {
      SharkTopLevelBlock *locker =
        new SharkTopLevelBlock(this, start_block->ciblock());
      locker->add_incoming(entry_state);

      set_block_insertion_point(start_block->entry_block());
      locker->acquire_method_lock();

      entry_state = locker->current_state();
    }
  }

  // Transition into the method proper
  start_block->add_incoming(entry_state);
  builder()->CreateBr(start_block->entry_block());

  // Parse the blocks
  for (int i = 0; i < block_count(); i++) {
    if (!block(i)->entered())
      continue;

    if (i + 1 < block_count())
      set_block_insertion_point(block(i + 1)->entry_block());
    else
      set_block_insertion_point(NULL);

    block(i)->emit_IR();
  }
  do_deferred_zero_checks();
}
Ejemplo n.º 10
0
void SharkNativeWrapper::initialize(const char *name) {
  // Create the function
  _function = Function::Create(
    SharkType::entry_point_type(),
    GlobalVariable::InternalLinkage,
    name);

  // Get our arguments
  Function::arg_iterator ai = function()->arg_begin();
  Argument *method = ai++;
  method->setName("method");
  Argument *base_pc = ai++;
  base_pc->setName("base_pc");
  code_buffer()->set_base_pc(base_pc);
  Argument *thread = ai++;
  thread->setName("thread");
  set_thread(thread);

  // Create and push our stack frame
  builder()->SetInsertPoint(CreateBlock());
  _stack = SharkStack::CreateBuildAndPushFrame(this, method);
  NOT_PRODUCT(method = NULL);

  // Create the oopmap.  We use the one oopmap for every call site in
  // the wrapper, which results in the odd mild inefficiency but is a
  // damn sight easier to code.
  OopMap *oopmap = new OopMap(
    SharkStack::oopmap_slot_munge(stack()->oopmap_frame_size()),
    SharkStack::oopmap_slot_munge(arg_size()));
  oopmap->set_oop(SharkStack::slot2reg(stack()->method_slot_offset()));

  // Set up the oop_tmp slot if required:
  //  - For static methods we use it to handlize the class argument
  //    for the call, and to protect the same during slow path locks
  //    (if synchronized).
  //  - For methods returning oops, we use it to protect the return
  //    value across safepoints or slow path unlocking.
  if (is_static() || is_returning_oop()) {
    _oop_tmp_slot = stack()->slot_addr(
      stack()->oop_tmp_slot_offset(),
      SharkType::oop_type(),
      "oop_tmp_slot");

    oopmap->set_oop(SharkStack::slot2reg(stack()->oop_tmp_slot_offset()));
  }

  // Set up the monitor slot, for synchronized methods
  if (is_synchronized()) {
    Unimplemented();
    _lock_slot_offset = 23;
  }

  // Start building the argument list
  std::vector<const Type*> param_types;
  std::vector<Value*> param_values;
  const PointerType *box_type = PointerType::getUnqual(SharkType::oop_type());

  // First argument is the JNIEnv
  param_types.push_back(SharkType::jniEnv_type());
  param_values.push_back(
    builder()->CreateAddressOfStructEntry(
      thread,
      JavaThread::jni_environment_offset(),
      SharkType::jniEnv_type(),
      "jni_environment"));

  // For static methods, the second argument is the class
  if (is_static()) {
    builder()->CreateStore(
      builder()->CreateInlineOop(
        JNIHandles::make_local(
          target()->method_holder()->klass_part()->java_mirror())),
      oop_tmp_slot());

    param_types.push_back(box_type);
    param_values.push_back(oop_tmp_slot());

    _receiver_slot_offset = stack()->oop_tmp_slot_offset();
  }
  else if (is_returning_oop()) {
    // The oop_tmp slot is registered in the oopmap,
    // so we need to clear it.  This is one of the
    // mild inefficiencies I mentioned earlier.
    builder()->CreateStore(LLVMValue::null(), oop_tmp_slot());
  }

  // Parse the arguments
  for (int i = 0; i < arg_size(); i++) {
    int slot_offset = stack()->locals_slots_offset() + arg_size() - 1 - i;
    int adjusted_offset = slot_offset;
    BasicBlock *null, *not_null, *merge;
    Value *box;
    PHINode *phi;

    switch (arg_type(i)) {
    case T_VOID:
      break;

    case T_OBJECT:
    case T_ARRAY:
      null     = CreateBlock("null");
      not_null = CreateBlock("not_null");
      merge    = CreateBlock("merge");

      box = stack()->slot_addr(slot_offset, SharkType::oop_type());
      builder()->CreateCondBr(
        builder()->CreateICmp(
          ICmpInst::ICMP_EQ,
          builder()->CreateLoad(box),
          LLVMValue::null()),
        null, not_null);

      builder()->SetInsertPoint(null);
      builder()->CreateBr(merge);

      builder()->SetInsertPoint(not_null);
      builder()->CreateBr(merge);

      builder()->SetInsertPoint(merge);
      phi = builder()->CreatePHI(box_type, "boxed_object");
      phi->addIncoming(ConstantPointerNull::get(box_type), null);
      phi->addIncoming(box, not_null);
      box = phi;

      param_types.push_back(box_type);
      param_values.push_back(box);

      oopmap->set_oop(SharkStack::slot2reg(slot_offset));

      if (i == 0 && !is_static())
        _receiver_slot_offset = slot_offset;

      break;

    case T_LONG:
    case T_DOUBLE:
      adjusted_offset--;
      // fall through

    default:
      const Type *param_type = SharkType::to_stackType(arg_type(i));

      param_types.push_back(param_type);
      param_values.push_back(
        builder()->CreateLoad(stack()->slot_addr(adjusted_offset, param_type)));
    }
  }

  // The oopmap is now complete, and everything is written
  // into the frame except the PC.
  int pc_offset = code_buffer()->create_unique_offset();

  _oop_maps = new OopMapSet();
  oop_maps()->add_gc_map(pc_offset, oopmap);

  builder()->CreateStore(
    builder()->code_buffer_address(pc_offset),
    stack()->slot_addr(stack()->pc_slot_offset()));

  // Set up the Java frame anchor
  stack()->CreateSetLastJavaFrame();

  // Lock if necessary
  if (is_synchronized())
    Unimplemented();

  // Change the thread state to _thread_in_native
  CreateSetThreadState(_thread_in_native);

  // Make the call
  BasicType result_type = target()->result_type();
  const Type* return_type;
  if (result_type == T_VOID)
    return_type = SharkType::void_type();
  else if (is_returning_oop())
    return_type = box_type;
  else
    return_type = SharkType::to_arrayType(result_type);
  Value* native_function = builder()->CreateIntToPtr(
     LLVMValue::intptr_constant((intptr_t) target()->native_function()),
     PointerType::getUnqual(
       FunctionType::get(return_type, param_types, false)));
  Value *result = builder()->CreateCall(
    native_function, param_values.begin(), param_values.end());

  // Start the transition back to _thread_in_Java
  CreateSetThreadState(_thread_in_native_trans);

  // Make sure new state is visible in the GC thread
  if (os::is_MP()) {
    if (UseMembar)
      builder()->CreateMemoryBarrier(SharkBuilder::BARRIER_STORELOAD);
    else
      CreateWriteMemorySerializePage();
  }

  // Handle safepoint operations, pending suspend requests,
  // and pending asynchronous exceptions.
  BasicBlock *check_thread = CreateBlock("check_thread");
  BasicBlock *do_safepoint = CreateBlock("do_safepoint");
  BasicBlock *safepointed  = CreateBlock("safepointed");

  Value *global_state = builder()->CreateLoad(
    builder()->CreateIntToPtr(
      LLVMValue::intptr_constant(
        (intptr_t) SafepointSynchronize::address_of_state()),
      PointerType::getUnqual(SharkType::jint_type())),
    "global_state");

  builder()->CreateCondBr(
    builder()->CreateICmpNE(
      global_state,
      LLVMValue::jint_constant(SafepointSynchronize::_not_synchronized)),
    do_safepoint, check_thread);

  builder()->SetInsertPoint(check_thread);
  Value *thread_state = builder()->CreateValueOfStructEntry(
    thread,
    JavaThread::suspend_flags_offset(),
    SharkType::jint_type(),
    "thread_state");

  builder()->CreateCondBr(
    builder()->CreateICmpNE(
      thread_state,
      LLVMValue::jint_constant(0)),
    do_safepoint, safepointed);

  builder()->SetInsertPoint(do_safepoint);
  builder()->CreateCall(
    builder()->check_special_condition_for_native_trans(), thread);
  builder()->CreateBr(safepointed);

  // Finally we can change the thread state to _thread_in_Java
  builder()->SetInsertPoint(safepointed);
  CreateSetThreadState(_thread_in_Java);

  // Clear the frame anchor
  stack()->CreateResetLastJavaFrame();

  // If there is a pending exception then we can just unwind and
  // return.  It seems totally wrong that unlocking is skipped here
  // but apparently the template interpreter does this so we do too.
  BasicBlock *exception    = CreateBlock("exception");
  BasicBlock *no_exception = CreateBlock("no_exception");

  builder()->CreateCondBr(
    builder()->CreateICmpEQ(
      CreateLoadPendingException(),
      LLVMValue::null()),
    no_exception, exception);

  builder()->SetInsertPoint(exception);
  CreateResetHandleBlock();
  stack()->CreatePopFrame(0);
  builder()->CreateRet(LLVMValue::jint_constant(0));

  builder()->SetInsertPoint(no_exception);

  // If the result was an oop then unbox it before
  // releasing the handle it might be protected by
  if (is_returning_oop()) {
    BasicBlock *null     = builder()->GetInsertBlock();
    BasicBlock *not_null = CreateBlock("not_null");
    BasicBlock *merge    = CreateBlock("merge");

    builder()->CreateCondBr(
      builder()->CreateICmpNE(result, ConstantPointerNull::get(box_type)),
      not_null, merge);

    builder()->SetInsertPoint(not_null);
    Value *unboxed_result = builder()->CreateLoad(result);
    builder()->CreateBr(merge);

    builder()->SetInsertPoint(merge);
    PHINode *phi = builder()->CreatePHI(SharkType::oop_type(), "result");
    phi->addIncoming(LLVMValue::null(), null);
    phi->addIncoming(unboxed_result, not_null);
    result = phi;
  }

  // Reset handle block
  CreateResetHandleBlock();

  // Unlock if necessary.
  if (is_synchronized())
    Unimplemented();

  // Unwind and return
  Value *result_addr = stack()->CreatePopFrame(type2size[result_type]);
  if (result_type != T_VOID) {
    bool needs_cast = false;
    bool is_signed = false;
    switch (result_type) {
    case T_BOOLEAN:
      result = builder()->CreateICmpNE(result, LLVMValue::jbyte_constant(0));
      needs_cast = true;
      break;

    case T_CHAR:
      needs_cast = true;
      break;

    case T_BYTE:
    case T_SHORT:
      needs_cast = true;
      is_signed = true;
      break;
    }
    if (needs_cast) {
      result = builder()->CreateIntCast(
        result, SharkType::to_stackType(result_type), is_signed);
    }

    builder()->CreateStore(
      result,
      builder()->CreateIntToPtr(
        result_addr,
        PointerType::getUnqual(SharkType::to_stackType(result_type))));
  }
  builder()->CreateRet(LLVMValue::jint_constant(0));
}
Ejemplo n.º 11
0
// Creates the helper function that will do the setjmp() call and
// function call for implementing Invoke.  Creates the call to the
// helper function.  Returns a Value which is zero on the normal
// execution path and non-zero if the landingpad block should be
// entered.
Value *FuncRewriter::createSetjmpWrappedCall(InvokeInst *Invoke) {
  Type *I32 = Type::getInt32Ty(Func->getContext());

  // Allocate space for storing the invoke's result temporarily (so
  // that the helper function can return multiple values).  We don't
  // need to do this if the result is unused, and we can't if its type
  // is void.
  Instruction *ResultAlloca = NULL;
  if (!Invoke->use_empty()) {
    ResultAlloca = new AllocaInst(Invoke->getType(), "invoke_result_ptr");
    Func->getEntryBlock().getInstList().push_front(ResultAlloca);
  }

  // Create type for the helper function.
  SmallVector<Type *, 10> ArgTypes;
  for (unsigned I = 0, E = Invoke->getNumArgOperands(); I < E; ++I)
    ArgTypes.push_back(Invoke->getArgOperand(I)->getType());
  ArgTypes.push_back(Invoke->getCalledValue()->getType());
  ArgTypes.push_back(FrameJmpBuf->getType());
  if (ResultAlloca)
    ArgTypes.push_back(Invoke->getType()->getPointerTo());
  FunctionType *FTy = FunctionType::get(I32, ArgTypes, false);

  // Create the helper function.
  Function *HelperFunc = Function::Create(
      FTy, GlobalValue::InternalLinkage, Func->getName() + "_setjmp_caller");
  Func->getParent()->getFunctionList().insertAfter(Func, HelperFunc);
  BasicBlock *EntryBB = BasicBlock::Create(Func->getContext(), "", HelperFunc);
  BasicBlock *NormalBB = BasicBlock::Create(Func->getContext(), "normal",
                                            HelperFunc);
  BasicBlock *ExceptionBB = BasicBlock::Create(Func->getContext(), "exception",
                                               HelperFunc);

  // Unpack the helper function's arguments.
  Function::arg_iterator ArgIter = HelperFunc->arg_begin();
  SmallVector<Value *, 10> InnerCallArgs;
  for (unsigned I = 0, E = Invoke->getNumArgOperands(); I < E; ++I) {
    ArgIter->setName("arg");
    InnerCallArgs.push_back(ArgIter++);
  }
  Argument *CalleeArg = ArgIter++;
  Argument *JmpBufArg = ArgIter++;
  CalleeArg->setName("func_ptr");
  JmpBufArg->setName("jmp_buf");

  // Create setjmp() call.
  Value *SetjmpArgs[] = { JmpBufArg };
  CallInst *SetjmpCall = CallInst::Create(SetjmpIntrinsic, SetjmpArgs,
                                          "invoke_sj", EntryBB);
  CopyDebug(SetjmpCall, Invoke);
  // Setting the "returns_twice" attribute here prevents optimization
  // passes from inlining HelperFunc into its caller.
  SetjmpCall->setCanReturnTwice();
  // Check setjmp()'s result.
  Value *IsZero = CopyDebug(new ICmpInst(*EntryBB, CmpInst::ICMP_EQ, SetjmpCall,
                                         ConstantInt::get(I32, 0),
                                         "invoke_sj_is_zero"), Invoke);
  CopyDebug(BranchInst::Create(NormalBB, ExceptionBB, IsZero, EntryBB), Invoke);
  // Handle the normal, non-exceptional code path.
  CallInst *InnerCall = CallInst::Create(CalleeArg, InnerCallArgs, "",
                                         NormalBB);
  CopyDebug(InnerCall, Invoke);
  InnerCall->setAttributes(Invoke->getAttributes());
  InnerCall->setCallingConv(Invoke->getCallingConv());
  if (ResultAlloca) {
    InnerCall->setName("result");
    Argument *ResultArg = ArgIter++;
    ResultArg->setName("result_ptr");
    CopyDebug(new StoreInst(InnerCall, ResultArg, NormalBB), Invoke);
  }
  ReturnInst::Create(Func->getContext(), ConstantInt::get(I32, 0), NormalBB);
  // Handle the exceptional code path.
  ReturnInst::Create(Func->getContext(), ConstantInt::get(I32, 1), ExceptionBB);

  // Create the outer call to the helper function.
  SmallVector<Value *, 10> OuterCallArgs;
  for (unsigned I = 0, E = Invoke->getNumArgOperands(); I < E; ++I)
    OuterCallArgs.push_back(Invoke->getArgOperand(I));
  OuterCallArgs.push_back(Invoke->getCalledValue());
  OuterCallArgs.push_back(FrameJmpBuf);
  if (ResultAlloca)
    OuterCallArgs.push_back(ResultAlloca);
  CallInst *OuterCall = CallInst::Create(HelperFunc, OuterCallArgs,
                                         "invoke_is_exc", Invoke);
  CopyDebug(OuterCall, Invoke);

  // Retrieve the function return value stored in the alloca.  We only
  // need to do this on the non-exceptional path, but we currently do
  // it unconditionally because that is simpler.
  if (ResultAlloca) {
    Value *Result = new LoadInst(ResultAlloca, "", Invoke);
    Result->takeName(Invoke);
    Invoke->replaceAllUsesWith(Result);
  }
  return OuterCall;
}
Ejemplo n.º 12
0
void initLLVM() {
  InitializeNativeTarget();
  
  // Create some module to put our function into it.
  std::unique_ptr<Module> Owner = make_unique<Module>("test", Context);
  Module *M = Owner.get();
  
  // Create the add1 function entry and insert this entry into module M.  The
  // function will have a return type of "int" and take an argument of "int".
  // The '0' terminates the list of argument types.
  Function *Add1F = cast<Function>(M->getOrInsertFunction(
    "add1", Type::getInt32Ty(Context), Type::getInt32Ty(Context), (Type*)0
  ));
  
  // Add a basic block to the function. As before, it automatically inserts
  // because of the last argument.
  BasicBlock *BB = BasicBlock::Create(Context, "EntryBlock", Add1F);
  
  // Create a basic block builder with default parameters.  The builder will
  // automatically append instructions to the basic block `BB'.
  IRBuilder<> builder(BB);
  
  // Get pointers to the constant `1'.
  Value *One = builder.getInt32(1);
  
  // Get pointers to the integer argument of the add1 function...
  assert(Add1F->arg_begin() != Add1F->arg_end()); // Make sure there's an arg
  Argument *ArgX = Add1F->arg_begin();  // Get the arg
  ArgX->setName("AnArg");            // Give it a nice symbolic name for fun.
  
  // Create the add instruction, inserting it into the end of BB.
  Value *Add = builder.CreateAdd(One, ArgX);
  
  // Create the return instruction and add it to the basic block
  builder.CreateRet(Add);
  
  // Now, function add1 is ready.
  
  
  // Now we're going to create function `foo',
  // which returns an int and takes no arguments.
  FooF = cast<Function>(M->getOrInsertFunction(
    "foo", Type::getInt32Ty(Context), (Type *)0
  ));
  
  // Add a basic block to the FooF function.
  BB = BasicBlock::Create(Context, "EntryBlock", FooF);
  
  // Tell the basic block builder to attach itself to the new basic block
  builder.SetInsertPoint(BB);
  
  // Get pointer to the constant `10'.
  Value *Ten = builder.getInt32(10);
  
  // Pass Ten to the call to Add1F
  CallInst *Add1CallRes = builder.CreateCall(Add1F, Ten);
  Add1CallRes->setTailCall(true);
  
  // Create the return instruction and add it to the basic block.
  builder.CreateRet(Add1CallRes);
  
  // Now we create the JIT.
  EE = EngineBuilder(std::move(Owner)).create();
  /*
  outs() << "We just constructed this LLVM module:\n\n" << *M;
  outs() << "\n\nRunning foo: ";
  outs().flush();
  */
}