chromium/tools/clang/stack_maps/IdentifySafepoints/IdentifySafepoints.cpp

// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "llvm/IR/Function.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"

#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"

using namespace llvm;

static int kGCAddressSpace = 1;

bool IsManaged(AllocaInst* AI) {
  auto* T = AI->getType();

  // If it looks like a Handle, it probably is a Handle. This brittle way of
  // checking for managed on-stack values returns true if a single element
  // struct has a GC address-spaced pointer field.
  if (T->getElementType()->isStructTy()) {
    auto* ST = dyn_cast<StructType>(&*T->getElementType());
    if (ST->getNumElements() == 1 && ST->getElementType(0)->isPointerTy()) {
      if (ST->getElementType(0)->getPointerAddressSpace() == kGCAddressSpace)
        return true;
    }
  }
  return false;
}

namespace {
struct IdentifySafepoints : public FunctionPass {
  static char ID;
  IdentifySafepoints() : FunctionPass(ID) {}

  bool runOnFunction(Function& F) override {
    for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
      if (auto* AI = dyn_cast_or_null<AllocaInst>(&*I)) {
        if (IsManaged(AI)) {
          F.addFnAttr("statepoint");
          return false;
        }
      }
    }
    return false;
  }
};

char IdentifySafepoints::ID;
}  // namespace

static RegisterPass<IdentifySafepoints> X("-identify-safepoints",
                                          "Identify Safepoints",
                                          false /* Only looks at CFG */,
                                          true /* Analysis Pass */);

static RegisterStandardPasses Y(PassManagerBuilder::EP_EarlyAsPossible,
                                [](const PassManagerBuilder& Builder,
                                   legacy::PassManagerBase& PM) {
                                  PM.add(new IdentifySafepoints());
                                });