コード例 #1
0
/// Track uses of the arguments, recording in the summary any accesses
/// started by a begin_access and any flows of the arguments to other
/// functions.
void AccessSummaryAnalysis::processArgument(FunctionInfo *info,
                                             SILFunctionArgument *argument,
                                             ArgumentSummary &summary,
                                             FunctionOrder &order) {
  unsigned argumentIndex = argument->getIndex();

  // Use a worklist to track argument uses to be processed.
  llvm::SmallVector<Operand *, 32> worklist;

  // Start by adding the immediate uses of the argument to the worklist.
  worklist.append(argument->use_begin(), argument->use_end());

  // Iterate to follow uses of the arguments.
  while (!worklist.empty()) {
    Operand *operand = worklist.pop_back_val();
    SILInstruction *user = operand->getUser();

    switch (user->getKind()) {
    case ValueKind::BeginAccessInst: {
      auto *BAI = cast<BeginAccessInst>(user);
      summary.mergeWith(BAI->getAccessKind(), BAI->getLoc());
      // We don't add the users of the begin_access to the worklist because
      // even if these users eventually begin an access to the address
      // or a projection from it, that access can't begin more exclusive
      // access than this access -- otherwise it will be diagnosed
      // elsewhere.
      break;
    }
    case ValueKind::EndUnpairedAccessInst:
      // Don't diagnose unpaired access statically.
      assert(cast<EndUnpairedAccessInst>(user)->getEnforcement() ==
             SILAccessEnforcement::Dynamic);
      break;
    case ValueKind::StructElementAddrInst:
    case ValueKind::TupleElementAddrInst:
      // Eventually we'll summarize individual struct elements separately.
      // For now an access to a part of the struct is treated as an access
      // to the whole struct.
      worklist.append(user->use_begin(), user->use_end());
      break;
    case ValueKind::DebugValueAddrInst:
    case ValueKind::AddressToPointerInst:
      // Ignore these uses, they don't affect formal accesses.
      break;
    case ValueKind::PartialApplyInst:
      processPartialApply(info, argumentIndex, cast<PartialApplyInst>(user),
                          operand, order);
      break;
    case ValueKind::ApplyInst:
      processFullApply(info, argumentIndex, cast<ApplyInst>(user), operand,
                       order);
      break;
    case ValueKind::TryApplyInst:
      processFullApply(info, argumentIndex, cast<TryApplyInst>(user), operand,
                       order);
      break;
    case ValueKind::CopyAddrInst:
    case ValueKind::ExistentialMetatypeInst:
    case ValueKind::ValueMetatypeInst:
    case ValueKind::LoadInst:
    case ValueKind::LoadBorrowInst:
    case ValueKind::EndBorrowInst:
    case ValueKind::OpenExistentialAddrInst:
    case ValueKind::ProjectBlockStorageInst:
      // These likely represent scenarios in which we're not generating
      // begin access markers. Ignore these for now. But we really should
      // add SIL verification to ensure all loads and stores have associated
      // access markers.
      break;
    default:
      // TODO: These requirements should be checked for in the SIL verifier.
      // This is an assertion rather than llvm_unreachable() because
      // it is likely the whitelist above for scenarios in which we'ren
      // not generating access markers is not comprehensive.
      assert(false && "Unrecognized argument use");
      break;
    }
  }
}
コード例 #2
0
/// Track uses of the arguments, recording in the summary any accesses
/// started by a begin_access and any flows of the arguments to other
/// functions.
void AccessSummaryAnalysis::processArgument(FunctionInfo *info,
                                             SILFunctionArgument *argument,
                                             ArgumentSummary &summary,
                                             FunctionOrder &order) {
  unsigned argumentIndex = argument->getIndex();

  // Use a worklist to track argument uses to be processed.
  llvm::SmallVector<Operand *, 32> worklist;

  // Start by adding the immediate uses of the argument to the worklist.
  worklist.append(argument->use_begin(), argument->use_end());

  // Iterate to follow uses of the arguments.
  while (!worklist.empty()) {
    Operand *operand = worklist.pop_back_val();
    SILInstruction *user = operand->getUser();

    switch (user->getKind()) {
    case SILInstructionKind::BeginAccessInst: {
      auto *BAI = cast<BeginAccessInst>(user);
      const IndexTrieNode *subPath = findSubPathAccessed(BAI);
      summary.mergeWith(BAI->getAccessKind(), BAI->getLoc(), subPath);
      // We don't add the users of the begin_access to the worklist because
      // even if these users eventually begin an access to the address
      // or a projection from it, that access can't begin more exclusive
      // access than this access -- otherwise it will be diagnosed
      // elsewhere.
      break;
    }
    case SILInstructionKind::EndUnpairedAccessInst:
      // Don't diagnose unpaired access statically.
      assert(cast<EndUnpairedAccessInst>(user)->getEnforcement() ==
             SILAccessEnforcement::Dynamic);
      break;
    case SILInstructionKind::StructElementAddrInst:
    case SILInstructionKind::TupleElementAddrInst: {
      // Eventually we'll summarize individual struct elements separately.
      // For now an access to a part of the struct is treated as an access
      // to the whole struct.
      auto inst = cast<SingleValueInstruction>(user);
      worklist.append(inst->use_begin(), inst->use_end());
      break;
    }
    case SILInstructionKind::DebugValueAddrInst:
    case SILInstructionKind::AddressToPointerInst:
      // Ignore these uses, they don't affect formal accesses.
      break;
    case SILInstructionKind::PartialApplyInst:
      processPartialApply(info, argumentIndex, cast<PartialApplyInst>(user),
                          operand, order);
      break;
    case SILInstructionKind::ApplyInst:
      processFullApply(info, argumentIndex, cast<ApplyInst>(user), operand,
                       order);
      break;
    case SILInstructionKind::TryApplyInst:
      processFullApply(info, argumentIndex, cast<TryApplyInst>(user), operand,
                       order);
      break;
    default:
      // FIXME: These likely represent scenarios in which we're not generating
      // begin access markers. Ignore these for now. But we really should
      // add SIL verification to ensure all loads and stores have associated
      // access markers. Once SIL verification is implemented, enable the
      // following assert to verify that the cases handled above are
      // comprehensive, which guarantees that exclusivity enforcement is
      // complete.
      //   assert(false && "Unrecognized argument use");
      break;
    }
  }
}