<commit_before>/*
 ***********************************************************************************************************************
 *
 *  Copyright (c) 2019-2021 Advanced Micro Devices, Inc. All Rights Reserved.
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 *
 **********************************************************************************************************************/
/**
 ***********************************************************************************************************************
 * @file  LgcContext.cpp
 * @brief LLPC source file: implementation of llpc::LgcContext class for creating and using lgc::Builder
 ***********************************************************************************************************************
 */
#include "lgc/LgcContext.h"
#include "lgc/Builder.h"
#include "lgc/PassManager.h"
#include "lgc/patch/Patch.h"
#include "lgc/state/PassManagerCache.h"
#include "lgc/state/PipelineState.h"
#include "lgc/state/TargetInfo.h"
#include "lgc/util/Debug.h"
#include "lgc/util/Internal.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Bitcode/BitcodeWriterPass.h"
#include "llvm/CodeGen/CommandFlags.h"
#include "llvm/CodeGen/LinkAllCodegenComponents.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/InitializePasses.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"

#define DEBUG_TYPE "lgc-context"

namespace llvm {

namespace cl {

// Set the optimization level
extern opt<CodeGenOpt::Level> OptLevel;

} // namespace cl
} // namespace llvm

using namespace lgc;
using namespace llvm;

namespace llvm {
void initializeBuilderReplayerPass(PassRegistry &);
} // namespace llvm

static codegen::RegisterCodeGenFlags CGF;

#ifndef NDEBUG
static bool Initialized;
#endif

raw_ostream *LgcContext::m_llpcOuts;

// -emit-llvm: emit LLVM assembly instead of ISA
static cl::opt<bool> EmitLlvm("emit-llvm", cl::desc("Emit LLVM assembly instead of AMD GPU ISA"), cl::init(false));

// -emit-llvm-bc: emit LLVM bitcode instead of ISA
static cl::opt<bool> EmitLlvmBc("emit-llvm-bc", cl::desc("Emit LLVM bitcode instead of AMD GPU ISA"), cl::init(false));

// -emit-lgc: emit LLVM assembly suitable for input to LGC (middle-end compiler)
static cl::opt<bool> EmitLgc("emit-lgc", cl::desc("Emit LLVM assembly suitable for input to LGC (middle-end compiler)"),
                             cl::init(false));

// -show-encoding: show the instruction encoding when emitting assembler. This mirrors llvm-mc behaviour
static cl::opt<bool> ShowEncoding("show-encoding", cl::desc("Show instruction encodings"), cl::init(false));

// =====================================================================================================================
// Set default for a command-line option, but only if command-line processing has not happened yet, or did not see
// an occurrence of this option.
//
// @param name : Option name
// @param value : Default option value
static void setOptionDefault(const char *name, StringRef value) {
  auto optIterator = cl::getRegisteredOptions().find(name);
  assert(optIterator != cl::getRegisteredOptions().end() && "Failed to find option to set default");
  cl::Option *opt = optIterator->second;
  if (opt->getNumOccurrences())
    return;
  // Setting MultiArg means that addOccurrence will not increment the option's occurrence count, so the user
  // can still specify it to override our default here.
  bool setFailed = opt->addOccurrence(0, opt->ArgStr, value, /*MultiArg=*/true);
  assert(!setFailed && "Failed to set default for option");
  ((void)setFailed);
}

// =====================================================================================================================
// Initialize the middle-end. This must be called before the first LgcContext::Create, although you are
// allowed to call it again after that. It must also be called before LLVM command-line processing, so
// that you can use a pass name in an option such as -print-after. If multiple concurrent compiles are
// possible, this should be called in a thread-safe way.
void LgcContext::initialize() {
#ifndef NDEBUG
  Initialized = true;
#endif

  auto &passRegistry = *PassRegistry::getPassRegistry();

  // Initialize LLVM target: AMDGPU
  LLVMInitializeAMDGPUTargetInfo();
  LLVMInitializeAMDGPUTarget();
  LLVMInitializeAMDGPUTargetMC();
  LLVMInitializeAMDGPUAsmPrinter();
  LLVMInitializeAMDGPUAsmParser();
  LLVMInitializeAMDGPUDisassembler();

  // Initialize core LLVM passes so they can be referenced by -stop-before etc.
  initializeCore(passRegistry);
  initializeTransformUtils(passRegistry);
  initializeScalarOpts(passRegistry);
  initializeVectorization(passRegistry);
  initializeInstCombine(passRegistry);
  initializeAggressiveInstCombine(passRegistry);
  initializeIPO(passRegistry);
  initializeCodeGen(passRegistry);
  initializeShadowStackGCLoweringPass(passRegistry);
  initializeExpandReductionsPass(passRegistry);
  initializeRewriteSymbolsLegacyPassPass(passRegistry);

  // Initialize LGC passes so they can be referenced by -stop-before etc.
  initializeUtilPasses(passRegistry);
  initializeStatePasses(passRegistry);
  initializeBuilderReplayerPass(passRegistry);
  initializePatchPasses(passRegistry);

  // Initialize some command-line option defaults.
  setOptionDefault("filetype", "obj");
  setOptionDefault("amdgpu-unroll-max-block-to-analyze", "20");
  setOptionDefault("unroll-max-percent-threshold-boost", "1000");
  setOptionDefault("unroll-allow-partial", "1");
  setOptionDefault("simplifycfg-sink-common", "0");
  setOptionDefault("amdgpu-vgpr-index-mode", "1"); // force VGPR indexing on GFX8
  setOptionDefault("amdgpu-atomic-optimizations", "1");
  setOptionDefault("use-gpu-divergence-analysis", "1");
  setOptionDefault("structurizecfg-skip-uniform-regions", "1");
  setOptionDefault("spec-exec-max-speculation-cost", "10");
#if !defined(LLVM_HAVE_BRANCH_AMD_GFX)
#warning[!amd-gfx] Conditional discard transformations not supported
#else
  setOptionDefault("amdgpu-conditional-discard-transformations", "1");
#endif
}

// =====================================================================================================================
// Create the LgcContext. Returns nullptr on failure to recognize the AMDGPU target whose name is specified
//
// @param context : LLVM context to give each Builder
// @param gpuName : LLVM GPU name (e.g. "gfx900"); empty to use -mcpu option setting
// @param palAbiVersion : PAL pipeline ABI version to compile for
LgcContext *LgcContext::Create(LLVMContext &context, StringRef gpuName, unsigned palAbiVersion) {
  assert(Initialized && "Must call LgcContext::Initialize before LgcContext::Create");

  LgcContext *builderContext = new LgcContext(context, palAbiVersion);

  std::string mcpuName = codegen::getMCPU(); // -mcpu setting from llvm/CodeGen/CommandFlags.h
  if (gpuName == "")
    gpuName = mcpuName;

  builderContext->m_targetInfo = new TargetInfo;
  if (!builderContext->m_targetInfo->setTargetInfo(gpuName)) {
    delete builderContext;
    return nullptr;
  }

  // Get the LLVM target and create the target machine. This should not fail, as we determined above
  // that we support the requested target.
  const std::string triple = "amdgcn--amdpal";
  std::string errMsg;
  const Target *target = TargetRegistry::lookupTarget(triple, errMsg);
  // Allow no signed zeros - this enables omod modifiers (div:2, mul:2)
  TargetOptions targetOpts;
  targetOpts.NoSignedZerosFPMath = true;

  // Enable instruction encoding output - outputs hex in comment mirroring
  // llvm-mc behaviour
  if (ShowEncoding) {
    targetOpts.MCOptions.ShowMCEncoding = true;
    targetOpts.MCOptions.AsmVerbose = true;
  }

  LLPC_OUTS("TargetMachine optimization level = " << cl::OptLevel << "\n");

  builderContext->m_targetMachine =
      target->createTargetMachine(triple, gpuName, "", targetOpts, Optional<Reloc::Model>(), None, cl::OptLevel);
  assert(builderContext->m_targetMachine);
  return builderContext;
}

// =====================================================================================================================
//
// @param context : LLVM context to give each Builder
// @param palAbiVersion : PAL pipeline ABI version to compile for
LgcContext::LgcContext(LLVMContext &context, unsigned palAbiVersion) : m_context(context) {
}

// =====================================================================================================================
LgcContext::~LgcContext() {
  delete m_targetMachine;
  delete m_targetInfo;
  delete m_passManagerCache;
}

// =====================================================================================================================
// Create a Pipeline object for a pipeline compile.
// This actually creates a PipelineState, but returns the Pipeline superclass that is visible to
// the front-end.
Pipeline *LgcContext::createPipeline() {
  return new PipelineState(this, EmitLgc);
}

// =====================================================================================================================
// Create a Builder object. For a shader compile (pPipeline is nullptr), useBuilderRecorder is ignored
// because it always uses BuilderRecorder.
//
// @param pipeline : Pipeline object for pipeline compile, nullptr for shader compile
// @param useBuilderRecorder : True to use BuilderRecorder, false to use BuilderImpl
Builder *LgcContext::createBuilder(Pipeline *pipeline, bool useBuilderRecorder) {
  if (!pipeline || useBuilderRecorder || EmitLgc)
    return Builder::createBuilderRecorder(this, pipeline, EmitLgc);
  return Builder::createBuilderImpl(this, pipeline);
}

// =====================================================================================================================
// Prepare a pass manager. This manually adds a target-aware TLI pass, so middle-end optimizations do not think that
// we have library functions.
//
// @param [in/out] passMgr : Pass manager
void LgcContext::preparePassManager(legacy::PassManager *passMgr) {
  TargetLibraryInfoImpl targetLibInfo(getTargetMachine()->getTargetTriple());

  // Adjust it to allow memcpy and memset.
  // TODO: Investigate why the latter is necessary. I found that
  // test/shaderdb/ObjStorageBlock_TestMemCpyInt32.comp
  // got unrolled far too much, and at too late a stage for the descriptor loads to be commoned up. It might
  // be an unfortunate interaction between LoopIdiomRecognize and fat pointer laundering.
  targetLibInfo.setAvailable(LibFunc_memcpy);
  targetLibInfo.setAvailable(LibFunc_memset);

  auto targetLibInfoPass = new TargetLibraryInfoWrapperPass(targetLibInfo);
  passMgr->add(targetLibInfoPass);
}

// =====================================================================================================================
// Adds target passes to pass manager, depending on "-filetype" and "-emit-llvm" options
//
// @param [in/out] passMgr : Pass manager to add passes to
// @param codeGenTimer : Timer to time target passes with, nullptr if not timing
// @param [out] outStream : Output stream
void LgcContext::addTargetPasses(lgc::PassManager &passMgr, Timer *codeGenTimer, raw_pwrite_stream &outStream) {
  // Start timer for codegen passes.
  if (codeGenTimer)
    passMgr.add(createStartStopTimer(codeGenTimer, true));

  // Dump the module just before codegen.
  if (raw_ostream *outs = getLgcOuts()) {
    passMgr.add(
        createPrintModulePass(*outs, "===============================================================================\n"
                                     "// LLPC final pipeline module info\n"));
  }

  if (EmitLlvm && EmitLlvmBc)
    report_fatal_error("-emit-llvm conflicts with -emit-llvm-bc");

  if (EmitLlvm) {
    // For -emit-llvm, add a pass to output the LLVM IR, then tell the pass manager to stop adding
    // passes. We do it this way to ensure that we still get the immutable passes from
    // TargetMachine::addPassesToEmitFile, as they can affect LLVM middle-end optimizations.
    passMgr.add(createPrintModulePass(outStream));
    passMgr.stop();
  }

  if (EmitLlvmBc) {
    // For -emit-llvm-bc, add a pass to output the LLVM IR, then tell the pass manager to stop adding
    // passes. We do it this way to ensure that we still get the immutable passes from
    // TargetMachine::addPassesToEmitFile, as they can affect LLVM middle-end optimizations.
    passMgr.add(createBitcodeWriterPass(outStream));
    passMgr.stop();
  }

  // TODO: We should probably be using InitTargetOptionsFromCodeGenFlags() here.
  // Currently we are not, and it would give an "unused function" warning when compiled with
  // CLANG. So we avoid the warning by referencing it here.
  (void(&codegen::InitTargetOptionsFromCodeGenFlags)); // unused

  if (getTargetMachine()->addPassesToEmitFile(passMgr, outStream, nullptr, codegen::getFileType()))
    report_fatal_error("Target machine cannot emit a file of this type");

  // Stop timer for codegen passes.
  if (codeGenTimer)
    passMgr.add(createStartStopTimer(codeGenTimer, false));
}

// =====================================================================================================================
// Get pass manager cache
PassManagerCache *LgcContext::getPassManagerCache() {
  if (!m_passManagerCache)
    m_passManagerCache = new PassManagerCache(this);
  return m_passManagerCache;
}
<commit_msg>Disable phi-of-op optimization in NewGVN<commit_after>/*
 ***********************************************************************************************************************
 *
 *  Copyright (c) 2019-2021 Advanced Micro Devices, Inc. All Rights Reserved.
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 *
 **********************************************************************************************************************/
/**
 ***********************************************************************************************************************
 * @file  LgcContext.cpp
 * @brief LLPC source file: implementation of llpc::LgcContext class for creating and using lgc::Builder
 ***********************************************************************************************************************
 */
#include "lgc/LgcContext.h"
#include "lgc/Builder.h"
#include "lgc/PassManager.h"
#include "lgc/patch/Patch.h"
#include "lgc/state/PassManagerCache.h"
#include "lgc/state/PipelineState.h"
#include "lgc/state/TargetInfo.h"
#include "lgc/util/Debug.h"
#include "lgc/util/Internal.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Bitcode/BitcodeWriterPass.h"
#include "llvm/CodeGen/CommandFlags.h"
#include "llvm/CodeGen/LinkAllCodegenComponents.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/InitializePasses.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"

#define DEBUG_TYPE "lgc-context"

namespace llvm {

namespace cl {

// Set the optimization level
extern opt<CodeGenOpt::Level> OptLevel;

} // namespace cl
} // namespace llvm

using namespace lgc;
using namespace llvm;

namespace llvm {
void initializeBuilderReplayerPass(PassRegistry &);
} // namespace llvm

static codegen::RegisterCodeGenFlags CGF;

#ifndef NDEBUG
static bool Initialized;
#endif

raw_ostream *LgcContext::m_llpcOuts;

// -emit-llvm: emit LLVM assembly instead of ISA
static cl::opt<bool> EmitLlvm("emit-llvm", cl::desc("Emit LLVM assembly instead of AMD GPU ISA"), cl::init(false));

// -emit-llvm-bc: emit LLVM bitcode instead of ISA
static cl::opt<bool> EmitLlvmBc("emit-llvm-bc", cl::desc("Emit LLVM bitcode instead of AMD GPU ISA"), cl::init(false));

// -emit-lgc: emit LLVM assembly suitable for input to LGC (middle-end compiler)
static cl::opt<bool> EmitLgc("emit-lgc", cl::desc("Emit LLVM assembly suitable for input to LGC (middle-end compiler)"),
                             cl::init(false));

// -show-encoding: show the instruction encoding when emitting assembler. This mirrors llvm-mc behaviour
static cl::opt<bool> ShowEncoding("show-encoding", cl::desc("Show instruction encodings"), cl::init(false));

// =====================================================================================================================
// Set default for a command-line option, but only if command-line processing has not happened yet, or did not see
// an occurrence of this option.
//
// @param name : Option name
// @param value : Default option value
static void setOptionDefault(const char *name, StringRef value) {
  auto optIterator = cl::getRegisteredOptions().find(name);
  assert(optIterator != cl::getRegisteredOptions().end() && "Failed to find option to set default");
  cl::Option *opt = optIterator->second;
  if (opt->getNumOccurrences())
    return;
  // Setting MultiArg means that addOccurrence will not increment the option's occurrence count, so the user
  // can still specify it to override our default here.
  bool setFailed = opt->addOccurrence(0, opt->ArgStr, value, /*MultiArg=*/true);
  assert(!setFailed && "Failed to set default for option");
  ((void)setFailed);
}

// =====================================================================================================================
// Initialize the middle-end. This must be called before the first LgcContext::Create, although you are
// allowed to call it again after that. It must also be called before LLVM command-line processing, so
// that you can use a pass name in an option such as -print-after. If multiple concurrent compiles are
// possible, this should be called in a thread-safe way.
void LgcContext::initialize() {
#ifndef NDEBUG
  Initialized = true;
#endif

  auto &passRegistry = *PassRegistry::getPassRegistry();

  // Initialize LLVM target: AMDGPU
  LLVMInitializeAMDGPUTargetInfo();
  LLVMInitializeAMDGPUTarget();
  LLVMInitializeAMDGPUTargetMC();
  LLVMInitializeAMDGPUAsmPrinter();
  LLVMInitializeAMDGPUAsmParser();
  LLVMInitializeAMDGPUDisassembler();

  // Initialize core LLVM passes so they can be referenced by -stop-before etc.
  initializeCore(passRegistry);
  initializeTransformUtils(passRegistry);
  initializeScalarOpts(passRegistry);
  initializeVectorization(passRegistry);
  initializeInstCombine(passRegistry);
  initializeAggressiveInstCombine(passRegistry);
  initializeIPO(passRegistry);
  initializeCodeGen(passRegistry);
  initializeShadowStackGCLoweringPass(passRegistry);
  initializeExpandReductionsPass(passRegistry);
  initializeRewriteSymbolsLegacyPassPass(passRegistry);

  // Initialize LGC passes so they can be referenced by -stop-before etc.
  initializeUtilPasses(passRegistry);
  initializeStatePasses(passRegistry);
  initializeBuilderReplayerPass(passRegistry);
  initializePatchPasses(passRegistry);

  // Initialize some command-line option defaults.
  setOptionDefault("filetype", "obj");
  setOptionDefault("amdgpu-unroll-max-block-to-analyze", "20");
  setOptionDefault("unroll-max-percent-threshold-boost", "1000");
  setOptionDefault("unroll-allow-partial", "1");
  // TODO: phi-of-ops optimization in NewGVN has some problems, we temporarily
  // disable this to avoid mis-compile, see (https://github.com/GPUOpen-Drivers/llpc/issues/1206).
  setOptionDefault("enable-phi-of-ops", "0");
  setOptionDefault("simplifycfg-sink-common", "0");
  setOptionDefault("amdgpu-vgpr-index-mode", "1"); // force VGPR indexing on GFX8
  setOptionDefault("amdgpu-atomic-optimizations", "1");
  setOptionDefault("use-gpu-divergence-analysis", "1");
  setOptionDefault("structurizecfg-skip-uniform-regions", "1");
  setOptionDefault("spec-exec-max-speculation-cost", "10");
#if !defined(LLVM_HAVE_BRANCH_AMD_GFX)
#warning[!amd-gfx] Conditional discard transformations not supported
#else
  setOptionDefault("amdgpu-conditional-discard-transformations", "1");
#endif
}

// =====================================================================================================================
// Create the LgcContext. Returns nullptr on failure to recognize the AMDGPU target whose name is specified
//
// @param context : LLVM context to give each Builder
// @param gpuName : LLVM GPU name (e.g. "gfx900"); empty to use -mcpu option setting
// @param palAbiVersion : PAL pipeline ABI version to compile for
LgcContext *LgcContext::Create(LLVMContext &context, StringRef gpuName, unsigned palAbiVersion) {
  assert(Initialized && "Must call LgcContext::Initialize before LgcContext::Create");

  LgcContext *builderContext = new LgcContext(context, palAbiVersion);

  std::string mcpuName = codegen::getMCPU(); // -mcpu setting from llvm/CodeGen/CommandFlags.h
  if (gpuName == "")
    gpuName = mcpuName;

  builderContext->m_targetInfo = new TargetInfo;
  if (!builderContext->m_targetInfo->setTargetInfo(gpuName)) {
    delete builderContext;
    return nullptr;
  }

  // Get the LLVM target and create the target machine. This should not fail, as we determined above
  // that we support the requested target.
  const std::string triple = "amdgcn--amdpal";
  std::string errMsg;
  const Target *target = TargetRegistry::lookupTarget(triple, errMsg);
  // Allow no signed zeros - this enables omod modifiers (div:2, mul:2)
  TargetOptions targetOpts;
  targetOpts.NoSignedZerosFPMath = true;

  // Enable instruction encoding output - outputs hex in comment mirroring
  // llvm-mc behaviour
  if (ShowEncoding) {
    targetOpts.MCOptions.ShowMCEncoding = true;
    targetOpts.MCOptions.AsmVerbose = true;
  }

  LLPC_OUTS("TargetMachine optimization level = " << cl::OptLevel << "\n");

  builderContext->m_targetMachine =
      target->createTargetMachine(triple, gpuName, "", targetOpts, Optional<Reloc::Model>(), None, cl::OptLevel);
  assert(builderContext->m_targetMachine);
  return builderContext;
}

// =====================================================================================================================
//
// @param context : LLVM context to give each Builder
// @param palAbiVersion : PAL pipeline ABI version to compile for
LgcContext::LgcContext(LLVMContext &context, unsigned palAbiVersion) : m_context(context) {
}

// =====================================================================================================================
LgcContext::~LgcContext() {
  delete m_targetMachine;
  delete m_targetInfo;
  delete m_passManagerCache;
}

// =====================================================================================================================
// Create a Pipeline object for a pipeline compile.
// This actually creates a PipelineState, but returns the Pipeline superclass that is visible to
// the front-end.
Pipeline *LgcContext::createPipeline() {
  return new PipelineState(this, EmitLgc);
}

// =====================================================================================================================
// Create a Builder object. For a shader compile (pPipeline is nullptr), useBuilderRecorder is ignored
// because it always uses BuilderRecorder.
//
// @param pipeline : Pipeline object for pipeline compile, nullptr for shader compile
// @param useBuilderRecorder : True to use BuilderRecorder, false to use BuilderImpl
Builder *LgcContext::createBuilder(Pipeline *pipeline, bool useBuilderRecorder) {
  if (!pipeline || useBuilderRecorder || EmitLgc)
    return Builder::createBuilderRecorder(this, pipeline, EmitLgc);
  return Builder::createBuilderImpl(this, pipeline);
}

// =====================================================================================================================
// Prepare a pass manager. This manually adds a target-aware TLI pass, so middle-end optimizations do not think that
// we have library functions.
//
// @param [in/out] passMgr : Pass manager
void LgcContext::preparePassManager(legacy::PassManager *passMgr) {
  TargetLibraryInfoImpl targetLibInfo(getTargetMachine()->getTargetTriple());

  // Adjust it to allow memcpy and memset.
  // TODO: Investigate why the latter is necessary. I found that
  // test/shaderdb/ObjStorageBlock_TestMemCpyInt32.comp
  // got unrolled far too much, and at too late a stage for the descriptor loads to be commoned up. It might
  // be an unfortunate interaction between LoopIdiomRecognize and fat pointer laundering.
  targetLibInfo.setAvailable(LibFunc_memcpy);
  targetLibInfo.setAvailable(LibFunc_memset);

  auto targetLibInfoPass = new TargetLibraryInfoWrapperPass(targetLibInfo);
  passMgr->add(targetLibInfoPass);
}

// =====================================================================================================================
// Adds target passes to pass manager, depending on "-filetype" and "-emit-llvm" options
//
// @param [in/out] passMgr : Pass manager to add passes to
// @param codeGenTimer : Timer to time target passes with, nullptr if not timing
// @param [out] outStream : Output stream
void LgcContext::addTargetPasses(lgc::PassManager &passMgr, Timer *codeGenTimer, raw_pwrite_stream &outStream) {
  // Start timer for codegen passes.
  if (codeGenTimer)
    passMgr.add(createStartStopTimer(codeGenTimer, true));

  // Dump the module just before codegen.
  if (raw_ostream *outs = getLgcOuts()) {
    passMgr.add(
        createPrintModulePass(*outs, "===============================================================================\n"
                                     "// LLPC final pipeline module info\n"));
  }

  if (EmitLlvm && EmitLlvmBc)
    report_fatal_error("-emit-llvm conflicts with -emit-llvm-bc");

  if (EmitLlvm) {
    // For -emit-llvm, add a pass to output the LLVM IR, then tell the pass manager to stop adding
    // passes. We do it this way to ensure that we still get the immutable passes from
    // TargetMachine::addPassesToEmitFile, as they can affect LLVM middle-end optimizations.
    passMgr.add(createPrintModulePass(outStream));
    passMgr.stop();
  }

  if (EmitLlvmBc) {
    // For -emit-llvm-bc, add a pass to output the LLVM IR, then tell the pass manager to stop adding
    // passes. We do it this way to ensure that we still get the immutable passes from
    // TargetMachine::addPassesToEmitFile, as they can affect LLVM middle-end optimizations.
    passMgr.add(createBitcodeWriterPass(outStream));
    passMgr.stop();
  }

  // TODO: We should probably be using InitTargetOptionsFromCodeGenFlags() here.
  // Currently we are not, and it would give an "unused function" warning when compiled with
  // CLANG. So we avoid the warning by referencing it here.
  (void(&codegen::InitTargetOptionsFromCodeGenFlags)); // unused

  if (getTargetMachine()->addPassesToEmitFile(passMgr, outStream, nullptr, codegen::getFileType()))
    report_fatal_error("Target machine cannot emit a file of this type");

  // Stop timer for codegen passes.
  if (codeGenTimer)
    passMgr.add(createStartStopTimer(codeGenTimer, false));
}

// =====================================================================================================================
// Get pass manager cache
PassManagerCache *LgcContext::getPassManagerCache() {
  if (!m_passManagerCache)
    m_passManagerCache = new PassManagerCache(this);
  return m_passManagerCache;
}
<|endoftext|>


<commit_before>//===--- Expr.cpp - Expression Constant Evaluator -------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Expr constant evaluator.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/Support/Compiler.h"

using namespace clang;

#define USE_NEW_EVALUATOR 0

static bool CalcFakeICEVal(const Expr* Expr,
                           llvm::APSInt& Result,
                           ASTContext& Context) {
  // Calculate the value of an expression that has a calculatable
  // value, but isn't an ICE. Currently, this only supports
  // a very narrow set of extensions, but it can be expanded if needed.
  if (const ParenExpr *PE = dyn_cast<ParenExpr>(Expr))
    return CalcFakeICEVal(PE->getSubExpr(), Result, Context);

  if (const CastExpr *CE = dyn_cast<CastExpr>(Expr)) {
    QualType CETy = CE->getType();
    if ((CETy->isIntegralType() && !CETy->isBooleanType()) ||
        CETy->isPointerType()) {
      if (CalcFakeICEVal(CE->getSubExpr(), Result, Context)) {
        Result.extOrTrunc(Context.getTypeSize(CETy));
        // FIXME: This assumes pointers are signed.
        Result.setIsSigned(CETy->isSignedIntegerType() ||
                           CETy->isPointerType());
        return true;
      }
    }
  }

  if (Expr->getType()->isIntegralType())
    return Expr->isIntegerConstantExpr(Result, Context);

  return false;
}

namespace {
class VISIBILITY_HIDDEN PointerExprEvaluator
  : public StmtVisitor<PointerExprEvaluator, APValue> {
  ASTContext &Ctx;

  PointerExprEvaluator(ASTContext &ctx)
    : Ctx(ctx) {}

public:
  static bool Evaluate(const Expr* E, APValue& Result, ASTContext &Ctx) {
    if (!E->getType()->isPointerType())
      return false;
    Result = PointerExprEvaluator(Ctx).Visit(const_cast<Expr*>(E));
    return Result.isLValue();
  }

  APValue VisitStmt(Stmt *S) {
    // FIXME: Remove this when we support more expressions.
    printf("Unhandled pointer statement\n");
    S->dump();
    return APValue();
  }

  APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }

  APValue VisitBinaryOperator(const BinaryOperator *E);
  APValue VisitCastExpr(const CastExpr* E);

};

class VISIBILITY_HIDDEN IntExprEvaluator
  : public StmtVisitor<IntExprEvaluator, APValue> {
  ASTContext &Ctx;

  IntExprEvaluator(ASTContext &ctx)
    : Ctx(ctx) {}

public:
  static bool Evaluate(const Expr* E, llvm::APSInt& Result, ASTContext &Ctx) {
    APValue Value = IntExprEvaluator(Ctx).Visit(const_cast<Expr*>(E));
    if (!Value.isSInt())
      return false;

    Result = Value.getSInt();
    return true;
  }

  //===--------------------------------------------------------------------===//
  //                            Visitor Methods
  //===--------------------------------------------------------------------===//
  APValue VisitStmt(Stmt *S) {
    // FIXME: Remove this when we support more expressions.
    printf("unhandled int expression");
    S->dump();
    return APValue();
  }

  APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }

  APValue VisitBinaryOperator(const BinaryOperator *E);
  APValue VisitUnaryOperator(const UnaryOperator *E);

  APValue HandleCast(const Expr* SubExpr, QualType DestType);
  APValue VisitCastExpr(const CastExpr* E) {
    return HandleCast(E->getSubExpr(), E->getType());
  }
  APValue VisitImplicitCastExpr(const ImplicitCastExpr* E) {
    return HandleCast(E->getSubExpr(), E->getType());
  }
  APValue VisitSizeOfAlignOfTypeExpr(const SizeOfAlignOfTypeExpr *E);

  APValue VisitIntegerLiteral(const IntegerLiteral *E) {
    llvm::APSInt Result(Ctx.getTypeSize(E->getType()));

    Result = E->getValue();
    return APValue(Result);
  }

};

APValue PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E)
{
  if (E->getOpcode() != BinaryOperator::Add &&
      E->getOpcode() != BinaryOperator::Sub)
    return APValue();

  const Expr *PExp = E->getLHS();
  const Expr *IExp = E->getRHS();
  if (IExp->getType()->isPointerType())
  std::swap(PExp, IExp);

  APValue ResultLValue;
  if (!PointerExprEvaluator::Evaluate(PExp, ResultLValue, Ctx))
    return APValue();
  llvm::APSInt AdditionalOffset(32);
  if (!IntExprEvaluator::Evaluate(IExp, AdditionalOffset, Ctx))
    return APValue();

  uint64_t Offset = ResultLValue.getLValueOffset();
  if (E->getOpcode() == BinaryOperator::Add)
    Offset += AdditionalOffset.getZExtValue();
  else
    Offset -= AdditionalOffset.getZExtValue();

  return APValue(ResultLValue.getLValueBase(), Offset);
}

APValue PointerExprEvaluator::VisitCastExpr(const CastExpr* E)
{
  const Expr* SubExpr = E->getSubExpr();

   // Check for pointer->pointer cast
  if (SubExpr->getType()->isPointerType()) {
    APValue Result;
    if (PointerExprEvaluator::Evaluate(SubExpr, Result, Ctx))
      return Result;
    else
      return APValue();
  }

  if (SubExpr->getType()->isArithmeticType()) {
    llvm::APSInt Result(32);
    if (IntExprEvaluator::Evaluate(SubExpr, Result, Ctx)) {
      Result.extOrTrunc(static_cast<uint32_t>(Ctx.getTypeSize(E->getType())));
      return APValue(0, Result.getZExtValue());
    }
  }

  assert(0 && "Unhandled cast");
  return APValue();
}

APValue IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
  // The LHS of a constant expr is always evaluated and needed.
  llvm::APSInt Result(32);
  if (!Evaluate(E->getLHS(), Result, Ctx))
    return APValue();

  llvm::APSInt RHS(32);
  if (!Evaluate(E->getRHS(), RHS, Ctx))
    return APValue();

  switch (E->getOpcode()) {
  default:
    return APValue();
  case BinaryOperator::Mul:
    Result *= RHS;
    break;
  case BinaryOperator::Div:
    if (RHS == 0)
      return APValue();
   Result /= RHS;
     break;
  case BinaryOperator::Rem:
    if (RHS == 0)
      return APValue();
    Result %= RHS;
    break;
  case BinaryOperator::Add: Result += RHS; break;
  case BinaryOperator::Sub: Result -= RHS; break;
  case BinaryOperator::Shl:
    Result <<=
      static_cast<uint32_t>(RHS.getLimitedValue(Result.getBitWidth()-1));
    break;
  case BinaryOperator::Shr:
    Result >>=
      static_cast<uint32_t>(RHS.getLimitedValue(Result.getBitWidth()-1));
    break;
  case BinaryOperator::LT:  Result = Result < RHS; break;
  case BinaryOperator::GT:  Result = Result > RHS; break;
  case BinaryOperator::LE:  Result = Result <= RHS; break;
  case BinaryOperator::GE:  Result = Result >= RHS; break;
  case BinaryOperator::EQ:  Result = Result == RHS; break;
  case BinaryOperator::NE:  Result = Result != RHS; break;
  case BinaryOperator::And: Result &= RHS; break;
  case BinaryOperator::Xor: Result ^= RHS; break;
  case BinaryOperator::Or:  Result |= RHS; break;

  case BinaryOperator::Comma:
    // C99 6.6p3: "shall not contain assignment, ..., or comma operators,
    // *except* when they are contained within a subexpression that is not
    // evaluated".  Note that Assignment can never happen due to constraints
    // on the LHS subexpr, so we don't need to check it here.
    // FIXME: Need to come up with an efficient way to deal with the C99
    // rules on evaluation while still evaluating this.  Maybe a
    // "evaluated comma" out parameter?
    return APValue();
  }

  Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());

  return APValue(Result);
}

APValue IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
  llvm::APSInt Result(32);

  if (E->isOffsetOfOp())
    Result = E->evaluateOffsetOf(Ctx);
  else if (E->isSizeOfAlignOfOp()) {
    // Return the result in the right width.
    Result.zextOrTrunc(static_cast<uint32_t>(Ctx.getTypeSize(E->getType())));

    // sizeof(void) and __alignof__(void) = 1 as a gcc extension.
    if (E->getSubExpr()->getType()->isVoidType())
      Result = 1;

    // sizeof(vla) is not a constantexpr: C99 6.5.3.4p2.
    if (!E->getSubExpr()->getType()->isConstantSizeType()) {
      // FIXME: Should we attempt to evaluate this?
      return APValue();
    }

    // Get information about the size or align.
    if (E->getSubExpr()->getType()->isFunctionType()) {
      // GCC extension: sizeof(function) = 1.
      // FIXME: AlignOf shouldn't be unconditionally 4!
      Result = E->getOpcode() == UnaryOperator::AlignOf ? 4 : 1;
    } else {
      unsigned CharSize = Ctx.Target.getCharWidth();
      if (E->getOpcode() == UnaryOperator::AlignOf)
        Result = Ctx.getTypeAlign(E->getSubExpr()->getType()) / CharSize;
      else
        Result = Ctx.getTypeSize(E->getSubExpr()->getType()) / CharSize;
    }
  } else {
    // Get the operand value.  If this is sizeof/alignof, do not evalute the
    // operand.  This affects C99 6.6p3.
    if (!Evaluate(E->getSubExpr(), Result, Ctx))
      return APValue();

    switch (E->getOpcode()) {
      // Address, indirect, pre/post inc/dec, etc are not valid constant exprs.
      // See C99 6.6p3.
    default:
      return APValue();
    case UnaryOperator::Extension:
      assert(0 && "Handle UnaryOperator::Extension");
      return APValue();
    case UnaryOperator::LNot: {
      bool Val = Result == 0;
      uint32_t typeSize = Ctx.getTypeSize(E->getType());
      Result.zextOrTrunc(typeSize);
      Result = Val;
      break;
    }
    case UnaryOperator::Plus:
      break;
    case UnaryOperator::Minus:
      Result = -Result;
      break;
    case UnaryOperator::Not:
      Result = ~Result;
      break;
    }
  }

  Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
  return APValue(Result);
}

APValue IntExprEvaluator::HandleCast(const Expr* SubExpr, QualType DestType) {
  llvm::APSInt Result(32);

  uint32_t DestWidth = static_cast<uint32_t>(Ctx.getTypeSize(DestType));

  // Handle simple integer->integer casts.
  if (SubExpr->getType()->isIntegerType()) {
    if (!Evaluate(SubExpr, Result, Ctx))
      return APValue();

    // Figure out if this is a truncate, extend or noop cast.
    // If the input is signed, do a sign extend, noop, or truncate.
    if (DestType->isBooleanType()) {
      // Conversion to bool compares against zero.
      Result = Result != 0;
      Result.zextOrTrunc(DestWidth);
    }
    else
      Result.extOrTrunc(DestWidth);
  } else if (SubExpr->getType()->isPointerType()) {
    APValue LV;
    if (!PointerExprEvaluator::Evaluate(SubExpr, LV, Ctx))
      return APValue();
    if (LV.getLValueBase())
      return APValue();

    Result.extOrTrunc(DestWidth);
    Result = LV.getLValueOffset();
  } else {
    assert(0 && "Unhandled cast!");
  }

  Result.setIsUnsigned(DestType->isUnsignedIntegerType());
  return APValue(Result);
}

APValue IntExprEvaluator::VisitSizeOfAlignOfTypeExpr
  (const SizeOfAlignOfTypeExpr *E)
{
  llvm::APSInt Result(32);

  // Return the result in the right width.
  Result.zextOrTrunc(static_cast<uint32_t>(Ctx.getTypeSize(E->getType())));

  // sizeof(void) and __alignof__(void) = 1 as a gcc extension.
  if (E->getArgumentType()->isVoidType()) {
    Result = 1;
    Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
    return APValue(Result);
  }

  // alignof always evaluates to a constant, sizeof does if arg is not VLA.
  if (E->isSizeOf() && !E->getArgumentType()->isConstantSizeType())
    return APValue();

  // Get information about the size or align.
  if (E->getArgumentType()->isFunctionType()) {
    // GCC extension: sizeof(function) = 1.
    Result = E->isSizeOf() ? 1 : 4;
  } else {
    unsigned CharSize = Ctx.Target.getCharWidth();
    if (E->isSizeOf())
      Result = Ctx.getTypeSize(E->getArgumentType()) / CharSize;
    else
      Result = Ctx.getTypeAlign(E->getArgumentType()) / CharSize;
  }

  Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
  return APValue(Result);
}

}

bool Expr::tryEvaluate(APValue& Result, ASTContext &Ctx) const
{
  llvm::APSInt sInt(1);

#if USE_NEW_EVALUATOR
  if (getType()->isIntegerType()) {
    if (IntExprEvaluator::Evaluate(this, sInt, Ctx)) {
      Result = APValue(sInt);
      return true;
    }
  } else
    return false;

#else
  if (CalcFakeICEVal(this, sInt, Ctx)) {
    Result = APValue(sInt);
    return true;
  }
#endif

  return false;
}
<commit_msg>rearrange some code, no functionality changes.<commit_after>//===--- Expr.cpp - Expression Constant Evaluator -------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Expr constant evaluator.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/Support/Compiler.h"
using namespace clang;
using llvm::APSInt;

#define USE_NEW_EVALUATOR 0

static bool CalcFakeICEVal(const Expr *Expr,
                           llvm::APSInt &Result,
                           ASTContext &Context) {
  // Calculate the value of an expression that has a calculatable
  // value, but isn't an ICE. Currently, this only supports
  // a very narrow set of extensions, but it can be expanded if needed.
  if (const ParenExpr *PE = dyn_cast<ParenExpr>(Expr))
    return CalcFakeICEVal(PE->getSubExpr(), Result, Context);

  if (const CastExpr *CE = dyn_cast<CastExpr>(Expr)) {
    QualType CETy = CE->getType();
    if ((CETy->isIntegralType() && !CETy->isBooleanType()) ||
        CETy->isPointerType()) {
      if (CalcFakeICEVal(CE->getSubExpr(), Result, Context)) {
        Result.extOrTrunc(Context.getTypeSize(CETy));
        // FIXME: This assumes pointers are signed.
        Result.setIsSigned(CETy->isSignedIntegerType() ||
                           CETy->isPointerType());
        return true;
      }
    }
  }

  if (Expr->getType()->isIntegralType())
    return Expr->isIntegerConstantExpr(Result, Context);

  return false;
}

static bool EvaluatePointer(const Expr *E, APValue &Result, ASTContext &Ctx);
static bool EvaluateInteger(const Expr *E, APSInt  &Result, ASTContext &Ctx);

//===----------------------------------------------------------------------===//
// Pointer Evaluation
//===----------------------------------------------------------------------===//

namespace {
class VISIBILITY_HIDDEN PointerExprEvaluator
  : public StmtVisitor<PointerExprEvaluator, APValue> {
  ASTContext &Ctx;
public:

  PointerExprEvaluator(ASTContext &ctx) : Ctx(ctx) {}

  APValue VisitStmt(Stmt *S) {
    // FIXME: Remove this when we support more expressions.
    printf("Unhandled pointer statement\n");
    S->dump();
    return APValue();
  }

  APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }

  APValue VisitBinaryOperator(const BinaryOperator *E);
  APValue VisitCastExpr(const CastExpr* E);
};
} // end anonymous namespace

static bool EvaluatePointer(const Expr* E, APValue& Result, ASTContext &Ctx) {
  if (!E->getType()->isPointerType())
    return false;
  Result = PointerExprEvaluator(Ctx).Visit(const_cast<Expr*>(E));
  return Result.isLValue();
}

APValue PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
  if (E->getOpcode() != BinaryOperator::Add &&
      E->getOpcode() != BinaryOperator::Sub)
    return APValue();

  const Expr *PExp = E->getLHS();
  const Expr *IExp = E->getRHS();
  if (IExp->getType()->isPointerType())
    std::swap(PExp, IExp);

  APValue ResultLValue;
  if (!EvaluatePointer(PExp, ResultLValue, Ctx))
    return APValue();

  llvm::APSInt AdditionalOffset(32);
  if (!EvaluateInteger(IExp, AdditionalOffset, Ctx))
    return APValue();

  uint64_t Offset = ResultLValue.getLValueOffset();
  if (E->getOpcode() == BinaryOperator::Add)
    Offset += AdditionalOffset.getZExtValue();
  else
    Offset -= AdditionalOffset.getZExtValue();

  return APValue(ResultLValue.getLValueBase(), Offset);
}

APValue PointerExprEvaluator::VisitCastExpr(const CastExpr* E)
{
  const Expr* SubExpr = E->getSubExpr();

   // Check for pointer->pointer cast
  if (SubExpr->getType()->isPointerType()) {
    APValue Result;
    if (EvaluatePointer(SubExpr, Result, Ctx))
      return Result;
    return APValue();
  }

  if (SubExpr->getType()->isArithmeticType()) {
    llvm::APSInt Result(32);
    if (EvaluateInteger(SubExpr, Result, Ctx)) {
      Result.extOrTrunc(static_cast<uint32_t>(Ctx.getTypeSize(E->getType())));
      return APValue(0, Result.getZExtValue());
    }
  }

  assert(0 && "Unhandled cast");
  return APValue();
}

//===----------------------------------------------------------------------===//
// Integer Evaluation
//===----------------------------------------------------------------------===//

namespace {
class VISIBILITY_HIDDEN IntExprEvaluator
  : public StmtVisitor<IntExprEvaluator, APValue> {
  ASTContext &Ctx;

public:
  IntExprEvaluator(ASTContext &ctx) : Ctx(ctx) {}

  //===--------------------------------------------------------------------===//
  //                            Visitor Methods
  //===--------------------------------------------------------------------===//
  APValue VisitStmt(Stmt *S) {
    // FIXME: Remove this when we support more expressions.
    printf("unhandled int expression");
    S->dump();
    return APValue();
  }

  APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }

  APValue VisitBinaryOperator(const BinaryOperator *E);
  APValue VisitUnaryOperator(const UnaryOperator *E);

  APValue HandleCast(const Expr* SubExpr, QualType DestType);
  APValue VisitCastExpr(const CastExpr* E) {
    return HandleCast(E->getSubExpr(), E->getType());
  }
  APValue VisitImplicitCastExpr(const ImplicitCastExpr* E) {
    return HandleCast(E->getSubExpr(), E->getType());
  }
  APValue VisitSizeOfAlignOfTypeExpr(const SizeOfAlignOfTypeExpr *E);

  APValue VisitIntegerLiteral(const IntegerLiteral *E) {
    llvm::APSInt Result(Ctx.getTypeSize(E->getType()));

    Result = E->getValue();
    return APValue(Result);
  }
};
} // end anonymous namespace

static bool EvaluateInteger(const Expr* E, APSInt &Result, ASTContext &Ctx) {
  APValue Value = IntExprEvaluator(Ctx).Visit(const_cast<Expr*>(E));
  if (!Value.isSInt())
    return false;

  Result = Value.getSInt();
  return true;
}

APValue IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
  // The LHS of a constant expr is always evaluated and needed.
  llvm::APSInt Result(32);
  if (!EvaluateInteger(E->getLHS(), Result, Ctx))
    return APValue();

  llvm::APSInt RHS(32);
  if (!EvaluateInteger(E->getRHS(), RHS, Ctx))
    return APValue();

  switch (E->getOpcode()) {
  default:
    return APValue();
  case BinaryOperator::Mul:
    Result *= RHS;
    break;
  case BinaryOperator::Div:
    if (RHS == 0)
      return APValue();
   Result /= RHS;
     break;
  case BinaryOperator::Rem:
    if (RHS == 0)
      return APValue();
    Result %= RHS;
    break;
  case BinaryOperator::Add: Result += RHS; break;
  case BinaryOperator::Sub: Result -= RHS; break;
  case BinaryOperator::Shl:
    Result <<=
      static_cast<uint32_t>(RHS.getLimitedValue(Result.getBitWidth()-1));
    break;
  case BinaryOperator::Shr:
    Result >>=
      static_cast<uint32_t>(RHS.getLimitedValue(Result.getBitWidth()-1));
    break;
  case BinaryOperator::LT:  Result = Result < RHS; break;
  case BinaryOperator::GT:  Result = Result > RHS; break;
  case BinaryOperator::LE:  Result = Result <= RHS; break;
  case BinaryOperator::GE:  Result = Result >= RHS; break;
  case BinaryOperator::EQ:  Result = Result == RHS; break;
  case BinaryOperator::NE:  Result = Result != RHS; break;
  case BinaryOperator::And: Result &= RHS; break;
  case BinaryOperator::Xor: Result ^= RHS; break;
  case BinaryOperator::Or:  Result |= RHS; break;

  case BinaryOperator::Comma:
    // C99 6.6p3: "shall not contain assignment, ..., or comma operators,
    // *except* when they are contained within a subexpression that is not
    // evaluated".  Note that Assignment can never happen due to constraints
    // on the LHS subexpr, so we don't need to check it here.
    // FIXME: Need to come up with an efficient way to deal with the C99
    // rules on evaluation while still evaluating this.  Maybe a
    // "evaluated comma" out parameter?
    return APValue();
  }

  Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());

  return APValue(Result);
}

APValue IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
  llvm::APSInt Result(32);

  if (E->isOffsetOfOp())
    Result = E->evaluateOffsetOf(Ctx);
  else if (E->isSizeOfAlignOfOp()) {
    // Return the result in the right width.
    Result.zextOrTrunc(static_cast<uint32_t>(Ctx.getTypeSize(E->getType())));

    // sizeof(void) and __alignof__(void) = 1 as a gcc extension.
    if (E->getSubExpr()->getType()->isVoidType())
      Result = 1;

    // sizeof(vla) is not a constantexpr: C99 6.5.3.4p2.
    if (!E->getSubExpr()->getType()->isConstantSizeType()) {
      // FIXME: Should we attempt to evaluate this?
      return APValue();
    }

    // Get information about the size or align.
    if (E->getSubExpr()->getType()->isFunctionType()) {
      // GCC extension: sizeof(function) = 1.
      // FIXME: AlignOf shouldn't be unconditionally 4!
      Result = E->getOpcode() == UnaryOperator::AlignOf ? 4 : 1;
    } else {
      unsigned CharSize = Ctx.Target.getCharWidth();
      if (E->getOpcode() == UnaryOperator::AlignOf)
        Result = Ctx.getTypeAlign(E->getSubExpr()->getType()) / CharSize;
      else
        Result = Ctx.getTypeSize(E->getSubExpr()->getType()) / CharSize;
    }
  } else {
    // Get the operand value.  If this is sizeof/alignof, do not evalute the
    // operand.  This affects C99 6.6p3.
    if (!EvaluateInteger(E->getSubExpr(), Result, Ctx))
      return APValue();

    switch (E->getOpcode()) {
      // Address, indirect, pre/post inc/dec, etc are not valid constant exprs.
      // See C99 6.6p3.
    default:
      return APValue();
    case UnaryOperator::Extension:
      assert(0 && "Handle UnaryOperator::Extension");
      return APValue();
    case UnaryOperator::LNot: {
      bool Val = Result == 0;
      uint32_t typeSize = Ctx.getTypeSize(E->getType());
      Result.zextOrTrunc(typeSize);
      Result = Val;
      break;
    }
    case UnaryOperator::Plus:
      break;
    case UnaryOperator::Minus:
      Result = -Result;
      break;
    case UnaryOperator::Not:
      Result = ~Result;
      break;
    }
  }

  Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
  return APValue(Result);
}

APValue IntExprEvaluator::HandleCast(const Expr* SubExpr, QualType DestType) {
  llvm::APSInt Result(32);

  uint32_t DestWidth = static_cast<uint32_t>(Ctx.getTypeSize(DestType));

  // Handle simple integer->integer casts.
  if (SubExpr->getType()->isIntegerType()) {
    if (!EvaluateInteger(SubExpr, Result, Ctx))
      return APValue();

    // Figure out if this is a truncate, extend or noop cast.
    // If the input is signed, do a sign extend, noop, or truncate.
    if (DestType->isBooleanType()) {
      // Conversion to bool compares against zero.
      Result = Result != 0;
      Result.zextOrTrunc(DestWidth);
    }
    else
      Result.extOrTrunc(DestWidth);
  } else if (SubExpr->getType()->isPointerType()) {
    APValue LV;
    if (!EvaluatePointer(SubExpr, LV, Ctx))
      return APValue();
    if (LV.getLValueBase())
      return APValue();

    Result.extOrTrunc(DestWidth);
    Result = LV.getLValueOffset();
  } else {
    assert(0 && "Unhandled cast!");
  }

  Result.setIsUnsigned(DestType->isUnsignedIntegerType());
  return APValue(Result);
}

APValue IntExprEvaluator::
  VisitSizeOfAlignOfTypeExpr(const SizeOfAlignOfTypeExpr *E) {
  llvm::APSInt Result(32);

  // Return the result in the right width.
  Result.zextOrTrunc(static_cast<uint32_t>(Ctx.getTypeSize(E->getType())));

  // sizeof(void) and __alignof__(void) = 1 as a gcc extension.
  if (E->getArgumentType()->isVoidType()) {
    Result = 1;
    Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
    return APValue(Result);
  }

  // alignof always evaluates to a constant, sizeof does if arg is not VLA.
  if (E->isSizeOf() && !E->getArgumentType()->isConstantSizeType())
    return APValue();

  // Get information about the size or align.
  if (E->getArgumentType()->isFunctionType()) {
    // GCC extension: sizeof(function) = 1.
    Result = E->isSizeOf() ? 1 : 4;
  } else {
    unsigned CharSize = Ctx.Target.getCharWidth();
    if (E->isSizeOf())
      Result = Ctx.getTypeSize(E->getArgumentType()) / CharSize;
    else
      Result = Ctx.getTypeAlign(E->getArgumentType()) / CharSize;
  }

  Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
  return APValue(Result);
}

//===----------------------------------------------------------------------===//
// Top level TryEvaluate.
//===----------------------------------------------------------------------===//

bool Expr::tryEvaluate(APValue& Result, ASTContext &Ctx) const {
  llvm::APSInt sInt(1);

#if USE_NEW_EVALUATOR
  if (getType()->isIntegerType()) {
    if (IntExprEvaluator::Evaluate(this, sInt, Ctx)) {
      Result = APValue(sInt);
      return true;
    }
  } else
    return false;

#else
  if (CalcFakeICEVal(this, sInt, Ctx)) {
    Result = APValue(sInt);
    return true;
  }
#endif

  return false;
}
<|endoftext|>


<commit_before>#include "mainwindow.h"

#include "apitrace.h"
#include "apitracecall.h"

#include "os_string.hpp"
#include "os_process.hpp"

#include <QApplication>
#include <QMetaType>
#include <QVariant>
#include <QImage>

#include <stdio.h>

Q_DECLARE_METATYPE(QList<ApiTraceFrame*>);
Q_DECLARE_METATYPE(QVector<ApiTraceCall*>);
Q_DECLARE_METATYPE(Qt::CaseSensitivity);
Q_DECLARE_METATYPE(ApiTrace::SearchResult);
Q_DECLARE_METATYPE(ApiTrace::SearchRequest);
Q_DECLARE_METATYPE(QList<QImage>);

static void usage(void)
{
    qWarning("usage: qapitrace [options] [TRACE] [CALLNO]\n"
             "Valid options include:\n"
             "    -h, --help            Print this help message\n"
             "    --remote-target HOST  Replay trace on remote target HOST\n");
}

int main(int argc, char **argv)
{
    QApplication::setGraphicsSystem("raster");
    QApplication app(argc, argv);

    qRegisterMetaType<QList<ApiTraceFrame*> >();
    qRegisterMetaType<QVector<ApiTraceCall*> >();
    qRegisterMetaType<ApiTraceState>();
    qRegisterMetaType<Qt::CaseSensitivity>();
    qRegisterMetaType<ApiTrace::SearchResult>();
    qRegisterMetaType<ApiTrace::SearchRequest>();
    qRegisterMetaType<QList<QImage> >();

#ifndef Q_OS_WIN
    os::String currentProcess = os::getProcessName();
    currentProcess.trimFilename();
    QString path = qgetenv("PATH");
    path = QLatin1String(currentProcess.str()) + QLatin1String(":") + path;
    qputenv("PATH", path.toLatin1());
#endif

    QStringList args = app.arguments();
    QString remoteTarget;

    int i = 1;
    while (i < args.count()) {
        QString arg = args[i];
        if (arg[0] != QLatin1Char('-')) {
            break;
        }
        ++i;
        if (arg == QLatin1String("--")) {
            break;
        } else if (arg == QLatin1String("--remote-target")) {
            if (i == args.count()) {
                qWarning("Option --remote-target requires an argument.\n");
                exit(1);
            }
            remoteTarget = args[i];
            ++i;
        } else if (arg == QLatin1String("-h") ||
                   arg == QLatin1String("--help")) {
            usage();
            exit(0);
        } else {
            usage();
            exit(1);
        }
    }

    MainWindow window;
    window.show();

    if (i < args.count()) {
        QString fileName = args[i++];

        int callNum = -1;
        if (i < args.count()) {
            callNum = args[i++].toInt();
        }
        window.loadTrace(fileName, callNum);
    }

    if (remoteTarget.length()) {
        window.setRemoteTarget(remoteTarget);
    }

    app.exec();
}
<commit_msg>gui: Fix includes.<commit_after>#include <stdlib.h>

#include "mainwindow.h"

#include "apitrace.h"
#include "apitracecall.h"

#include "os_string.hpp"
#include "os_process.hpp"

#include <QApplication>
#include <QMetaType>
#include <QVariant>
#include <QImage>

Q_DECLARE_METATYPE(QList<ApiTraceFrame*>);
Q_DECLARE_METATYPE(QVector<ApiTraceCall*>);
Q_DECLARE_METATYPE(Qt::CaseSensitivity);
Q_DECLARE_METATYPE(ApiTrace::SearchResult);
Q_DECLARE_METATYPE(ApiTrace::SearchRequest);
Q_DECLARE_METATYPE(QList<QImage>);

static void usage(void)
{
    qWarning("usage: qapitrace [options] [TRACE] [CALLNO]\n"
             "Valid options include:\n"
             "    -h, --help            Print this help message\n"
             "    --remote-target HOST  Replay trace on remote target HOST\n");
}

int main(int argc, char **argv)
{
    QApplication::setGraphicsSystem("raster");
    QApplication app(argc, argv);

    qRegisterMetaType<QList<ApiTraceFrame*> >();
    qRegisterMetaType<QVector<ApiTraceCall*> >();
    qRegisterMetaType<ApiTraceState>();
    qRegisterMetaType<Qt::CaseSensitivity>();
    qRegisterMetaType<ApiTrace::SearchResult>();
    qRegisterMetaType<ApiTrace::SearchRequest>();
    qRegisterMetaType<QList<QImage> >();

#ifndef Q_OS_WIN
    os::String currentProcess = os::getProcessName();
    currentProcess.trimFilename();
    QString path = qgetenv("PATH");
    path = QLatin1String(currentProcess.str()) + QLatin1String(":") + path;
    qputenv("PATH", path.toLatin1());
#endif

    QStringList args = app.arguments();
    QString remoteTarget;

    int i = 1;
    while (i < args.count()) {
        QString arg = args[i];
        if (arg[0] != QLatin1Char('-')) {
            break;
        }
        ++i;
        if (arg == QLatin1String("--")) {
            break;
        } else if (arg == QLatin1String("--remote-target")) {
            if (i == args.count()) {
                qWarning("Option --remote-target requires an argument.\n");
                exit(1);
            }
            remoteTarget = args[i];
            ++i;
        } else if (arg == QLatin1String("-h") ||
                   arg == QLatin1String("--help")) {
            usage();
            exit(0);
        } else {
            usage();
            exit(1);
        }
    }

    MainWindow window;
    window.show();

    if (i < args.count()) {
        QString fileName = args[i++];

        int callNum = -1;
        if (i < args.count()) {
            callNum = args[i++].toInt();
        }
        window.loadTrace(fileName, callNum);
    }

    if (remoteTarget.length()) {
        window.setRemoteTarget(remoteTarget);
    }

    app.exec();
}
<|endoftext|>


<commit_before>//===--- Diagnostic.cpp - C Language Family Diagnostic Handling -----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements the Diagnostic-related interfaces.
//
//===----------------------------------------------------------------------===//

#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceLocation.h"
#include <cassert>
#include <vector>
#include <map>
#include <cstring>
using namespace clang;

//===----------------------------------------------------------------------===//
// Builtin Diagnostic information
//===----------------------------------------------------------------------===//

/// Flag values for diagnostics.
enum {
  // Diagnostic classes.
  NOTE       = 0x01,
  WARNING    = 0x02,
  EXTENSION  = 0x03,
  EXTWARN    = 0x04,
  ERROR      = 0x05,
  class_mask = 0x07
};

/// DiagnosticFlags - A set of flags, or'd together, that describe the
/// diagnostic.
static unsigned char DiagnosticFlags[] = {
#define DIAG(ENUM,FLAGS,DESC) FLAGS,
#include "clang/Basic/DiagnosticKinds.def"
  0
};

/// getDiagClass - Return the class field of the diagnostic.
///
static unsigned getBuiltinDiagClass(unsigned DiagID) {
  assert(DiagID < diag::NUM_BUILTIN_DIAGNOSTICS &&
         "Diagnostic ID out of range!");
  return DiagnosticFlags[DiagID] & class_mask;
}

/// DiagnosticText - An english message to print for the diagnostic.  These
/// should be localized.
static const char * const DiagnosticText[] = {
#define DIAG(ENUM,FLAGS,DESC) DESC,
#include "clang/Basic/DiagnosticKinds.def"
  0
};

//===----------------------------------------------------------------------===//
// Custom Diagnostic information
//===----------------------------------------------------------------------===//

namespace clang {
  namespace diag {
    class CustomDiagInfo {
      typedef std::pair<Diagnostic::Level, std::string> DiagDesc;
      std::vector<DiagDesc> DiagInfo;
      std::map<DiagDesc, unsigned> DiagIDs;
    public:

      /// getDescription - Return the description of the specified custom
      /// diagnostic.
      const char *getDescription(unsigned DiagID) const {
        assert(this && DiagID-diag::NUM_BUILTIN_DIAGNOSTICS < DiagInfo.size() &&
               "Invalid diagnosic ID");
        return DiagInfo[DiagID-diag::NUM_BUILTIN_DIAGNOSTICS].second.c_str();
      }

      /// getLevel - Return the level of the specified custom diagnostic.
      Diagnostic::Level getLevel(unsigned DiagID) const {
        assert(this && DiagID-diag::NUM_BUILTIN_DIAGNOSTICS < DiagInfo.size() &&
               "Invalid diagnosic ID");
        return DiagInfo[DiagID-diag::NUM_BUILTIN_DIAGNOSTICS].first;
      }

      unsigned getOrCreateDiagID(Diagnostic::Level L, const char *Message) {
        DiagDesc D(L, Message);
        // Check to see if it already exists.
        std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
        if (I != DiagIDs.end() && I->first == D)
          return I->second;

        // If not, assign a new ID.
        unsigned ID = DiagInfo.size()+diag::NUM_BUILTIN_DIAGNOSTICS;
        DiagIDs.insert(std::make_pair(D, ID));
        DiagInfo.push_back(D);
        return ID;
      }
    };

  } // end diag namespace
} // end clang namespace

//===----------------------------------------------------------------------===//
// Common Diagnostic implementation
//===----------------------------------------------------------------------===//

Diagnostic::Diagnostic(DiagnosticClient *client) : Client(client) {
  IgnoreAllWarnings = false;
  WarningsAsErrors = false;
  WarnOnExtensions = false;
  ErrorOnExtensions = false;
  SuppressSystemWarnings = false;
  // Clear all mappings, setting them to MAP_DEFAULT.
  memset(DiagMappings, 0, sizeof(DiagMappings));

  ErrorOccurred = false;
  NumDiagnostics = 0;
  NumErrors = 0;
  CustomDiagInfo = 0;
}

Diagnostic::~Diagnostic() {
  delete CustomDiagInfo;
}

/// getCustomDiagID - Return an ID for a diagnostic with the specified message
/// and level.  If this is the first request for this diagnosic, it is
/// registered and created, otherwise the existing ID is returned.
unsigned Diagnostic::getCustomDiagID(Level L, const char *Message) {
  if (CustomDiagInfo == 0)
    CustomDiagInfo = new diag::CustomDiagInfo();
  return CustomDiagInfo->getOrCreateDiagID(L, Message);
}

/// isBuiltinNoteWarningOrExtension - Return true if the unmapped diagnostic
/// level of the specified diagnostic ID is a Note, Warning, or Extension.
/// Note that this only works on builtin diagnostics, not custom ones.
bool Diagnostic::isBuiltinNoteWarningOrExtension(unsigned DiagID) {
  return DiagID < diag::NUM_BUILTIN_DIAGNOSTICS &&
         getBuiltinDiagClass(DiagID) < ERROR;
}

/// getDescription - Given a diagnostic ID, return a description of the
/// issue.
const char *Diagnostic::getDescription(unsigned DiagID) {
  if (DiagID < diag::NUM_BUILTIN_DIAGNOSTICS)
    return DiagnosticText[DiagID];
  else
    return CustomDiagInfo->getDescription(DiagID);
}

/// getDiagnosticLevel - Based on the way the client configured the Diagnostic
/// object, classify the specified diagnostic ID into a Level, consumable by
/// the DiagnosticClient.
Diagnostic::Level Diagnostic::getDiagnosticLevel(unsigned DiagID) const {
  // Handle custom diagnostics, which cannot be mapped.
  if (DiagID >= diag::NUM_BUILTIN_DIAGNOSTICS)
    return CustomDiagInfo->getLevel(DiagID);

  unsigned DiagClass = getBuiltinDiagClass(DiagID);

  // Specific non-error diagnostics may be mapped to various levels from ignored
  // to error.
  if (DiagClass < ERROR) {
    switch (getDiagnosticMapping((diag::kind)DiagID)) {
    case diag::MAP_DEFAULT: break;
    case diag::MAP_IGNORE:  return Diagnostic::Ignored;
    case diag::MAP_WARNING: DiagClass = WARNING; break;
    case diag::MAP_ERROR:   DiagClass = ERROR; break;
    }
  }

  // Map diagnostic classes based on command line argument settings.
  if (DiagClass == EXTENSION) {
    if (ErrorOnExtensions)
      DiagClass = ERROR;
    else if (WarnOnExtensions)
      DiagClass = WARNING;
    else
      return Ignored;
  } else if (DiagClass == EXTWARN) {
    DiagClass = ErrorOnExtensions ? ERROR : WARNING;
  }

  // If warnings are globally mapped to ignore or error, do it.
  if (DiagClass == WARNING) {
    if (IgnoreAllWarnings)
      return Diagnostic::Ignored;
    if (WarningsAsErrors)
      DiagClass = ERROR;
  }

  switch (DiagClass) {
  default: assert(0 && "Unknown diagnostic class!");
  case NOTE:        return Diagnostic::Note;
  case WARNING:     return Diagnostic::Warning;
  case ERROR:       return Diagnostic::Error;
  }
}

/// Report - Issue the message to the client.
///  DiagID is a member of the diag::kind enum.
void Diagnostic::Report(DiagnosticClient* C,
                        FullSourceLoc Loc, unsigned DiagID,
                        const std::string *Strs, unsigned NumStrs,
                        const SourceRange *Ranges, unsigned NumRanges) {

  // Figure out the diagnostic level of this message.
  Diagnostic::Level DiagLevel = getDiagnosticLevel(DiagID);

  // If the client doesn't care about this message, don't issue it.
  if (DiagLevel == Diagnostic::Ignored)
    return;

  // Set the diagnostic client if it isn't set already.
  if (!C) C = Client;

  // If this is not an error and we are in a system header, ignore it.  We
  // have to check on the original DiagID here, because we also want to
  // ignore extensions and warnings in -Werror and -pedantic-errors modes,
  // which *map* warnings/extensions to errors.
  if (SuppressSystemWarnings &&
      DiagID < diag::NUM_BUILTIN_DIAGNOSTICS &&
      getBuiltinDiagClass(DiagID) != ERROR &&
      Loc.isValid() && Loc.isFileID() && Loc.isInSystemHeader())
    return;

  if (DiagLevel >= Diagnostic::Error) {
    ErrorOccurred = true;

    if (C != 0 && C == Client)
      ++NumErrors;
  }

  // Finally, report it.

  if (C != 0)
    C->HandleDiagnostic(*this, DiagLevel, Loc, (diag::kind)DiagID,
                        Strs, NumStrs, Ranges, NumRanges);

  if (C != 0 && C == Client)
    ++NumDiagnostics;
}

DiagnosticClient::~DiagnosticClient() {}

std::string DiagnosticClient::FormatDiagnostic(Diagnostic &Diags,
                                               Diagnostic::Level Level,
                                               diag::kind ID,
                                               const std::string *Strs,
                                               unsigned NumStrs) {
  std::string Msg = Diags.getDescription(ID);

  // Replace all instances of %0 in Msg with 'Extra'.
  for (unsigned i = 0; i < Msg.size() - 1; ++i) {
    if (Msg[i] == '%' && isdigit(Msg[i + 1])) {
      unsigned StrNo = Msg[i + 1] - '0';
      Msg = std::string(Msg.begin(), Msg.begin() + i) +
            (StrNo < NumStrs ? Strs[StrNo] : "<<<INTERNAL ERROR>>>") +
            std::string(Msg.begin() + i + 2, Msg.end());
    }
  }

  return Msg;
}
<commit_msg>fix rdar://6288301: custom warnings don't respect -Werror.<commit_after>//===--- Diagnostic.cpp - C Language Family Diagnostic Handling -----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements the Diagnostic-related interfaces.
//
//===----------------------------------------------------------------------===//

#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceLocation.h"
#include <cassert>
#include <vector>
#include <map>
#include <cstring>
using namespace clang;

//===----------------------------------------------------------------------===//
// Builtin Diagnostic information
//===----------------------------------------------------------------------===//

/// Flag values for diagnostics.
enum {
  // Diagnostic classes.
  NOTE       = 0x01,
  WARNING    = 0x02,
  EXTENSION  = 0x03,
  EXTWARN    = 0x04,
  ERROR      = 0x05,
  class_mask = 0x07
};

/// DiagnosticFlags - A set of flags, or'd together, that describe the
/// diagnostic.
static unsigned char DiagnosticFlags[] = {
#define DIAG(ENUM,FLAGS,DESC) FLAGS,
#include "clang/Basic/DiagnosticKinds.def"
  0
};

/// getDiagClass - Return the class field of the diagnostic.
///
static unsigned getBuiltinDiagClass(unsigned DiagID) {
  assert(DiagID < diag::NUM_BUILTIN_DIAGNOSTICS &&
         "Diagnostic ID out of range!");
  return DiagnosticFlags[DiagID] & class_mask;
}

/// DiagnosticText - An english message to print for the diagnostic.  These
/// should be localized.
static const char * const DiagnosticText[] = {
#define DIAG(ENUM,FLAGS,DESC) DESC,
#include "clang/Basic/DiagnosticKinds.def"
  0
};

//===----------------------------------------------------------------------===//
// Custom Diagnostic information
//===----------------------------------------------------------------------===//

namespace clang {
  namespace diag {
    class CustomDiagInfo {
      typedef std::pair<Diagnostic::Level, std::string> DiagDesc;
      std::vector<DiagDesc> DiagInfo;
      std::map<DiagDesc, unsigned> DiagIDs;
    public:

      /// getDescription - Return the description of the specified custom
      /// diagnostic.
      const char *getDescription(unsigned DiagID) const {
        assert(this && DiagID-diag::NUM_BUILTIN_DIAGNOSTICS < DiagInfo.size() &&
               "Invalid diagnosic ID");
        return DiagInfo[DiagID-diag::NUM_BUILTIN_DIAGNOSTICS].second.c_str();
      }

      /// getLevel - Return the level of the specified custom diagnostic.
      Diagnostic::Level getLevel(unsigned DiagID) const {
        assert(this && DiagID-diag::NUM_BUILTIN_DIAGNOSTICS < DiagInfo.size() &&
               "Invalid diagnosic ID");
        return DiagInfo[DiagID-diag::NUM_BUILTIN_DIAGNOSTICS].first;
      }

      unsigned getOrCreateDiagID(Diagnostic::Level L, const char *Message,
                                 Diagnostic &Diags) {
        DiagDesc D(L, Message);
        // Check to see if it already exists.
        std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
        if (I != DiagIDs.end() && I->first == D)
          return I->second;

        // If not, assign a new ID.
        unsigned ID = DiagInfo.size()+diag::NUM_BUILTIN_DIAGNOSTICS;
        DiagIDs.insert(std::make_pair(D, ID));
        DiagInfo.push_back(D);

        // If this is a warning, and all warnings are supposed to map to errors,
        // insert the mapping now.
        if (L == Diagnostic::Warning && Diags.getWarningsAsErrors())
          Diags.setDiagnosticMapping((diag::kind)ID, diag::MAP_ERROR);
        return ID;
      }
    };

  } // end diag namespace
} // end clang namespace

//===----------------------------------------------------------------------===//
// Common Diagnostic implementation
//===----------------------------------------------------------------------===//

Diagnostic::Diagnostic(DiagnosticClient *client) : Client(client) {
  IgnoreAllWarnings = false;
  WarningsAsErrors = false;
  WarnOnExtensions = false;
  ErrorOnExtensions = false;
  SuppressSystemWarnings = false;
  // Clear all mappings, setting them to MAP_DEFAULT.
  memset(DiagMappings, 0, sizeof(DiagMappings));

  ErrorOccurred = false;
  NumDiagnostics = 0;
  NumErrors = 0;
  CustomDiagInfo = 0;
}

Diagnostic::~Diagnostic() {
  delete CustomDiagInfo;
}

/// getCustomDiagID - Return an ID for a diagnostic with the specified message
/// and level.  If this is the first request for this diagnosic, it is
/// registered and created, otherwise the existing ID is returned.
unsigned Diagnostic::getCustomDiagID(Level L, const char *Message) {
  if (CustomDiagInfo == 0)
    CustomDiagInfo = new diag::CustomDiagInfo();
  return CustomDiagInfo->getOrCreateDiagID(L, Message, *this);
}

/// isBuiltinNoteWarningOrExtension - Return true if the unmapped diagnostic
/// level of the specified diagnostic ID is a Note, Warning, or Extension.
/// Note that this only works on builtin diagnostics, not custom ones.
bool Diagnostic::isBuiltinNoteWarningOrExtension(unsigned DiagID) {
  return DiagID < diag::NUM_BUILTIN_DIAGNOSTICS &&
         getBuiltinDiagClass(DiagID) < ERROR;
}

/// getDescription - Given a diagnostic ID, return a description of the
/// issue.
const char *Diagnostic::getDescription(unsigned DiagID) {
  if (DiagID < diag::NUM_BUILTIN_DIAGNOSTICS)
    return DiagnosticText[DiagID];
  else
    return CustomDiagInfo->getDescription(DiagID);
}

/// getDiagnosticLevel - Based on the way the client configured the Diagnostic
/// object, classify the specified diagnostic ID into a Level, consumable by
/// the DiagnosticClient.
Diagnostic::Level Diagnostic::getDiagnosticLevel(unsigned DiagID) const {
  // Handle custom diagnostics, which cannot be mapped.
  if (DiagID >= diag::NUM_BUILTIN_DIAGNOSTICS)
    return CustomDiagInfo->getLevel(DiagID);

  unsigned DiagClass = getBuiltinDiagClass(DiagID);

  // Specific non-error diagnostics may be mapped to various levels from ignored
  // to error.
  if (DiagClass < ERROR) {
    switch (getDiagnosticMapping((diag::kind)DiagID)) {
    case diag::MAP_DEFAULT: break;
    case diag::MAP_IGNORE:  return Diagnostic::Ignored;
    case diag::MAP_WARNING: DiagClass = WARNING; break;
    case diag::MAP_ERROR:   DiagClass = ERROR; break;
    }
  }

  // Map diagnostic classes based on command line argument settings.
  if (DiagClass == EXTENSION) {
    if (ErrorOnExtensions)
      DiagClass = ERROR;
    else if (WarnOnExtensions)
      DiagClass = WARNING;
    else
      return Ignored;
  } else if (DiagClass == EXTWARN) {
    DiagClass = ErrorOnExtensions ? ERROR : WARNING;
  }

  // If warnings are globally mapped to ignore or error, do it.
  if (DiagClass == WARNING) {
    if (IgnoreAllWarnings)
      return Diagnostic::Ignored;
    if (WarningsAsErrors)
      DiagClass = ERROR;
  }

  switch (DiagClass) {
  default: assert(0 && "Unknown diagnostic class!");
  case NOTE:        return Diagnostic::Note;
  case WARNING:     return Diagnostic::Warning;
  case ERROR:       return Diagnostic::Error;
  }
}

/// Report - Issue the message to the client.
///  DiagID is a member of the diag::kind enum.
void Diagnostic::Report(DiagnosticClient* C,
                        FullSourceLoc Loc, unsigned DiagID,
                        const std::string *Strs, unsigned NumStrs,
                        const SourceRange *Ranges, unsigned NumRanges) {

  // Figure out the diagnostic level of this message.
  Diagnostic::Level DiagLevel = getDiagnosticLevel(DiagID);

  // If the client doesn't care about this message, don't issue it.
  if (DiagLevel == Diagnostic::Ignored)
    return;

  // Set the diagnostic client if it isn't set already.
  if (!C) C = Client;

  // If this is not an error and we are in a system header, ignore it.  We
  // have to check on the original DiagID here, because we also want to
  // ignore extensions and warnings in -Werror and -pedantic-errors modes,
  // which *map* warnings/extensions to errors.
  if (SuppressSystemWarnings &&
      DiagID < diag::NUM_BUILTIN_DIAGNOSTICS &&
      getBuiltinDiagClass(DiagID) != ERROR &&
      Loc.isValid() && Loc.isFileID() && Loc.isInSystemHeader())
    return;

  if (DiagLevel >= Diagnostic::Error) {
    ErrorOccurred = true;

    if (C != 0 && C == Client)
      ++NumErrors;
  }

  // Finally, report it.

  if (C != 0)
    C->HandleDiagnostic(*this, DiagLevel, Loc, (diag::kind)DiagID,
                        Strs, NumStrs, Ranges, NumRanges);

  if (C != 0 && C == Client)
    ++NumDiagnostics;
}

DiagnosticClient::~DiagnosticClient() {}

std::string DiagnosticClient::FormatDiagnostic(Diagnostic &Diags,
                                               Diagnostic::Level Level,
                                               diag::kind ID,
                                               const std::string *Strs,
                                               unsigned NumStrs) {
  std::string Msg = Diags.getDescription(ID);

  // Replace all instances of %0 in Msg with 'Extra'.
  for (unsigned i = 0; i < Msg.size() - 1; ++i) {
    if (Msg[i] == '%' && isdigit(Msg[i + 1])) {
      unsigned StrNo = Msg[i + 1] - '0';
      Msg = std::string(Msg.begin(), Msg.begin() + i) +
            (StrNo < NumStrs ? Strs[StrNo] : "<<<INTERNAL ERROR>>>") +
            std::string(Msg.begin() + i + 2, Msg.end());
    }
  }

  return Msg;
}
<|endoftext|>


<commit_before>//===-- InstrinsicInst.cpp - Intrinsic Instruction Wrappers -----*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements methods that make it really easy to deal with intrinsic
// functions.
//
// All intrinsic function calls are instances of the call instruction, so these
// are all subclasses of the CallInst class.  Note that none of these classes
// has state or virtual methods, which is an important part of this gross/neat
// hack working.
//
// In some cases, arguments to intrinsics need to be generic and are defined as
// type pointer to empty struct { }*.  To access the real item of interest the
// cast instruction needs to be stripped away.
//
//===----------------------------------------------------------------------===//

#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Metadata.h"
using namespace llvm;

//===----------------------------------------------------------------------===//
/// DbgInfoIntrinsic - This is the common base class for debug info intrinsics
///

static Value *CastOperand(Value *C) {
  if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C))
    if (CE->isCast())
      return CE->getOperand(0);
  return NULL;
}

Value *DbgInfoIntrinsic::StripCast(Value *C) {
  if (Value *CO = CastOperand(C)) {
    C = StripCast(CO);
  } else if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
    if (GV->hasInitializer())
      if (Value *CO = CastOperand(GV->getInitializer()))
        C = StripCast(CO);
  }
  return dyn_cast<GlobalVariable>(C);
}

//===----------------------------------------------------------------------===//
/// DbgDeclareInst - This represents the llvm.dbg.declare instruction.
///

Value *DbgDeclareInst::getAddress() const {
  if (MDNode* MD = cast_or_null<MDNode>(getArgOperand(0)))
    return MD->getOperand(0);
  else
    return NULL;
}

//===----------------------------------------------------------------------===//
/// DbgValueInst - This represents the llvm.dbg.value instruction.
///

const Value *DbgValueInst::getValue() const {
  return cast<MDNode>(getArgOperand(0))->getOperand(0);
}

Value *DbgValueInst::getValue() {
  return cast<MDNode>(getArgOperand(0))->getOperand(0);
}
<commit_msg>Remove spurious emacs major mode marker, these should only go on .h files.<commit_after>//===-- InstrinsicInst.cpp - Intrinsic Instruction Wrappers ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements methods that make it really easy to deal with intrinsic
// functions.
//
// All intrinsic function calls are instances of the call instruction, so these
// are all subclasses of the CallInst class.  Note that none of these classes
// has state or virtual methods, which is an important part of this gross/neat
// hack working.
//
// In some cases, arguments to intrinsics need to be generic and are defined as
// type pointer to empty struct { }*.  To access the real item of interest the
// cast instruction needs to be stripped away.
//
//===----------------------------------------------------------------------===//

#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Metadata.h"
using namespace llvm;

//===----------------------------------------------------------------------===//
/// DbgInfoIntrinsic - This is the common base class for debug info intrinsics
///

static Value *CastOperand(Value *C) {
  if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C))
    if (CE->isCast())
      return CE->getOperand(0);
  return NULL;
}

Value *DbgInfoIntrinsic::StripCast(Value *C) {
  if (Value *CO = CastOperand(C)) {
    C = StripCast(CO);
  } else if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
    if (GV->hasInitializer())
      if (Value *CO = CastOperand(GV->getInitializer()))
        C = StripCast(CO);
  }
  return dyn_cast<GlobalVariable>(C);
}

//===----------------------------------------------------------------------===//
/// DbgDeclareInst - This represents the llvm.dbg.declare instruction.
///

Value *DbgDeclareInst::getAddress() const {
  if (MDNode* MD = cast_or_null<MDNode>(getArgOperand(0)))
    return MD->getOperand(0);
  else
    return NULL;
}

//===----------------------------------------------------------------------===//
/// DbgValueInst - This represents the llvm.dbg.value instruction.
///

const Value *DbgValueInst::getValue() const {
  return cast<MDNode>(getArgOperand(0))->getOperand(0);
}

Value *DbgValueInst::getValue() {
  return cast<MDNode>(getArgOperand(0))->getOperand(0);
}
<|endoftext|>