Commit 0aef0d2b authored by Kevin Modzelewski's avatar Kevin Modzelewski

Source control fail: I started pyston from the wrong icbd branch.

Merge in the changesets that were missed:
- type recording
- better polymorphic IC performance
- build system improvements
- update to what was llvm trunk
parent 96f0ba58
......@@ -359,9 +359,6 @@ def _main():
obj = Sphere(Point(1,3,-10), 2)
surf = SimpleSurface((1.0,1.0,0.0))
surf.specularCoefficient = 0.5
surf.lambertCoefficient = 0.5
surf.ambientCoefficient = 0.0
s.addObject(obj.normalAt, obj.intersectionTime, surf.colourAt)
for y in range(6):
obj = Sphere(Point(-3 - y * 0.4, 2.3, -5), 0.4)
......
......@@ -492,7 +492,7 @@ index 2b7bb18..b827cbb 100644
+; Header
; CHECK-NEXT: .long 0
; Num Functions
; CHECK-NEXT: .long 14
; CHECK-NEXT: .long 15
-; CHECK-NEXT: .long _constantargs
-; CHECK-NEXT: .long 8
-; CHECK-NEXT: .long _osrinline
......@@ -521,11 +521,13 @@ index 2b7bb18..b827cbb 100644
-; CHECK-NEXT: .long 56
-; CHECK-NEXT: .long _longid
-; CHECK-NEXT: .long 8
-; CHECK-NEXT: .long _clobberScratch
-; CHECK-NEXT: .long 56
; Num LargeConstants
-; CHECK-NEXT: .long 3
+; CHECK-NEXT: .long 3
+; Num Callsites
+; CHECK-NEXT: .long 18
+; CHECK-NEXT: .long 19
+
+; Functions and stack size
+; CHECK-NEXT: .quad _constantargs
......@@ -556,13 +558,15 @@ index 2b7bb18..b827cbb 100644
+; CHECK-NEXT: .quad 56
+; CHECK-NEXT: .quad _longid
+; CHECK-NEXT: .quad 8
+; CHECK-NEXT: .quad _clobberScratch
+; CHECK-NEXT: .quad 56
+
+; Large Constants
; CHECK-NEXT: .quad 2147483648
; CHECK-NEXT: .quad 4294967295
; CHECK-NEXT: .quad 4294967296
-; Num Callsites
-; CHECK-NEXT: .long 18
-; CHECK-NEXT: .long 19
+; Callsites
; Constant arguments
......
......@@ -130,6 +130,7 @@ COMMON_CXXFLAGS += -I$(DEPS_DIR)/libunwind-1.1-install/include -Wno-extern-c-com
COMMON_CXXFLAGS += -DGITREV=$(shell git rev-parse HEAD | head -c 12) -DLLVMREV=$(LLVM_REVISION)
COMMON_CXXFLAGS += -DDEFAULT_PYTHON_MAJOR_VERSION=$(PYTHON_MAJOR_VERSION) -DDEFAULT_PYTHON_MINOR_VERSION=$(PYTHON_MINOR_VERSION) -DDEFAULT_PYTHON_MICRO_VERSION=$(PYTHON_MICRO_VERSION)
EXTRA_CXXFLAGS ?=
CXXFLAGS := $(LLVM_CXXFLAGS) $(COMMON_CXXFLAGS) -O0 -DBINARY_SUFFIX= -DBINARY_STRIPPED_SUFFIX=_stripped $(EXTRA_CXXFLAGS)
CXXFLAGS_PROFILE = $(LLVM_PROFILE_CXXFLAGS) $(COMMON_CXXFLAGS) -pg -O3 -DNDEBUG -DBINARY_SUFFIX=_release -DBINARY_STRIPPED_SUFFIX= -fno-function-sections $(EXTRA_CXXFLAGS)
CXXFLAGS_RELEASE := $(LLVM_RELEASE_CXXFLAGS) $(COMMON_CXXFLAGS) -O3 -fstrict-aliasing -enable-tbaa -DNDEBUG -DBINARY_SUFFIX=_release -DBINARY_STRIPPED_SUFFIX= $(EXTRA_CXXFLAGS)
......@@ -265,6 +266,13 @@ run_unittests:: run_$1_unittests
)
endef
override GDB_CMDS ?=
override GDB_CMDS := --ex "set confirm off" --ex run --ex "bt 20" $(GDB_CMDS)
BR ?=
ARGS ?=
ifneq ($(BR),)
override GDB_CMDS := --ex "break $(BR)" $(GDB_CMDS)
endif
$(call add_unittest,gc)
$(call add_unittest,analysis)
......@@ -330,6 +338,7 @@ Makefile.local:
# - should rebuild the pyston targets *if and only if* one of their dependencies actually changes in the rebuild
# -- make should report them as "up to date"
LLVM_CONFIGURATION := $(LLVM_BUILD)/Makefile.config
# First, specify when we need to rebuild the different targets:
$(LLVM_BUILD)/built_quick: $(LLVM_SRC)/_patched $(LLVM_CONFIGURATION)
$(MAKE) llvm_quick
......@@ -373,13 +382,12 @@ NONFIRST_LLVM_BUILDS := $(filter-out $(FIRST_LLVM_BUILD),$(LLVM_BUILDS))
llvm: llvm_configs $(LLVM_BUILDS:%=llvm_%)
llvm_configs: $(LLVM_BUILDS:%=llvm/%/tools/llvm-config)
# Use the configure-created Makefile as evidence that llvm has been configured:
LLVM_CONFIGURATION := $(LLVM_BUILD)/Makefile.config
.PHONY: llvm_configure
llvm_configure:
rm -f $(LLVM_BUILD)/Makefile.config
$(MAKE) $(LLVM_CONFIGURATION)
$(LLVM_CONFIGURATION): $(LLVM_SRC)/configure
$(LLVM_CONFIGURATION): $(LLVM_SRC)/configure | $(LLVM_SRC)/_patched
mkdir -p $(LLVM_BUILD)
cd $(LLVM_BUILD) ; \
CXX=$(GPP) $(LLVM_SRC)/configure --enable-targets=host --with-gcc-toolchain=$(GCC_DIR)
......@@ -430,8 +438,12 @@ llvm_install: llvm_release
sudo $(MAKE) -C $(LLVM_SRC)/tools ENABLE_OPTIMIZED=1 DISABLE_ASSERTIONS=1 install
# Clear OPTIONAL_DIRS and OPTIONAL_PARALLEL_DIRS to make sure that clang doesn't get built+tested
llvm_test: llvm_quick
llvm_test: llvm_test_quick
$(MAKE) llvm_test_release
llvm_test_quick: llvm_test_quick
$(MAKE) -C $(LLVM_BUILD) OPTIONAL_DIRS= OPTIONAL_PARALLEL_DIRS= ENABLE_OPTIMIZED=1 check
llvm_test_release: llvm_release
$(MAKE) -C $(LLVM_BUILD) OPTIONAL_DIRS= OPTIONAL_PARALLEL_DIRS= ENABLE_OPTIMIZED=1 DISABLE_ASSERTIONS=1 check
llvm_test_all: llvm_release
$(MAKE) -C $(LLVM_BUILD) ENABLE_OPTIMIZED=1 DISABLE_ASSERTIONS=1 check-all
......@@ -646,10 +658,6 @@ run_release_%: %.py pyston $(RUN_DEPS)
zsh -c 'ulimit -v $(MAX_MEM_KB); ulimit -d $(MAX_MEM_KB); time ./pyston $(ARGS) $<'
$(call make_search,run_release_%)
override GDB_CMDS := --ex "set confirm off" --ex run --ex "bt 20" $(GDB_CMDS)
ifneq ($(BR),)
override GDB_CMDS := --ex "break $(BR)" $(GDB_CMDS)
endif
dbg_release_%: %.py pyston $(RUN_DEPS)
$(GDB) $(GDB_CMDS) --args ./pyston $(ARGS) $<
$(call make_search,dbg_release_%)
......
......@@ -21,6 +21,8 @@
#include "core/ast.h"
#include "core/cfg.h"
#include "codegen/type_recording.h"
#include "analysis/scoping_analysis.h"
#include "analysis/type_analysis.h"
......@@ -97,7 +99,7 @@ class BasicBlockTypePropagator : public ExprVisitor, public StmtVisitor {
assert(old_type);
assert(speculation != TypeAnalysis::NONE);
if (speculated_cls != NULL) {
if (speculated_cls != NULL && speculated_cls->is_constant) {
ConcreteCompilerType* speculated_type = unboxedType(typeFromClass(speculated_cls));
if (VERBOSITY() >= 2) {
printf("in propagator, speculating that %s would actually be %s, at:\n", old_type->debugName().c_str(), speculated_type->debugName().c_str());
......@@ -164,6 +166,11 @@ class BasicBlockTypePropagator : public ExprVisitor, public StmtVisitor {
//rtn = processSpeculation(float_cls, node, rtn);
//}
if (speculation != TypeAnalysis::NONE) {
BoxedClass *speculated_class = predictClassFor(node);
rtn = processSpeculation(speculated_class, node, rtn);
}
if (VERBOSITY() >= 2 && rtn == UNDEF) {
printf("Think %s.%s is undefined, at %d:%d\n", t->debugName().c_str(), node->attr.c_str(), node->lineno, node->col_offset);
print_ast(node);
......
......@@ -129,6 +129,10 @@ int ICSlotRewrite::getScratchBytes() {
return ic->stack_info.scratch_bytes;
}
TypeRecorder* ICSlotRewrite::getTypeRecorder() {
return ic->type_recorder;
}
assembler::GenericRegister ICSlotRewrite::returnRegister() {
return ic->return_register;
}
......@@ -153,7 +157,10 @@ ICSlotInfo* ICInfo::pickEntryForRewrite(uint64_t decision_path, const char* debu
}
}
for (int i = 0; i < getNumSlots(); i++) {
int num_slots = getNumSlots();
for (int _i = 0; _i < num_slots; _i++) {
int i = (_i + next_slot_to_try) % num_slots;
SlotInfo &sinfo = slots[i];
if (sinfo.is_patched && sinfo.decision_path != decision_path) {
continue;
......@@ -162,6 +169,7 @@ ICSlotInfo* ICInfo::pickEntryForRewrite(uint64_t decision_path, const char* debu
if (VERBOSITY()) {
printf("committing %s icentry to in-use slot %d at %p\n", debug_name, i, start_addr);
}
next_slot_to_try++;
sinfo.is_patched = true;
sinfo.decision_path = decision_path;
......@@ -173,7 +181,7 @@ ICSlotInfo* ICInfo::pickEntryForRewrite(uint64_t decision_path, const char* debu
ICInfo::ICInfo(void* start_addr, void* continue_addr, StackInfo stack_info, int num_slots, int slot_size, llvm::CallingConv::ID calling_conv, const std::unordered_set<int> &live_outs, assembler::GenericRegister return_register) : stack_info(stack_info), num_slots(num_slots), slot_size(slot_size), calling_conv(calling_conv), live_outs(live_outs.begin(), live_outs.end()), return_register(return_register), start_addr(start_addr), continue_addr(continue_addr) {
ICInfo::ICInfo(void* start_addr, void* continue_addr, StackInfo stack_info, int num_slots, int slot_size, llvm::CallingConv::ID calling_conv, const std::unordered_set<int> &live_outs, assembler::GenericRegister return_register, TypeRecorder *type_recorder) : next_slot_to_try(0), stack_info(stack_info), num_slots(num_slots), slot_size(slot_size), calling_conv(calling_conv), live_outs(live_outs.begin(), live_outs.end()), return_register(return_register), type_recorder(type_recorder), start_addr(start_addr), continue_addr(continue_addr) {
for (int i = 0; i < num_slots; i++) {
slots.push_back(SlotInfo(this, i));
}
......@@ -234,7 +242,7 @@ void registerCompiledPatchpoint(uint8_t* start_addr, PatchpointSetupInfo* pp, St
writer->jmp(JumpDestination::fromStart(pp->slot_size * (pp->num_slots - i)));
}
ics_by_return_addr[rtn_addr] = new ICInfo(start_addr, end_addr, stack_info, pp->num_slots, pp->slot_size, pp->getCallingConvention(), live_outs, return_register);
ics_by_return_addr[rtn_addr] = new ICInfo(start_addr, end_addr, stack_info, pp->num_slots, pp->slot_size, pp->getCallingConvention(), live_outs, return_register, pp->type_recorder);
}
ICInfo* getICInfo(void* rtn_addr) {
......
......@@ -24,6 +24,8 @@
namespace pyston {
class TypeRecorder;
class ICInfo;
class ICInvalidator;
......@@ -63,6 +65,8 @@ class ICSlotRewrite {
int getScratchRbpOffset();
int getScratchBytes();
TypeRecorder* getTypeRecorder();
assembler::GenericRegister returnRegister();
void addDependenceOn(ICInvalidator&);
......@@ -81,6 +85,11 @@ class ICInfo {
SlotInfo(ICInfo* ic, int idx) : is_patched(false), decision_path(0), entry(ic, idx) {}
};
std::vector<SlotInfo> slots;
// For now, just use a round-robin eviction policy.
// This is probably a bunch worse than LRU, but it's also
// probably a bunch better than the "always evict slot #0" policy
// that it's replacing.
int next_slot_to_try;
const StackInfo stack_info;
const int num_slots;
......@@ -88,6 +97,7 @@ class ICInfo {
const llvm::CallingConv::ID calling_conv;
const std::vector<int> live_outs;
const assembler::GenericRegister return_register;
TypeRecorder * const type_recorder;
// for ICSlotRewrite:
ICSlotInfo *pickEntryForRewrite(uint64_t decision_path, const char* debug_name);
......@@ -95,7 +105,7 @@ class ICInfo {
void* getSlowpathStart();
public:
ICInfo(void* start_addr, void* continue_addr, StackInfo stack_info, int num_slots, int slot_size, llvm::CallingConv::ID calling_conv, const std::unordered_set<int> &live_outs, assembler::GenericRegister return_register);
ICInfo(void* start_addr, void* continue_addr, StackInfo stack_info, int num_slots, int slot_size, llvm::CallingConv::ID calling_conv, const std::unordered_set<int> &live_outs, assembler::GenericRegister return_register, TypeRecorder *type_recorder);
void *const start_addr, *const continue_addr;
int getSlotSize() { return slot_size; }
......
......@@ -88,6 +88,9 @@ bool Location::isClobberedByCall() const {
if (type == Scratch)
return false;
if (type == Constant)
return false;
RELEASE_ASSERT(0, "%d", type);
}
......@@ -107,6 +110,11 @@ void Location::dump() const {
return;
}
if (type == Constant) {
printf("imm(%d)\n", constant_val);
return;
}
RELEASE_ASSERT(0, "%d", type);
}
......@@ -207,6 +215,12 @@ RewriterVarUsage2& RewriterVarUsage2::operator=(RewriterVarUsage2 &&usage) {
return *this;
}
void RewriterVar2::dump() {
printf("RewriterVar2 at %p: %d uses. %ld locations:\n", this, num_uses, locations.size());
for (Location l : locations)
l.dump();
}
assembler::Immediate RewriterVar2::tryGetAsImmediate(bool *is_immediate) {
for (Location l : locations) {
if (l.type == Location::Constant) {
......@@ -436,22 +450,54 @@ RewriterVarUsage2 Rewriter2::call(bool can_call_into_python, void* func_addr, st
for (int i = 0; i < args.size(); i++) {
Location l(Location::forArg(i));
RewriterVar2 *var = args[i].var;
//printf("%d ", i);
//var->dump();
if (!var->isInLocation(l)) {
assembler::Register r = l.asRegister();
assembler::Register r2 = allocReg(l);
assert(r == r2);
assert(vars_by_location.count(l) == 0);
{
// this forces the register allocator to spill this register:
assembler::Register r2 = allocReg(l);
assert(r == r2);
assert(vars_by_location.count(l) == 0);
}
// FIXME: get rid of tryGetAsImmediate
// instead do that work here; ex this could be a stack location
bool is_immediate;
assembler::Immediate imm = var->tryGetAsImmediate(&is_immediate);
assert(is_immediate);
assembler->mov(imm, r);
addLocationToVar(var, l);
if (is_immediate) {
assembler->mov(imm, r);
addLocationToVar(var, l);
} else {
assembler::Register r2 = var->getInReg(l);
assert(var->locations.count(r2));
assert(r2 == r);
}
}
assert(var->isInLocation(Location::forArg(i)));
}
#ifndef NDEBUG
for (int i = 0; i < args.size(); i++) {
RewriterVar2 *var = args[i].var;
if (!var->isInLocation(Location::forArg(i))) {
var->dump();
}
assert(var->isInLocation(Location::forArg(i)));
}
#endif
// This is kind of hacky: we release the use of these right now,
// and then expect that everything else will not clobber any of the arguments.
// Naively moving this below the reg spilling will always spill the arguments;
// but sometimes you need to do that if the argument lives past the call.
// Hacky, but the right way to do it requires a bit of reworking so that it can
// spill but keep its current use.
for (int i = 0; i < args.size(); i++) {
args[i].setDoneUsing();
}
......@@ -490,11 +536,13 @@ RewriterVarUsage2 Rewriter2::call(bool can_call_into_python, void* func_addr, st
for (auto p : vars_by_location) {
Location l = p.first;
//l.dump();
if (l.isClobberedByCall()) {
p.second->dump();
}
assert(!l.isClobberedByCall());
}
#endif
assembler->mov(assembler::Immediate(func_addr), r);
assembler->callq(r);
......@@ -663,6 +711,8 @@ void Rewriter2::addLocationToVar(RewriterVar2 *var, Location l) {
assert(!var->isInLocation(l));
assert(vars_by_location.count(l) == 0);
ASSERT(l.type == Location::Register || l.type == Location::XMMRegister || l.type == Location::Scratch, "%d", l.type);
var->locations.insert(l);
vars_by_location[l] = var;
}
......@@ -683,6 +733,10 @@ RewriterVarUsage2 Rewriter2::createNewVar(Location dest) {
return var;
}
TypeRecorder* Rewriter2::getTypeRecorder() {
return rewrite->getTypeRecorder();
}
Rewriter2::Rewriter2(ICSlotRewrite* rewrite, int num_args, const std::vector<int> &live_outs) :
rewrite(rewrite), assembler(rewrite->getAssembler()),
return_location(rewrite->returnRegister()), done_guarding(false) {
......
......@@ -21,6 +21,8 @@
namespace pyston {
class TypeRecorder;
class ICInfo;
class ICSlotInfo;
class ICSlotRewrite;
......@@ -41,27 +43,36 @@ struct Location {
AnyReg, // special type for use when specifying a location as a destination
None, // special type that represents the lack of a location, ex where a "ret void" gets returned
Uninitialized, // special type for an uninitialized (and invalid) location
};
public:
const LocationType type;
LocationType type;
union {
// only valid if type==Register; uses X86 numbering, not dwarf numbering.
// also valid if type==XMMRegister
const int32_t regnum;
int32_t regnum;
// only valid if type==Stack; this is the offset from bottom of the original frame.
// ie argument #6 will have a stack_offset of 0, #7 will have a stack offset of 8, etc
const int32_t stack_offset;
int32_t stack_offset;
// only valid if type == Scratch; offset from the beginning of the scratch area
const int32_t scratch_offset;
int32_t scratch_offset;
// only valid if type==Constant
const int32_t constant_val;
int32_t constant_val;
const int32_t _data;
int32_t _data;
};
constexpr Location() : type(Uninitialized), _data(-1) {}
constexpr Location(const Location &r) : type(r.type), _data(r._data) {}
Location operator=(const Location &r) {
type = r.type;
_data = r._data;
return *this;
}
constexpr Location(LocationType type, int32_t data) : type(type), _data(data) {
}
......@@ -190,6 +201,8 @@ class RewriterVar2 {
// If this is an immediate, try getting it as one
assembler::Immediate tryGetAsImmediate(bool *is_immediate);
void dump();
public:
void incUse();
void decUse();
......@@ -253,6 +266,8 @@ class Rewriter2 : public ICSlotRewrite::CommitHook {
bool isDoneGuarding() { return done_guarding; }
void setDoneGuarding();
TypeRecorder* getTypeRecorder();
void trap();
RewriterVarUsage2 loadConst(int64_t val, Location loc=Location::any());
RewriterVarUsage2 call(bool can_call_into_python, void* func_addr, std::vector<RewriterVarUsage2> args);
......
......@@ -87,6 +87,7 @@ extern GlobalState g;
// in runtime_hooks.cpp:
void initGlobalFuncs(GlobalState &g);
}
#endif
This diff is collapsed.
This diff is collapsed.
......@@ -17,9 +17,9 @@
#include <iostream>
#include <sstream>
#include "llvm/DIBuilder.h"
#include "llvm/PassManager.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Support/FileSystem.h"
......@@ -86,7 +86,8 @@ static void optimizeIR(llvm::Function *f, EffortLevel::EffortLevel effort) {
llvm::FunctionPassManager fpm(g.cur_module);
fpm.add(new llvm::DataLayout(*g.tm->getDataLayout()));
// TODO: using this as a pass is a legacy cludge that shouldn't be necessary any more; can it be updated?
fpm.add(new llvm::DataLayoutPass(*g.tm->getDataLayout()));
if (ENABLE_INLINING && effort >= EffortLevel::MAXIMAL) fpm.add(makeFPInliner(275));
fpm.add(llvm::createCFGSimplificationPass());
......
......@@ -48,15 +48,10 @@ class PatchpointSetupInfo;
class IREmitter {
public:
enum Target {
INTERPRETER,
COMPILATION,
};
typedef llvm::IRBuilder<true, llvm::ConstantFolder, MyInserter> IRBuilder;
virtual ~IREmitter() {}
virtual Target getTarget() = 0;
virtual IRBuilder* getBuilder() = 0;
virtual GCBuilder* getGC() = 0;
virtual CompiledFunction* currentFunction() = 0;
......@@ -67,6 +62,19 @@ class IREmitter {
CompiledFunction* compileFunction(SourceInfo *source, const OSREntryDescriptor *entry_descriptor, EffortLevel::EffortLevel effort, FunctionSignature *sig, const std::vector<AST_expr*> &arg_names, std::string nameprefix);
class TypeRecorder;
class OpInfo {
private:
const EffortLevel::EffortLevel effort;
TypeRecorder* const type_recorder;
public:
OpInfo(EffortLevel::EffortLevel effort, TypeRecorder* type_recorder) : effort(effort), type_recorder(type_recorder) {
}
bool isInterpreted() const { return effort == EffortLevel::INTERPRETED; }
TypeRecorder* getTypeRecorder() const { return type_recorder; }
};
}
#endif
This diff is collapsed.
......@@ -16,9 +16,9 @@
#include <unordered_map>
#include "llvm/IR/Constants.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/InstIterator.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "core/common.h"
......
......@@ -468,6 +468,7 @@ Box* interpretFunction(llvm::Function *f, int nargs, Box* arg1, Box* arg2, Box*
int arg_start;
if (ci->getCalledFunction() && (ci->getCalledFunction()->getName() == "llvm.experimental.patchpoint.void" || ci->getCalledFunction()->getName() == "llvm.experimental.patchpoint.i64")) {
//ci->dump();
assert(0 && "shouldn't be generating patchpoints for interpretation!");
f = (void*)fetch(ci->getArgOperand(2), dl, symbols).n;
arg_start = 4;
} else {
......@@ -625,7 +626,7 @@ Box* interpretFunction(llvm::Function *f, int nargs, Box* arg1, Box* arg2, Box*
it->dump();
RELEASE_ASSERT(0, "");
RELEASE_ASSERT(1, "");
}
}
......
......@@ -18,7 +18,6 @@
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Support/raw_ostream.h"
#ifndef STANDALONE
......
......@@ -21,9 +21,8 @@
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Pass.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Support/InstIterator.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
......
......@@ -18,17 +18,13 @@
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/PostDominators.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/Pass.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/InstIterator.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Support/raw_ostream.h"
#include "core/common.h"
......@@ -186,7 +182,7 @@ class DeadAllocsPass : public FunctionPass {
AliasAnalysis* aa = &getAnalysis<AliasAnalysis>();
assert(aa);
DataLayout* dl = &getAnalysis<DataLayout>();
const DataLayout* dl = &getAnalysis<DataLayoutPass>().getDataLayout();
assert(dl);
Type *elt_type = cast<PointerType>(ptr->getType())->getElementType();
......@@ -391,7 +387,7 @@ class DeadAllocsPass : public FunctionPass {
virtual void getAnalysisUsage(AnalysisUsage &info) const {
info.setPreservesCFG();
info.addRequiredTransitive<AliasAnalysis>();
info.addRequiredTransitive<DataLayout>();
info.addRequiredTransitive<DataLayoutPass>();
}
virtual bool runOnFunction(Function &F) {
......
......@@ -18,17 +18,13 @@
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/PostDominators.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/Pass.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/InstIterator.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Support/raw_ostream.h"
#include "core/common.h"
......@@ -50,7 +46,7 @@ EscapeAnalysis::~EscapeAnalysis() {
void EscapeAnalysis::getAnalysisUsage(llvm::AnalysisUsage &info) const {
info.setPreservesCFG();
info.addRequiredTransitive<DataLayout>();
info.addRequiredTransitive<DataLayoutPass>();
}
bool EscapeAnalysis::runOnFunction(Function &F) {
......@@ -141,7 +137,7 @@ bool EscapeAnalysis::runOnFunction(Function &F) {
use_it->dump();
(*use_it)->dump();
RELEASE_ASSERT(0, "");
}
}
......
......@@ -16,12 +16,12 @@
#include "llvm/PassManager.h"
#include "llvm/Analysis/InlineCost.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Support/InstIterator.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
......
......@@ -17,16 +17,12 @@
#include <set>
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/PostDominators.h"
#include "llvm/Pass.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/InstIterator.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/PostDominators.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Support/raw_ostream.h"
#include "core/common.h"
......
......@@ -41,11 +41,11 @@ int64_t PatchpointSetupInfo::getPatchpointId() const {
static std::unordered_map<int64_t, PatchpointSetupInfo*> new_patchpoints_by_id;
PatchpointSetupInfo* PatchpointSetupInfo::initialize(bool has_return_value, int num_slots, int slot_size, CompiledFunction *parent_cf, patchpoints::PatchpointType type) {
PatchpointSetupInfo* PatchpointSetupInfo::initialize(bool has_return_value, int num_slots, int slot_size, CompiledFunction *parent_cf, patchpoints::PatchpointType type, TypeRecorder* type_recorder) {
static int64_t next_id = 100;
int64_t id = next_id++;
PatchpointSetupInfo* rtn = new PatchpointSetupInfo(id, type, num_slots, slot_size, parent_cf, has_return_value);
PatchpointSetupInfo* rtn = new PatchpointSetupInfo(id, type, num_slots, slot_size, parent_cf, has_return_value, type_recorder);
new_patchpoints_by_id[id] = rtn;
return rtn;
}
......@@ -111,40 +111,40 @@ void processStackmap(StackMap* stackmap) {
new_patchpoints_by_id.clear();
}
PatchpointSetupInfo* createGenericPatchpoint(CompiledFunction *parent_cf, bool has_return_value, int size) {
return PatchpointSetupInfo::initialize(has_return_value, 1, size, parent_cf, Generic);
PatchpointSetupInfo* createGenericPatchpoint(CompiledFunction *parent_cf, TypeRecorder* type_recorder, bool has_return_value, int size) {
return PatchpointSetupInfo::initialize(has_return_value, 1, size, parent_cf, Generic, type_recorder);
}
PatchpointSetupInfo* createGetattrPatchpoint(CompiledFunction *parent_cf) {
return PatchpointSetupInfo::initialize(true, 1, 128, parent_cf, Getattr);
PatchpointSetupInfo* createGetattrPatchpoint(CompiledFunction *parent_cf, TypeRecorder* type_recorder) {
return PatchpointSetupInfo::initialize(true, 1, 128, parent_cf, Getattr, type_recorder);
}
PatchpointSetupInfo* createGetitemPatchpoint(CompiledFunction *parent_cf) {
return PatchpointSetupInfo::initialize(true, 1, 128, parent_cf, Getitem);
PatchpointSetupInfo* createGetitemPatchpoint(CompiledFunction *parent_cf, TypeRecorder* type_recorder) {
return PatchpointSetupInfo::initialize(true, 1, 128, parent_cf, Getitem, type_recorder);
}
PatchpointSetupInfo* createSetitemPatchpoint(CompiledFunction *parent_cf) {
return PatchpointSetupInfo::initialize(true, 1, 144, parent_cf, Setitem);
PatchpointSetupInfo* createSetitemPatchpoint(CompiledFunction *parent_cf, TypeRecorder* type_recorder) {
return PatchpointSetupInfo::initialize(true, 1, 144, parent_cf, Setitem, type_recorder);
}
PatchpointSetupInfo* createSetattrPatchpoint(CompiledFunction *parent_cf) {
return PatchpointSetupInfo::initialize(false, 2, 128, parent_cf, Setattr);
PatchpointSetupInfo* createSetattrPatchpoint(CompiledFunction *parent_cf, TypeRecorder* type_recorder) {
return PatchpointSetupInfo::initialize(false, 2, 128, parent_cf, Setattr, type_recorder);
}
PatchpointSetupInfo* createCallsitePatchpoint(CompiledFunction *parent_cf, int num_args) {
return PatchpointSetupInfo::initialize(true, 3, 256 + 36 * num_args, parent_cf, Callsite);
PatchpointSetupInfo* createCallsitePatchpoint(CompiledFunction *parent_cf, TypeRecorder* type_recorder, int num_args) {
return PatchpointSetupInfo::initialize(true, 3, 256 + 36 * num_args, parent_cf, Callsite, type_recorder);
}
PatchpointSetupInfo* createGetGlobalPatchpoint(CompiledFunction *parent_cf) {
return PatchpointSetupInfo::initialize(true, 1, 80, parent_cf, GetGlobal);
PatchpointSetupInfo* createGetGlobalPatchpoint(CompiledFunction *parent_cf, TypeRecorder* type_recorder) {
return PatchpointSetupInfo::initialize(true, 1, 80, parent_cf, GetGlobal, type_recorder);
}
PatchpointSetupInfo* createBinexpPatchpoint(CompiledFunction *parent_cf) {
return PatchpointSetupInfo::initialize(true, 4, 196, parent_cf, Binexp);
PatchpointSetupInfo* createBinexpPatchpoint(CompiledFunction *parent_cf, TypeRecorder* type_recorder) {
return PatchpointSetupInfo::initialize(true, 4, 196, parent_cf, Binexp, type_recorder);
}
PatchpointSetupInfo* createNonzeroPatchpoint(CompiledFunction *parent_cf) {
return PatchpointSetupInfo::initialize(true, 1, 64, parent_cf, Nonzero);
PatchpointSetupInfo* createNonzeroPatchpoint(CompiledFunction *parent_cf, TypeRecorder* type_recorder) {
return PatchpointSetupInfo::initialize(true, 2, 64, parent_cf, Nonzero, type_recorder);
}
} // namespace patchpoints
......
......@@ -22,6 +22,8 @@
namespace pyston {
class TypeRecorder;
namespace patchpoints {
enum PatchpointType {
......@@ -42,8 +44,8 @@ class CompiledFunction;
class PatchpointSetupInfo {
private:
PatchpointSetupInfo(int64_t pp_id, patchpoints::PatchpointType type, int num_slots, int slot_size, CompiledFunction* parent_cf, bool has_return_value) :
pp_id(pp_id), type(type), num_slots(num_slots), slot_size(slot_size), has_return_value(has_return_value), parent_cf(parent_cf) {
PatchpointSetupInfo(int64_t pp_id, patchpoints::PatchpointType type, int num_slots, int slot_size, CompiledFunction* parent_cf, bool has_return_value, TypeRecorder *type_recorder) :
pp_id(pp_id), type(type), num_slots(num_slots), slot_size(slot_size), has_return_value(has_return_value), parent_cf(parent_cf), type_recorder(type_recorder) {
}
const int64_t pp_id;
......@@ -53,7 +55,7 @@ class PatchpointSetupInfo {
const int num_slots, slot_size;
const bool has_return_value;
CompiledFunction * const parent_cf;
void* metadata;
TypeRecorder *const type_recorder;
int totalSize() const;
int64_t getPatchpointId() const;
......@@ -70,7 +72,7 @@ class PatchpointSetupInfo {
return llvm::CallingConv::C;
}
static PatchpointSetupInfo* initialize(bool has_return_value, int num_slots, int slot_size, CompiledFunction* parent_cf, patchpoints::PatchpointType type);
static PatchpointSetupInfo* initialize(bool has_return_value, int num_slots, int slot_size, CompiledFunction* parent_cf, patchpoints::PatchpointType type, TypeRecorder *type_recorder);
};
struct StackMap;
......@@ -79,15 +81,15 @@ namespace patchpoints {
void processStackmap(StackMap* stackmap);
PatchpointSetupInfo* createGenericPatchpoint(CompiledFunction* parent_cf, bool has_return_value, int size);
PatchpointSetupInfo* createCallsitePatchpoint(CompiledFunction* parent_cf, int num_args);
PatchpointSetupInfo* createGetGlobalPatchpoint(CompiledFunction* parent_cf);
PatchpointSetupInfo* createGetattrPatchpoint(CompiledFunction* parent_cf);
PatchpointSetupInfo* createSetattrPatchpoint(CompiledFunction* parent_cf);
PatchpointSetupInfo* createGetitemPatchpoint(CompiledFunction* parent_cf);
PatchpointSetupInfo* createSetitemPatchpoint(CompiledFunction* parent_cf);
PatchpointSetupInfo* createBinexpPatchpoint(CompiledFunction* parent_cf);
PatchpointSetupInfo* createNonzeroPatchpoint(CompiledFunction* parent_cf);
PatchpointSetupInfo* createGenericPatchpoint(CompiledFunction* parent_cf, TypeRecorder *type_recorder, bool has_return_value, int size);
PatchpointSetupInfo* createCallsitePatchpoint(CompiledFunction* parent_cf, TypeRecorder *type_recorder, int num_args);
PatchpointSetupInfo* createGetGlobalPatchpoint(CompiledFunction* parent_cf, TypeRecorder *type_recorder);
PatchpointSetupInfo* createGetattrPatchpoint(CompiledFunction* parent_cf, TypeRecorder *type_recorder);
PatchpointSetupInfo* createSetattrPatchpoint(CompiledFunction* parent_cf, TypeRecorder *type_recorder);
PatchpointSetupInfo* createGetitemPatchpoint(CompiledFunction* parent_cf, TypeRecorder *type_recorder);
PatchpointSetupInfo* createSetitemPatchpoint(CompiledFunction* parent_cf, TypeRecorder *type_recorder);
PatchpointSetupInfo* createBinexpPatchpoint(CompiledFunction* parent_cf, TypeRecorder *type_recorder);
PatchpointSetupInfo* createNonzeroPatchpoint(CompiledFunction* parent_cf, TypeRecorder *type_recorder);
}
......
// Copyright (c) 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <unordered_map>
#include "core/options.h"
#include "core/types.h"
#include "codegen/type_recording.h"
namespace pyston {
static std::unordered_map<AST*, TypeRecorder*> type_recorders;
TypeRecorder* getTypeRecorderForNode(AST* node) {
TypeRecorder* &r = type_recorders[node];
if (r == NULL)
r = new TypeRecorder();
return r;
}
Box* recordType(TypeRecorder* self, Box* obj) {
BoxedClass *cls = obj->cls;
if (cls != self->last_seen) {
self->last_seen = cls;
self->last_count = 1;
} else {
self->last_count++;
}
//printf("Seen %s %ld times\n", getNameOfClass(cls)->c_str(), self->last_count);
return obj;
}
BoxedClass* predictClassFor(AST* node) {
auto it = type_recorders.find(node);
if (it == type_recorders.end())
return NULL;
TypeRecorder* r = it->second;
return r->predict();
}
BoxedClass* TypeRecorder::predict() {
if (!ENABLE_TYPE_FEEDBACK)
return NULL;
if (last_count > 100)
return last_seen;
return NULL;
}
}
// Copyright (c) 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PYSTON_CODEGEN_TYPERECORDING_H
#define PYSTON_CODEGEN_TYPERECORDING_H
namespace pyston {
class AST;
class Box;
class BoxedClass;
class TypeRecorder;
// Have this be a non-function-scoped friend function;
// the benefit of doing it this way, as opposed to being a member function,
// is that we can extern "C" and get a guaranteed ABI, for calling from the patchpoints.
// (I think most compilers pass "this" as the argument 0 and then shift the rest of the
// arguments, but I'd rather not depend on that behavior since I can't find where that's
// specified.)
extern "C" Box* recordType(TypeRecorder *recorder, Box* obj);
class TypeRecorder {
private:
BoxedClass *last_seen;
int64_t last_count;
public:
constexpr TypeRecorder() : last_seen(NULL), last_count(0) {}
BoxedClass* predict();
friend Box* recordType(TypeRecorder*, Box*);
};
TypeRecorder* getTypeRecorderForNode(AST* node);
BoxedClass* predictClassFor(AST* node);
}
#endif
......@@ -16,8 +16,8 @@
#include <sys/types.h>
#include <unistd.h>
#include "llvm/DebugInfo.h"
#include "llvm/DebugInfo/DIContext.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/ExecutionEngine/JITEventListener.h"
#include "llvm/ExecutionEngine/ObjectImage.h"
......
......@@ -50,5 +50,6 @@ bool ENABLE_LLVMOPTS = 1 && _GLOBAL_ENABLE;
bool ENABLE_INLINING = 1 && _GLOBAL_ENABLE;
bool ENABLE_REOPT = 1 && _GLOBAL_ENABLE;
bool ENABLE_PYSTON_PASSES = 1 && _GLOBAL_ENABLE;
bool ENABLE_TYPE_FEEDBACK = 1 && _GLOBAL_ENABLE;
}
......@@ -28,7 +28,7 @@ extern int MAX_OPT_ITERATIONS;
extern bool SHOW_DISASM, FORCE_OPTIMIZE, BENCH, PROFILE, DUMPJIT, TRAP, USE_STRIPPED_STDLIB, ENABLE_INTERPRETER;
extern bool ENABLE_ICS, ENABLE_ICGENERICS, ENABLE_ICGETITEMS, ENABLE_ICSETITEMS, ENABLE_ICBINEXPS, ENABLE_ICNONZEROS, ENABLE_ICCALLSITES, ENABLE_ICSETATTRS, ENABLE_ICGETATTRS, ENABLE_ICGETGLOBALS, ENABLE_SPECULATION, ENABLE_OSR, ENABLE_LLVMOPTS, ENABLE_INLINING, ENABLE_REOPT, ENABLE_PYSTON_PASSES;
extern bool ENABLE_ICS, ENABLE_ICGENERICS, ENABLE_ICGETITEMS, ENABLE_ICSETITEMS, ENABLE_ICBINEXPS, ENABLE_ICNONZEROS, ENABLE_ICCALLSITES, ENABLE_ICSETATTRS, ENABLE_ICGETATTRS, ENABLE_ICGETGLOBALS, ENABLE_SPECULATION, ENABLE_OSR, ENABLE_LLVMOPTS, ENABLE_INLINING, ENABLE_REOPT, ENABLE_PYSTON_PASSES, ENABLE_TYPE_FEEDBACK;
}
}
......
......@@ -367,6 +367,7 @@ extern "C" BoxedModule* createModule(const std::string *name, const std::string
std::string getPythonFuncAt(void* ip, void* sp);
}
#endif
......@@ -346,9 +346,13 @@ Box* floatNeg(BoxedFloat *self) {
return boxFloat(-self->d);
}
Box* floatNonzero(BoxedFloat *self) {
bool floatNonzeroUnboxed(BoxedFloat *self) {
assert(self->cls == float_cls);
return boxBool(self->d != 0.0);
return self->d != 0.0;
}
Box* floatNonzero(BoxedFloat *self) {
return boxBool(floatNonzeroUnboxed(self));
}
std::string floatFmt(double x, int precision, char code) {
......@@ -509,7 +513,10 @@ void setupFloat() {
float_cls->giveAttr("__new__", new BoxedFunction(__new__));
float_cls->giveAttr("__neg__", new BoxedFunction(boxRTFunction((void*)floatNeg, NULL, 1, false)));
float_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)floatNonzero, NULL, 1, false)));
CLFunction *nonzero = boxRTFunction((void*)floatNonzeroUnboxed, BOOL, 1, false);
addRTFunction(nonzero, (void*)floatNonzero, UNKNOWN, 1, false);
float_cls->giveAttr("__nonzero__", new BoxedFunction(nonzero));
//float_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)floatNonzero, NULL, 1, false)));
float_cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)floatStr, NULL, 1, false)));
float_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)floatRepr, NULL, 1, false)));
float_cls->freeze();
......
......@@ -15,8 +15,15 @@
#ifndef PYSTON_RUNTIME_FLOAT_H
#define PYSTON_RUNTIME_FLOAT_H
namespace pyston {
extern "C" double mod_float_float(double lhs, double rhs);
extern "C" double div_float_float(double lhs, double rhs);
extern "C" double pow_float_float(double lhs, double rhs);
class BoxedFloat;
bool floatNonzeroUnboxed(BoxedFloat *self);
}
#endif
......@@ -24,10 +24,13 @@
#include "core/stats.h"
#include "core/types.h"
#include "codegen/type_recording.h"
#include "asm_writing/icinfo.h"
#include "asm_writing/rewriter.h"
#include "asm_writing/rewriter2.h"
#include "runtime/float.h"
#include "runtime/gc_runtime.h"
#include "runtime/importing.h"
#include "runtime/objmodel.h"
......@@ -734,11 +737,24 @@ extern "C" Box* getattr(Box* obj, const char* attr) {
Box* val;
if (rewriter.get()) {
//rewriter->trap();
GetattrRewriteArgs2 rewrite_args(rewriter.get(), rewriter->getArg(0), rewriter->getReturnDestination(), false);
Location dest;
TypeRecorder* recorder = rewriter->getTypeRecorder();
if (recorder)
dest = Location::forArg(1);
else
dest = rewriter->getReturnDestination();
GetattrRewriteArgs2 rewrite_args(rewriter.get(), rewriter->getArg(0), dest, false);
val = getattr_internal(obj, attr, 1, true, NULL, &rewrite_args);
if (rewrite_args.out_success && val) {
rewriter->commitReturning(std::move(rewrite_args.out_rtn));
if (recorder) {
RewriterVarUsage2 record_rtn = rewriter->call(false, (void*)recordType, rewriter->loadConst((intptr_t)recorder, Location::forArg(0)), std::move(rewrite_args.out_rtn));
rewriter->commitReturning(std::move(record_rtn));
recordType(recorder, val);
} else {
rewriter->commitReturning(std::move(rewrite_args.out_rtn));
}
} else {
rewrite_args.obj.setDoneUsing();
}
......@@ -854,9 +870,18 @@ extern "C" bool nonzero(Box* obj) {
BoxedInt *int_obj = static_cast<BoxedInt*>(obj);
return int_obj->n != 0;
} else if (obj->cls == float_cls) {
if (rewriter.get()) {
rewriter->call((void*)floatNonzeroUnboxed);
rewriter->commit();
}
return static_cast<BoxedFloat*>(obj)->d != 0;
}
// FIXME we have internal functions calling this method;
// instead, we should break this out into an external and internal function.
// slowpath_* counters are supposed to count external calls; putting it down
// here gets a better representation of that.
// TODO move internal callers to nonzeroInternal, and log *all* calls to nonzero
slowpath_nonzero.log();
//int id = Stats::getStatId("slowpath_nonzero_" + *getTypeName(obj));
......@@ -1636,6 +1661,10 @@ extern "C" Box* binop(Box* lhs, Box* rhs, int op_type) {
//Stats::log(id);
std::unique_ptr<Rewriter> rewriter((Rewriter*)NULL);
// Currently can't patchpoint user-defined binops since we can't assume that just because
// resolving it one way right now (ex, using the value from lhs.__add__) means that later
// we'll resolve it the same way, even for the same argument types.
// TODO implement full resolving semantics inside the rewrite?
bool can_patchpoint = !isUserDefined(lhs->cls) && !isUserDefined(rhs->cls);
if (can_patchpoint)
rewriter.reset(Rewriter::createRewriter(__builtin_extract_return_addr(__builtin_return_address(0)), 3, 1, "binop"));
......@@ -1670,6 +1699,10 @@ extern "C" Box* augbinop(Box* lhs, Box* rhs, int op_type) {
//Stats::log(id);
std::unique_ptr<Rewriter> rewriter((Rewriter*)NULL);
// Currently can't patchpoint user-defined binops since we can't assume that just because
// resolving it one way right now (ex, using the value from lhs.__add__) means that later
// we'll resolve it the same way, even for the same argument types.
// TODO implement full resolving semantics inside the rewrite?
bool can_patchpoint = !isUserDefined(lhs->cls) && !isUserDefined(rhs->cls);
if (can_patchpoint)
rewriter.reset(Rewriter::createRewriter(__builtin_extract_return_addr(__builtin_return_address(0)), 3, 1, "binop"));
......
......@@ -78,7 +78,12 @@ if __name__ == "__main__":
if patch_fn.startswith('.'):
continue
patch_fn = os.path.abspath(os.path.join(patch_dir, patch_fn))
subprocess.check_call(["git", "am", patch_fn], cwd=repo)
code = subprocess.call(["git", "am", patch_fn], cwd=repo)
if code != 0:
print "Running 'git am --abort'..."
subprocess.check_call(["git", "am", "--abort"], cwd=repo)
sys.exit(1)
if diffs:
subprocess.check_call(["git", "stash", "pop", "-q"], cwd=repo)
......@@ -8,6 +8,7 @@
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/MCJIT.h"
#include "llvm/ExecutionEngine/ObjectCache.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/IRReader/IRReader.h"
......@@ -15,7 +16,6 @@
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/InstIterator.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
......@@ -138,8 +138,7 @@ int main(int argc, char **argv) {
SMDiagnostic Err;
OwningPtr<Module> M;
M.reset(ParseIRFile(InputFilename, Err, Context));
std::unique_ptr<Module> M(ParseIRFile(InputFilename, Err, Context));
if (M.get() == 0) {
Err.print(argv[0], errs());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment