Fixing a bunch of valgrind errors and reworking globals.
This commit is contained in:
parent
b29dd22850
commit
791f14182c
|
@ -14,3 +14,8 @@ if [ ! -f "$EXEC" ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
$EXEC "$@"
|
$EXEC "$@"
|
||||||
|
|
||||||
|
|
||||||
|
# TODO(benvanik): add --valgrind and --leaks
|
||||||
|
# xbb --debug && rm valgrind.txt && valgrind --log-file=valgrind.txt --dsymutil=yes build/xenia/debug/xenia-run "$@"
|
||||||
|
# --track-origins=yes --leak-check=full
|
||||||
|
|
|
@ -50,6 +50,7 @@ public:
|
||||||
void Dump();
|
void Dump();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
int InjectGlobals();
|
||||||
int Init();
|
int Init();
|
||||||
int Uninit();
|
int Uninit();
|
||||||
|
|
||||||
|
|
|
@ -10,45 +10,54 @@
|
||||||
#ifndef XENIA_CPU_PPC_STATE_H_
|
#ifndef XENIA_CPU_PPC_STATE_H_
|
||||||
#define XENIA_CPU_PPC_STATE_H_
|
#define XENIA_CPU_PPC_STATE_H_
|
||||||
|
|
||||||
#include <xenia/common.h>
|
|
||||||
|
/**
|
||||||
|
* NOTE: this file is included by xethunk and as such should have a *MINIMAL*
|
||||||
|
* set of dependencies!
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
namespace xe {
|
// namespace FPRF {
|
||||||
namespace cpu {
|
// enum FPRF_e {
|
||||||
namespace ppc {
|
// QUIET_NAN = 0x00088000,
|
||||||
|
// NEG_INFINITY = 0x00090000,
|
||||||
|
// NEG_NORMALIZED = 0x00010000,
|
||||||
|
// NEG_DENORMALIZED = 0x00018000,
|
||||||
|
// NEG_ZERO = 0x00048000,
|
||||||
|
// POS_ZERO = 0x00040000,
|
||||||
|
// POS_DENORMALIZED = 0x00028000,
|
||||||
|
// POS_NORMALIZED = 0x00020000,
|
||||||
|
// POS_INFINITY = 0x000A0000,
|
||||||
|
// };
|
||||||
|
// } // FPRF
|
||||||
|
|
||||||
|
|
||||||
namespace SPR {
|
typedef struct XECACHEALIGN {
|
||||||
enum SPR_e {
|
union {
|
||||||
XER = 1,
|
struct {
|
||||||
LR = 8,
|
float x;
|
||||||
CTR = 9,
|
float y;
|
||||||
|
float z;
|
||||||
|
float w;
|
||||||
|
};
|
||||||
|
float f4[4];
|
||||||
|
struct {
|
||||||
|
uint64_t low;
|
||||||
|
uint64_t high;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
} // SPR
|
} xe_float4_t;
|
||||||
|
|
||||||
|
|
||||||
namespace FPRF {
|
|
||||||
enum FPRF_e {
|
|
||||||
QUIET_NAN = 0x00088000,
|
|
||||||
NEG_INFINITY = 0x00090000,
|
|
||||||
NEG_NORMALIZED = 0x00010000,
|
|
||||||
NEG_DENORMALIZED = 0x00018000,
|
|
||||||
NEG_ZERO = 0x00048000,
|
|
||||||
POS_ZERO = 0x00040000,
|
|
||||||
POS_DENORMALIZED = 0x00028000,
|
|
||||||
POS_NORMALIZED = 0x00020000,
|
|
||||||
POS_INFINITY = 0x000A0000,
|
|
||||||
};
|
|
||||||
} // FPRF
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct XECACHEALIGN64 {
|
typedef struct XECACHEALIGN64 {
|
||||||
uint64_t r[32]; // General purpose registers
|
uint64_t r[32]; // General purpose registers
|
||||||
xefloat4_t v[128]; // VMX128 vector registers
|
xe_float4_t v[128]; // VMX128 vector registers
|
||||||
double f[32]; // Floating-point registers
|
double f[32]; // Floating-point registers
|
||||||
|
|
||||||
uint32_t pc; // Current PC (CIA)
|
uint32_t cia; // Current PC (CIA)
|
||||||
uint32_t npc; // Next PC (NIA)
|
uint32_t nia; // Next PC (NIA)
|
||||||
uint64_t xer; // XER register
|
uint64_t xer; // XER register
|
||||||
uint64_t lr; // Link register
|
uint64_t lr; // Link register
|
||||||
uint64_t ctr; // Count register
|
uint64_t ctr; // Count register
|
||||||
|
@ -109,23 +118,13 @@ typedef struct XECACHEALIGN64 {
|
||||||
} bits;
|
} bits;
|
||||||
} fpscr; // Floating-point status and control register
|
} fpscr; // Floating-point status and control register
|
||||||
|
|
||||||
uint32_t get_fprf() {
|
// uint32_t get_fprf() {
|
||||||
return fpscr.value & 0x000F8000;
|
// return fpscr.value & 0x000F8000;
|
||||||
}
|
// }
|
||||||
void set_fprf(const uint32_t v) {
|
// void set_fprf(const uint32_t v) {
|
||||||
fpscr.value = (fpscr.value & ~0x000F8000) | v;
|
// fpscr.value = (fpscr.value & ~0x000F8000) | v;
|
||||||
}
|
// }
|
||||||
} PpcRegisters;
|
} xe_ppc_state_t;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
PpcRegisters registers;
|
|
||||||
} PpcState;
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace ppc
|
|
||||||
} // namespace cpu
|
|
||||||
} // namespace xe
|
|
||||||
|
|
||||||
|
|
||||||
#endif // XENIA_CPU_PPC_STATE_H_
|
#endif // XENIA_CPU_PPC_STATE_H_
|
||||||
|
|
|
@ -49,6 +49,8 @@ private:
|
||||||
xe_memory_ref memory_;
|
xe_memory_ref memory_;
|
||||||
shared_ptr<llvm::ExecutionEngine> engine_;
|
shared_ptr<llvm::ExecutionEngine> engine_;
|
||||||
|
|
||||||
|
auto_ptr<llvm::LLVMContext> dummy_context_;
|
||||||
|
|
||||||
std::vector<ExecModule*> modules_;
|
std::vector<ExecModule*> modules_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -71,6 +71,8 @@ public:
|
||||||
kTargetNone = 4,
|
kTargetNone = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FunctionBlock();
|
||||||
|
|
||||||
uint32_t start_address;
|
uint32_t start_address;
|
||||||
uint32_t end_address;
|
uint32_t end_address;
|
||||||
|
|
||||||
|
@ -96,7 +98,7 @@ public:
|
||||||
kFlagRestGprLr = 1 << 2,
|
kFlagRestGprLr = 1 << 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
FunctionSymbol() : Symbol(Function) {}
|
FunctionSymbol();
|
||||||
virtual ~FunctionSymbol();
|
virtual ~FunctionSymbol();
|
||||||
|
|
||||||
FunctionBlock* GetBlock(uint32_t address);
|
FunctionBlock* GetBlock(uint32_t address);
|
||||||
|
@ -120,7 +122,7 @@ public:
|
||||||
|
|
||||||
class VariableSymbol : public Symbol {
|
class VariableSymbol : public Symbol {
|
||||||
public:
|
public:
|
||||||
VariableSymbol() : Symbol(Variable) {}
|
VariableSymbol();
|
||||||
virtual ~VariableSymbol();
|
virtual ~VariableSymbol();
|
||||||
|
|
||||||
uint32_t address;
|
uint32_t address;
|
||||||
|
@ -129,7 +131,7 @@ public:
|
||||||
|
|
||||||
class ExceptionEntrySymbol : public Symbol {
|
class ExceptionEntrySymbol : public Symbol {
|
||||||
public:
|
public:
|
||||||
ExceptionEntrySymbol() : Symbol(ExceptionEntry) {}
|
ExceptionEntrySymbol();
|
||||||
virtual ~ExceptionEntrySymbol() {}
|
virtual ~ExceptionEntrySymbol() {}
|
||||||
|
|
||||||
uint32_t address;
|
uint32_t address;
|
||||||
|
|
|
@ -117,21 +117,4 @@ typedef XECACHEALIGN volatile void xe_aligned_void_t;
|
||||||
#define XEIGNORE(expr) do { (void)(expr); } while(0)
|
#define XEIGNORE(expr) do { (void)(expr); } while(0)
|
||||||
|
|
||||||
|
|
||||||
typedef struct XECACHEALIGN {
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
float x;
|
|
||||||
float y;
|
|
||||||
float z;
|
|
||||||
float w;
|
|
||||||
};
|
|
||||||
float f4[4];
|
|
||||||
struct {
|
|
||||||
uint64_t low;
|
|
||||||
uint64_t high;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
} xefloat4_t;
|
|
||||||
|
|
||||||
|
|
||||||
#endif // XENIA_TYPES_H_
|
#endif // XENIA_TYPES_H_
|
||||||
|
|
|
@ -45,9 +45,16 @@ ModuleGenerator::ModuleGenerator(
|
||||||
sdb_ = sdb;
|
sdb_ = sdb;
|
||||||
context_ = context;
|
context_ = context;
|
||||||
gen_module_ = gen_module;
|
gen_module_ = gen_module;
|
||||||
|
di_builder_ = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModuleGenerator::~ModuleGenerator() {
|
ModuleGenerator::~ModuleGenerator() {
|
||||||
|
for (std::map<uint32_t, CodegenFunction*>::iterator it =
|
||||||
|
functions_.begin(); it != functions_.end(); ++it) {
|
||||||
|
delete it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete di_builder_;
|
||||||
xe_memory_release(memory_);
|
xe_memory_release(memory_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +66,7 @@ int ModuleGenerator::Generate() {
|
||||||
// fine grained than this, but for now it's something.
|
// fine grained than this, but for now it's something.
|
||||||
xechar_t dir[2048];
|
xechar_t dir[2048];
|
||||||
XEIGNORE(xestrcpy(dir, XECOUNT(dir), module_->path()));
|
XEIGNORE(xestrcpy(dir, XECOUNT(dir), module_->path()));
|
||||||
xechar_t *slash = xestrrchr(dir, '/');
|
xechar_t* slash = xestrrchr(dir, '/');
|
||||||
if (slash) {
|
if (slash) {
|
||||||
*(slash + 1) = 0;
|
*(slash + 1) = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <llvm/Bitcode/ReaderWriter.h>
|
#include <llvm/Bitcode/ReaderWriter.h>
|
||||||
#include <llvm/ExecutionEngine/GenericValue.h>
|
#include <llvm/ExecutionEngine/GenericValue.h>
|
||||||
#include <llvm/ExecutionEngine/ExecutionEngine.h>
|
#include <llvm/ExecutionEngine/ExecutionEngine.h>
|
||||||
|
#include <llvm/IR/Constants.h>
|
||||||
#include <llvm/IR/DataLayout.h>
|
#include <llvm/IR/DataLayout.h>
|
||||||
#include <llvm/IR/DerivedTypes.h>
|
#include <llvm/IR/DerivedTypes.h>
|
||||||
#include <llvm/IR/LLVMContext.h>
|
#include <llvm/IR/LLVMContext.h>
|
||||||
|
@ -108,6 +109,11 @@ int ExecModule::Prepare() {
|
||||||
new Module(module_->name(), *context_.get()));
|
new Module(module_->name(), *context_.get()));
|
||||||
// TODO(benavnik): addModuleFlag?
|
// TODO(benavnik): addModuleFlag?
|
||||||
|
|
||||||
|
// Inject globals.
|
||||||
|
// This should be done ASAP to ensure that JITed functions can use the
|
||||||
|
// constant addresses.
|
||||||
|
XEEXPECTZERO(InjectGlobals());
|
||||||
|
|
||||||
// Link shared module into generated module.
|
// Link shared module into generated module.
|
||||||
// This gives us a single module that we can optimize and prevents the need
|
// This gives us a single module that we can optimize and prevents the need
|
||||||
// for foreward declarations.
|
// for foreward declarations.
|
||||||
|
@ -165,19 +171,41 @@ XECLEANUP:
|
||||||
return result_code;
|
return result_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ExecModule::InjectGlobals() {
|
||||||
|
LLVMContext& context = *context_.get();
|
||||||
|
const DataLayout* dl = engine_->getDataLayout();
|
||||||
|
Type* voidPtrTy = PointerType::getUnqual(Type::getVoidTy(context));
|
||||||
|
Type* intPtrTy = dl->getIntPtrType(context);
|
||||||
|
GlobalVariable* gv;
|
||||||
|
|
||||||
|
// xe_memory_base
|
||||||
|
// This is the base void* pointer to the memory space.
|
||||||
|
gv = new GlobalVariable(
|
||||||
|
*gen_module_,
|
||||||
|
voidPtrTy,
|
||||||
|
true,
|
||||||
|
GlobalValue::ExternalLinkage,
|
||||||
|
0,
|
||||||
|
"xe_memory_base");
|
||||||
|
// Align to 64b - this makes SSE faster.
|
||||||
|
gv->setAlignment(64);
|
||||||
|
gv->setInitializer(ConstantExpr::getIntToPtr(
|
||||||
|
ConstantInt::get(intPtrTy, (uintptr_t)xe_memory_addr(memory_, 0)),
|
||||||
|
voidPtrTy));
|
||||||
|
|
||||||
|
// xe_ppc_state
|
||||||
|
// ...
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int ExecModule::Init() {
|
int ExecModule::Init() {
|
||||||
// Run static initializers. I'm not sure we'll have any, but who knows.
|
// Run static initializers. I'm not sure we'll have any, but who knows.
|
||||||
engine_->runStaticConstructorsDestructors(gen_module_.get(), false);
|
engine_->runStaticConstructorsDestructors(gen_module_.get(), false);
|
||||||
|
|
||||||
// Prepare init options.
|
|
||||||
xe_module_init_options_t init_options;
|
|
||||||
xe_zero_struct(&init_options, sizeof(init_options));
|
|
||||||
init_options.memory_base = xe_memory_addr(memory_, 0);
|
|
||||||
|
|
||||||
// Grab the init function and call it.
|
// Grab the init function and call it.
|
||||||
Function* xe_module_init = gen_module_->getFunction("xe_module_init");
|
Function* xe_module_init = gen_module_->getFunction("xe_module_init");
|
||||||
std::vector<GenericValue> args;
|
std::vector<GenericValue> args;
|
||||||
args.push_back(GenericValue(&init_options));
|
|
||||||
GenericValue ret = engine_->runFunction(xe_module_init, args);
|
GenericValue ret = engine_->runFunction(xe_module_init, args);
|
||||||
|
|
||||||
return ret.IntVal.getSExtValue();
|
return ret.IntVal.getSExtValue();
|
||||||
|
|
|
@ -71,8 +71,8 @@ int Processor::Setup() {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVMContext* dummy_context = new LLVMContext();
|
dummy_context_ = auto_ptr<LLVMContext>(new LLVMContext());
|
||||||
Module* dummy_module = new Module("dummy", *dummy_context);
|
Module* dummy_module = new Module("dummy", *dummy_context_.get());
|
||||||
|
|
||||||
std::string error_message;
|
std::string error_message;
|
||||||
engine_ = shared_ptr<ExecutionEngine>(
|
engine_ = shared_ptr<ExecutionEngine>(
|
||||||
|
|
|
@ -22,6 +22,19 @@ using namespace xe::cpu::sdb;
|
||||||
using namespace xe::kernel;
|
using namespace xe::kernel;
|
||||||
|
|
||||||
|
|
||||||
|
FunctionBlock::FunctionBlock() :
|
||||||
|
start_address(0), end_address(0),
|
||||||
|
outgoing_type(kTargetUnknown), outgoing_address(0),
|
||||||
|
outgoing_function(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionSymbol::FunctionSymbol() :
|
||||||
|
Symbol(Function),
|
||||||
|
start_address(0), end_address(0), name(0),
|
||||||
|
type(Unknown), flags(0),
|
||||||
|
kernel_export(0), ee(0) {
|
||||||
|
}
|
||||||
|
|
||||||
FunctionSymbol::~FunctionSymbol() {
|
FunctionSymbol::~FunctionSymbol() {
|
||||||
delete name;
|
delete name;
|
||||||
for (std::map<uint32_t, FunctionBlock*>::iterator it = blocks.begin();
|
for (std::map<uint32_t, FunctionBlock*>::iterator it = blocks.begin();
|
||||||
|
@ -68,10 +81,20 @@ FunctionBlock* FunctionSymbol::SplitBlock(uint32_t address) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VariableSymbol::VariableSymbol() :
|
||||||
|
Symbol(Variable),
|
||||||
|
address(0), name(0) {
|
||||||
|
}
|
||||||
|
|
||||||
VariableSymbol::~VariableSymbol() {
|
VariableSymbol::~VariableSymbol() {
|
||||||
delete name;
|
delete name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExceptionEntrySymbol::ExceptionEntrySymbol() :
|
||||||
|
Symbol(ExceptionEntry),
|
||||||
|
address(0), function(0) {
|
||||||
|
}
|
||||||
|
|
||||||
SymbolDatabase::SymbolDatabase(
|
SymbolDatabase::SymbolDatabase(
|
||||||
xe_memory_ref memory, ExportResolver* export_resolver, UserModule* module) {
|
xe_memory_ref memory, ExportResolver* export_resolver, UserModule* module) {
|
||||||
memory_ = xe_memory_retain(memory);
|
memory_ = xe_memory_retain(memory);
|
||||||
|
@ -419,6 +442,7 @@ int SymbolDatabase::AddImports(const xe_xex2_import_library_t* library) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xe_free(import_infos);
|
||||||
xe_xex2_release(xex);
|
xe_xex2_release(xex);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -438,6 +462,7 @@ int SymbolDatabase::AddMethodHints() {
|
||||||
// TODO(benvanik): something with prolog_length?
|
// TODO(benvanik): something with prolog_length?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xe_free(method_infos);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -21,15 +21,16 @@
|
||||||
|
|
||||||
// NOTE: only headers in this directory should be included.
|
// NOTE: only headers in this directory should be included.
|
||||||
#include "xethunk.h"
|
#include "xethunk.h"
|
||||||
|
#include <xenia/cpu/ppc/state.h>
|
||||||
|
|
||||||
|
|
||||||
// The base pointer that all guest addresses should be relative to.
|
// Global CPU state.
|
||||||
static void* xe_memory_base;
|
// Instructions that dereference the state use this.
|
||||||
|
// TODO(benvanik): noalias/invariant/etc?s
|
||||||
|
static xe_ppc_state_t* xe_ppc_state;
|
||||||
|
|
||||||
|
|
||||||
int xe_module_init(xe_module_init_options_t *options) {
|
int xe_module_init() {
|
||||||
xe_memory_base = options->memory_base;
|
|
||||||
|
|
||||||
// TODO(benvanik): setup call table, etc?
|
// TODO(benvanik): setup call table, etc?
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -17,11 +17,4 @@
|
||||||
#define XENIA_CPU_XELIB_H_
|
#define XENIA_CPU_XELIB_H_
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
void* memory_base;
|
|
||||||
|
|
||||||
// TODO(benvanik): execute call thunk
|
|
||||||
} xe_module_init_options_t;
|
|
||||||
|
|
||||||
|
|
||||||
#endif // XENIA_CPU_XELIB_H_
|
#endif // XENIA_CPU_XELIB_H_
|
||||||
|
|
|
@ -2,17 +2,7 @@
|
||||||
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
|
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
|
||||||
target triple = "x86_64-apple-macosx10.8.0"
|
target triple = "x86_64-apple-macosx10.8.0"
|
||||||
|
|
||||||
%struct.xe_module_init_options_t = type { i8* }
|
define i32 @xe_module_init() nounwind uwtable ssp {
|
||||||
|
|
||||||
@xe_memory_base = internal global i8* null, align 8
|
|
||||||
|
|
||||||
define i32 @xe_module_init(%struct.xe_module_init_options_t* %options) nounwind uwtable ssp {
|
|
||||||
%1 = alloca %struct.xe_module_init_options_t*, align 8
|
|
||||||
store %struct.xe_module_init_options_t* %options, %struct.xe_module_init_options_t** %1, align 8
|
|
||||||
%2 = load %struct.xe_module_init_options_t** %1, align 8
|
|
||||||
%3 = getelementptr inbounds %struct.xe_module_init_options_t* %2, i32 0, i32 0
|
|
||||||
%4 = load i8** %3, align 8
|
|
||||||
store i8* %4, i8** @xe_memory_base, align 8
|
|
||||||
ret i32 0
|
ret i32 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -394,7 +394,7 @@ class XethunkCommand(Command):
|
||||||
print ''
|
print ''
|
||||||
|
|
||||||
path = 'src/cpu/xethunk/xethunk'
|
path = 'src/cpu/xethunk/xethunk'
|
||||||
result = shell_call('clang -emit-llvm -O0 -c %s.c -o %s.bc' % (path, path),
|
result = shell_call('clang -emit-llvm -O0 -Iinclude/ -c %s.c -o %s.bc' % (path, path),
|
||||||
throw_on_error=False)
|
throw_on_error=False)
|
||||||
if result != 0:
|
if result != 0:
|
||||||
return result
|
return result
|
||||||
|
|
Loading…
Reference in New Issue