Adding gflags to handle command line flags.

It sucks, but is the best there is without using boost.
This commit is contained in:
Ben Vanik 2013-01-23 21:31:23 -08:00
parent 01fee047f7
commit 860a0739ec
14 changed files with 183 additions and 35 deletions

3
.gitmodules vendored
View File

@ -7,3 +7,6 @@
[submodule "third_party/gyp"]
path = third_party/gyp
url = https://github.com/benvanik/gyp.git
[submodule "third_party/gflags"]
path = third_party/gflags
url = https://github.com/benvanik/gflags.git

View File

@ -60,6 +60,7 @@
'release': {
'defines': [
'RELEASE',
'NDEBUG',
],
'msvs_configuration_attributes': {
'OutputDirectory': '<(DEPTH)\\build\\xenia\\release',

View File

@ -157,6 +157,7 @@ public:
int GetAllFunctions(vector<FunctionSymbol*>& functions);
void Write(const char* file_name);
void Dump();
void DumpFunctionBlocks(FunctionSymbol* fn);

View File

@ -26,6 +26,8 @@
#include <xenia/cpu/ppc.h>
#include <xenia/cpu/codegen/function_generator.h>
#include "cpu/cpu-private.h"
using namespace llvm;
using namespace xe;
@ -234,7 +236,7 @@ void ModuleGenerator::BuildFunction(CodegenFunction* cgf) {
void ModuleGenerator::OptimizeFunction(Module* m, Function* fn) {
FunctionPassManager pm(m);
#if XE_OPTION(OPTIMIZED)
if (FLAGS_optimize_ir_functions) {
PassManagerBuilder pmb;
pmb.OptLevel = 3;
pmb.SizeLevel = 0;
@ -242,7 +244,7 @@ void ModuleGenerator::OptimizeFunction(Module* m, Function* fn) {
pmb.Vectorize = true;
pmb.LoopVectorize = true;
pmb.populateFunctionPassManager(pm);
#endif // XE_OPTION(OPTIMIZED)
}
pm.add(createVerifierPass());
pm.run(*fn);
}

24
src/cpu/cpu-private.h Normal file
View File

@ -0,0 +1,24 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_CPU_PRIVATE_H_
#define XENIA_CPU_PRIVATE_H_
#include <gflags/gflags.h>
DECLARE_string(dump_path);
DECLARE_bool(dump_module_bitcode);
DECLARE_bool(dump_module_map);
DECLARE_bool(optimize_ir_modules);
DECLARE_bool(optimize_ir_functions);
#endif // XENIA_CPU_PRIVATE_H_

26
src/cpu/cpu.cc Normal file
View File

@ -0,0 +1,26 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "cpu/cpu-private.h"
// Dumping:
DEFINE_string(dump_path, "build/",
"Directory that dump files are placed into.");
DEFINE_bool(dump_module_bitcode, true,
"Writes the module bitcode both before and after optimizations.");
DEFINE_bool(dump_module_map, true,
"Dumps the module symbol database.");
// Optimizations:
DEFINE_bool(optimize_ir_modules, true,
"Whether to run LLVM optimizations on modules.");
DEFINE_bool(optimize_ir_functions, true,
"Whether to run LLVM optimizations on functions.");

View File

@ -31,6 +31,7 @@
#include <xenia/cpu/codegen/module_generator.h>
#include <xenia/cpu/sdb.h>
#include "cpu/cpu-private.h"
#include "cpu/xethunk/xethunk.h"
@ -67,6 +68,8 @@ int ExecModule::Prepare() {
int result_code = 1;
std::string error_message;
char file_name[2048];
OwningPtr<MemoryBuffer> shared_module_buffer;
auto_ptr<Module> shared_module;
auto_ptr<raw_ostream> outs;
@ -80,7 +83,7 @@ int ExecModule::Prepare() {
// Calculate a cache path based on the module, the CPU version, and other
// bits.
// TODO(benvanik): cache path calculation.
const char *cache_path = "build/generated.bc";
//const char *cache_path = "build/generated.bc";
// Check the cache to see if the bitcode exists.
// If it does, load that module directly. In the future we could also cache
@ -104,6 +107,13 @@ int ExecModule::Prepare() {
// Analyze the module and add its symbols to the symbol database.
XEEXPECTZERO(sdb_->Analyze());
// Dump the symbol database.
if (FLAGS_dump_module_map) {
xesnprintf(file_name, XECOUNT(file_name),
"%s%s.map", FLAGS_dump_path.c_str(), module_->name());
sdb_->Write(file_name);
}
// Initialize the module.
gen_module_ = shared_ptr<Module>(
new Module(module_->name(), *context_.get()));
@ -126,14 +136,19 @@ int ExecModule::Prepare() {
context_.get(), gen_module_.get()));
XEEXPECTZERO(codegen_->Generate());
gen_module_->dump();
// Write to cache.
// TODO(benvanik): cache stuff
// Dump pre-optimized module to disk.
if (FLAGS_dump_module_bitcode) {
xesnprintf(file_name, XECOUNT(file_name),
"%s%s-preopt.bc", FLAGS_dump_path.c_str(), module_->name());
outs = auto_ptr<raw_ostream>(new raw_fd_ostream(
cache_path, error_message, raw_fd_ostream::F_Binary));
file_name, error_message, raw_fd_ostream::F_Binary));
XEEXPECTTRUE(error_message.empty());
WriteBitcodeToFile(gen_module_.get(), *outs);
}
}
// Link optimizations.
XEEXPECTZERO(gen_module_->MaterializeAllPermanently(&error_message));
@ -143,7 +158,7 @@ int ExecModule::Prepare() {
// Run full module optimizations.
pm.add(new DataLayout(gen_module_.get()));
#if XE_OPTION(OPTIMIZED)
if (FLAGS_optimize_ir_modules) {
pm.add(createVerifierPass());
pmb.OptLevel = 3;
pmb.SizeLevel = 0;
@ -152,10 +167,20 @@ int ExecModule::Prepare() {
pmb.LoopVectorize = true;
pmb.populateModulePassManager(pm);
pmb.populateLTOPassManager(pm, false, true);
#endif // XE_OPTION(OPTIMIZED)
}
pm.add(createVerifierPass());
pm.run(*gen_module_);
// Dump post-optimized module to disk.
if (FLAGS_optimize_ir_modules && FLAGS_dump_module_bitcode) {
xesnprintf(file_name, XECOUNT(file_name),
"%s%s.bc", FLAGS_dump_path.c_str(), module_->name());
outs = auto_ptr<raw_ostream>(new raw_fd_ostream(
file_name, error_message, raw_fd_ostream::F_Binary));
XEEXPECTTRUE(error_message.empty());
WriteBitcodeToFile(gen_module_.get(), *outs);
}
// TODO(benvanik): experiment with LLD to see if we can write out a dll.
// Initialize the module.
@ -225,6 +250,6 @@ int ExecModule::Uninit() {
}
void ExecModule::Dump() {
// sdb_->Dump();
// gen_module_->dump();
sdb_->Dump();
gen_module_->dump();
}

View File

@ -241,6 +241,10 @@ int SymbolDatabase::GetAllFunctions(vector<FunctionSymbol*>& functions) {
return 0;
}
void SymbolDatabase::Write(const char* file_name) {
// TODO(benvanik): write to file.
}
void SymbolDatabase::Dump() {
uint32_t previous = 0;
for (SymbolMap::iterator it = symbols_.begin(); it != symbols_.end(); ++it) {

View File

@ -1,6 +1,7 @@
# Copyright 2013 Ben Vanik. All Rights Reserved.
{
'sources': [
'cpu.cc',
'exec_module.cc',
'processor.cc',
'sdb.cc',

1
third_party/gflags vendored Submodule

@ -0,0 +1 @@
Subproject commit 56e77c6a2f10020f775cb68022f92fbb38e61804

34
third_party/gflags.gypi vendored Normal file
View File

@ -0,0 +1,34 @@
# Copyright 2013 Ben Vanik. All Rights Reserved.
{
'targets': [
{
'target_name': 'gflags',
'type': 'static_library',
'direct_dependent_settings': {
'include_dirs': [
'gflags/src/',
],
},
'include_dirs': [
'gflags/src/',
],
'sources': [
'gflags/src/gflags.cc',
'gflags/src/gflags_completions.cc',
'gflags/src/gflags_nc.cc',
'gflags/src/gflags_reporting.cc',
],
'conditions': [
['OS == "win"', {
'sources!': [
'gflags/src/windows/port.cc',
],
}],
],
}
]
}

View File

@ -9,6 +9,8 @@
#include <xenia/xenia.h>
#include <gflags/gflags.h>
using namespace xe;
using namespace xe::cpu;
@ -16,6 +18,12 @@ using namespace xe::kernel;
int xenia_info(int argc, xechar_t **argv) {
std::string usage = "usage: ";
usage = usage + argv[0] + " some.xex";
google::SetUsageMessage(usage);
google::SetVersionString("1.0");
google::ParseCommandLineFlags(&argc, &argv, true);
int result_code = 1;
xe_pal_ref pal = NULL;
@ -23,9 +31,9 @@ int xenia_info(int argc, xechar_t **argv) {
shared_ptr<Processor> processor;
shared_ptr<Runtime> runtime;
// TODO(benvanik): real command line parsing.
// Grab path.
if (argc < 2) {
printf("usage: xenia-info some.xex\n");
google::ShowUsageWithFlags(argv[0]);
return 1;
}
const xechar_t *path = argv[1];
@ -51,6 +59,8 @@ int xenia_info(int argc, xechar_t **argv) {
XECLEANUP:
xe_memory_release(memory);
xe_pal_release(pal);
google::ShutDownCommandLineFlags();
return result_code;
}
XE_MAIN_THUNK(xenia_info);

View File

@ -9,6 +9,8 @@
#include <xenia/xenia.h>
#include <gflags/gflags.h>
using namespace xe;
using namespace xe::cpu;
@ -70,14 +72,20 @@ int Run::Launch() {
}
int xenia_run(int argc, xechar_t **argv) {
std::string usage = "usage: ";
usage = usage + argv[0] + " some.xex";
google::SetUsageMessage(usage);
google::SetVersionString("1.0");
google::ParseCommandLineFlags(&argc, &argv, true);
// Dummy call to keep the GPU code linking in to ensure it's working.
do_gpu_stuff();
int result_code = 1;
// TODO(benvanik): real command line parsing.
// Grab path.
if (argc < 2) {
printf("usage: xenia-run some.xex\n");
google::ShowUsageWithFlags(argv[0]);
return 1;
}
const xechar_t *path = argv[1];
@ -91,9 +99,10 @@ int xenia_run(int argc, xechar_t **argv) {
run->Launch();
return 0;
result_code = 0;
XECLEANUP:
google::ShutDownCommandLineFlags();
return result_code;
}
XE_MAIN_THUNK(xenia_run);

View File

@ -3,6 +3,7 @@
'includes': [
'common.gypi',
'tools/tools.gypi',
'third_party/gflags.gypi',
],
'targets': [
@ -11,6 +12,13 @@
'product_name': 'xeniacore',
'type': 'static_library',
'dependencies': [
'gflags',
],
'export_dependent_settings': [
'gflags',
],
'direct_dependent_settings': {
'include_dirs': [
'include/',
@ -36,7 +44,6 @@
'dependencies': [
'xeniacore',
],
'export_dependent_settings': [
'xeniacore',
],