chromium/components/nacl/renderer/platform_info.cc

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

#include <string_view>

#include "base/strings/string_util.h"
#include "build/build_config.h"

#if defined(ARCH_CPU_X86_FAMILY)
#include "base/cpu.h"
#endif

namespace nacl {

const char* GetSandboxArch() {
#if defined(ARCH_CPU_ARM_FAMILY)
  return "arm";
#elif defined(ARCH_CPU_MIPS_FAMILY)
  return "mips32";
#elif defined(ARCH_CPU_X86_FAMILY)

#if ARCH_CPU_64_BITS
  return "x86-64";
#else
  return "x86-32";
#endif  // ARCH_CPU_64_BITS

#else
#error Architecture not supported.
#endif
}

std::string GetCpuFeatures() {
  // PNaCl's translator from pexe to nexe can be told exactly what
  // capabilities the user's machine has because the pexe to nexe
  // translation is specific to the machine, and CPU information goes
  // into the translation cache. This allows the translator to generate
  // faster code.
  //
  // Care must be taken to avoid instructions which aren't supported by
  // the NaCl sandbox. Ideally the translator would do this, but there's
  // no point in not doing the allowlist here.
  //
  // TODO(jfb) Some features are missing, either because the NaCl
  //           sandbox doesn't support them, because base::CPU doesn't
  //           detect them, or because they don't help vector shuffles
  //           (and we omit them because it simplifies testing). Add the
  //           other features.
  //
  // TODO(jfb) The following is x86-specific. The base::CPU class
  //           doesn't handle other architectures very well, and we
  //           should at least detect the presence of ARM's integer
  //           divide.
  std::vector<std::string_view> features;
#if defined(ARCH_CPU_X86_FAMILY)
  base::CPU cpu;

  // On x86, SSE features are ordered: the most recent one implies the
  // others. Care is taken here to only specify the latest SSE version,
  // whereas non-SSE features don't follow this model: POPCNT is
  // effectively always implied by SSE4.2 but has to be specified
  // separately.
  //
  // TODO: AVX2, AVX, SSE 4.2.
  if (cpu.has_sse41()) features.push_back("+sse4.1");
  // TODO: SSE 4A, SSE 4.
  else if (cpu.has_ssse3()) features.push_back("+ssse3");
  // TODO: SSE 3
  else if (cpu.has_sse2()) features.push_back("+sse2");

  if (cpu.has_popcnt()) features.push_back("+popcnt");

  // TODO: AES, LZCNT, ...
#endif

  return base::JoinString(features, ",");
}

}  // namespace nacl