예제 #1
0
void init_builtins(CodeGenState *code_gen) {
    code_gen->builtin_types[Builtin::Void] = Type::getVoidTy(code_gen->ctx);
    code_gen->builtin_types[Builtin::S8] = Type::getInt8Ty(code_gen->ctx);
    code_gen->builtin_types[Builtin::U8] = Type::getInt8Ty(code_gen->ctx);
    code_gen->builtin_types[Builtin::S16] = Type::getInt16Ty(code_gen->ctx);
    code_gen->builtin_types[Builtin::U16] = Type::getInt16Ty(code_gen->ctx);
    code_gen->builtin_types[Builtin::S32] = Type::getInt32Ty(code_gen->ctx);
    code_gen->builtin_types[Builtin::U32] = Type::getInt32Ty(code_gen->ctx);
    code_gen->builtin_types[Builtin::S64] = Type::getInt64Ty(code_gen->ctx);
    code_gen->builtin_types[Builtin::U64] = Type::getInt64Ty(code_gen->ctx);
    code_gen->builtin_types[Builtin::Float32] = Type::getFloatTy(code_gen->ctx);
    code_gen->builtin_types[Builtin::Float64] = Type::getDoubleTy(code_gen->ctx);
    // TODO: is it a good idea to use i1 here?
    code_gen->builtin_types[Builtin::Bool] = Type::getInt1Ty(code_gen->ctx);

    {
        // TODO: read doxygen, not sure how it works
        SmallVector<AttributeSet, 4> Attrs;
        AttributeSet PAS;
        {
            AttrBuilder B;
            B.addAttribute(Attribute::NoUnwind);
            PAS = AttributeSet::get(code_gen->ctx, ~0U, B);
        }

        Attrs.push_back(PAS);
        code_gen->default_func_attr = AttributeSet::get(code_gen->ctx, Attrs);
    }
}
// removeAttribute() currently does not work on Attribute::Alignment
// (it fails with an assertion error), so we have to take a more
// convoluted route to removing this attribute by recreating the
// AttributeSet.
AttributeSet RemoveAttrs(LLVMContext &Context, AttributeSet Attrs) {
  SmallVector<AttributeSet, 8> AttrList;
  for (unsigned Slot = 0; Slot < Attrs.getNumSlots(); ++Slot) {
    unsigned Index = Attrs.getSlotIndex(Slot);
    AttrBuilder AB;
    for (AttributeSet::iterator Attr = Attrs.begin(Slot), E = Attrs.end(Slot);
         Attr != E; ++Attr) {
      if (Attr->isEnumAttribute() &&
          Attr->getKindAsEnum() != Attribute::ByVal &&
          Attr->getKindAsEnum() != Attribute::StructRet) {
        AB.addAttribute(*Attr);
      }
      // IR semantics require that ByVal implies NoAlias.  However, IR
      // semantics do not require StructRet to imply NoAlias.  For
      // example, a global variable address can be passed as a
      // StructRet argument, although Clang does not do so and Clang
      // explicitly adds NoAlias to StructRet arguments.
      if (Attr->isEnumAttribute() &&
          Attr->getKindAsEnum() == Attribute::ByVal) {
        AB.addAttribute(Attribute::get(Context, Attribute::NoAlias));
      }
    }
    AttrList.push_back(AttributeSet::get(Context, Index, AB));
  }
  return AttributeSet::get(Context, AttrList);
}
예제 #3
0
파일: Inliner.cpp 프로젝트: hsorby/opencor
/// \brief If the inlined function had a higher stack protection level than the
/// calling function, then bump up the caller's stack protection level.
static void AdjustCallerSSPLevel(Function *Caller, Function *Callee) {
  // If upgrading the SSP attribute, clear out the old SSP Attributes first.
  // Having multiple SSP attributes doesn't actually hurt, but it adds useless
  // clutter to the IR.
  AttrBuilder B;
  B.addAttribute(Attribute::StackProtect)
    .addAttribute(Attribute::StackProtectStrong)
    .addAttribute(Attribute::StackProtectReq);
  AttributeSet OldSSPAttr = AttributeSet::get(Caller->getContext(),
                                              AttributeSet::FunctionIndex,
                                              B);

  if (Callee->hasFnAttribute(Attribute::SafeStack)) {
    Caller->removeAttributes(AttributeSet::FunctionIndex, OldSSPAttr);
    Caller->addFnAttr(Attribute::SafeStack);
  } else if (Callee->hasFnAttribute(Attribute::StackProtectReq) &&
             !Caller->hasFnAttribute(Attribute::SafeStack)) {
    Caller->removeAttributes(AttributeSet::FunctionIndex, OldSSPAttr);
    Caller->addFnAttr(Attribute::StackProtectReq);
  } else if (Callee->hasFnAttribute(Attribute::StackProtectStrong) &&
             !Caller->hasFnAttribute(Attribute::SafeStack) &&
             !Caller->hasFnAttribute(Attribute::StackProtectReq)) {
    Caller->removeAttributes(AttributeSet::FunctionIndex, OldSSPAttr);
    Caller->addFnAttr(Attribute::StackProtectStrong);
  } else if (Callee->hasFnAttribute(Attribute::StackProtect) &&
             !Caller->hasFnAttribute(Attribute::SafeStack) &&
             !Caller->hasFnAttribute(Attribute::StackProtectReq) &&
             !Caller->hasFnAttribute(Attribute::StackProtectStrong))
    Caller->addFnAttr(Attribute::StackProtect);
}
예제 #4
0
extern "C" void LLVMAddFunctionAttribute(LLVMValueRef Fn, unsigned index,
                                         uint64_t Val) {
  Function *A = unwrap<Function>(Fn);
  AttrBuilder B;
  B.addRawValue(Val);
  A->addAttributes(index, AttributeSet::get(A->getContext(), index, B));
}
예제 #5
0
void X86RetpolineThunks::createThunkFunction(Module &M, StringRef Name) {
  assert(Name.startswith(ThunkNamePrefix) &&
         "Created a thunk with an unexpected prefix!");

  LLVMContext &Ctx = M.getContext();
  auto Type = FunctionType::get(Type::getVoidTy(Ctx), false);
  Function *F =
      Function::Create(Type, GlobalValue::LinkOnceODRLinkage, Name, &M);
  F->setVisibility(GlobalValue::HiddenVisibility);
  F->setComdat(M.getOrInsertComdat(Name));

  // Add Attributes so that we don't create a frame, unwind information, or
  // inline.
  AttrBuilder B;
  B.addAttribute(llvm::Attribute::NoUnwind);
  B.addAttribute(llvm::Attribute::Naked);
  F->addAttributes(llvm::AttributeList::FunctionIndex, B);

  // Populate our function a bit so that we can verify.
  BasicBlock *Entry = BasicBlock::Create(Ctx, "entry", F);
  IRBuilder<> Builder(Entry);

  Builder.CreateRetVoid();

  // MachineFunctions/MachineBasicBlocks aren't created automatically for the
  // IR-level constructs we already made. Create them and insert them into the
  // module.
  MachineFunction &MF = MMI->getOrCreateMachineFunction(*F);
  MachineBasicBlock *EntryMBB = MF.CreateMachineBasicBlock(Entry);

  // Insert EntryMBB into MF. It's not in the module until we do this.
  MF.insert(MF.end(), EntryMBB);
}
예제 #6
0
void DynInstMarker::insertInstrumentation(BasicBlock::iterator& ii, 
                                          Function::iterator& bi,
                                            Module* mod) {
  std::vector<Type*>FuncTy_4_args;
  FunctionType* FuncTy_4 = FunctionType::get(
   /*Result=*/Type::getVoidTy(mod->getContext()),
   /*Params=*/FuncTy_4_args,
   /*isVarArg=*/false);
  
  InlineAsm* ptr_10 = InlineAsm::get(FuncTy_4, "nop", "~{dirflag},~{fpsr},~{flags}",true);
   CallInst* void_9 = CallInst::Create(ptr_10, "", (&(*ii)));
   void_9->setCallingConv(CallingConv::C);
   void_9->setTailCall(false);
   AttributeSet void_9_PAL;
   {
    SmallVector<AttributeSet, 4> Attrs;
    AttributeSet PAS;
     {
      AttrBuilder B;
      B.addAttribute(Attribute::NoUnwind);
      PAS = AttributeSet::get(mod->getContext(), ~0U, B);
     }
 
    Attrs.push_back(PAS);
    void_9_PAL = AttributeSet::get(mod->getContext(), Attrs);
 
   }
   void_9->setAttributes(void_9_PAL);
}
예제 #7
0
extern "C" void LLVMRustAddDereferenceableAttr(LLVMValueRef Fn, unsigned Index,
                                               uint64_t Bytes) {
  Function *A = unwrap<Function>(Fn);
  AttrBuilder B;
  B.addDereferenceableAttr(Bytes);
  A->addAttributes(Index, AttributeSet::get(A->getContext(), Index, B));
}
예제 #8
0
extern "C" void LLVMAddFunctionAttrStringValue(LLVMValueRef Fn, unsigned index,
                                               const char *Name,
                                               const char *Value) {
  Function *F = unwrap<Function>(Fn);
  AttrBuilder B;
  B.addAttribute(Name, Value);
  F->addAttributes(index, AttributeSet::get(F->getContext(), index, B));
}
예제 #9
0
Value* NFunctionDeclaration::codeGen(CodeGenContext& context)
{
	vector<Type*> argTypes;
	VariableList::const_iterator it;

	for (it = arguments.begin(); it != arguments.end(); it++) 
	{
		argTypes.push_back(typeOf((**it).type));
	}
	FunctionType *ftype = FunctionType::get(typeOf(type), makeArrayRef(argTypes), false);
	Function *function = Function::Create(ftype, GlobalValue::ExternalLinkage, id.name.c_str(), context.module);
	BasicBlock *bblock = BasicBlock::Create(getGlobalContext(), "entry", function, 0);
	BasicBlock *returnBlock = BasicBlock::Create(getGlobalContext(), "return", function, 0);

	function->setCallingConv(CallingConv::C);

	AttributeSet func_func_PAL;
	{
	 	SmallVector<AttributeSet, 4> Attrs;
	  	AttributeSet PAS;
	  	{
	    	AttrBuilder B;
	    	B.addAttribute(Attribute::NoUnwind);
	    	PAS = AttributeSet::get(getGlobalContext(), ~0U, B);
	    }
	  
	  	Attrs.push_back(PAS);
	  	func_func_PAL = AttributeSet::get(getGlobalContext(), Attrs);
	}
	function->setAttributes(func_func_PAL);

	context.setCurrentFunction(function);
	context.setReturnBlock(returnBlock);
	context.isTopLevel = false;

	context.pushBlock(bblock, false);

	Function::arg_iterator argsValues = function->arg_begin();
    Value* argumentValue;

	for (it = arguments.begin(); it != arguments.end(); it++) 
	{
		(**it).codeGen(context);
		
		argumentValue = argsValues++;
		argumentValue->setName((*it)->id.name.c_str());
		StoreInst *inst = new StoreInst(argumentValue, context.locals()[(*it)->id.name], false, bblock);
	}
	
	block.codeGen(context);
	ReturnInst::Create(getGlobalContext(), context.getCurrentReturnValue(), context.getReturnBlock());

	context.popBlock();
	context.isTopLevel = true;
	std::cout << "Creating function: " << id.name << endl;
	
	return function;
}
예제 #10
0
extern "C" void LLVMAddCallSiteAttribute(LLVMValueRef Instr, unsigned index, uint64_t Val) {
  CallSite Call = CallSite(unwrap<Instruction>(Instr));
  AttrBuilder B;
  B.addRawValue(Val);
  Call.setAttributes(
    Call.getAttributes().addAttributes(Call->getContext(), index,
                                       AttributeSet::get(Call->getContext(),
                                                         index, B)));
}
예제 #11
0
extern "C" void LLVMAddDereferenceableCallSiteAttr(LLVMValueRef Instr, unsigned idx, uint64_t b) {
  CallSite Call = CallSite(unwrap<Instruction>(Instr));
  AttrBuilder B;
  B.addDereferenceableAttr(b);
  Call.setAttributes(
    Call.getAttributes().addAttributes(Call->getContext(), idx,
                                       AttributeSet::get(Call->getContext(),
                                                         idx, B)));
}
예제 #12
0
//
// remove the use-soft-float attribute
//
static void removeUseSoftFloat(Function &F) {
  AttrBuilder B;
  DEBUG(errs() << "removing -use-soft-float\n");
  B.addAttribute("use-soft-float", "false");
  F.removeAttributes(AttributeList::FunctionIndex, B);
  if (F.hasFnAttribute("use-soft-float")) {
    DEBUG(errs() << "still has -use-soft-float\n");
  }
  F.addAttributes(AttributeList::FunctionIndex, B);
}
예제 #13
0
const AttributeSetImpl *LLVM_General_GetSlotAttributeSet(
	LLVMContextRef context,
	unsigned index,
	const AttributeImpl **attributes,
	unsigned length
) {
	AttrBuilder builder;
	for (unsigned i = 0; i < length; i++) builder.addAttribute(unwrap(attributes[i]));
	return wrap(AttributeSet::get(*unwrap(context), index, builder));
}
예제 #14
0
static bool addReadAttrs(const SCCNodeSet &SCCNodes, AARGetterT AARGetter) {
    // Check if any of the functions in the SCC read or write memory.  If they
    // write memory then they can't be marked readnone or readonly.
    bool ReadsMemory = false;
    for (Function *F : SCCNodes) {
        // Call the callable parameter to look up AA results for this function.
        AAResults &AAR = AARGetter(*F);

        switch (checkFunctionMemoryAccess(*F, AAR, SCCNodes)) {
        case MAK_MayWrite:
            return false;
        case MAK_ReadOnly:
            ReadsMemory = true;
            break;
        case MAK_ReadNone:
            // Nothing to do!
            break;
        }
    }

    // Success!  Functions in this SCC do not access memory, or only read memory.
    // Give them the appropriate attribute.
    bool MadeChange = false;
    for (Function *F : SCCNodes) {
        if (F->doesNotAccessMemory())
            // Already perfect!
            continue;

        if (F->onlyReadsMemory() && ReadsMemory)
            // No change.
            continue;

        MadeChange = true;

        // Clear out any existing attributes.
        AttrBuilder B;
        B.addAttribute(Attribute::ReadOnly).addAttribute(Attribute::ReadNone);
        F->removeAttributes(
            AttributeSet::FunctionIndex,
            AttributeSet::get(F->getContext(), AttributeSet::FunctionIndex, B));

        // Add in the new attribute.
        F->addAttribute(AttributeSet::FunctionIndex,
                        ReadsMemory ? Attribute::ReadOnly : Attribute::ReadNone);

        if (ReadsMemory)
            ++NumReadOnly;
        else
            ++NumReadNone;
    }

    return MadeChange;
}
예제 #15
0
extern "C" void LLVMRemoveFunctionAttrString(LLVMValueRef fn, unsigned index, const char *Name) {
  Function *f = unwrap<Function>(fn);
  LLVMContext &C = f->getContext();
  AttrBuilder B;
  B.addAttribute(Name);
  AttributeSet to_remove = AttributeSet::get(C, index, B);

  AttributeSet attrs = f->getAttributes();
  f->setAttributes(attrs.removeAttributes(f->getContext(),
                                          index,
                                          to_remove));
}
예제 #16
0
/// Deduce returned attributes for the SCC.
static bool addArgumentReturnedAttrs(const SCCNodeSet &SCCNodes) {
  bool Changed = false;

  AttrBuilder B;
  B.addAttribute(Attribute::Returned);

  // Check each function in turn, determining if an argument is always returned.
  for (Function *F : SCCNodes) {
    // We can infer and propagate function attributes only when we know that the
    // definition we'll get at link time is *exactly* the definition we see now.
    // For more details, see GlobalValue::mayBeDerefined.
    if (!F->hasExactDefinition())
      continue;

    if (F->getReturnType()->isVoidTy())
      continue;

    // There is nothing to do if an argument is already marked as 'returned'.
    if (any_of(F->args(),
               [](const Argument &Arg) { return Arg.hasReturnedAttr(); }))
      continue;

    auto FindRetArg = [&]() -> Value * {
      Value *RetArg = nullptr;
      for (BasicBlock &BB : *F)
        if (auto *Ret = dyn_cast<ReturnInst>(BB.getTerminator())) {
          // Note that stripPointerCasts should look through functions with
          // returned arguments.
          Value *RetVal = Ret->getReturnValue()->stripPointerCasts();
          if (!isa<Argument>(RetVal) || RetVal->getType() != F->getReturnType())
            return nullptr;

          if (!RetArg)
            RetArg = RetVal;
          else if (RetArg != RetVal)
            return nullptr;
        }

      return RetArg;
    };

    if (Value *RetArg = FindRetArg()) {
      auto *A = cast<Argument>(RetArg);
      A->addAttr(AttributeSet::get(F->getContext(), A->getArgNo() + 1, B));
      ++NumReturned;
      Changed = true;
    }
  }

  return Changed;
}
예제 #17
0
/**
 * Set the shader type we want to compile
 *
 * @param type shader type to set
 */
extern "C" void
radeon_llvm_shader_type(LLVMValueRef F, unsigned type)
{
  Function *Func = unwrap<Function>(F);
  int Idx = AttributeSet::FunctionIndex;
  AttrBuilder B;
  char Str[2];

  sprintf(Str, "%1d", type);
  B.addAttribute("ShaderType", Str);

  AttributeSet Set = AttributeSet::get(Func->getContext(), Idx, B);
  Func->addAttributes(Idx, Set);
}
예제 #18
0
파일: abi_x86.cpp 프로젝트: IntelLabs/julia
bool needPassByRef(jl_datatype_t *dt, AttrBuilder &ab) override
{
    size_t size = jl_datatype_size(dt);
    if (is_complex64(dt) || is_complex128(dt) || (jl_is_primitivetype(dt) && size <= 8))
        return false;
    ab.addAttribute(Attribute::ByVal);
    return true;
}
예제 #19
0
bool needPassByRef(jl_datatype_t *dt, AttrBuilder &ab) override
{
    jl_datatype_t *ty0 = NULL;
    bool hva = false;
    if (jl_datatype_size(dt) > 64 && isHFA(dt, &ty0, &hva) > 8) {
        ab.addAttribute(Attribute::ByVal);
        return true;
    }
    return false;
}
예제 #20
0
/* Compile the AST into a module */
void CodeGenContext::generateCode(NBlock& root)
{
	std::cout << "Generating code...\n";
	
	/* Create the top level interpreter function to call as entry */
	vector<Type*> argTypes;
	FunctionType *ftype = FunctionType::get(Type::getVoidTy(getGlobalContext()), makeArrayRef(argTypes), false);
	//mainFunction = Function::Create(ftype, GlobalValue::ExternalLinkage, "main", module);
	//BasicBlock *bblock = BasicBlock::Create(getGlobalContext(), "entry", mainFunction, 0);
	//mainFunction->setCallingConv(CallingConv::C);

	AttributeSet func_func_PAL;
	{
	 	SmallVector<AttributeSet, 4> Attrs;
	  	AttributeSet PAS;
	  	{
	    	AttrBuilder B;
	    	B.addAttribute(Attribute::NoUnwind);
	    	PAS = AttributeSet::get(getGlobalContext(), ~0U, B);
	    }
	  
	  	Attrs.push_back(PAS);
	  	func_func_PAL = AttributeSet::get(getGlobalContext(), Attrs);
	 }
	 //mainFunction->setAttributes(func_func_PAL);
	
	/* Push a new variable/block context */
	//pushBlock(bblock, false);
	root.codeGen(*this); /* emit bytecode for the toplevel block */
	//ReturnInst::Create(getGlobalContext(), bblock);
	//popBlock();
	
	/* Print the bytecode in a human-readable format 
	   to see if our program compiled properly
	 */
	std::cout << "Code is generated.\n";
	//module->dump();
	verifyModule(*module, PrintMessageAction);
	PassManager pm;
	pm.add(createPrintModulePass(&outs()));
	pm.run(*module);
}
예제 #21
0
/// Replaces the given call site (Call or Invoke) with a gc.statepoint
/// intrinsic with an empty deoptimization arguments list.  This does
/// NOT do explicit relocation for GC support.
static Value *ReplaceWithStatepoint(const CallSite &CS /* to replace */) {
  assert(CS.getInstruction()->getModule() && "must be set");

  // TODO: technically, a pass is not allowed to get functions from within a
  // function pass since it might trigger a new function addition.  Refactor
  // this logic out to the initialization of the pass.  Doesn't appear to
  // matter in practice.

  // Then go ahead and use the builder do actually do the inserts.  We insert
  // immediately before the previous instruction under the assumption that all
  // arguments will be available here.  We can't insert afterwards since we may
  // be replacing a terminator.
  IRBuilder<> Builder(CS.getInstruction());

  // Note: The gc args are not filled in at this time, that's handled by
  // RewriteStatepointsForGC (which is currently under review).

  // Create the statepoint given all the arguments
  Instruction *Token = nullptr;

  uint64_t ID;
  uint32_t NumPatchBytes;

  AttributeSet OriginalAttrs = CS.getAttributes();
  Attribute AttrID =
      OriginalAttrs.getAttribute(AttributeSet::FunctionIndex, "statepoint-id");
  Attribute AttrNumPatchBytes = OriginalAttrs.getAttribute(
      AttributeSet::FunctionIndex, "statepoint-num-patch-bytes");

  AttrBuilder AttrsToRemove;
  bool HasID = AttrID.isStringAttribute() &&
               !AttrID.getValueAsString().getAsInteger(10, ID);

  if (HasID)
    AttrsToRemove.addAttribute("statepoint-id");
  else
    ID = 0xABCDEF00;

  bool HasNumPatchBytes =
      AttrNumPatchBytes.isStringAttribute() &&
      !AttrNumPatchBytes.getValueAsString().getAsInteger(10, NumPatchBytes);

  if (HasNumPatchBytes)
    AttrsToRemove.addAttribute("statepoint-num-patch-bytes");
  else
    NumPatchBytes = 0;

  OriginalAttrs = OriginalAttrs.removeAttributes(
      CS.getInstruction()->getContext(), AttributeSet::FunctionIndex,
      AttrsToRemove);

  if (CS.isCall()) {
    CallInst *ToReplace = cast<CallInst>(CS.getInstruction());
    CallInst *Call = Builder.CreateGCStatepointCall(
        ID, NumPatchBytes, CS.getCalledValue(),
        makeArrayRef(CS.arg_begin(), CS.arg_end()), None, None,
        "safepoint_token");
    Call->setTailCall(ToReplace->isTailCall());
    Call->setCallingConv(ToReplace->getCallingConv());

    // In case if we can handle this set of attributes - set up function
    // attributes directly on statepoint and return attributes later for
    // gc_result intrinsic.
    Call->setAttributes(OriginalAttrs.getFnAttributes());

    Token = Call;

    // Put the following gc_result and gc_relocate calls immediately after
    // the old call (which we're about to delete).
    assert(ToReplace->getNextNode() && "not a terminator, must have next");
    Builder.SetInsertPoint(ToReplace->getNextNode());
    Builder.SetCurrentDebugLocation(ToReplace->getNextNode()->getDebugLoc());
  } else if (CS.isInvoke()) {
    InvokeInst *ToReplace = cast<InvokeInst>(CS.getInstruction());

    // Insert the new invoke into the old block.  We'll remove the old one in a
    // moment at which point this will become the new terminator for the
    // original block.
    Builder.SetInsertPoint(ToReplace->getParent());
    InvokeInst *Invoke = Builder.CreateGCStatepointInvoke(
        ID, NumPatchBytes, CS.getCalledValue(), ToReplace->getNormalDest(),
        ToReplace->getUnwindDest(), makeArrayRef(CS.arg_begin(), CS.arg_end()),
        None, None, "safepoint_token");

    Invoke->setCallingConv(ToReplace->getCallingConv());

    // In case if we can handle this set of attributes - set up function
    // attributes directly on statepoint and return attributes later for
    // gc_result intrinsic.
    Invoke->setAttributes(OriginalAttrs.getFnAttributes());

    Token = Invoke;

    // We'll insert the gc.result into the normal block
    BasicBlock *NormalDest = ToReplace->getNormalDest();
    // Can not insert gc.result in case of phi nodes preset.
    // Should have removed this cases prior to running this function
    assert(!isa<PHINode>(NormalDest->begin()));
    Instruction *IP = &*(NormalDest->getFirstInsertionPt());
    Builder.SetInsertPoint(IP);
  } else {
    llvm_unreachable("unexpect type of CallSite");
  }
  assert(Token);

  // Handle the return value of the original call - update all uses to use a
  // gc_result hanging off the statepoint node we just inserted

  // Only add the gc_result iff there is actually a used result
  if (!CS.getType()->isVoidTy() && !CS.getInstruction()->use_empty()) {
    std::string TakenName =
        CS.getInstruction()->hasName() ? CS.getInstruction()->getName() : "";
    CallInst *GCResult = Builder.CreateGCResult(Token, CS.getType(), TakenName);
    GCResult->setAttributes(OriginalAttrs.getRetAttributes());
    return GCResult;
  } else {
    // No return value for the call.
    return nullptr;
  }
}
예제 #22
0
Module* makeLLVMModule() {
 // Module Construction
 Module* mod = new Module("./test/test1.ll", getGlobalContext());
 mod->setDataLayout("0x37c1810");
 mod->setTargetTriple("x86_64-pc-linux-gnu");
 
 // Type Definitions
 PointerType* PointerTy_0 = PointerType::get(IntegerType::get(mod->getContext(), 32), 0);
 
 ArrayType* ArrayTy_1 = ArrayType::get(IntegerType::get(mod->getContext(), 32), 3);//数组大小根据ast信息生成
 
 PointerType* PointerTy_2 = PointerType::get(ArrayTy_1, 0);
 
 ArrayType* ArrayTy_3 = ArrayType::get(IntegerType::get(mod->getContext(), 32), 2);
 
 PointerType* PointerTy_4 = PointerType::get(ArrayTy_3, 0);
 
 std::vector<Type*>FuncTy_5_args;
 FunctionType* FuncTy_5 = FunctionType::get(
  /*Result=*/Type::getVoidTy(mod->getContext()),
  /*Params=*/FuncTy_5_args,
  /*isVarArg=*/false);
 
 PointerType* PointerTy_6 = PointerType::get(IntegerType::get(mod->getContext(), 8), 0);
 
 std::vector<Type*>FuncTy_8_args;
 FuncTy_8_args.push_back(PointerTy_6);
 FuncTy_8_args.push_back(PointerTy_6);
 FuncTy_8_args.push_back(IntegerType::get(mod->getContext(), 64));
 FuncTy_8_args.push_back(IntegerType::get(mod->getContext(), 32));
 FuncTy_8_args.push_back(IntegerType::get(mod->getContext(), 1));
 FunctionType* FuncTy_8 = FunctionType::get(
  /*Result=*/Type::getVoidTy(mod->getContext()),
  /*Params=*/FuncTy_8_args,
  /*isVarArg=*/false);
 
 PointerType* PointerTy_7 = PointerType::get(FuncTy_8, 0);
 
 PointerType* PointerTy_9 = PointerType::get(FuncTy_5, 0);
 
 
 // Function Declarations
 
 Function* func_antest = mod->getFunction("antest");
 if (!func_antest) {
 func_antest = Function::Create(
  /*Type=*/FuncTy_5,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"antest", mod); 
 func_antest->setCallingConv(CallingConv::C);
 }
 AttributeSet func_antest_PAL;
 {
  SmallVector<AttributeSet, 4> Attrs;
  AttributeSet PAS;
   {
    AttrBuilder B;
    B.addAttribute(Attribute::NoUnwind);
    PAS = AttributeSet::get(mod->getContext(), ~0U, B);
   }
  
  Attrs.push_back(PAS);
  func_antest_PAL = AttributeSet::get(mod->getContext(), Attrs);
  
 }
 func_antest->setAttributes(func_antest_PAL);
 
 Function* func_llvm_memcpy_p0i8_p0i8_i64 = mod->getFunction("llvm.memcpy.p0i8.p0i8.i64");
 if (!func_llvm_memcpy_p0i8_p0i8_i64) {
 func_llvm_memcpy_p0i8_p0i8_i64 = Function::Create(
  /*Type=*/FuncTy_8,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"llvm.memcpy.p0i8.p0i8.i64", mod); // (external, no body)
 func_llvm_memcpy_p0i8_p0i8_i64->setCallingConv(CallingConv::C);
 }
 AttributeSet func_llvm_memcpy_p0i8_p0i8_i64_PAL;
 {
  SmallVector<AttributeSet, 4> Attrs;
  AttributeSet PAS;
   {
    AttrBuilder B;
    B.addAttribute(Attribute::NoCapture);
    PAS = AttributeSet::get(mod->getContext(), 1U, B);
   }
  
  Attrs.push_back(PAS);
  {
   AttrBuilder B;
   B.addAttribute(Attribute::ReadOnly);
   B.addAttribute(Attribute::NoCapture);
   PAS = AttributeSet::get(mod->getContext(), 2U, B);
  }
 
 Attrs.push_back(PAS);
 {
  AttrBuilder B;
  B.addAttribute(Attribute::NoUnwind);
  PAS = AttributeSet::get(mod->getContext(), ~0U, B);
 }

Attrs.push_back(PAS);
func_llvm_memcpy_p0i8_p0i8_i64_PAL = AttributeSet::get(mod->getContext(), Attrs);

}
func_llvm_memcpy_p0i8_p0i8_i64->setAttributes(func_llvm_memcpy_p0i8_p0i8_i64_PAL);

Function* func_testf = mod->getFunction("testf");
if (!func_testf) {
func_testf = Function::Create(
 /*Type=*/FuncTy_5,
 /*Linkage=*/GlobalValue::ExternalLinkage,
 /*Name=*/"testf", mod); 
func_testf->setCallingConv(CallingConv::C);
}
AttributeSet func_testf_PAL;
{
 SmallVector<AttributeSet, 4> Attrs;
 AttributeSet PAS;
  {
   AttrBuilder B;
   B.addAttribute(Attribute::NoUnwind);
   PAS = AttributeSet::get(mod->getContext(), ~0U, B);
  }
 
 Attrs.push_back(PAS);
 func_testf_PAL = AttributeSet::get(mod->getContext(), Attrs);
 
}
func_testf->setAttributes(func_testf_PAL);

Function* func_main = mod->getFunction("main");
if (!func_main) {
func_main = Function::Create(
 /*Type=*/FuncTy_5,
 /*Linkage=*/GlobalValue::ExternalLinkage,
 /*Name=*/"main", mod); 
func_main->setCallingConv(CallingConv::C);
}
AttributeSet func_main_PAL;
{
 SmallVector<AttributeSet, 4> Attrs;
 AttributeSet PAS;
  {
   AttrBuilder B;
   B.addAttribute(Attribute::NoUnwind);
   PAS = AttributeSet::get(mod->getContext(), ~0U, B);
  }
 
 Attrs.push_back(PAS);
 func_main_PAL = AttributeSet::get(mod->getContext(), Attrs);
 
}
func_main->setAttributes(func_main_PAL);

// Global Variable Declarations ------global按照这个写,区别只在于isConstant的值,自然可区分开
//局部变量,若为数组,则也是按照global储存的,link做成了private


GlobalVariable* gvar_int32_a = new GlobalVariable(/*Module=*/*mod, 
/*Type=*/IntegerType::get(mod->getContext(), 32),
/*isConstant=*/false,
/*Linkage=*/GlobalValue::ExternalLinkage,
/*Initializer=*/0, // has initializer, specified below
/*Name=*/"a");
gvar_int32_a->setAlignment(4);
ConstantInt* const_int32_10 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("0"), 10));
gvar_int32_a->setInitializer(const_int32_10);

GlobalVariable* gvar_int32_csta = new GlobalVariable(/*Module=*/*mod, 
/*Type=*/IntegerType::get(mod->getContext(), 32),
/*isConstant=*/true,
/*Linkage=*/GlobalValue::ExternalLinkage,
/*Initializer=*/0, // has initializer, specified below
/*Name=*/"csta");
gvar_int32_csta->setAlignment(4);
ConstantInt* const_int32_11 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("1"), 10));
gvar_int32_csta->setInitializer(const_int32_11);		//gvar_int32_csta是global var类型

GlobalVariable* gvar_array_astr = new GlobalVariable(/*Module=*/*mod, 
/*Type=*/ArrayTy_1,
/*isConstant=*/true,
/*Linkage=*/GlobalValue::ExternalLinkage,
/*Initializer=*/0, // has initializer, specified below
/*Name=*/"astr");
gvar_array_astr->setAlignment(4);
std::vector<Constant*> const_array_12_elems;
ConstantInt* const_int32_13 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("9"), 10));
const_array_12_elems.push_back(const_int32_13);
ConstantInt* const_int32_14 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("8"), 10));
const_array_12_elems.push_back(const_int32_14);
ConstantInt* const_int32_15 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("7"), 10));
const_array_12_elems.push_back(const_int32_15);
Constant* const_array_12 = ConstantArray::get(ArrayTy_1, const_array_12_elems);
gvar_array_astr->setInitializer(const_array_12);

GlobalVariable* gvar_array_alot = new GlobalVariable(/*Module=*/*mod, 
/*Type=*/ArrayTy_1,
/*isConstant=*/true,
/*Linkage=*/GlobalValue::ExternalLinkage,
/*Initializer=*/0, // has initializer, specified below
/*Name=*/"alot");
gvar_array_alot->setAlignment(4);
std::vector<Constant*> const_array_16_elems;
ConstantInt* const_int32_17 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("6"), 10));
const_array_16_elems.push_back(const_int32_17);
ConstantInt* const_int32_18 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("5"), 10));
const_array_16_elems.push_back(const_int32_18);
ConstantInt* const_int32_19 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("4"), 10));
const_array_16_elems.push_back(const_int32_19);
Constant* const_array_16 = ConstantArray::get(ArrayTy_1, const_array_16_elems);
gvar_array_alot->setInitializer(const_array_16);

GlobalVariable* gvar_array_antest_sthrl = new GlobalVariable(/*Module=*/*mod, 
/*Type=*/ArrayTy_1,
/*isConstant=*/true,
/*Linkage=*/GlobalValue::PrivateLinkage,
/*Initializer=*/0, // has initializer, specified below
/*Name=*/"antest.sthrl");
gvar_array_antest_sthrl->setAlignment(4);

GlobalVariable* gvar_array_antest_hehe = new GlobalVariable(/*Module=*/*mod, 
/*Type=*/ArrayTy_3,
/*isConstant=*/true,
/*Linkage=*/GlobalValue::PrivateLinkage,
/*Initializer=*/0, // has initializer, specified below
/*Name=*/"antest.hehe");
gvar_array_antest_hehe->setAlignment(4);

GlobalVariable* gvar_int32_xka = new GlobalVariable(/*Module=*/*mod, 
/*Type=*/IntegerType::get(mod->getContext(), 32),
/*isConstant=*/false,
/*Linkage=*/GlobalValue::CommonLinkage,
/*Initializer=*/0, // has initializer, specified below
/*Name=*/"xka");
gvar_int32_xka->setAlignment(4);
gvar_int32_xka->setInitializer(const_int32_10);
// Constant Definitions			为了之后的赋值

std::vector<Constant*> const_array_20_elems;
ConstantInt* const_int32_21 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("3"), 10));
const_array_20_elems.push_back(const_int32_21);
ConstantInt* const_int32_22 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("11"), 10));
const_array_20_elems.push_back(const_int32_22);
ConstantInt* const_int32_23 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("22"), 10));
const_array_20_elems.push_back(const_int32_23);
Constant* const_array_20 = ConstantArray::get(ArrayTy_1, const_array_20_elems);
std::vector<Constant*> const_array_24_elems;
ConstantInt* const_int32_25 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("-1"), 10));
const_array_24_elems.push_back(const_int32_25);
ConstantInt* const_int32_26 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("-2"), 10));
const_array_24_elems.push_back(const_int32_26);
Constant* const_array_24 = ConstantArray::get(ArrayTy_3, const_array_24_elems);
ConstantInt* const_int32_27 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("123"), 10));
ConstantInt* const_int32_28 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("234"), 10));
ConstantInt* const_int32_29 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("456"), 10));
ConstantInt* const_int32_30 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("567"), 10));
Constant* const_ptr_31 = ConstantExpr::getCast(Instruction::BitCast, gvar_array_antest_sthrl, PointerTy_6);
ConstantInt* const_int64_32 = ConstantInt::get(mod->getContext(), APInt(64, StringRef("12"), 10));
ConstantInt* const_int1_33 = ConstantInt::get(mod->getContext(), APInt(1, StringRef("0"), 10));
Constant* const_ptr_34 = ConstantExpr::getCast(Instruction::BitCast, gvar_array_antest_hehe, PointerTy_6);
ConstantInt* const_int64_35 = ConstantInt::get(mod->getContext(), APInt(64, StringRef("8"), 10));
ConstantInt* const_int32_36 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("21"), 10));

// Global Variable Definitions

gvar_array_antest_sthrl->setInitializer(const_array_20);  //alot sthrl astr都是用的ArrayTy_1,规定了数组大小
gvar_array_antest_hehe->setInitializer(const_array_24);


// Function Definitions

// Function: antest (func_antest)
{
 
 BasicBlock* label_37 = BasicBlock::Create(mod->getContext(), "",func_antest,0);
 
 // Block  (label_37)
 AllocaInst* ptr_abc = new AllocaInst(IntegerType::get(mod->getContext(), 32), "abc", label_37);
 ptr_abc->setAlignment(4);
 AllocaInst* ptr_abc1 = new AllocaInst(IntegerType::get(mod->getContext(), 32), "abc1", label_37);
 ptr_abc1->setAlignment(4);
 AllocaInst* ptr_abc2 = new AllocaInst(IntegerType::get(mod->getContext(), 32), "abc2", label_37);
 ptr_abc2->setAlignment(4);
 AllocaInst* ptr_antab = new AllocaInst(IntegerType::get(mod->getContext(), 32), "antab", label_37);
 ptr_antab->setAlignment(4);
 AllocaInst* ptr_antab3 = new AllocaInst(IntegerType::get(mod->getContext(), 32), "antab3", label_37);
 ptr_antab3->setAlignment(4);
 AllocaInst* ptr_antab4 = new AllocaInst(IntegerType::get(mod->getContext(), 32), "antab4", label_37);
 ptr_antab4->setAlignment(4);
 AllocaInst* ptr_asgnah = new AllocaInst(ArrayTy_1, "asgnah", label_37);
 ptr_asgnah->setAlignment(4);
 AllocaInst* ptr_sthrl = new AllocaInst(ArrayTy_1, "sthrl", label_37);
 ptr_sthrl->setAlignment(4);
 AllocaInst* ptr_hehe = new AllocaInst(ArrayTy_3, "hehe", label_37);
 ptr_hehe->setAlignment(4);
 StoreInst* void_38 = new StoreInst(const_int32_27, ptr_abc, false, label_37);
 void_38->setAlignment(4);
 StoreInst* void_39 = new StoreInst(const_int32_28, ptr_abc1, false, label_37);
 void_39->setAlignment(4);
 StoreInst* void_40 = new StoreInst(const_int32_29, ptr_antab, false, label_37);
 void_40->setAlignment(4);
 StoreInst* void_41 = new StoreInst(const_int32_30, ptr_antab4, false, label_37);
 void_41->setAlignment(4);
 CastInst* ptr_42 = new BitCastInst(ptr_sthrl, PointerTy_6, "", label_37);
//ptr_sthrl是AllocaInst*,是在label37这个block中申到的存储空间地址,
 std::vector<Value*> void_43_params;
 void_43_params.push_back(ptr_42);
 void_43_params.push_back(const_ptr_31);
 void_43_params.push_back(const_int64_32);
 void_43_params.push_back(const_int32_19);
 void_43_params.push_back(const_int1_33);
 CallInst* void_43 = CallInst::Create(func_llvm_memcpy_p0i8_p0i8_i64, void_43_params, "", label_37);
 void_43->setCallingConv(CallingConv::C);
 void_43->setTailCall(false);
 AttributeSet void_43_PAL;
 void_43->setAttributes(void_43_PAL);
 
 CastInst* ptr_44 = new BitCastInst(ptr_hehe, PointerTy_6, "", label_37);
 std::vector<Value*> void_45_params;
 void_45_params.push_back(ptr_44);
 void_45_params.push_back(const_ptr_34);
 void_45_params.push_back(const_int64_35);
 void_45_params.push_back(const_int32_19);		//6,5,4的4
 void_45_params.push_back(const_int1_33);
 CallInst* void_45 = CallInst::Create(func_llvm_memcpy_p0i8_p0i8_i64, void_45_params, "", label_37);
 void_45->setCallingConv(CallingConv::C);
 void_45->setTailCall(false);//尾调用,因为C1暂时不支持返回,暂时无用
 AttributeSet void_45_PAL;
 void_45->setAttributes(void_45_PAL);
 
 ReturnInst::Create(mod->getContext(), label_37);
 
}

// Function: testf (func_testf)
{
 
 BasicBlock* label_47 = BasicBlock::Create(mod->getContext(), "",func_testf,0);
 
 // Block  (label_47)
 AllocaInst* ptr_acb = new AllocaInst(IntegerType::get(mod->getContext(), 32), "acb", label_47);
 ptr_acb->setAlignment(4);
 CallInst* void_48 = CallInst::Create(func_antest, "", label_47);
 void_48->setCallingConv(CallingConv::C);
 void_48->setTailCall(false);
 AttributeSet void_48_PAL;
 void_48->setAttributes(void_48_PAL);
 
 LoadInst* int32_49 = new LoadInst(gvar_int32_a, "", false, label_47);
 int32_49->setAlignment(4);
 StoreInst* void_50 = new StoreInst(int32_49, ptr_acb, false, label_47);
 void_50->setAlignment(4);
 ReturnInst::Create(mod->getContext(), label_47);
 
}

// Function: main (func_main)
{
 
 BasicBlock* label_52 = BasicBlock::Create(mod->getContext(), "",func_main,0);
 
 // Block  (label_52)
 AllocaInst* ptr_a = new AllocaInst(IntegerType::get(mod->getContext(), 32), "a", label_52);
 ptr_a->setAlignment(4);
 StoreInst* void_53 = new StoreInst(const_int32_36, ptr_a, false, label_52);
 void_53->setAlignment(4);
 CallInst* void_54 = CallInst::Create(func_testf, "", label_52);
 void_54->setCallingConv(CallingConv::C);
 void_54->setTailCall(false);
 AttributeSet void_54_PAL;
 void_54->setAttributes(void_54_PAL);
 
 ReturnInst::Create(mod->getContext(), label_52);
 
}

return mod;
}
예제 #23
0
Value *ABICallSignature::emitCall(GenIR &Reader, Value *Target, bool MayThrow,
                                  ArrayRef<Value *> Args,
                                  Value *IndirectionCell, bool IsJmp,
                                  Value **CallNode) const {
  assert(isa<llvm::Function>(Target) ||
         Target->getType()->isIntegerTy(Reader.TargetPointerSizeInBits));

  LLVMContext &Context = *Reader.JitContext->LLVMContext;

  // Compute the function type
  bool HasIndirectResult = Result.getKind() == ABIArgInfo::Indirect;
  bool HasIndirectionCell = IndirectionCell != nullptr;
  bool IsUnmanagedCall =
      Signature.getCallingConvention() != CORINFO_CALLCONV_DEFAULT;
  bool CallerHasSecretParameter = Reader.MethodSignature.hasSecretParameter();
  bool IsJmpWithSecretParam = IsJmp && CallerHasSecretParameter;
  assert(((HasIndirectionCell ? 1 : 0) + (IsUnmanagedCall ? 1 : 0) +
          (IsJmpWithSecretParam ? 1 : 0)) <= 1);

  uint32_t NumSpecialArgs = 0;
  if (HasIndirectionCell || IsJmpWithSecretParam) {
    NumSpecialArgs = 1;
  }

  uint32_t NumExtraArgs = (HasIndirectResult ? 1 : 0) + NumSpecialArgs;
  const uint32_t NumArgs = getNumABIArgs() + NumExtraArgs;
  Value *ResultNode = nullptr;
  SmallVector<Type *, 16> ArgumentTypes(NumArgs);
  SmallVector<Value *, 16> Arguments(NumArgs);
  SmallVector<AttributeSet, 16> Attrs(NumArgs + 1);
  IRBuilder<> &Builder = *Reader.LLVMBuilder;

  // Check for calls with special args.
  //
  // Any special arguments are passed immediately preceeding the normal
  // arguments. The backend will place these arguments in the appropriate
  // registers according to the calling convention. Each special argument should
  // be machine-word-sized.
  if (HasIndirectionCell) {
    assert(IndirectionCell->getType()->isIntegerTy(
        Reader.TargetPointerSizeInBits));
    ArgumentTypes[0] = IndirectionCell->getType();
    Arguments[0] = IndirectionCell;
  } else if (IsJmpWithSecretParam) {
    Arguments[0] = Reader.secretParam();
    ArgumentTypes[0] = Arguments[0]->getType();
  }

  int32_t ResultIndex = -1;
  if (HasIndirectResult) {
    ResultIndex = (int32_t)NumSpecialArgs + (Signature.hasThis() ? 1 : 0);
    Type *ResultTy = Result.getType();
    // Jmp target signature has to match the caller's signature. Since we type
    // the caller's indirect result parameters as managed pointers, jmp target's
    // indirect result parameters also have to be typed as managed pointers.
    ArgumentTypes[ResultIndex] = IsJmp
                                     ? Reader.getManagedPointerType(ResultTy)
                                     : Reader.getUnmanagedPointerType(ResultTy);
    if (IsJmp) {
      // When processing jmp, pass the pointer that we got from the caller
      // rather than a pointer to a copy in the current frame.
      Arguments[ResultIndex] = ResultNode = Reader.IndirectResult;
    } else {
      Arguments[ResultIndex] = ResultNode = Reader.createTemporary(ResultTy);
    }
    if (ResultTy->isStructTy()) {
      Reader.setValueRepresentsStruct(ResultNode);
    }
  } else {
    AttrBuilder RetAttrs;

    if (Result.getKind() == ABIArgInfo::ZeroExtend) {
      RetAttrs.addAttribute(Attribute::ZExt);
    } else if (Result.getKind() == ABIArgInfo::SignExtend) {
      RetAttrs.addAttribute(Attribute::SExt);
    }

    if (RetAttrs.hasAttributes()) {
      Attrs.push_back(
          AttributeSet::get(Context, AttributeSet::ReturnIndex, RetAttrs));
    }
  }

  uint32_t I = NumSpecialArgs, J = 0;
  for (auto Arg : Args) {
    AttrBuilder ArgAttrs;

    if (ResultIndex >= 0 && I == (uint32_t)ResultIndex) {
      I++;
    }

    const ABIArgInfo &ArgInfo = this->Args[J];
    Type *ArgType = Arg->getType();

    switch (ArgInfo.getKind()) {
    case ABIArgInfo::Indirect:
      if (IsJmp) {
        // When processing jmp pass the pointer that we got from the caller
        // rather than a pointer to a copy in the current frame.
        Arguments[I] = Arg;
        ArgumentTypes[I] = ArgType;
      } else {
        Value *Temp = nullptr;
        if (Reader.doesValueRepresentStruct(Arg)) {
          StructType *ArgStructTy =
              cast<StructType>(ArgType->getPointerElementType());
          ArgumentTypes[I] = ArgType;
          Temp = Reader.createTemporary(ArgStructTy);
          const bool IsVolatile = false;
          Reader.copyStructNoBarrier(ArgStructTy, Temp, Arg, IsVolatile);
        } else {
          ArgumentTypes[I] = ArgType->getPointerTo();
          Temp = Reader.createTemporary(ArgType);
          Builder.CreateStore(Arg, Temp);
        }
        Arguments[I] = Temp;
      }
      break;

    case ABIArgInfo::Expand: {
      const bool IsResult = false;
      ArrayRef<ABIArgInfo::Expansion> Expansions = ArgInfo.getExpansions();
      MutableArrayRef<Value *> Values =
          MutableArrayRef<Value *>(Arguments).slice(I, Expansions.size());
      MutableArrayRef<Type *> Types =
          MutableArrayRef<Type *>(ArgumentTypes).slice(I, Expansions.size());
      expand(Reader, ArgInfo.getExpansions(), Arg, Values, Types, IsResult);
      I += Expansions.size() - 1;
      break;
    }

    case ABIArgInfo::ZeroExtend:
      ArgAttrs.addAttribute(Attribute::ZExt);
      goto direct;

    case ABIArgInfo::SignExtend:
      ArgAttrs.addAttribute(Attribute::SExt);
      goto direct;

    case ABIArgInfo::Direct: {
    direct:
      Type *ArgTy = ArgInfo.getType();
      Arg = coerce(Reader, ArgTy, Arg);

      if (ArgTy->isStructTy()) {
        assert(Arg->getType()->isPointerTy());
        assert(Arg->getType()->getPointerElementType() == ArgTy);

        ArgTy = ArgTy->getPointerTo();
        ArgAttrs.addAttribute(Attribute::ByVal);
      } else if (ArgTy->isVectorTy()) {
        assert(Arg->getType() == ArgTy);

        Value *Temp = Reader.createTemporary(ArgTy);
        Builder.CreateStore(Arg, Temp);
        Arg = Temp;

        ArgTy = ArgTy->getPointerTo();
        ArgAttrs.addAttribute(Attribute::ByVal);
      }

      ArgumentTypes[I] = ArgTy;
      Arguments[I] = Arg;

      if (ArgAttrs.hasAttributes()) {
        const unsigned Idx = I + 1; // Add one to accomodate the return attrs.
        Attrs.push_back(AttributeSet::get(Context, Idx, ArgAttrs));
      }
    }
    }

    I++, J++;
  }

  const bool IsVarArg = false;
  Type *FunctionTy = FunctionType::get(FuncResultType, ArgumentTypes, IsVarArg);
  Type *FunctionPtrTy = Reader.getUnmanagedPointerType(FunctionTy);

  // If we're passed a function value, we might need to update the type here
  // to match, since we didn't know the right type when we created the function.
  if (isa<llvm::Function>(Target)) {
    llvm::Function *TargetFunc = cast<llvm::Function>(Target);
    if (TargetFunc->getType() != FunctionPtrTy) {
      bool MutateType = false;
      // If we're going to Jmp to the target, don't mutate the type,
      // since we may have added parameters to satisfy the constraints
      // of LLVM's musttail that would cause this signature to diverge
      // from what we'd have come up with in a normal call to the target.
      if (!IsJmp) {
        // We shouldn't change our view of function types multiple times,
        // so only modify the type if it's the placeholder type we installed
        // in makeDirectCallTargetNode.
        Type *VoidType = Type::getVoidTy(Context);
        PointerType *PlaceholderTy =
            FunctionType::get(VoidType, false)->getPointerTo();
        MutateType = TargetFunc->getType() == PlaceholderTy;
      }

      if (MutateType) {
        // Update the type now that we know the full set of normal
        // and special arguments.
        TargetFunc->mutateType(FunctionPtrTy);
      } else {
        // Cast to the type we need for this call
        Target = Builder.CreatePointerCast(Target, FunctionPtrTy);
      }
    }
  } else {
    Target = Builder.CreateIntToPtr(Target, FunctionPtrTy);
  }

  // The most straightforward way to satisfy the constraints imposed by the GC
  // on threads that are executing unmanaged code is to make the transition to
  // and from unmanaged code immediately preceeding and following the machine
  // call instruction, respectively. Unfortunately, there is no way to express
  // this in "standard" LLVM IR, hence the intrinsic. This intrinsic is also
  // a special GC statepoint that forces any GC pointers in callee-saved
  // registers to be spilled to the stack.
  CallSite Call;
  if (IsUnmanagedCall) {
    Call = emitUnmanagedCall(Reader, Target, MayThrow, Arguments);
  } else {
    Call = Reader.makeCall(Target, MayThrow, Arguments);
  }

  CallingConv::ID CC;
  if (HasIndirectionCell) {
    assert(Signature.getCallingConvention() == CORINFO_CALLCONV_DEFAULT);
    CC = CallingConv::CLR_VirtualDispatchStub;
  } else if (IsJmpWithSecretParam) {
    assert(Signature.getCallingConvention() == CORINFO_CALLCONV_DEFAULT);
    CC = CallingConv::CLR_SecretParameter;
  } else {
    bool Unused;
    CC = getLLVMCallingConv(getNormalizedCallingConvention(Signature), Unused);
  }
  Call.setCallingConv(CC);

  if (Attrs.size() > 0) {
    Call.setAttributes(AttributeSet::get(Context, Attrs));
  }

  Value *TheCallInst = Call.getInstruction();
  if (HasIndirectResult) {
    assert(ResultNode != nullptr);
    if (!Reader.doesValueRepresentStruct(ResultNode)) {
      ResultNode = Builder.CreateLoad(ResultNode);
    }
  } else {
    assert(ResultNode == nullptr);

    const CallArgType &SigResultType = Signature.getResultType();
    Type *Ty = Reader.getType(SigResultType.CorType, SigResultType.Class);

    Value *CallResult = TheCallInst;

    if (!Ty->isVoidTy()) {
      if (Result.getKind() == ABIArgInfo::Expand) {
        assert(FuncResultType->isStructTy());
        ResultNode = Reader.createTemporary(Ty, "CallResult");
        Reader.setValueRepresentsStruct(ResultNode);

        Type *BytePtrTy = Type::getInt8PtrTy(Context, 0);
        Value *DestPtr = Builder.CreatePointerCast(ResultNode, BytePtrTy);

        assert(Result.getExpansions().size() ==
               FuncResultType->getStructNumElements());

        ArrayRef<ABIArgInfo::Expansion> Expansions = Result.getExpansions();
        int32_t expansionCount = Expansions.size();
        for (int32_t I = 0; I < expansionCount; I++) {
          Value *StoreVal = Builder.CreateExtractValue(CallResult, I);
          collapse(Reader, Expansions[I], StoreVal, DestPtr);
        }
      } else {
        ResultNode = coerce(Reader, Ty, CallResult);
      }
    } else {
      ResultNode = TheCallInst;
    }
  }

  *CallNode = TheCallInst;

  if (IsJmp) {
    cast<CallInst>(TheCallInst)
        ->setTailCallKind(CallInst::TailCallKind::TCK_MustTail);
  }

  return ResultNode;
}
예제 #24
0
Function *ABIMethodSignature::createFunction(GenIR &Reader, Module &M) {
  // Compute the function type
  LLVMContext &Context = M.getContext();
  bool HasIndirectResult = Result.getKind() == ABIArgInfo::Indirect;
  uint32_t NumExtraArgs = HasIndirectResult ? 1 : 0;
  const uint32_t NumArgs = getNumABIArgs() + NumExtraArgs;
  int32_t ResultIndex = -1;
  SmallVector<Type *, 16> ArgumentTypes(NumArgs);
  SmallVector<AttributeSet, 16> Attrs(NumArgs + 1);

  if (HasIndirectResult) {
    ResultIndex = Signature->hasThis() ? 1 : 0;
    Result.setIndex((uint32_t)ResultIndex);
    ArgumentTypes[ResultIndex] = Reader.getManagedPointerType(Result.getType());
  } else {
    AttrBuilder RetAttrs;

    if (Result.getKind() == ABIArgInfo::ZeroExtend) {
      RetAttrs.addAttribute(Attribute::ZExt);
    } else if (Result.getKind() == ABIArgInfo::SignExtend) {
      RetAttrs.addAttribute(Attribute::SExt);
    }

    if (RetAttrs.hasAttributes()) {
      Attrs.push_back(
          AttributeSet::get(Context, AttributeSet::ReturnIndex, RetAttrs));
    }
  }

  uint32_t I = 0;
  for (auto &Arg : Args) {
    AttrBuilder ArgAttrs;

    if (ResultIndex >= 0 && I == (uint32_t)ResultIndex) {
      I++;
    }

    switch (Arg.getKind()) {
    case ABIArgInfo::Indirect:
      ArgumentTypes[I] = Reader.getManagedPointerType(Arg.getType());
      break;

    case ABIArgInfo::Expand:
      for (const ABIArgInfo::Expansion &Exp : Arg.getExpansions()) {
        ArgumentTypes[I++] = Exp.TheType;
      }
      I--;
      break;

    case ABIArgInfo::ZeroExtend:
      ArgAttrs.addAttribute(Attribute::ZExt);
      goto direct;

    case ABIArgInfo::SignExtend:
      ArgAttrs.addAttribute(Attribute::SExt);
      goto direct;

    case ABIArgInfo::Direct: {
    direct:
      Type *ArgTy = Arg.getType();
      if (ArgTy->isStructTy()) {
        ArgTy = ArgTy->getPointerTo();
        ArgAttrs.addAttribute(Attribute::ByVal);
      }

      ArgumentTypes[I] = ArgTy;
      if (ArgAttrs.hasAttributes()) {
        const unsigned Idx = I + 1; // Add one to accomodate the return attrs.
        Attrs.push_back(AttributeSet::get(Context, Idx, ArgAttrs));
      }
    }
    }
    Arg.setIndex(I);

    I++;
  }

  const bool IsVarArg = false;
  FunctionType *FunctionTy =
      FunctionType::get(FuncResultType, ArgumentTypes, IsVarArg);
  Function *F = Function::Create(FunctionTy, Function::ExternalLinkage,
                                 M.getModuleIdentifier(), &M);

  // Use "param" for these initial parameter values. Numbering here
  // is strictly positional (hence includes implicit parameters).
  uint32_t N = 0;
  for (Function::arg_iterator Args = F->arg_begin(); Args != F->arg_end();
       Args++) {
    Args->setName(Twine("param") + Twine(N++));
  }

  CallingConv::ID CC = Signature->hasSecretParameter()
                           ? CallingConv::CLR_SecretParameter
                           : CallingConv::C;
  F->setCallingConv(CC);

  if (Attrs.size() > 0) {
    F->setAttributes(AttributeSet::get(Context, Attrs));
  }

  F->setGC("coreclr");

  return F;
}
예제 #25
0
/// Deduce nocapture attributes for the SCC.
static bool addArgumentAttrs(const SCCNodeSet &SCCNodes) {
    bool Changed = false;

    ArgumentGraph AG;

    AttrBuilder B;
    B.addAttribute(Attribute::NoCapture);

    // Check each function in turn, determining which pointer arguments are not
    // captured.
    for (Function *F : SCCNodes) {
        // Definitions with weak linkage may be overridden at linktime with
        // something that captures pointers, so treat them like declarations.
        if (F->isDeclaration() || F->mayBeOverridden())
            continue;

        // Functions that are readonly (or readnone) and nounwind and don't return
        // a value can't capture arguments. Don't analyze them.
        if (F->onlyReadsMemory() && F->doesNotThrow() &&
                F->getReturnType()->isVoidTy()) {
            for (Function::arg_iterator A = F->arg_begin(), E = F->arg_end(); A != E;
                    ++A) {
                if (A->getType()->isPointerTy() && !A->hasNoCaptureAttr()) {
                    A->addAttr(AttributeSet::get(F->getContext(), A->getArgNo() + 1, B));
                    ++NumNoCapture;
                    Changed = true;
                }
            }
            continue;
        }

        for (Function::arg_iterator A = F->arg_begin(), E = F->arg_end(); A != E;
                ++A) {
            if (!A->getType()->isPointerTy())
                continue;
            bool HasNonLocalUses = false;
            if (!A->hasNoCaptureAttr()) {
                ArgumentUsesTracker Tracker(SCCNodes);
                PointerMayBeCaptured(&*A, &Tracker);
                if (!Tracker.Captured) {
                    if (Tracker.Uses.empty()) {
                        // If it's trivially not captured, mark it nocapture now.
                        A->addAttr(
                            AttributeSet::get(F->getContext(), A->getArgNo() + 1, B));
                        ++NumNoCapture;
                        Changed = true;
                    } else {
                        // If it's not trivially captured and not trivially not captured,
                        // then it must be calling into another function in our SCC. Save
                        // its particulars for Argument-SCC analysis later.
                        ArgumentGraphNode *Node = AG[&*A];
                        for (SmallVectorImpl<Argument *>::iterator
                                UI = Tracker.Uses.begin(),
                                UE = Tracker.Uses.end();
                                UI != UE; ++UI) {
                            Node->Uses.push_back(AG[*UI]);
                            if (*UI != A)
                                HasNonLocalUses = true;
                        }
                    }
                }
                // Otherwise, it's captured. Don't bother doing SCC analysis on it.
            }
            if (!HasNonLocalUses && !A->onlyReadsMemory()) {
                // Can we determine that it's readonly/readnone without doing an SCC?
                // Note that we don't allow any calls at all here, or else our result
                // will be dependent on the iteration order through the functions in the
                // SCC.
                SmallPtrSet<Argument *, 8> Self;
                Self.insert(&*A);
                Attribute::AttrKind R = determinePointerReadAttrs(&*A, Self);
                if (R != Attribute::None) {
                    AttrBuilder B;
                    B.addAttribute(R);
                    A->addAttr(AttributeSet::get(A->getContext(), A->getArgNo() + 1, B));
                    Changed = true;
                    R == Attribute::ReadOnly ? ++NumReadOnlyArg : ++NumReadNoneArg;
                }
            }
        }
    }

    // The graph we've collected is partial because we stopped scanning for
    // argument uses once we solved the argument trivially. These partial nodes
    // show up as ArgumentGraphNode objects with an empty Uses list, and for
    // these nodes the final decision about whether they capture has already been
    // made.  If the definition doesn't have a 'nocapture' attribute by now, it
    // captures.

    for (scc_iterator<ArgumentGraph *> I = scc_begin(&AG); !I.isAtEnd(); ++I) {
        const std::vector<ArgumentGraphNode *> &ArgumentSCC = *I;
        if (ArgumentSCC.size() == 1) {
            if (!ArgumentSCC[0]->Definition)
                continue; // synthetic root node

            // eg. "void f(int* x) { if (...) f(x); }"
            if (ArgumentSCC[0]->Uses.size() == 1 &&
                    ArgumentSCC[0]->Uses[0] == ArgumentSCC[0]) {
                Argument *A = ArgumentSCC[0]->Definition;
                A->addAttr(AttributeSet::get(A->getContext(), A->getArgNo() + 1, B));
                ++NumNoCapture;
                Changed = true;
            }
            continue;
        }

        bool SCCCaptured = false;
        for (auto I = ArgumentSCC.begin(), E = ArgumentSCC.end();
                I != E && !SCCCaptured; ++I) {
            ArgumentGraphNode *Node = *I;
            if (Node->Uses.empty()) {
                if (!Node->Definition->hasNoCaptureAttr())
                    SCCCaptured = true;
            }
        }
        if (SCCCaptured)
            continue;

        SmallPtrSet<Argument *, 8> ArgumentSCCNodes;
        // Fill ArgumentSCCNodes with the elements of the ArgumentSCC.  Used for
        // quickly looking up whether a given Argument is in this ArgumentSCC.
        for (auto I = ArgumentSCC.begin(), E = ArgumentSCC.end(); I != E; ++I) {
            ArgumentSCCNodes.insert((*I)->Definition);
        }

        for (auto I = ArgumentSCC.begin(), E = ArgumentSCC.end();
                I != E && !SCCCaptured; ++I) {
            ArgumentGraphNode *N = *I;
            for (SmallVectorImpl<ArgumentGraphNode *>::iterator UI = N->Uses.begin(),
                    UE = N->Uses.end();
                    UI != UE; ++UI) {
                Argument *A = (*UI)->Definition;
                if (A->hasNoCaptureAttr() || ArgumentSCCNodes.count(A))
                    continue;
                SCCCaptured = true;
                break;
            }
        }
        if (SCCCaptured)
            continue;

        for (unsigned i = 0, e = ArgumentSCC.size(); i != e; ++i) {
            Argument *A = ArgumentSCC[i]->Definition;
            A->addAttr(AttributeSet::get(A->getContext(), A->getArgNo() + 1, B));
            ++NumNoCapture;
            Changed = true;
        }

        // We also want to compute readonly/readnone. With a small number of false
        // negatives, we can assume that any pointer which is captured isn't going
        // to be provably readonly or readnone, since by definition we can't
        // analyze all uses of a captured pointer.
        //
        // The false negatives happen when the pointer is captured by a function
        // that promises readonly/readnone behaviour on the pointer, then the
        // pointer's lifetime ends before anything that writes to arbitrary memory.
        // Also, a readonly/readnone pointer may be returned, but returning a
        // pointer is capturing it.

        Attribute::AttrKind ReadAttr = Attribute::ReadNone;
        for (unsigned i = 0, e = ArgumentSCC.size(); i != e; ++i) {
            Argument *A = ArgumentSCC[i]->Definition;
            Attribute::AttrKind K = determinePointerReadAttrs(A, ArgumentSCCNodes);
            if (K == Attribute::ReadNone)
                continue;
            if (K == Attribute::ReadOnly) {
                ReadAttr = Attribute::ReadOnly;
                continue;
            }
            ReadAttr = K;
            break;
        }

        if (ReadAttr != Attribute::None) {
            AttrBuilder B, R;
            B.addAttribute(ReadAttr);
            R.addAttribute(Attribute::ReadOnly).addAttribute(Attribute::ReadNone);
            for (unsigned i = 0, e = ArgumentSCC.size(); i != e; ++i) {
                Argument *A = ArgumentSCC[i]->Definition;
                // Clear out existing readonly/readnone attributes
                A->removeAttr(AttributeSet::get(A->getContext(), A->getArgNo() + 1, R));
                A->addAttr(AttributeSet::get(A->getContext(), A->getArgNo() + 1, B));
                ReadAttr == Attribute::ReadOnly ? ++NumReadOnlyArg : ++NumReadNoneArg;
                Changed = true;
            }
        }
    }

    return Changed;
}
예제 #26
0
Function *ABIMethodSignature::createFunction(GenIR &Reader, Module &M) {
  // Compute the function type
  LLVMContext &Context = M.getContext();
  bool HasIndirectResult = Result.getKind() == ABIArgInfo::Indirect;
  uint32_t NumExtraArgs = HasIndirectResult ? 1 : 0;
  const uint32_t NumArgs = Args.size() + NumExtraArgs;
  int32_t ResultIndex = -1;
  SmallVector<Type *, 16> ArgumentTypes(NumArgs);
  SmallVector<AttributeSet, 16> Attrs(NumArgs + 1);

  if (HasIndirectResult) {
    ResultIndex = Signature->hasThis() ? 1 : 0;
    Result.setIndex((uint32_t)ResultIndex);
    ArgumentTypes[ResultIndex] = Reader.getManagedPointerType(Result.getType());
  } else {
    AttrBuilder RetAttrs;

    if (Result.getKind() == ABIArgInfo::ZeroExtend) {
      RetAttrs.addAttribute(Attribute::ZExt);
    } else if (Result.getKind() == ABIArgInfo::SignExtend) {
      RetAttrs.addAttribute(Attribute::SExt);
    }

    if (RetAttrs.hasAttributes()) {
      Attrs.push_back(
          AttributeSet::get(Context, AttributeSet::ReturnIndex, RetAttrs));
    }
  }

  uint32_t I = 0;
  for (auto &Arg : Args) {
    AttrBuilder ArgAttrs;

    if (ResultIndex >= 0 && I == (uint32_t)ResultIndex) {
      I++;
    }

    if (Arg.getKind() == ABIArgInfo::Indirect) {
      // TODO: byval attribute support
      ArgumentTypes[I] = Reader.getManagedPointerType(Arg.getType());
    } else {
      ArgumentTypes[I] = Arg.getType();

      if (Arg.getKind() == ABIArgInfo::ZeroExtend) {
        ArgAttrs.addAttribute(Attribute::ZExt);
      } else if (Arg.getKind() == ABIArgInfo::SignExtend) {
        ArgAttrs.addAttribute(Attribute::SExt);
      }

      if (ArgAttrs.hasAttributes()) {
        const unsigned Idx = I + 1; // Add one to accomodate the return attrs.
        Attrs.push_back(AttributeSet::get(Context, Idx, ArgAttrs));
      }
    }
    Arg.setIndex(I);

    I++;
  }

  const bool IsVarArg = false;
  FunctionType *FunctionTy =
      FunctionType::get(FuncResultType, ArgumentTypes, IsVarArg);
  Function *F = Function::Create(FunctionTy, Function::ExternalLinkage,
                                 M.getModuleIdentifier(), &M);

  // Use "param" for these initial parameter values. Numbering here
  // is strictly positional (hence includes implicit parameters).
  uint32_t N = 0;
  for (Function::arg_iterator Args = F->arg_begin(); Args != F->arg_end();
       Args++) {
    Args->setName(Twine("param") + Twine(N++));
  }

  CallingConv::ID CC;
  if (Signature->hasSecretParameter()) {
    assert((--F->arg_end())->getType()->isIntegerTy());

    AttrBuilder SecretParamAttrs;
    SecretParamAttrs.addAttribute("CLR_SecretParameter");
    Attrs.push_back(
        AttributeSet::get(Context, F->arg_size(), SecretParamAttrs));

    CC = CallingConv::CLR_SecretParameter;
  } else {
    CC = CallingConv::C;
  }
  F->setCallingConv(CC);

  if (Attrs.size() > 0) {
    F->setAttributes(AttributeSet::get(Context, Attrs));
  }

  if (Reader.JitContext->Options->DoInsertStatepoints) {
    F->setGC("coreclr");
  }

  return F;
}
예제 #27
0
Value *ABICallSignature::emitCall(GenIR &Reader, Value *Target, bool MayThrow,
                                  ArrayRef<Value *> Args,
                                  Value *IndirectionCell,
                                  Value **CallNode) const {
  assert(Target->getType()->isIntegerTy(Reader.TargetPointerSizeInBits));

  LLVMContext &Context = *Reader.JitContext->LLVMContext;

  // Compute the function type
  bool HasIndirectResult = Result.getKind() == ABIArgInfo::Indirect;
  bool HasIndirectionCell = IndirectionCell != nullptr;
  bool IsUnmanagedCall =
      Signature.getCallingConvention() != CORINFO_CALLCONV_DEFAULT;
  assert(((HasIndirectionCell ? 1 : 0) + (IsUnmanagedCall ? 1 : 0)) <= 1);

  uint32_t NumSpecialArgs = 0;
  if (HasIndirectionCell) {
    NumSpecialArgs = 1;
  }

  uint32_t NumExtraArgs = (HasIndirectResult ? 1 : 0) + NumSpecialArgs;
  const uint32_t NumArgs = Args.size() + NumExtraArgs;
  Value *ResultNode = nullptr;
  SmallVector<Type *, 16> ArgumentTypes(NumArgs);
  SmallVector<Value *, 16> Arguments(NumArgs);
  SmallVector<AttributeSet, 16> Attrs(NumArgs + 1);
  IRBuilder<> &Builder = *Reader.LLVMBuilder;

  // Check for calls with special args.
  //
  // Any special arguments are passed immediately preceeding the normal
  // arguments. The backend will place these arguments in the appropriate
  // registers according to the calling convention. Each special argument should
  // be machine-word-sized.
  if (HasIndirectionCell) {
    assert(IndirectionCell->getType()->isIntegerTy(
        Reader.TargetPointerSizeInBits));
    ArgumentTypes[0] = IndirectionCell->getType();
    Arguments[0] = IndirectionCell;
  }

  int32_t ResultIndex = -1;
  if (HasIndirectResult) {
    ResultIndex = (int32_t)NumSpecialArgs + (Signature.hasThis() ? 1 : 0);
    Type *ResultTy = Result.getType();
    ArgumentTypes[ResultIndex] = Reader.getUnmanagedPointerType(ResultTy);
    Arguments[ResultIndex] = ResultNode = Reader.createTemporary(ResultTy);

    if (ResultTy->isStructTy()) {
      Reader.setValueRepresentsStruct(ResultNode);
    }
  } else {
    AttrBuilder RetAttrs;

    if (Result.getKind() == ABIArgInfo::ZeroExtend) {
      RetAttrs.addAttribute(Attribute::ZExt);
    } else if (Result.getKind() == ABIArgInfo::SignExtend) {
      RetAttrs.addAttribute(Attribute::SExt);
    }

    if (RetAttrs.hasAttributes()) {
      Attrs.push_back(
          AttributeSet::get(Context, AttributeSet::ReturnIndex, RetAttrs));
    }
  }

  uint32_t I = NumSpecialArgs, J = 0;
  for (auto Arg : Args) {
    AttrBuilder ArgAttrs;

    if (ResultIndex >= 0 && I == (uint32_t)ResultIndex) {
      I++;
    }

    const ABIArgInfo &ArgInfo = this->Args[J];
    Type *ArgType = Arg->getType();

    if (ArgInfo.getKind() == ABIArgInfo::Indirect) {
      // TODO: byval attribute support
      Value *Temp = nullptr;
      if (Reader.doesValueRepresentStruct(Arg)) {
        StructType *ArgStructTy =
            cast<StructType>(ArgType->getPointerElementType());
        ArgumentTypes[I] = ArgType;
        Temp = Reader.createTemporary(ArgStructTy);
        const bool IsVolatile = false;
        Reader.copyStruct(ArgStructTy, Temp, Arg, IsVolatile);
      } else {
        ArgumentTypes[I] = ArgType->getPointerTo();
        Temp = Reader.createTemporary(ArgType);
        Builder.CreateStore(Arg, Temp);
      }
      Arguments[I] = Temp;
    } else {
      ArgumentTypes[I] = ArgInfo.getType();
      Arguments[I] = coerce(Reader, ArgInfo.getType(), Arg);

      if (ArgInfo.getKind() == ABIArgInfo::ZeroExtend) {
        ArgAttrs.addAttribute(Attribute::ZExt);
      } else if (ArgInfo.getKind() == ABIArgInfo::SignExtend) {
        ArgAttrs.addAttribute(Attribute::SExt);
      }

      if (ArgAttrs.hasAttributes()) {
        const unsigned Idx = I + 1; // Add one to accomodate the return attrs.
        Attrs.push_back(AttributeSet::get(Context, Idx, ArgAttrs));
      }
    }

    I++, J++;
  }

  const bool IsVarArg = false;
  Type *FunctionTy = FunctionType::get(FuncResultType, ArgumentTypes, IsVarArg);
  Type *FunctionPtrTy = Reader.getUnmanagedPointerType(FunctionTy);

  Target = Builder.CreateIntToPtr(Target, FunctionPtrTy);

  // The most straightforward way to satisfy the constraints imposed by the GC
  // on threads that are executing unmanaged code is to make the transition to
  // and from unmanaged code immediately preceeding and following the machine
  // call instruction, respectively. Unfortunately, there is no way to express
  // this in "standard" LLVM IR, hence the intrinsic. This intrinsic is also
  // a special GC statepoint that forces any GC pointers in callee-saved
  // registers to be spilled to the stack.
  CallSite Call;
  Value *UnmanagedCallResult = nullptr;
  if (IsUnmanagedCall) {
    Call = emitUnmanagedCall(Reader, Target, MayThrow, Arguments,
                             UnmanagedCallResult);
  } else {
    Call = Reader.makeCall(Target, MayThrow, Arguments);
  }

  CallingConv::ID CC;
  if (HasIndirectionCell) {
    assert(Signature.getCallingConvention() == CORINFO_CALLCONV_DEFAULT);
    CC = CallingConv::CLR_VirtualDispatchStub;
  } else {
    bool Unused;
    CC = getLLVMCallingConv(getNormalizedCallingConvention(Signature), Unused);
  }
  Call.setCallingConv(CC);

  if (Attrs.size() > 0) {
    Call.setAttributes(AttributeSet::get(Context, Attrs));
  }

  if (ResultNode == nullptr) {
    assert(!HasIndirectResult);
    const CallArgType &SigResultType = Signature.getResultType();
    Type *Ty = Reader.getType(SigResultType.CorType, SigResultType.Class);
    if (!Ty->isVoidTy()) {
      ResultNode = coerce(Reader, Ty, IsUnmanagedCall ? UnmanagedCallResult
                                                      : Call.getInstruction());
    } else {
      ResultNode = Call.getInstruction();
    }
  } else {
    if (!Reader.doesValueRepresentStruct(ResultNode)) {
      ResultNode = Builder.CreateLoad(ResultNode);
    }
  }

  *CallNode = Call.getInstruction();
  return ResultNode;
}
예제 #28
0
bool PruneEH::runOnSCC(CallGraphSCC &SCC) {
  SmallPtrSet<CallGraphNode *, 8> SCCNodes;
  CallGraph &CG = getAnalysis<CallGraph>();
  bool MadeChange = false;

  // Fill SCCNodes with the elements of the SCC.  Used for quickly
  // looking up whether a given CallGraphNode is in this SCC.
  for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I)
    SCCNodes.insert(*I);

  // First pass, scan all of the functions in the SCC, simplifying them
  // according to what we know.
  for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I)
    if (Function *F = (*I)->getFunction())
      MadeChange |= SimplifyFunction(F);

  // Next, check to see if any callees might throw or if there are any external
  // functions in this SCC: if so, we cannot prune any functions in this SCC.
  // Definitions that are weak and not declared non-throwing might be 
  // overridden at linktime with something that throws, so assume that.
  // If this SCC includes the unwind instruction, we KNOW it throws, so
  // obviously the SCC might throw.
  //
  bool SCCMightUnwind = false, SCCMightReturn = false;
  for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); 
       (!SCCMightUnwind || !SCCMightReturn) && I != E; ++I) {
    Function *F = (*I)->getFunction();
    if (F == 0) {
      SCCMightUnwind = true;
      SCCMightReturn = true;
    } else if (F->isDeclaration() || F->mayBeOverridden()) {
      SCCMightUnwind |= !F->doesNotThrow();
      SCCMightReturn |= !F->doesNotReturn();
    } else {
      bool CheckUnwind = !SCCMightUnwind && !F->doesNotThrow();
      bool CheckReturn = !SCCMightReturn && !F->doesNotReturn();

      if (!CheckUnwind && !CheckReturn)
        continue;

      // Check to see if this function performs an unwind or calls an
      // unwinding function.
      for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
        if (CheckUnwind && isa<ResumeInst>(BB->getTerminator())) {
          // Uses unwind / resume!
          SCCMightUnwind = true;
        } else if (CheckReturn && isa<ReturnInst>(BB->getTerminator())) {
          SCCMightReturn = true;
        }

        // Invoke instructions don't allow unwinding to continue, so we are
        // only interested in call instructions.
        if (CheckUnwind && !SCCMightUnwind)
          for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I)
            if (CallInst *CI = dyn_cast<CallInst>(I)) {
              if (CI->doesNotThrow()) {
                // This call cannot throw.
              } else if (Function *Callee = CI->getCalledFunction()) {
                CallGraphNode *CalleeNode = CG[Callee];
                // If the callee is outside our current SCC then we may
                // throw because it might.
                if (!SCCNodes.count(CalleeNode)) {
                  SCCMightUnwind = true;
                  break;
                }
              } else {
                // Indirect call, it might throw.
                SCCMightUnwind = true;
                break;
              }
            }
        if (SCCMightUnwind && SCCMightReturn) break;
      }
    }
  }

  // If the SCC doesn't unwind or doesn't throw, note this fact.
  if (!SCCMightUnwind || !SCCMightReturn)
    for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) {
      AttrBuilder NewAttributes;

      if (!SCCMightUnwind)
        NewAttributes.addAttribute(Attributes::NoUnwind);
      if (!SCCMightReturn)
        NewAttributes.addAttribute(Attributes::NoReturn);

      Function *F = (*I)->getFunction();
      const AttributeSet &PAL = F->getAttributes();
      const AttributeSet &NPAL = PAL.addAttr(F->getContext(), ~0,
                                            Attributes::get(F->getContext(),
                                                            NewAttributes));
      if (PAL != NPAL) {
        MadeChange = true;
        F->setAttributes(NPAL);
      }
    }

  for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) {
    // Convert any invoke instructions to non-throwing functions in this node
    // into call instructions with a branch.  This makes the exception blocks
    // dead.
    if (Function *F = (*I)->getFunction())
      MadeChange |= SimplifyFunction(F);
  }

  return MadeChange;
}
예제 #29
0
파일: foo.ll.cpp 프로젝트: csMOOC/CSE231
Module* makeLLVMModule() {
 // Module Construction
 Module* mod = new Module("foo.ll", getGlobalContext());
 mod->setDataLayout("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128");
 mod->setTargetTriple("x86_64-unknown-linux-gnu");
 
 // Type Definitions
 ArrayType* ArrayTy_0 = ArrayType::get(IntegerType::get(mod->getContext(), 8), 5);
 
 PointerType* PointerTy_1 = PointerType::get(ArrayTy_0, 0);
 
 std::vector<Type*>FuncTy_2_args;
 PointerType* PointerTy_3 = PointerType::get(IntegerType::get(mod->getContext(), 8), 0);
 
 FuncTy_2_args.push_back(PointerTy_3);
 FuncTy_2_args.push_back(IntegerType::get(mod->getContext(), 32));
 FunctionType* FuncTy_2 = FunctionType::get(
  /*Result=*/Type::getVoidTy(mod->getContext()),
  /*Params=*/FuncTy_2_args,
  /*isVarArg=*/false);
 
 PointerType* PointerTy_4 = PointerType::get(PointerTy_3, 0);
 
 PointerType* PointerTy_5 = PointerType::get(IntegerType::get(mod->getContext(), 32), 0);
 
 std::vector<Type*>FuncTy_6_args;
 FunctionType* FuncTy_6 = FunctionType::get(
  /*Result=*/IntegerType::get(mod->getContext(), 32),
  /*Params=*/FuncTy_6_args,
  /*isVarArg=*/false);
 
 PointerType* PointerTy_7 = PointerType::get(FuncTy_2, 0);
 
 
 // Function Declarations
 
 Function* func_foo = mod->getFunction("foo");
 if (!func_foo) {
 func_foo = Function::Create(
  /*Type=*/FuncTy_2,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"foo", mod); 
 func_foo->setCallingConv(CallingConv::C);
 }
 AttributeSet func_foo_PAL;
 {
  SmallVector<AttributeSet, 4> Attrs;
  AttributeSet PAS;
   {
    AttrBuilder B;
    B.addAttribute(Attribute::NoUnwind);
    B.addAttribute(Attribute::UWTable);
    PAS = AttributeSet::get(mod->getContext(), ~0U, B);
   }
  
  Attrs.push_back(PAS);
  func_foo_PAL = AttributeSet::get(mod->getContext(), Attrs);
  
 }
 func_foo->setAttributes(func_foo_PAL);
 
 Function* func_main = mod->getFunction("main");
 if (!func_main) {
 func_main = Function::Create(
  /*Type=*/FuncTy_6,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"main", mod); 
 func_main->setCallingConv(CallingConv::C);
 }
 AttributeSet func_main_PAL;
 {
  SmallVector<AttributeSet, 4> Attrs;
  AttributeSet PAS;
   {
    AttrBuilder B;
    B.addAttribute(Attribute::NoUnwind);
    B.addAttribute(Attribute::UWTable);
    PAS = AttributeSet::get(mod->getContext(), ~0U, B);
   }
  
  Attrs.push_back(PAS);
  func_main_PAL = AttributeSet::get(mod->getContext(), Attrs);
  
 }
 func_main->setAttributes(func_main_PAL);
 
 // Global Variable Declarations

 
 GlobalVariable* gvar_array__str = new GlobalVariable(/*Module=*/*mod, 
 /*Type=*/ArrayTy_0,
 /*isConstant=*/true,
 /*Linkage=*/GlobalValue::PrivateLinkage,
 /*Initializer=*/0, // has initializer, specified below
 /*Name=*/".str");
 gvar_array__str->setAlignment(1);
 
 // Constant Definitions
 Constant *const_array_8 = ConstantDataArray::getString(mod->getContext(), "gogo", true);
 ConstantInt* const_int32_9 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("1"), 10));
 std::vector<Constant*> const_ptr_10_indices;
 ConstantInt* const_int32_11 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("0"), 10));
 const_ptr_10_indices.push_back(const_int32_11);
 const_ptr_10_indices.push_back(const_int32_11);
 Constant* const_ptr_10 = ConstantExpr::getGetElementPtr(gvar_array__str, const_ptr_10_indices);
 ConstantInt* const_int32_12 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("3"), 10));
 
 // Global Variable Definitions
 gvar_array__str->setInitializer(const_array_8);
 
 // Function Definitions
 
 // Function: foo (func_foo)
 {
  Function::arg_iterator args = func_foo->arg_begin();
  Value* ptr_name = args++;
  ptr_name->setName("name");
  Value* int32_count = args++;
  int32_count->setName("count");
  
  BasicBlock* label_entry = BasicBlock::Create(mod->getContext(), "entry",func_foo,0);
  
  // Block entry (label_entry)
  AllocaInst* ptr_name_addr = new AllocaInst(PointerTy_3, "name.addr", label_entry);
  ptr_name_addr->setAlignment(8);
  AllocaInst* ptr_count_addr = new AllocaInst(IntegerType::get(mod->getContext(), 32), "count.addr", label_entry);
  ptr_count_addr->setAlignment(4);
  StoreInst* void_13 = new StoreInst(ptr_name, ptr_name_addr, false, label_entry);
  void_13->setAlignment(8);
  StoreInst* void_14 = new StoreInst(int32_count, ptr_count_addr, false, label_entry);
  void_14->setAlignment(4);
  ReturnInst::Create(mod->getContext(), label_entry);
  
 }
 
 // Function: main (func_main)
 {
  
  BasicBlock* label_entry_16 = BasicBlock::Create(mod->getContext(), "entry",func_main,0);
  
  // Block entry (label_entry_16)
  AllocaInst* ptr_myarg1 = new AllocaInst(PointerTy_3, "myarg1", label_entry_16);
  ptr_myarg1->setAlignment(8);
  AllocaInst* ptr_myarg2 = new AllocaInst(IntegerType::get(mod->getContext(), 32), "myarg2", label_entry_16);
  ptr_myarg2->setAlignment(4);
  StoreInst* void_17 = new StoreInst(const_ptr_10, ptr_myarg1, false, label_entry_16);
  void_17->setAlignment(8);
  StoreInst* void_18 = new StoreInst(const_int32_12, ptr_myarg2, false, label_entry_16);
  void_18->setAlignment(4);
  LoadInst* ptr_19 = new LoadInst(ptr_myarg1, "", false, label_entry_16);
  ptr_19->setAlignment(8);
  LoadInst* int32_20 = new LoadInst(ptr_myarg2, "", false, label_entry_16);
  int32_20->setAlignment(4);
  std::vector<Value*> void_21_params;
  void_21_params.push_back(ptr_19);
  void_21_params.push_back(int32_20);
  CallInst* void_21 = CallInst::Create(func_foo, void_21_params, "", label_entry_16);
  void_21->setCallingConv(CallingConv::C);
  void_21->setTailCall(false);
  AttributeSet void_21_PAL;
  void_21->setAttributes(void_21_PAL);
  
  ReturnInst::Create(mod->getContext(), const_int32_11, label_entry_16);
  
 }
 
 return mod;
}
예제 #30
0
static void addExplicitArguments(std::vector<LLValue *> &args, AttrSet &attrs,
                                 IrFuncTy &irFty, LLFunctionType *callableTy,
                                 const std::vector<DValue *> &argvals,
                                 int numFormalParams) {
  // Number of arguments added to the LLVM type that are implicit on the
  // frontend side of things (this, context pointers, etc.)
  const size_t implicitLLArgCount = args.size();

  // Number of formal arguments in the LLVM type (i.e. excluding varargs).
  const size_t formalLLArgCount = irFty.args.size();

  // The number of explicit arguments in the D call expression (including
  // varargs), not all of which necessarily generate a LLVM argument.
  const size_t explicitDArgCount = argvals.size();

  // construct and initialize an IrFuncTyArg object for each vararg
  std::vector<IrFuncTyArg *> optionalIrArgs;
  for (size_t i = numFormalParams; i < explicitDArgCount; i++) {
    Type *argType = argvals[i]->getType();
    bool passByVal = gABI->passByVal(argType);

    AttrBuilder initialAttrs;
    if (passByVal) {
      initialAttrs.add(LLAttribute::ByVal);
    } else {
      initialAttrs.add(DtoShouldExtend(argType));
    }

    optionalIrArgs.push_back(new IrFuncTyArg(argType, passByVal, initialAttrs));
    optionalIrArgs.back()->parametersIdx = i;
  }

  // let the ABI rewrite the IrFuncTyArg objects
  gABI->rewriteVarargs(irFty, optionalIrArgs);

  const size_t explicitLLArgCount = formalLLArgCount + optionalIrArgs.size();
  args.resize(implicitLLArgCount + explicitLLArgCount,
              static_cast<llvm::Value *>(nullptr));

  // Iterate the explicit arguments from left to right in the D source,
  // which is the reverse of the LLVM order if irFty.reverseParams is true.
  for (size_t i = 0; i < explicitLLArgCount; ++i) {
    const bool isVararg = (i >= irFty.args.size());
    IrFuncTyArg *irArg = nullptr;
    if (isVararg) {
      irArg = optionalIrArgs[i - numFormalParams];
    } else {
      irArg = irFty.args[i];
    }

    DValue *const argval = argvals[irArg->parametersIdx];
    Type *const argType = argval->getType();

    llvm::Value *llVal = nullptr;
    if (isVararg) {
      llVal = irFty.putParam(*irArg, argval);
    } else {
      llVal = irFty.putParam(i, argval);
    }

    const size_t llArgIdx =
        implicitLLArgCount +
        (irFty.reverseParams ? explicitLLArgCount - i - 1 : i);
    llvm::Type *const callableArgType =
        (isVararg ? nullptr : callableTy->getParamType(llArgIdx));

    // Hack around LDC assuming structs and static arrays are in memory:
    // If the function wants a struct, and the argument value is a
    // pointer to a struct, load from it before passing it in.
    if (isaPointer(llVal) && DtoIsPassedByRef(argType) &&
        ((!isVararg && !isaPointer(callableArgType)) ||
         (isVararg && !irArg->byref && !irArg->isByVal()))) {
      Logger::println("Loading struct type for function argument");
      llVal = DtoLoad(llVal);
    }

    // parameter type mismatch, this is hard to get rid of
    if (!isVararg && llVal->getType() != callableArgType) {
      IF_LOG {
        Logger::cout() << "arg:     " << *llVal << '\n';
        Logger::cout() << "expects: " << *callableArgType << '\n';
      }
      if (isaStruct(llVal)) {
        llVal = DtoAggrPaint(llVal, callableArgType);
      } else {
        llVal = DtoBitCast(llVal, callableArgType);
      }
    }

    args[llArgIdx] = llVal;
    // +1 as index 0 contains the function attributes.
    attrs.add(llArgIdx + 1, irArg->attrs);

    if (isVararg) {
      delete irArg;
    }
  }