コード例 #1
0
RValue AtomicInfo::convertTempToRValue(llvm::Value *addr,
                                       AggValueSlot resultSlot) const {
  if (EvaluationKind == TEK_Aggregate) {
    // Nothing to do if the result is ignored.
    if (resultSlot.isIgnored()) return resultSlot.asRValue();

    assert(resultSlot.getAddr() == addr || hasPadding());

    // In these cases, we should have emitted directly into the result slot.
    if (!hasPadding() || resultSlot.isValueOfAtomic())
      return resultSlot.asRValue();

    // Otherwise, fall into the common path.
  }

  // Drill into the padding structure if we have one.
  if (hasPadding())
    addr = CGF.Builder.CreateStructGEP(addr, 0);

  // If we're emitting to an aggregate, copy into the result slot.
  if (EvaluationKind == TEK_Aggregate) {
    CGF.EmitAggregateCopy(resultSlot.getAddr(), addr, getValueType(),
                          resultSlot.isVolatile());
    return resultSlot.asRValue();
  }

  // Otherwise, just convert the temporary to an r-value using the
  // normal conversion routine.
  return CGF.convertTempToRValue(addr, getValueType());
}
コード例 #2
0
ファイル: CGExprAgg.cpp プロジェクト: 5432935/crossbridge
/// CheckAggExprForMemSetUse - If the initializer is large and has a lot of
/// zeros in it, emit a memset and avoid storing the individual zeros.
///
static void CheckAggExprForMemSetUse(AggValueSlot &Slot, const Expr *E,
                                     CodeGenFunction &CGF) {
  // If the slot is already known to be zeroed, nothing to do.  Don't mess with
  // volatile stores.
  if (Slot.isZeroed() || Slot.isVolatile() || Slot.getAddr() == 0) return;
  
  // If the type is 16-bytes or smaller, prefer individual stores over memset.
  std::pair<uint64_t, unsigned> TypeInfo =
    CGF.getContext().getTypeInfo(E->getType());
  if (TypeInfo.first/8 <= 16)
    return;

  // Check to see if over 3/4 of the initializer are known to be zero.  If so,
  // we prefer to emit memset + individual stores for the rest.
  uint64_t NumNonZeroBytes = GetNumNonZeroBytesInInit(E, CGF);
  if (NumNonZeroBytes*4 > TypeInfo.first/8)
    return;
  
  // Okay, it seems like a good idea to use an initial memset, emit the call.
  llvm::Constant *SizeVal = CGF.Builder.getInt64(TypeInfo.first/8);
  unsigned Align = TypeInfo.second/8;

  llvm::Value *Loc = Slot.getAddr();
  const llvm::Type *BP = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
  
  Loc = CGF.Builder.CreateBitCast(Loc, BP);
  CGF.Builder.CreateMemSet(Loc, CGF.Builder.getInt8(0), SizeVal, Align, false);
  
  // Tell the AggExprEmitter that the slot is known zero.
  Slot.setZeroed();
}
コード例 #3
0
ファイル: CGExprAgg.cpp プロジェクト: jrk/clang
/// CheckAggExprForMemSetUse - If the initializer is large and has a lot of
/// zeros in it, emit a memset and avoid storing the individual zeros.
///
static void CheckAggExprForMemSetUse(AggValueSlot &Slot, const Expr *E,
                                     CodeGenFunction &CGF) {
  // If the slot is already known to be zeroed, nothing to do.  Don't mess with
  // volatile stores.
  if (Slot.isZeroed() || Slot.isVolatile() || Slot.getAddr() == 0) return;

  // C++ objects with a user-declared constructor don't need zero'ing.
  if (CGF.getContext().getLangOptions().CPlusPlus)
    if (const RecordType *RT = CGF.getContext()
                       .getBaseElementType(E->getType())->getAs<RecordType>()) {
      const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
      if (RD->hasUserDeclaredConstructor())
        return;
    }

  // If the type is 16-bytes or smaller, prefer individual stores over memset.
  std::pair<CharUnits, CharUnits> TypeInfo =
    CGF.getContext().getTypeInfoInChars(E->getType());
  if (TypeInfo.first <= CharUnits::fromQuantity(16))
    return;

  // Check to see if over 3/4 of the initializer are known to be zero.  If so,
  // we prefer to emit memset + individual stores for the rest.
  CharUnits NumNonZeroBytes = GetNumNonZeroBytesInInit(E, CGF);
  if (NumNonZeroBytes*4 > TypeInfo.first)
    return;
  
  // Okay, it seems like a good idea to use an initial memset, emit the call.
  llvm::Constant *SizeVal = CGF.Builder.getInt64(TypeInfo.first.getQuantity());
  CharUnits Align = TypeInfo.second;

  llvm::Value *Loc = Slot.getAddr();
  llvm::Type *BP = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
  
  Loc = CGF.Builder.CreateBitCast(Loc, BP);
  CGF.Builder.CreateMemSet(Loc, CGF.Builder.getInt8(0), SizeVal, 
                           Align.getQuantity(), false);
  
  // Tell the AggExprEmitter that the slot is known zero.
  Slot.setZeroed();
}
コード例 #4
0
ファイル: CGAtomic.cpp プロジェクト: Henauxg/minix
RValue AtomicInfo::convertIntToValue(llvm::Value *IntVal,
                                     AggValueSlot ResultSlot,
                                     SourceLocation Loc) const {
  // Try not to in some easy cases.
  assert(IntVal->getType()->isIntegerTy() && "Expected integer value");
  if (getEvaluationKind() == TEK_Scalar && !hasPadding()) {
    auto *ValTy = CGF.ConvertTypeForMem(ValueTy);
    if (ValTy->isIntegerTy()) {
      assert(IntVal->getType() == ValTy && "Different integer types.");
      return RValue::get(IntVal);
    } else if (ValTy->isPointerTy())
      return RValue::get(CGF.Builder.CreateIntToPtr(IntVal, ValTy));
    else if (llvm::CastInst::isBitCastable(IntVal->getType(), ValTy))
      return RValue::get(CGF.Builder.CreateBitCast(IntVal, ValTy));
  }

  // Create a temporary.  This needs to be big enough to hold the
  // atomic integer.
  llvm::Value *Temp;
  bool TempIsVolatile = false;
  CharUnits TempAlignment;
  if (getEvaluationKind() == TEK_Aggregate) {
    assert(!ResultSlot.isIgnored());
    Temp = ResultSlot.getAddr();
    TempAlignment = getValueAlignment();
    TempIsVolatile = ResultSlot.isVolatile();
  } else {
    Temp = CGF.CreateMemTemp(getAtomicType(), "atomic-temp");
    TempAlignment = getAtomicAlignment();
  }

  // Slam the integer into the temporary.
  llvm::Value *CastTemp = emitCastToAtomicIntPointer(Temp);
  CGF.Builder.CreateAlignedStore(IntVal, CastTemp, TempAlignment.getQuantity())
      ->setVolatile(TempIsVolatile);

  return convertTempToRValue(Temp, ResultSlot, Loc);
}
コード例 #5
0
ファイル: CGAtomic.cpp プロジェクト: Bigcheese/clang
/// Emit a load from an l-value of atomic type.  Note that the r-value
/// we produce is an r-value of the atomic *value* type.
RValue CodeGenFunction::EmitAtomicLoad(LValue src, SourceLocation loc,
                                       AggValueSlot resultSlot) {
  AtomicInfo atomics(*this, src);

  // Check whether we should use a library call.
  if (atomics.shouldUseLibcall()) {
    llvm::Value *tempAddr;
    if (!resultSlot.isIgnored()) {
      assert(atomics.getEvaluationKind() == TEK_Aggregate);
      tempAddr = resultSlot.getAddr();
    } else {
      tempAddr = CreateMemTemp(atomics.getAtomicType(), "atomic-load-temp");
    }

    // void __atomic_load(size_t size, void *mem, void *return, int order);
    CallArgList args;
    args.add(RValue::get(atomics.getAtomicSizeValue()),
             getContext().getSizeType());
    args.add(RValue::get(EmitCastToVoidPtr(src.getAddress())),
             getContext().VoidPtrTy);
    args.add(RValue::get(EmitCastToVoidPtr(tempAddr)),
             getContext().VoidPtrTy);
    args.add(RValue::get(llvm::ConstantInt::get(
                 IntTy, AtomicExpr::AO_ABI_memory_order_seq_cst)),
             getContext().IntTy);
    emitAtomicLibcall(*this, "__atomic_load", getContext().VoidTy, args);

    // Produce the r-value.
    return atomics.convertTempToRValue(tempAddr, resultSlot, loc);
  }

  // Okay, we're doing this natively.
  llvm::Value *addr = atomics.emitCastToAtomicIntPointer(src.getAddress());
  llvm::LoadInst *load = Builder.CreateLoad(addr, "atomic-load");
  load->setAtomic(llvm::SequentiallyConsistent);

  // Other decoration.
  load->setAlignment(src.getAlignment().getQuantity());
  if (src.isVolatileQualified())
    load->setVolatile(true);
  if (src.getTBAAInfo())
    CGM.DecorateInstruction(load, src.getTBAAInfo());

  // Okay, turn that back into the original value type.
  QualType valueType = atomics.getValueType();
  llvm::Value *result = load;

  // If we're ignoring an aggregate return, don't do anything.
  if (atomics.getEvaluationKind() == TEK_Aggregate && resultSlot.isIgnored())
    return RValue::getAggregate(0, false);

  // The easiest way to do this this is to go through memory, but we
  // try not to in some easy cases.
  if (atomics.getEvaluationKind() == TEK_Scalar && !atomics.hasPadding()) {
    llvm::Type *resultTy = CGM.getTypes().ConvertTypeForMem(valueType);
    if (isa<llvm::IntegerType>(resultTy)) {
      assert(result->getType() == resultTy);
      result = EmitFromMemory(result, valueType);
    } else if (isa<llvm::PointerType>(resultTy)) {
      result = Builder.CreateIntToPtr(result, resultTy);
    } else {
      result = Builder.CreateBitCast(result, resultTy);
    }
    return RValue::get(result);
  }

  // Create a temporary.  This needs to be big enough to hold the
  // atomic integer.
  llvm::Value *temp;
  bool tempIsVolatile = false;
  CharUnits tempAlignment;
  if (atomics.getEvaluationKind() == TEK_Aggregate) {
    assert(!resultSlot.isIgnored());
    temp = resultSlot.getAddr();
    tempAlignment = atomics.getValueAlignment();
    tempIsVolatile = resultSlot.isVolatile();
  } else {
    temp = CreateMemTemp(atomics.getAtomicType(), "atomic-load-temp");
    tempAlignment = atomics.getAtomicAlignment();
  }

  // Slam the integer into the temporary.
  llvm::Value *castTemp = atomics.emitCastToAtomicIntPointer(temp);
  Builder.CreateAlignedStore(result, castTemp, tempAlignment.getQuantity())
    ->setVolatile(tempIsVolatile);

  return atomics.convertTempToRValue(temp, resultSlot, loc);
}