コード例 #1
0
ファイル: abisignature.cpp プロジェクト: ANDREENKOS/llilc
ABISignature::ABISignature(const ReaderCallSignature &Signature, GenIR &Reader,
                           const ABIInfo &TheABIInfo) {
  const CallArgType &ResultType = Signature.getResultType();
  const std::vector<CallArgType> &ArgTypes = Signature.getArgumentTypes();
  const uint32_t NumArgs = ArgTypes.size();

  ABIType ABIResultType(Reader.getType(ResultType.CorType, ResultType.Class),
                        GenIR::isSignedIntegralType(ResultType.CorType));

  SmallVector<ABIType, 16> ABIArgTypes(NumArgs);
  uint32_t I = 0;
  for (const CallArgType &Arg : ArgTypes) {
    ABIArgTypes[I++] = ABIType(Reader.getType(Arg.CorType, Arg.Class),
                               GenIR::isSignedIntegralType(Arg.CorType));
  }

  bool IsManagedCallingConv = false;
  CallingConv::ID CC = getLLVMCallingConv(
      getNormalizedCallingConvention(Signature), IsManagedCallingConv);
  TheABIInfo.computeSignatureInfo(CC, IsManagedCallingConv, ABIResultType,
                                  ABIArgTypes, Result, Args);

  if (Result.getKind() == ABIArgInfo::Indirect) {
    FuncResultType = Reader.getManagedPointerType(Result.getType());
  } else {
    FuncResultType = Result.getType();
  }
}
コード例 #2
0
ファイル: abisignature.cpp プロジェクト: Anbu2388/llilc
void ABISignature::expand(GenIR &Reader,
                          ArrayRef<ABIArgInfo::Expansion> Expansions,
                          Value *Source, MutableArrayRef<Value *> Values,
                          MutableArrayRef<Type *> Types, bool IsResult) {
  assert(Source != nullptr);
  assert(Source->getType()->isPointerTy());
  assert(Reader.doesValueRepresentStruct(Source));
  assert(Expansions.size() > 0);
  assert((IsResult && Values.size() == 1) ||
         (Values.size() == Expansions.size()));

  LLVMContext &LLVMContext = *Reader.JitContext->LLVMContext;
  IRBuilder<> &Builder = *Reader.LLVMBuilder;

  Type *ResultType = nullptr;
  Value *ResultValue = nullptr;
  if (IsResult) {
    ResultType = getExpandedResultType(LLVMContext, Expansions);
    ResultValue = Constant::getNullValue(ResultType);
  }

  Type *BytePtrTy = Type::getInt8PtrTy(LLVMContext, 0);
  Value *SourcePtr = Builder.CreatePointerCast(Source, BytePtrTy);
  for (int32_t I = 0; I < static_cast<int32_t>(Expansions.size()); I++) {
    const ABIArgInfo::Expansion &Exp = Expansions[I];
    Value *LoadPtr = Builder.CreateConstGEP1_32(SourcePtr, Exp.Offset);
    LoadPtr = Builder.CreatePointerCast(LoadPtr, Exp.TheType->getPointerTo(0));
    const bool IsVolatile = false;
    Value *Value = Builder.CreateLoad(LoadPtr, IsVolatile);

    if (IsResult) {
      ResultValue = Builder.CreateInsertValue(ResultValue, Value, I);
    } else {
      Values[I] = Value;
    }

    if (Types.size() > 0) {
      Types[I] = Exp.TheType;
    }
  }

  if (IsResult) {
    Values[0] = ResultValue;
  }
}
コード例 #3
0
ファイル: abisignature.cpp プロジェクト: ANDREENKOS/llilc
CallSite ABICallSignature::emitUnmanagedCall(GenIR &Reader, Value *Target,
                                             bool MayThrow,
                                             ArrayRef<Value *> Arguments,
                                             Value *&Result) const {
  const LLILCJitContext &JitContext = *Reader.JitContext;
  const struct CORINFO_EE_INFO::InlinedCallFrameInfo &CallFrameInfo =
      JitContext.EEInfo.inlinedCallFrameInfo;
  LLVMContext &LLVMContext = *JitContext.LLVMContext;
  Type *Int8Ty = Type::getInt8Ty(LLVMContext);
  Type *Int32Ty = Type::getInt32Ty(LLVMContext);
  Type *Int64Ty = Type::getInt64Ty(LLVMContext);
  Type *Int8PtrTy = Reader.getUnmanagedPointerType(Int8Ty);
  IRBuilder<> &Builder = *Reader.LLVMBuilder;

  Reader.insertIRForUnmanagedCallFrame();

  Value *CallFrame = Reader.UnmanagedCallFrame;
  Value *Thread = Reader.ThreadPointer;
  assert(CallFrame != nullptr);
  assert(Thread != nullptr);

  // Set m_pDatum if necessary
  //
  // TODO: this needs to be updated for direct unmanaged calls, which require
  //       the target method handle instead of the stub secret parameter.
  if (Reader.MethodSignature.hasSecretParameter()) {
    Value *SecretParameter = Reader.secretParam();
    Value *CallTargetAddress =
        getFieldAddress(Builder, CallFrame, CallFrameInfo.offsetOfCallTarget,
                        SecretParameter->getType());
    Builder.CreateStore(SecretParameter, CallTargetAddress);
  }

  // Push the unmanaged call frame
  Value *FrameVPtr = getFieldAddress(Builder, CallFrame,
                                     CallFrameInfo.offsetOfFrameVptr, Int8Ty);
  Value *ThreadBase = Builder.CreateLoad(Thread);
  Value *ThreadFrameAddress = getFieldAddress(
      Builder, ThreadBase, JitContext.EEInfo.offsetOfThreadFrame, Int8PtrTy);
  Builder.CreateStore(FrameVPtr, ThreadFrameAddress);

  // Compute the address of the return address field
  Value *ReturnAddressAddress = getFieldAddress(
      Builder, CallFrame, CallFrameInfo.offsetOfReturnAddress, Int8PtrTy);

  // Compute the address of the GC mode field
  Value *GCStateAddress = getFieldAddress(
      Builder, ThreadBase, JitContext.EEInfo.offsetOfGCState, Int8Ty);

  // Compute address of the thread trap field
  Value *ThreadTrapAddress = nullptr;
  Type *ThreadTrapAddressTy = Reader.getUnmanagedPointerType(Int32Ty);
  void *IndirectAddrOfCaptureThreadGlobal = nullptr;
  void *AddrOfCaptureThreadGlobal =
      (void *)JitContext.JitInfo->getAddrOfCaptureThreadGlobal(
          &IndirectAddrOfCaptureThreadGlobal);
  if (AddrOfCaptureThreadGlobal != nullptr) {
    Value *RawThreadTrapAddress = ConstantInt::get(
        LLVMContext, APInt(Reader.TargetPointerSizeInBits,
                           (uint64_t)AddrOfCaptureThreadGlobal));
    ThreadTrapAddress =
        Builder.CreateIntToPtr(RawThreadTrapAddress, ThreadTrapAddressTy);
  } else {
    Value *IndirectThreadTrapAddress = ConstantInt::get(
        LLVMContext, APInt(Reader.TargetPointerSizeInBits,
                           (uint64_t)IndirectAddrOfCaptureThreadGlobal));
    Type *IndirectAddressTy =
        Reader.getUnmanagedPointerType(ThreadTrapAddressTy);
    Value *TypedIndirectAddress =
        Builder.CreateIntToPtr(IndirectThreadTrapAddress, IndirectAddressTy);
    ThreadTrapAddress = Builder.CreateLoad(TypedIndirectAddress);
  }

  // Compute address of GC pause helper
  Value *PauseHelperAddress =
      (Value *)Reader.getHelperCallAddress(CORINFO_HELP_STOP_FOR_GC);

  // Construct the call.
  //
  // The signature of the intrinsic is:
  // @llvm.experimental_gc_transition(
  //   fn_ptr target,
  //   i32 numCallArgs,
  //   i32 flags,
  //   ... call args ...,
  //   i32 numTransitionArgs,
  //   ... transition args...,
  //   i32 numDeoptArgs,
  //   ... deopt args...)
  //
  // In the case of CoreCLR, there are 4 transition args and 0 deopt args.
  //
  // The transition args are:
  // 0) Address of the return address field
  // 1) Address of the GC mode field
  // 2) Address of the thread trap global
  // 3) Address of CORINFO_HELP_STOP_FOR_GC
  Module *M = Reader.Function->getParent();
  Type *CallTypeArgs[] = {Target->getType()};
  Function *CallIntrinsic = Intrinsic::getDeclaration(
      M, Intrinsic::experimental_gc_statepoint, CallTypeArgs);

  const uint32_t PrefixArgCount = 5;
  const uint32_t TransitionArgCount = 4;
  const uint32_t PostfixArgCount = TransitionArgCount + 2;
  const uint32_t TargetArgCount = Arguments.size();
  SmallVector<Value *, 24> IntrinsicArgs(PrefixArgCount + TargetArgCount +
                                         PostfixArgCount);

  // ID, nop bytes, call target and target arguments
  IntrinsicArgs[0] = ConstantInt::get(Int64Ty, 0);
  IntrinsicArgs[1] = ConstantInt::get(Int32Ty, 0);
  IntrinsicArgs[2] = Target;
  IntrinsicArgs[3] = ConstantInt::get(Int32Ty, TargetArgCount);
  IntrinsicArgs[4] =
      ConstantInt::get(Int32Ty, (uint32_t)StatepointFlags::GCTransition);

  uint32_t I, J;
  for (I = 0, J = PrefixArgCount; I < TargetArgCount; I++, J++) {
    IntrinsicArgs[J] = Arguments[I];
  }

  // GC transition arguments
  IntrinsicArgs[J] = ConstantInt::get(Int32Ty, TransitionArgCount);
  IntrinsicArgs[J + 1] = ReturnAddressAddress;
  IntrinsicArgs[J + 2] = GCStateAddress;
  IntrinsicArgs[J + 3] = ThreadTrapAddress;
  IntrinsicArgs[J + 4] = PauseHelperAddress;

  // Deopt arguments
  IntrinsicArgs[J + 5] = ConstantInt::get(Int32Ty, 0);

  CallSite Call = Reader.makeCall(CallIntrinsic, MayThrow, IntrinsicArgs);

  // Get the call result if necessary
  if (!FuncResultType->isVoidTy()) {
    Type *ResultTypeArgs[] = {FuncResultType};
    Function *ResultIntrinsic = Intrinsic::getDeclaration(
        M, Intrinsic::experimental_gc_result, ResultTypeArgs);
    Result = Builder.CreateCall(ResultIntrinsic, Call.getInstruction());
  }

  // Deactivate the unmanaged call frame
  Builder.CreateStore(Constant::getNullValue(Int8PtrTy), ReturnAddressAddress);

  // Pop the unmanaged call frame
  Value *FrameLinkAddress = getFieldAddress(
      Builder, CallFrame, CallFrameInfo.offsetOfFrameLink, Int8PtrTy);
  Value *FrameLink = Builder.CreateLoad(FrameLinkAddress);
  Builder.CreateStore(FrameLink, ThreadFrameAddress);

  return Call;
}
コード例 #4
0
ファイル: abisignature.cpp プロジェクト: Anbu2388/llilc
CallSite
ABICallSignature::emitUnmanagedCall(GenIR &Reader, Value *Target, bool MayThrow,
                                    ArrayRef<Value *> Arguments) const {
  const LLILCJitContext &JitContext = *Reader.JitContext;
  const struct CORINFO_EE_INFO::InlinedCallFrameInfo &CallFrameInfo =
      JitContext.EEInfo.inlinedCallFrameInfo;
  LLVMContext &LLVMContext = *JitContext.LLVMContext;
  Type *Int8Ty = Type::getInt8Ty(LLVMContext);
  Type *Int32Ty = Type::getInt32Ty(LLVMContext);
  Type *Int8PtrTy = Reader.getUnmanagedPointerType(Int8Ty);
  IRBuilder<> &Builder = *Reader.LLVMBuilder;

  Reader.insertIRForUnmanagedCallFrame();

  Value *CallFrame = Reader.UnmanagedCallFrame;
  Value *Thread = Reader.ThreadPointer;
  assert(CallFrame != nullptr);
  assert(Thread != nullptr);

  // Set m_pDatum if necessary
  //
  // TODO: this needs to be updated for direct unmanaged calls, which require
  //       the target method handle instead of the stub secret parameter.
  if (Reader.MethodSignature.hasSecretParameter()) {
    Value *SecretParameter = Reader.secretParam();
    Value *CallTargetAddress =
        getFieldAddress(Builder, CallFrame, CallFrameInfo.offsetOfCallTarget,
                        SecretParameter->getType());
    Builder.CreateStore(SecretParameter, CallTargetAddress);
  }

  // Push the unmanaged call frame
  Value *FrameVPtr = getFieldAddress(Builder, CallFrame,
                                     CallFrameInfo.offsetOfFrameVptr, Int8Ty);
  Value *ThreadBase = Builder.CreateLoad(Thread);
  Value *ThreadFrameAddress = getFieldAddress(
      Builder, ThreadBase, JitContext.EEInfo.offsetOfThreadFrame, Int8PtrTy);
  Builder.CreateStore(FrameVPtr, ThreadFrameAddress);

  // Compute the address of the return address field
  Value *ReturnAddressAddress = getFieldAddress(
      Builder, CallFrame, CallFrameInfo.offsetOfReturnAddress, Int8PtrTy);

  // Compute the address of the GC mode field
  Value *GCStateAddress = getFieldAddress(
      Builder, ThreadBase, JitContext.EEInfo.offsetOfGCState, Int8Ty);

  // Compute address of the thread trap field
  Value *ThreadTrapAddress = nullptr;
  Type *ThreadTrapAddressTy = Reader.getUnmanagedPointerType(Int32Ty);
  void *IndirectAddrOfCaptureThreadGlobal = nullptr;
  void *AddrOfCaptureThreadGlobal =
      (void *)JitContext.JitInfo->getAddrOfCaptureThreadGlobal(
          &IndirectAddrOfCaptureThreadGlobal);
  void *AddrOfCaptureThreadHandle;
  bool IsIndirect;
  const bool IsReadOnly = true;
  const bool IsRelocatable = true;
  const bool IsCallTarget = false;
  if (AddrOfCaptureThreadGlobal != nullptr) {
    AddrOfCaptureThreadHandle = AddrOfCaptureThreadGlobal;
    IsIndirect = false;
  } else {
    AddrOfCaptureThreadHandle = IndirectAddrOfCaptureThreadGlobal;
    IsIndirect = true;
  }
  Value *RawThreadTrapAddress =
      Reader.handleToIRNode(mdtCaptureThreadGlobal, AddrOfCaptureThreadHandle,
                            AddrOfCaptureThreadHandle, IsIndirect, IsReadOnly,
                            IsRelocatable, IsCallTarget);
  ThreadTrapAddress =
      Builder.CreateIntToPtr(RawThreadTrapAddress, ThreadTrapAddressTy);

  // Compute address of GC pause helper
  Value *PauseHelperAddress =
      (Value *)Reader.getHelperCallAddress(CORINFO_HELP_STOP_FOR_GC);

  // Construct the call.
  //
  // The transition args are:
  // 0) Address of the return address field
  // 1) Address of the GC mode field
  // 2) Address of the thread trap global
  // 3) Address of CORINFO_HELP_STOP_FOR_GC
  Value *TransitionArgs[] = {ReturnAddressAddress, GCStateAddress,
                             ThreadTrapAddress, PauseHelperAddress};
  OperandBundleDef TransitionBundle("gc-transition", TransitionArgs);

  CallSite Call =
      Reader.makeCall(Target, MayThrow, Arguments, {TransitionBundle});
  assert(Call.getOperandBundle(LLVMContext::OB_gc_transition).hasValue() &&
         "tag string mismatch?");

  // Deactivate the unmanaged call frame
  Builder.CreateStore(Constant::getNullValue(Int8PtrTy), ReturnAddressAddress);

  // Pop the unmanaged call frame
  Value *FrameLinkAddress = getFieldAddress(
      Builder, CallFrame, CallFrameInfo.offsetOfFrameLink, Int8PtrTy);
  Value *FrameLink = Builder.CreateLoad(FrameLinkAddress);
  Builder.CreateStore(FrameLink, ThreadFrameAddress);

  return Call;
}