Adding gflags to handle command line flags.
It sucks, but is the best there is without using boost.
This commit is contained in:
parent
01fee047f7
commit
860a0739ec
|
@ -7,3 +7,6 @@
|
||||||
[submodule "third_party/gyp"]
|
[submodule "third_party/gyp"]
|
||||||
path = third_party/gyp
|
path = third_party/gyp
|
||||||
url = https://github.com/benvanik/gyp.git
|
url = https://github.com/benvanik/gyp.git
|
||||||
|
[submodule "third_party/gflags"]
|
||||||
|
path = third_party/gflags
|
||||||
|
url = https://github.com/benvanik/gflags.git
|
||||||
|
|
|
@ -60,6 +60,7 @@
|
||||||
'release': {
|
'release': {
|
||||||
'defines': [
|
'defines': [
|
||||||
'RELEASE',
|
'RELEASE',
|
||||||
|
'NDEBUG',
|
||||||
],
|
],
|
||||||
'msvs_configuration_attributes': {
|
'msvs_configuration_attributes': {
|
||||||
'OutputDirectory': '<(DEPTH)\\build\\xenia\\release',
|
'OutputDirectory': '<(DEPTH)\\build\\xenia\\release',
|
||||||
|
|
|
@ -157,6 +157,7 @@ public:
|
||||||
|
|
||||||
int GetAllFunctions(vector<FunctionSymbol*>& functions);
|
int GetAllFunctions(vector<FunctionSymbol*>& functions);
|
||||||
|
|
||||||
|
void Write(const char* file_name);
|
||||||
void Dump();
|
void Dump();
|
||||||
void DumpFunctionBlocks(FunctionSymbol* fn);
|
void DumpFunctionBlocks(FunctionSymbol* fn);
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
#include <xenia/cpu/ppc.h>
|
#include <xenia/cpu/ppc.h>
|
||||||
#include <xenia/cpu/codegen/function_generator.h>
|
#include <xenia/cpu/codegen/function_generator.h>
|
||||||
|
|
||||||
|
#include "cpu/cpu-private.h"
|
||||||
|
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
using namespace xe;
|
using namespace xe;
|
||||||
|
@ -234,15 +236,15 @@ void ModuleGenerator::BuildFunction(CodegenFunction* cgf) {
|
||||||
|
|
||||||
void ModuleGenerator::OptimizeFunction(Module* m, Function* fn) {
|
void ModuleGenerator::OptimizeFunction(Module* m, Function* fn) {
|
||||||
FunctionPassManager pm(m);
|
FunctionPassManager pm(m);
|
||||||
#if XE_OPTION(OPTIMIZED)
|
if (FLAGS_optimize_ir_functions) {
|
||||||
PassManagerBuilder pmb;
|
PassManagerBuilder pmb;
|
||||||
pmb.OptLevel = 3;
|
pmb.OptLevel = 3;
|
||||||
pmb.SizeLevel = 0;
|
pmb.SizeLevel = 0;
|
||||||
pmb.Inliner = createFunctionInliningPass();
|
pmb.Inliner = createFunctionInliningPass();
|
||||||
pmb.Vectorize = true;
|
pmb.Vectorize = true;
|
||||||
pmb.LoopVectorize = true;
|
pmb.LoopVectorize = true;
|
||||||
pmb.populateFunctionPassManager(pm);
|
pmb.populateFunctionPassManager(pm);
|
||||||
#endif // XE_OPTION(OPTIMIZED)
|
}
|
||||||
pm.add(createVerifierPass());
|
pm.add(createVerifierPass());
|
||||||
pm.run(*fn);
|
pm.run(*fn);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_
|
|
@ -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.");
|
|
@ -31,6 +31,7 @@
|
||||||
#include <xenia/cpu/codegen/module_generator.h>
|
#include <xenia/cpu/codegen/module_generator.h>
|
||||||
#include <xenia/cpu/sdb.h>
|
#include <xenia/cpu/sdb.h>
|
||||||
|
|
||||||
|
#include "cpu/cpu-private.h"
|
||||||
#include "cpu/xethunk/xethunk.h"
|
#include "cpu/xethunk/xethunk.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -67,6 +68,8 @@ int ExecModule::Prepare() {
|
||||||
int result_code = 1;
|
int result_code = 1;
|
||||||
std::string error_message;
|
std::string error_message;
|
||||||
|
|
||||||
|
char file_name[2048];
|
||||||
|
|
||||||
OwningPtr<MemoryBuffer> shared_module_buffer;
|
OwningPtr<MemoryBuffer> shared_module_buffer;
|
||||||
auto_ptr<Module> shared_module;
|
auto_ptr<Module> shared_module;
|
||||||
auto_ptr<raw_ostream> outs;
|
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
|
// Calculate a cache path based on the module, the CPU version, and other
|
||||||
// bits.
|
// bits.
|
||||||
// TODO(benvanik): cache path calculation.
|
// 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.
|
// Check the cache to see if the bitcode exists.
|
||||||
// If it does, load that module directly. In the future we could also cache
|
// 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.
|
// Analyze the module and add its symbols to the symbol database.
|
||||||
XEEXPECTZERO(sdb_->Analyze());
|
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.
|
// Initialize the module.
|
||||||
gen_module_ = shared_ptr<Module>(
|
gen_module_ = shared_ptr<Module>(
|
||||||
new Module(module_->name(), *context_.get()));
|
new Module(module_->name(), *context_.get()));
|
||||||
|
@ -126,13 +136,18 @@ int ExecModule::Prepare() {
|
||||||
context_.get(), gen_module_.get()));
|
context_.get(), gen_module_.get()));
|
||||||
XEEXPECTZERO(codegen_->Generate());
|
XEEXPECTZERO(codegen_->Generate());
|
||||||
|
|
||||||
gen_module_->dump();
|
|
||||||
|
|
||||||
// Write to cache.
|
// Write to cache.
|
||||||
outs = auto_ptr<raw_ostream>(new raw_fd_ostream(
|
// TODO(benvanik): cache stuff
|
||||||
cache_path, error_message, raw_fd_ostream::F_Binary));
|
|
||||||
XEEXPECTTRUE(error_message.empty());
|
// Dump pre-optimized module to disk.
|
||||||
WriteBitcodeToFile(gen_module_.get(), *outs);
|
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(
|
||||||
|
file_name, error_message, raw_fd_ostream::F_Binary));
|
||||||
|
XEEXPECTTRUE(error_message.empty());
|
||||||
|
WriteBitcodeToFile(gen_module_.get(), *outs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Link optimizations.
|
// Link optimizations.
|
||||||
|
@ -143,19 +158,29 @@ int ExecModule::Prepare() {
|
||||||
|
|
||||||
// Run full module optimizations.
|
// Run full module optimizations.
|
||||||
pm.add(new DataLayout(gen_module_.get()));
|
pm.add(new DataLayout(gen_module_.get()));
|
||||||
#if XE_OPTION(OPTIMIZED)
|
if (FLAGS_optimize_ir_modules) {
|
||||||
pm.add(createVerifierPass());
|
pm.add(createVerifierPass());
|
||||||
pmb.OptLevel = 3;
|
pmb.OptLevel = 3;
|
||||||
pmb.SizeLevel = 0;
|
pmb.SizeLevel = 0;
|
||||||
pmb.Inliner = createFunctionInliningPass();
|
pmb.Inliner = createFunctionInliningPass();
|
||||||
pmb.Vectorize = true;
|
pmb.Vectorize = true;
|
||||||
pmb.LoopVectorize = true;
|
pmb.LoopVectorize = true;
|
||||||
pmb.populateModulePassManager(pm);
|
pmb.populateModulePassManager(pm);
|
||||||
pmb.populateLTOPassManager(pm, false, true);
|
pmb.populateLTOPassManager(pm, false, true);
|
||||||
#endif // XE_OPTION(OPTIMIZED)
|
}
|
||||||
pm.add(createVerifierPass());
|
pm.add(createVerifierPass());
|
||||||
pm.run(*gen_module_);
|
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.
|
// TODO(benvanik): experiment with LLD to see if we can write out a dll.
|
||||||
|
|
||||||
// Initialize the module.
|
// Initialize the module.
|
||||||
|
@ -225,6 +250,6 @@ int ExecModule::Uninit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExecModule::Dump() {
|
void ExecModule::Dump() {
|
||||||
// sdb_->Dump();
|
sdb_->Dump();
|
||||||
// gen_module_->dump();
|
gen_module_->dump();
|
||||||
}
|
}
|
||||||
|
|
|
@ -241,6 +241,10 @@ int SymbolDatabase::GetAllFunctions(vector<FunctionSymbol*>& functions) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SymbolDatabase::Write(const char* file_name) {
|
||||||
|
// TODO(benvanik): write to file.
|
||||||
|
}
|
||||||
|
|
||||||
void SymbolDatabase::Dump() {
|
void SymbolDatabase::Dump() {
|
||||||
uint32_t previous = 0;
|
uint32_t previous = 0;
|
||||||
for (SymbolMap::iterator it = symbols_.begin(); it != symbols_.end(); ++it) {
|
for (SymbolMap::iterator it = symbols_.begin(); it != symbols_.end(); ++it) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# Copyright 2013 Ben Vanik. All Rights Reserved.
|
# Copyright 2013 Ben Vanik. All Rights Reserved.
|
||||||
{
|
{
|
||||||
'sources': [
|
'sources': [
|
||||||
|
'cpu.cc',
|
||||||
'exec_module.cc',
|
'exec_module.cc',
|
||||||
'processor.cc',
|
'processor.cc',
|
||||||
'sdb.cc',
|
'sdb.cc',
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 56e77c6a2f10020f775cb68022f92fbb38e61804
|
|
@ -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',
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
],
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
#include <xenia/xenia.h>
|
#include <xenia/xenia.h>
|
||||||
|
|
||||||
|
#include <gflags/gflags.h>
|
||||||
|
|
||||||
|
|
||||||
using namespace xe;
|
using namespace xe;
|
||||||
using namespace xe::cpu;
|
using namespace xe::cpu;
|
||||||
|
@ -16,6 +18,12 @@ using namespace xe::kernel;
|
||||||
|
|
||||||
|
|
||||||
int xenia_info(int argc, xechar_t **argv) {
|
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;
|
int result_code = 1;
|
||||||
|
|
||||||
xe_pal_ref pal = NULL;
|
xe_pal_ref pal = NULL;
|
||||||
|
@ -23,9 +31,9 @@ int xenia_info(int argc, xechar_t **argv) {
|
||||||
shared_ptr<Processor> processor;
|
shared_ptr<Processor> processor;
|
||||||
shared_ptr<Runtime> runtime;
|
shared_ptr<Runtime> runtime;
|
||||||
|
|
||||||
// TODO(benvanik): real command line parsing.
|
// Grab path.
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
printf("usage: xenia-info some.xex\n");
|
google::ShowUsageWithFlags(argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
const xechar_t *path = argv[1];
|
const xechar_t *path = argv[1];
|
||||||
|
@ -51,6 +59,8 @@ int xenia_info(int argc, xechar_t **argv) {
|
||||||
XECLEANUP:
|
XECLEANUP:
|
||||||
xe_memory_release(memory);
|
xe_memory_release(memory);
|
||||||
xe_pal_release(pal);
|
xe_pal_release(pal);
|
||||||
|
|
||||||
|
google::ShutDownCommandLineFlags();
|
||||||
return result_code;
|
return result_code;
|
||||||
}
|
}
|
||||||
XE_MAIN_THUNK(xenia_info);
|
XE_MAIN_THUNK(xenia_info);
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
#include <xenia/xenia.h>
|
#include <xenia/xenia.h>
|
||||||
|
|
||||||
|
#include <gflags/gflags.h>
|
||||||
|
|
||||||
|
|
||||||
using namespace xe;
|
using namespace xe;
|
||||||
using namespace xe::cpu;
|
using namespace xe::cpu;
|
||||||
|
@ -70,14 +72,20 @@ int Run::Launch() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int xenia_run(int argc, xechar_t **argv) {
|
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.
|
// Dummy call to keep the GPU code linking in to ensure it's working.
|
||||||
do_gpu_stuff();
|
do_gpu_stuff();
|
||||||
|
|
||||||
int result_code = 1;
|
int result_code = 1;
|
||||||
|
|
||||||
// TODO(benvanik): real command line parsing.
|
// Grab path.
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
printf("usage: xenia-run some.xex\n");
|
google::ShowUsageWithFlags(argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
const xechar_t *path = argv[1];
|
const xechar_t *path = argv[1];
|
||||||
|
@ -91,9 +99,10 @@ int xenia_run(int argc, xechar_t **argv) {
|
||||||
|
|
||||||
run->Launch();
|
run->Launch();
|
||||||
|
|
||||||
return 0;
|
result_code = 0;
|
||||||
|
|
||||||
XECLEANUP:
|
XECLEANUP:
|
||||||
|
|
||||||
|
google::ShutDownCommandLineFlags();
|
||||||
return result_code;
|
return result_code;
|
||||||
}
|
}
|
||||||
XE_MAIN_THUNK(xenia_run);
|
XE_MAIN_THUNK(xenia_run);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
'includes': [
|
'includes': [
|
||||||
'common.gypi',
|
'common.gypi',
|
||||||
'tools/tools.gypi',
|
'tools/tools.gypi',
|
||||||
|
'third_party/gflags.gypi',
|
||||||
],
|
],
|
||||||
|
|
||||||
'targets': [
|
'targets': [
|
||||||
|
@ -11,6 +12,13 @@
|
||||||
'product_name': 'xeniacore',
|
'product_name': 'xeniacore',
|
||||||
'type': 'static_library',
|
'type': 'static_library',
|
||||||
|
|
||||||
|
'dependencies': [
|
||||||
|
'gflags',
|
||||||
|
],
|
||||||
|
'export_dependent_settings': [
|
||||||
|
'gflags',
|
||||||
|
],
|
||||||
|
|
||||||
'direct_dependent_settings': {
|
'direct_dependent_settings': {
|
||||||
'include_dirs': [
|
'include_dirs': [
|
||||||
'include/',
|
'include/',
|
||||||
|
@ -36,7 +44,6 @@
|
||||||
'dependencies': [
|
'dependencies': [
|
||||||
'xeniacore',
|
'xeniacore',
|
||||||
],
|
],
|
||||||
|
|
||||||
'export_dependent_settings': [
|
'export_dependent_settings': [
|
||||||
'xeniacore',
|
'xeniacore',
|
||||||
],
|
],
|
||||||
|
|
Loading…
Reference in New Issue