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
......@@ -95,11 +95,11 @@ class InstanceMethodType : public ValuedCompilerType<RawInstanceMethod*> {
val->func->decvref(emitter);
delete val;
}
virtual CompilerVariable* call(IREmitter &emitter, ValuedCompilerVariable<RawInstanceMethod*> *var, const std::vector<CompilerVariable*>& args) {
virtual CompilerVariable* call(IREmitter &emitter, const OpInfo& info, ValuedCompilerVariable<RawInstanceMethod*> *var, const std::vector<CompilerVariable*>& args) {
std::vector<CompilerVariable*> new_args;
new_args.push_back(var->getValue()->obj);
new_args.insert(new_args.end(), args.begin(), args.end());
return var->getValue()->func->call(emitter, new_args);
return var->getValue()->func->call(emitter, info, new_args);
}
virtual bool canConvertTo(ConcreteCompilerType* other_type) {
return other_type == UNKNOWN;
......@@ -183,21 +183,21 @@ class UnknownType : public ConcreteCompilerType {
emitter.getBuilder()->CreateCall(g.funcs.print, var->getValue());
}
virtual CompilerVariable* getattr(IREmitter &emitter, ConcreteCompilerVariable *var, const std::string *attr, bool cls_only);
virtual CompilerVariable* call(IREmitter &emitter, ConcreteCompilerVariable *var, const std::vector<CompilerVariable*> &args);
virtual CompilerVariable* callattr(IREmitter &emitter, ConcreteCompilerVariable *var, const std::string *attr, bool clsonly, const std::vector<CompilerVariable*> &args);
virtual ConcreteCompilerVariable* nonzero(IREmitter &emitter, ConcreteCompilerVariable *var);
virtual CompilerVariable* getattr(IREmitter &emitter, const OpInfo& info, ConcreteCompilerVariable *var, const std::string *attr, bool cls_only);
virtual CompilerVariable* call(IREmitter &emitter, const OpInfo& info, ConcreteCompilerVariable *var, const std::vector<CompilerVariable*> &args);
virtual CompilerVariable* callattr(IREmitter &emitter, const OpInfo& info, ConcreteCompilerVariable *var, const std::string *attr, bool clsonly, const std::vector<CompilerVariable*> &args);
virtual ConcreteCompilerVariable* nonzero(IREmitter &emitter, const OpInfo& info, ConcreteCompilerVariable *var);
void setattr(IREmitter &emitter, ConcreteCompilerVariable *var, const std::string *attr, CompilerVariable *v) {
void setattr(IREmitter &emitter, const OpInfo& info, ConcreteCompilerVariable *var, const std::string *attr, CompilerVariable *v) {
llvm::Constant* ptr = getStringConstantPtr(*attr + '\0');
ConcreteCompilerVariable *converted = v->makeConverted(emitter, UNKNOWN);
//g.funcs.setattr->dump();
//var->getValue()->dump(); llvm::errs() << '\n';
//ptr->dump(); llvm::errs() << '\n';
//converted->getValue()->dump(); llvm::errs() << '\n';
bool do_patchpoint = ENABLE_ICSETATTRS && emitter.getTarget() != IREmitter::INTERPRETER;
bool do_patchpoint = ENABLE_ICSETATTRS && !info.isInterpreted();
if (do_patchpoint) {
PatchpointSetupInfo *pp = patchpoints::createSetattrPatchpoint(emitter.currentFunction());
PatchpointSetupInfo *pp = patchpoints::createSetattrPatchpoint(emitter.currentFunction(), info.getTypeRecorder());
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(var->getValue());
......@@ -242,11 +242,11 @@ class UnknownType : public ConcreteCompilerType {
abort();
}
virtual ConcreteCompilerVariable* len(IREmitter &emitter, ConcreteCompilerVariable *var) {
bool do_patchpoint = ENABLE_ICGENERICS && emitter.getTarget() != IREmitter::INTERPRETER;
virtual ConcreteCompilerVariable* len(IREmitter &emitter, const OpInfo& info, ConcreteCompilerVariable *var) {
bool do_patchpoint = ENABLE_ICGENERICS && !info.isInterpreted();
llvm::Value* rtn;
if (do_patchpoint) {
PatchpointSetupInfo *pp = patchpoints::createGenericPatchpoint(emitter.currentFunction(), true, 160);
PatchpointSetupInfo *pp = patchpoints::createGenericPatchpoint(emitter.currentFunction(), info.getTypeRecorder(), true, 160);
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(var->getValue());
......@@ -259,13 +259,13 @@ class UnknownType : public ConcreteCompilerType {
return new ConcreteCompilerVariable(INT, rtn, true);
}
virtual CompilerVariable* getitem(IREmitter &emitter, ConcreteCompilerVariable *var, CompilerVariable *slice) {
virtual CompilerVariable* getitem(IREmitter &emitter, const OpInfo& info, ConcreteCompilerVariable *var, CompilerVariable *slice) {
ConcreteCompilerVariable *converted_slice = slice->makeConverted(emitter, slice->getBoxType());
bool do_patchpoint = ENABLE_ICGETITEMS && emitter.getTarget() != IREmitter::INTERPRETER;
bool do_patchpoint = ENABLE_ICGETITEMS && !info.isInterpreted();
llvm::Value *rtn;
if (do_patchpoint) {
PatchpointSetupInfo *pp = patchpoints::createGetitemPatchpoint(emitter.currentFunction());
PatchpointSetupInfo *pp = patchpoints::createGetitemPatchpoint(emitter.currentFunction(), info.getTypeRecorder());
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(var->getValue());
......@@ -285,7 +285,7 @@ class UnknownType : public ConcreteCompilerType {
ConcreteCompilerType *UNKNOWN = new UnknownType();
CompilerVariable* UnknownType::getattr(IREmitter &emitter, ConcreteCompilerVariable *var, const std::string *attr, bool cls_only) {
CompilerVariable* UnknownType::getattr(IREmitter &emitter, const OpInfo& info, ConcreteCompilerVariable *var, const std::string *attr, bool cls_only) {
llvm::Constant* ptr = getStringConstantPtr(*attr + '\0');
llvm::Value* rtn_val = NULL;
......@@ -300,9 +300,9 @@ CompilerVariable* UnknownType::getattr(IREmitter &emitter, ConcreteCompilerVaria
raw_func = (void*)pyston::getattr;
}
bool do_patchpoint = ENABLE_ICGETATTRS && emitter.getTarget() != IREmitter::INTERPRETER;
bool do_patchpoint = ENABLE_ICGETATTRS && !info.isInterpreted();
if (do_patchpoint) {
PatchpointSetupInfo *pp = patchpoints::createGetattrPatchpoint(emitter.currentFunction());
PatchpointSetupInfo *pp = patchpoints::createGetattrPatchpoint(emitter.currentFunction(), info.getTypeRecorder());
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(var->getValue());
......@@ -316,7 +316,7 @@ CompilerVariable* UnknownType::getattr(IREmitter &emitter, ConcreteCompilerVaria
return new ConcreteCompilerVariable(UNKNOWN, rtn_val, true);
}
static ConcreteCompilerVariable* _call(IREmitter &emitter, llvm::Value* func, void* func_addr, const std::vector<llvm::Value*> other_args, const std::vector<CompilerVariable*> args, ConcreteCompilerType *rtn_type) {
static ConcreteCompilerVariable* _call(IREmitter &emitter, const OpInfo& info, llvm::Value* func, void* func_addr, const std::vector<llvm::Value*> other_args, const std::vector<CompilerVariable*> args, ConcreteCompilerType *rtn_type) {
std::vector<BoxedClass*> guaranteed_classes;
std::vector<ConcreteCompilerVariable*> converted_args;
for (int i = 0; i < args.size(); i++) {
......@@ -342,7 +342,7 @@ static ConcreteCompilerVariable* _call(IREmitter &emitter, llvm::Value* func, vo
if (args.size() >= 4) {
llvm::Value *arg_array;
if (emitter.getTarget() == IREmitter::INTERPRETER) {
if (info.isInterpreted()) {
llvm::Value *n_bytes = getConstantInt((args.size() - 3) * sizeof(Box*), g.i64);
mallocsave = emitter.getBuilder()->CreateCall(g.funcs.malloc, n_bytes);
arg_array = emitter.getBuilder()->CreateBitCast(mallocsave, g.llvm_value_type_ptr->getPointerTo());
......@@ -370,11 +370,11 @@ static ConcreteCompilerVariable* _call(IREmitter &emitter, llvm::Value* func, vo
llvm::Value* rtn;
bool do_patchpoint = ENABLE_ICCALLSITES && emitter.getTarget() != IREmitter::INTERPRETER && (func_addr == runtimeCall || func_addr == pyston::callattr);
bool do_patchpoint = ENABLE_ICCALLSITES && !info.isInterpreted() && (func_addr == runtimeCall || func_addr == pyston::callattr);
if (do_patchpoint) {
assert(func_addr);
PatchpointSetupInfo *pp = patchpoints::createCallsitePatchpoint(emitter.currentFunction(), args.size());
PatchpointSetupInfo *pp = patchpoints::createCallsitePatchpoint(emitter.currentFunction(), info.getTypeRecorder(), args.size());
llvm::Value* uncasted = emitter.createPatchpoint(pp, func_addr, llvm_args);
......@@ -402,7 +402,7 @@ static ConcreteCompilerVariable* _call(IREmitter &emitter, llvm::Value* func, vo
return new ConcreteCompilerVariable(rtn_type, rtn, true);
}
CompilerVariable* UnknownType::call(IREmitter &emitter, ConcreteCompilerVariable *var, const std::vector<CompilerVariable*> &args) {
CompilerVariable* UnknownType::call(IREmitter &emitter, const OpInfo& info, ConcreteCompilerVariable *var, const std::vector<CompilerVariable*> &args) {
llvm::Value* func;
if (args.size() == 0)
func = g.funcs.runtimeCall0;
......@@ -420,10 +420,10 @@ CompilerVariable* UnknownType::call(IREmitter &emitter, ConcreteCompilerVariable
llvm::Value *nargs = llvm::ConstantInt::get(g.i64, args.size(), false);
other_args.push_back(nargs);
return _call(emitter, func, (void*)runtimeCall, other_args, args, UNKNOWN);
return _call(emitter, info, func, (void*)runtimeCall, other_args, args, UNKNOWN);
}
CompilerVariable* UnknownType::callattr(IREmitter &emitter, ConcreteCompilerVariable *var, const std::string *attr, bool clsonly, const std::vector<CompilerVariable*> &args) {
CompilerVariable* UnknownType::callattr(IREmitter &emitter, const OpInfo& info, ConcreteCompilerVariable *var, const std::string *attr, bool clsonly, const std::vector<CompilerVariable*> &args) {
llvm::Value* func;
if (args.size() == 0)
func = g.funcs.callattr0;
......@@ -443,14 +443,14 @@ CompilerVariable* UnknownType::callattr(IREmitter &emitter, ConcreteCompilerVari
llvm::Value *nargs = llvm::ConstantInt::get(g.i64, args.size(), false);
other_args.push_back(nargs);
return _call(emitter, func, (void*)pyston::callattr, other_args, args, UNKNOWN);
return _call(emitter, info, func, (void*)pyston::callattr, other_args, args, UNKNOWN);
}
ConcreteCompilerVariable* UnknownType::nonzero(IREmitter &emitter, ConcreteCompilerVariable *var) {
bool do_patchpoint = ENABLE_ICNONZEROS && emitter.getTarget() != IREmitter::INTERPRETER;
ConcreteCompilerVariable* UnknownType::nonzero(IREmitter &emitter, const OpInfo& info, ConcreteCompilerVariable *var) {
bool do_patchpoint = ENABLE_ICNONZEROS && !info.isInterpreted();
llvm::Value* rtn_val;
if (do_patchpoint) {
PatchpointSetupInfo *pp = patchpoints::createNonzeroPatchpoint(emitter.currentFunction());
PatchpointSetupInfo *pp = patchpoints::createNonzeroPatchpoint(emitter.currentFunction(), info.getTypeRecorder());
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(var->getValue());
......@@ -613,21 +613,21 @@ class IntType : public ConcreteCompilerType {
return BOXED_INT->getattrType(attr, cls_only);
}
virtual CompilerVariable* callattr(IREmitter &emitter, ConcreteCompilerVariable *var, const std::string *attr, bool clsonly, const std::vector<CompilerVariable*>& args) {
virtual CompilerVariable* callattr(IREmitter &emitter, const OpInfo& info, ConcreteCompilerVariable *var, const std::string *attr, bool clsonly, const std::vector<CompilerVariable*>& args) {
ConcreteCompilerVariable* converted = var->makeConverted(emitter, BOXED_INT);
CompilerVariable* rtn = converted->callattr(emitter, attr, clsonly, args);
CompilerVariable* rtn = converted->callattr(emitter, info, attr, clsonly, args);
converted->decvref(emitter);
return rtn;
}
virtual CompilerVariable* getattr(IREmitter &emitter, ConcreteCompilerVariable *var, const std::string *attr, bool cls_only) {
virtual CompilerVariable* getattr(IREmitter &emitter, const OpInfo& info, ConcreteCompilerVariable *var, const std::string *attr, bool cls_only) {
ConcreteCompilerVariable* converted = var->makeConverted(emitter, BOXED_INT);
CompilerVariable* rtn = converted->getattr(emitter, attr, cls_only);
CompilerVariable* rtn = converted->getattr(emitter, info, attr, cls_only);
converted->decvref(emitter);
return rtn;
}
virtual void setattr(IREmitter &emitter, VAR* var, const std::string *attr, CompilerVariable *v) {
virtual void setattr(IREmitter &emitter, const OpInfo& info, VAR* var, const std::string *attr, CompilerVariable *v) {
llvm::CallInst *call = emitter.getBuilder()->CreateCall2(g.funcs.raiseAttributeErrorStr, getStringConstantPtr("int\0"), getStringConstantPtr(*attr + '\0'));
call->setDoesNotReturn();
}
......@@ -645,20 +645,20 @@ class IntType : public ConcreteCompilerType {
}
}
virtual CompilerVariable *getitem(IREmitter &emitter, VAR *var, CompilerVariable *slice) {
virtual CompilerVariable *getitem(IREmitter &emitter, const OpInfo& info, VAR *var, CompilerVariable *slice) {
ConcreteCompilerVariable *converted = var->makeConverted(emitter, BOXED_INT);
CompilerVariable *rtn = converted->getitem(emitter, slice);
CompilerVariable *rtn = converted->getitem(emitter, info, slice);
converted->decvref(emitter);
return rtn;
}
virtual ConcreteCompilerVariable* len(IREmitter &emitter, VAR *var) {
virtual ConcreteCompilerVariable* len(IREmitter &emitter, const OpInfo& info, VAR *var) {
llvm::CallInst* call = emitter.getBuilder()->CreateCall(g.funcs.raiseNotIterableError, getStringConstantPtr("int"));
call->setDoesNotReturn();
return new ConcreteCompilerVariable(INT, llvm::UndefValue::get(g.i64), true);
}
virtual ConcreteCompilerVariable* nonzero(IREmitter &emitter, ConcreteCompilerVariable *var) {
virtual ConcreteCompilerVariable* nonzero(IREmitter &emitter, const OpInfo& info, ConcreteCompilerVariable *var) {
llvm::Value *cmp = emitter.getBuilder()->CreateICmpNE(var->getValue(), llvm::ConstantInt::get(g.i64, 0, false));
return new ConcreteCompilerVariable(BOOL, cmp, true);
}
......@@ -726,14 +726,14 @@ class FloatType : public ConcreteCompilerType {
return BOXED_FLOAT->getattrType(attr, cls_only);
}
virtual CompilerVariable* getattr(IREmitter &emitter, ConcreteCompilerVariable *var, const std::string *attr, bool cls_only) {
virtual CompilerVariable* getattr(IREmitter &emitter, const OpInfo& info, ConcreteCompilerVariable *var, const std::string *attr, bool cls_only) {
ConcreteCompilerVariable* converted = var->makeConverted(emitter, BOXED_INT);
CompilerVariable* rtn = converted->getattr(emitter, attr, cls_only);
CompilerVariable* rtn = converted->getattr(emitter, info, attr, cls_only);
converted->decvref(emitter);
return rtn;
}
virtual void setattr(IREmitter &emitter, VAR* var, const std::string *attr, CompilerVariable *v) {
virtual void setattr(IREmitter &emitter, const OpInfo& info, VAR* var, const std::string *attr, CompilerVariable *v) {
llvm::CallInst* call = emitter.getBuilder()->CreateCall2(g.funcs.raiseAttributeErrorStr, getStringConstantPtr("float\0"), getStringConstantPtr(*attr + '\0'));
call->setDoesNotReturn();
}
......@@ -751,7 +751,7 @@ class FloatType : public ConcreteCompilerType {
}
}
virtual ConcreteCompilerVariable* nonzero(IREmitter &emitter, ConcreteCompilerVariable *var) {
virtual ConcreteCompilerVariable* nonzero(IREmitter &emitter, const OpInfo& info, ConcreteCompilerVariable *var) {
llvm::Value *cmp = emitter.getBuilder()->CreateFCmpUNE(var->getValue(), llvm::ConstantFP::get(g.double_, 0));
return new ConcreteCompilerVariable(BOOL, cmp, true);
}
......@@ -828,7 +828,7 @@ class NormalObjectType : public ConcreteCompilerType {
var->incvref();
return var;
}
assert(other_type == UNKNOWN);
ASSERT(other_type == UNKNOWN, "%s", other_type->debugName().c_str());
return new ConcreteCompilerVariable(UNKNOWN, var->getValue(), false);
//return (new ConcreteCompilerVariable(UNKNOWN, var->getValue(), false))->split(emitter);
}
......@@ -865,7 +865,7 @@ class NormalObjectType : public ConcreteCompilerType {
return UNKNOWN;
}
CompilerVariable* getattr(IREmitter &emitter, ConcreteCompilerVariable *var, const std::string *attr, bool cls_only) {
CompilerVariable* getattr(IREmitter &emitter, const OpInfo& info, ConcreteCompilerVariable *var, const std::string *attr, bool cls_only) {
//printf("%s.getattr %s\n", debugName().c_str(), attr->c_str());
if (cls->is_constant && !cls->hasattrs) {
Box* rtattr = cls->peekattr(*attr);
......@@ -883,14 +883,14 @@ class NormalObjectType : public ConcreteCompilerType {
}
// TODO could specialize more since we know the class already
return UNKNOWN->getattr(emitter, var, attr, cls_only);
return UNKNOWN->getattr(emitter, info, var, attr, cls_only);
}
void setattr(IREmitter &emitter, ConcreteCompilerVariable *var, const std::string *attr, CompilerVariable *v) {
return UNKNOWN->setattr(emitter, var, attr, v);
void setattr(IREmitter &emitter, const OpInfo& info, ConcreteCompilerVariable *var, const std::string *attr, CompilerVariable *v) {
return UNKNOWN->setattr(emitter, info, var, attr, v);
}
virtual ConcreteCompilerVariable* nonzero(IREmitter &emitter, ConcreteCompilerVariable *var) {
virtual ConcreteCompilerVariable* nonzero(IREmitter &emitter, const OpInfo& info, ConcreteCompilerVariable *var) {
if (cls == bool_cls) {
llvm::Value *unboxed = emitter.getBuilder()->CreateCall(g.funcs.unboxBool, var->getValue());
assert(unboxed->getType() == g.i1);
......@@ -898,7 +898,7 @@ class NormalObjectType : public ConcreteCompilerType {
}
ConcreteCompilerVariable *converted = var->makeConverted(emitter, UNKNOWN);
ConcreteCompilerVariable *rtn = converted->nonzero(emitter);
ConcreteCompilerVariable *rtn = converted->nonzero(emitter, info);
converted->decvref(emitter);
return rtn;
}
......@@ -909,22 +909,22 @@ class NormalObjectType : public ConcreteCompilerType {
converted->decvref(emitter);
}
virtual CompilerVariable* getitem(IREmitter &emitter, ConcreteCompilerVariable *var, CompilerVariable *slice) {
return UNKNOWN->getitem(emitter, var, slice);
virtual CompilerVariable* getitem(IREmitter &emitter, const OpInfo& info, ConcreteCompilerVariable *var, CompilerVariable *slice) {
return UNKNOWN->getitem(emitter, info, var, slice);
}
virtual ConcreteCompilerVariable* len(IREmitter &emitter, ConcreteCompilerVariable *var) {
return UNKNOWN->len(emitter, var);
virtual ConcreteCompilerVariable* len(IREmitter &emitter, const OpInfo& info, ConcreteCompilerVariable *var) {
return UNKNOWN->len(emitter, info, var);
}
virtual CompilerVariable* call(IREmitter &emitter, ConcreteCompilerVariable *var, const std::vector<CompilerVariable*>& args) {
virtual CompilerVariable* call(IREmitter &emitter, const OpInfo& info, ConcreteCompilerVariable *var, const std::vector<CompilerVariable*>& args) {
ConcreteCompilerVariable *converted = var->makeConverted(emitter, UNKNOWN);
CompilerVariable *rtn = converted->call(emitter, args);
CompilerVariable *rtn = converted->call(emitter, info, args);
converted->decvref(emitter);
return rtn;
}
virtual CompilerVariable* callattr(IREmitter &emitter, ConcreteCompilerVariable *var, const std::string *attr, bool clsonly, const std::vector<CompilerVariable*>& args) {
virtual CompilerVariable* callattr(IREmitter &emitter, const OpInfo& info, ConcreteCompilerVariable *var, const std::string *attr, bool clsonly, const std::vector<CompilerVariable*>& args) {
if (cls->is_constant && !cls->hasattrs) {
Box* rtattr = cls->peekattr(*attr);
if (rtattr == NULL) {
......@@ -991,7 +991,7 @@ class NormalObjectType : public ConcreteCompilerType {
std::vector<llvm::Value*> other_args;
ConcreteCompilerVariable* rtn = _call(emitter, linked_function, cf->code, other_args, new_args, cf->sig->rtn_type);
ConcreteCompilerVariable* rtn = _call(emitter, info, linked_function, cf->code, other_args, new_args, cf->sig->rtn_type);
assert(rtn->getType() == cf->sig->rtn_type);
assert(cf->sig->rtn_type != BOXED_INT);
......@@ -1003,7 +1003,7 @@ class NormalObjectType : public ConcreteCompilerType {
}
ConcreteCompilerVariable *converted = var->makeConverted(emitter, UNKNOWN);
CompilerVariable *rtn = converted->callattr(emitter, attr, clsonly, args);
CompilerVariable *rtn = converted->callattr(emitter, info, attr, clsonly, args);
converted->decvref(emitter);
return rtn;
}
......@@ -1060,23 +1060,23 @@ class StrConstantType : public ValuedCompilerType<std::string*> {
return (other == STR || other == UNKNOWN);
}
virtual CompilerVariable *getattr(IREmitter &emitter, VAR *var, const std::string *attr, bool cls_only) {
virtual CompilerVariable *getattr(IREmitter &emitter, const OpInfo& info, VAR *var, const std::string *attr, bool cls_only) {
ConcreteCompilerVariable *converted = var->makeConverted(emitter, STR);
CompilerVariable *rtn = converted->getattr(emitter, attr, cls_only);
CompilerVariable *rtn = converted->getattr(emitter, info, attr, cls_only);
converted->decvref(emitter);
return rtn;
}
virtual CompilerVariable* callattr(IREmitter &emitter, VAR *var, const std::string *attr, bool clsonly, const std::vector<CompilerVariable*> &args) {
virtual CompilerVariable* callattr(IREmitter &emitter, const OpInfo& info, VAR *var, const std::string *attr, bool clsonly, const std::vector<CompilerVariable*> &args) {
ConcreteCompilerVariable *converted = var->makeConverted(emitter, STR);
CompilerVariable *rtn = converted->callattr(emitter, attr, clsonly, args);
CompilerVariable *rtn = converted->callattr(emitter, info, attr, clsonly, args);
converted->decvref(emitter);
return rtn;
}
virtual CompilerVariable *getitem(IREmitter &emitter, VAR *var, CompilerVariable *slice) {
virtual CompilerVariable *getitem(IREmitter &emitter, const OpInfo& info, VAR *var, CompilerVariable *slice) {
ConcreteCompilerVariable *converted = var->makeConverted(emitter, STR);
CompilerVariable *rtn = converted->getitem(emitter, slice);
CompilerVariable *rtn = converted->getitem(emitter, info, slice);
converted->decvref(emitter);
return rtn;
}
......@@ -1131,7 +1131,7 @@ class BoolType : public ConcreteCompilerType {
emitter.getBuilder()->CreateCall(g.funcs.printf, selected);
}
virtual ConcreteCompilerVariable* nonzero(IREmitter &emitter, ConcreteCompilerVariable *var) {
virtual ConcreteCompilerVariable* nonzero(IREmitter &emitter, const OpInfo& info, ConcreteCompilerVariable *var) {
var->incvref();
return var;
}
......@@ -1201,6 +1201,8 @@ class TupleType : public ValuedCompilerType<const std::vector<CompilerVariable*>
elts->push_back((*orig_elts)[i]->dup(cache));
}
rtn = new VAR(this, elts, var->isGrabbed());
while (rtn->getVrefs() < var->getVrefs())
rtn->incvref();
}
return rtn;
}
......@@ -1265,7 +1267,7 @@ class TupleType : public ValuedCompilerType<const std::vector<CompilerVariable*>
return new TupleType(elt_types);
}
virtual CompilerVariable* getitem(IREmitter &emitter, VAR *var, CompilerVariable *slice) {
virtual CompilerVariable* getitem(IREmitter &emitter, const OpInfo& info, VAR *var, CompilerVariable *slice) {
if (slice->getType() == INT) {
llvm::Value* v = static_cast<ConcreteCompilerVariable*>(slice)->getValue();
assert(v->getType() == g.i64);
......@@ -1286,7 +1288,7 @@ class TupleType : public ValuedCompilerType<const std::vector<CompilerVariable*>
//return getConstantInt(var->getValue()->size(), g.i64);
}
virtual ConcreteCompilerVariable* len(IREmitter &emitter, VAR *var) {
virtual ConcreteCompilerVariable* len(IREmitter &emitter, const OpInfo& info, VAR *var) {
return new ConcreteCompilerVariable(INT, getConstantInt(var->getValue()->size(), g.i64), true);
}
......@@ -1323,7 +1325,7 @@ class UndefType : public ConcreteCompilerType {
return llvm::Type::getInt16Ty(g.context);
}
virtual CompilerVariable* call(IREmitter &emitter, VAR *var, const std::vector<CompilerVariable*>& args) {
virtual CompilerVariable* call(IREmitter &emitter, const OpInfo& info, VAR *var, const std::vector<CompilerVariable*>& args) {
return undefVariable();
}
virtual void drop(IREmitter &emitter, VAR *var) {}
......@@ -1343,11 +1345,11 @@ class UndefType : public ConcreteCompilerType {
llvm::Value *v = llvm::UndefValue::get(other_type->llvmType());
return new ConcreteCompilerVariable(other_type, v, true);
}
virtual CompilerVariable* getattr(IREmitter &emitter, VAR* var, const std::string *attr, bool cls_only) {
virtual CompilerVariable* getattr(IREmitter &emitter, const OpInfo& info, VAR* var, const std::string *attr, bool cls_only) {
return undefVariable();
}
virtual CompilerVariable* callattr(IREmitter &emitter, VAR *var, const std::string *attr, bool clsonly, const std::vector<CompilerVariable*>& args) {
virtual CompilerVariable* callattr(IREmitter &emitter, const OpInfo& info, VAR *var, const std::string *attr, bool clsonly, const std::vector<CompilerVariable*>& args) {
return undefVariable();
}
......@@ -1355,7 +1357,7 @@ class UndefType : public ConcreteCompilerType {
return UNDEF;
}
virtual ConcreteCompilerVariable* nonzero(IREmitter &emitter, VAR *var) {
virtual ConcreteCompilerVariable* nonzero(IREmitter &emitter, const OpInfo& info, VAR *var) {
return new ConcreteCompilerVariable(BOOL, llvm::UndefValue::get(g.i1), true);
}
......
......@@ -24,6 +24,8 @@
namespace pyston {
class OpInfo;
class CompilerType;
class IREmitter;
......@@ -52,11 +54,11 @@ class _ValuedCompilerType : public CompilerType {
printf("dup not defined for %s\n", debugName().c_str());
abort();
}
virtual ConcreteCompilerType* getConcreteType() {
ConcreteCompilerType* getConcreteType() override {
printf("getConcreteType not defined for %s\n", debugName().c_str());
abort();
}
virtual ConcreteCompilerType* getBoxType() {
ConcreteCompilerType* getBoxType() override {
printf("getBoxType not defined for %s\n", debugName().c_str());
abort();
}
......@@ -68,7 +70,7 @@ class _ValuedCompilerType : public CompilerType {
printf("grab not defined for %s\n", debugName().c_str());
abort();
}
virtual bool canConvertTo(ConcreteCompilerType* other_type) {
bool canConvertTo(ConcreteCompilerType* other_type) override {
printf("canConvertTo not defined for %s\n", debugName().c_str());
abort();
}
......@@ -76,23 +78,23 @@ class _ValuedCompilerType : public CompilerType {
printf("makeConverted not defined for %s\n", debugName().c_str());
abort();
}
virtual ConcreteCompilerVariable* nonzero(IREmitter &emitter, VAR* value) {
virtual ConcreteCompilerVariable* nonzero(IREmitter &emitter, const OpInfo& info, VAR* value) {
printf("nonzero not defined for %s\n", debugName().c_str());
abort();
}
virtual CompilerVariable* getattr(IREmitter &emitter, VAR* value, const std::string *attr, bool cls_only) {
virtual CompilerVariable* getattr(IREmitter &emitter, const OpInfo& info, VAR* value, const std::string *attr, bool cls_only) {
printf("getattr not defined for %s\n", debugName().c_str());
abort();
}
virtual void setattr(IREmitter &emitter, VAR* value, const std::string *attr, CompilerVariable *v) {
virtual void setattr(IREmitter &emitter, const OpInfo& info, VAR* value, const std::string *attr, CompilerVariable *v) {
printf("setattr not defined for %s\n", debugName().c_str());
abort();
}
virtual CompilerVariable* callattr(IREmitter &emitter, VAR* value, const std::string *attr, bool clsonly, const std::vector<CompilerVariable*>& args) {
virtual CompilerVariable* callattr(IREmitter &emitter, const OpInfo& info, VAR* value, const std::string *attr, bool clsonly, const std::vector<CompilerVariable*>& args) {
printf("callattr not defined for %s\n", debugName().c_str());
abort();
}
virtual CompilerVariable* call(IREmitter &emitter, VAR* value, const std::vector<CompilerVariable*>& args) {
virtual CompilerVariable* call(IREmitter &emitter, const OpInfo& info, VAR* value, const std::vector<CompilerVariable*>& args) {
printf("call not defined for %s\n", debugName().c_str());
abort();
}
......@@ -100,11 +102,11 @@ class _ValuedCompilerType : public CompilerType {
printf("print not defined for %s\n", debugName().c_str());
abort();
}
virtual ConcreteCompilerVariable* len(IREmitter &emitter, VAR* value) {
virtual ConcreteCompilerVariable* len(IREmitter &emitter, const OpInfo& info, VAR* value) {
printf("len not defined for %s\n", debugName().c_str());
abort();
}
virtual CompilerVariable* getitem(IREmitter &emitter, VAR* value, CompilerVariable *v) {
virtual CompilerVariable* getitem(IREmitter &emitter, const OpInfo& info, VAR* value, CompilerVariable *v) {
printf("getitem not defined for %s\n", debugName().c_str());
abort();
}
......@@ -112,15 +114,15 @@ class _ValuedCompilerType : public CompilerType {
printf("makeClassCheck not defined for %s\n", debugName().c_str());
abort();
}
virtual CompilerType* getattrType(const std::string *attr, bool cls_only) {
CompilerType* getattrType(const std::string *attr, bool cls_only) override {
printf("getattrType not defined for %s\n", debugName().c_str());
abort();
}
virtual CompilerType* callType(std::vector<CompilerType*> &arg_types) {
CompilerType* callType(std::vector<CompilerType*> &arg_types) override {
printf("callType not defined for %s\n", debugName().c_str());
abort();
}
virtual BoxedClass* guaranteedClass() {
BoxedClass* guaranteedClass() override {
ASSERT((CompilerType*)getConcreteType() != this, "%s", debugName().c_str());
return getConcreteType()->guaranteedClass();
}
......@@ -169,14 +171,19 @@ class CompilerVariable {
vrefs++;
}
void decvrefNodrop() {
ASSERT(vrefs, "%s", getType()->debugName().c_str());
assert(vrefs > 0 && vrefs < (1<<20));
// It'd be nice to print out the type of the variable, but this is all happening
// after the object got deleted so it's pretty precarious, and the getType()
// debugging call will probably segfault:
//ASSERT(vrefs, "%s", getType()->debugName().c_str());
vrefs--;
if (vrefs == 0) {
delete this;
}
}
void decvref(IREmitter &emitter) {
ASSERT(vrefs, "%s", getType()->debugName().c_str());
assert(vrefs > 0 && vrefs < (1<<20));
//ASSERT(vrefs, "%s", getType()->debugName().c_str());
vrefs--;
if (vrefs == 0) {
if (grabbed)
......@@ -204,14 +211,14 @@ class CompilerVariable {
virtual llvm::Value* makeClassCheck(IREmitter &emitter, BoxedClass* cls) = 0;
virtual BoxedClass* guaranteedClass() = 0;
virtual ConcreteCompilerVariable* nonzero(IREmitter &emitter) = 0;
virtual CompilerVariable* getattr(IREmitter &emitter, const std::string *attr, bool cls_only) = 0;
virtual void setattr(IREmitter &emitter, const std::string *attr, CompilerVariable* v) = 0;
virtual CompilerVariable* callattr(IREmitter &emitter, const std::string *attr, bool clsonly, const std::vector<CompilerVariable*>& args) = 0;
virtual CompilerVariable* call(IREmitter &emitter, const std::vector<CompilerVariable*>& args) = 0;
virtual ConcreteCompilerVariable* nonzero(IREmitter &emitter, const OpInfo& info) = 0;
virtual CompilerVariable* getattr(IREmitter &emitter, const OpInfo& info, const std::string *attr, bool cls_only) = 0;
virtual void setattr(IREmitter &emitter, const OpInfo& info, const std::string *attr, CompilerVariable* v) = 0;
virtual CompilerVariable* callattr(IREmitter &emitter, const OpInfo& info, const std::string *attr, bool clsonly, const std::vector<CompilerVariable*>& args) = 0;
virtual CompilerVariable* call(IREmitter &emitter, const OpInfo& info, const std::vector<CompilerVariable*>& args) = 0;
virtual void print(IREmitter &emitter) = 0;
virtual ConcreteCompilerVariable* len(IREmitter &emitter) = 0;
virtual CompilerVariable* getitem(IREmitter &emitter, CompilerVariable*) = 0;
virtual ConcreteCompilerVariable* len(IREmitter &emitter, const OpInfo& info) = 0;
virtual CompilerVariable* getitem(IREmitter &emitter, const OpInfo& info, CompilerVariable*) = 0;
};
template <class V>
......@@ -234,14 +241,14 @@ class ValuedCompilerVariable : public CompilerVariable {
virtual T* getType() { return type; }
virtual V getValue() { return value; }
virtual ConcreteCompilerType* getConcreteType() {
ConcreteCompilerType* getConcreteType() override {
return type->getConcreteType();
}
virtual ConcreteCompilerType* getBoxType() {
ConcreteCompilerType* getBoxType() override {
return type->getBoxType();
}
virtual ValuedCompilerVariable<V>* split(IREmitter &emitter) {
ValuedCompilerVariable<V>* split(IREmitter &emitter) override {
ValuedCompilerVariable<V>* rtn;
if (getVrefs() == 1) {
rtn = this;
......@@ -252,48 +259,50 @@ class ValuedCompilerVariable : public CompilerVariable {
rtn->ensureGrabbed(emitter);
return rtn;
}
virtual CompilerVariable* dup(DupCache &cache) {
return type->dup(this, cache);
//return new ValuedCompilerVariable<V>(type, value, isGrabbed());
CompilerVariable* dup(DupCache &cache) override {
CompilerVariable *rtn = type->dup(this, cache);
ASSERT(rtn->getVrefs() == getVrefs(), "%d %s", rtn->getVrefs(), type->debugName().c_str());
return rtn;
}
virtual bool canConvertTo(ConcreteCompilerType *other_type) {
bool canConvertTo(ConcreteCompilerType *other_type) override {
return type->canConvertTo(other_type);
}
virtual ConcreteCompilerVariable* makeConverted(IREmitter &emitter, ConcreteCompilerType *other_type) {
ConcreteCompilerVariable* makeConverted(IREmitter &emitter, ConcreteCompilerType *other_type) override {
ConcreteCompilerVariable* rtn = type->makeConverted(emitter, this, other_type);
ASSERT(rtn->getType() == other_type, "%s", type->debugName().c_str());
return rtn;
}
virtual ConcreteCompilerVariable* nonzero(IREmitter &emitter) {
return type->nonzero(emitter, this);
ConcreteCompilerVariable* nonzero(IREmitter &emitter, const OpInfo& info) override {
return type->nonzero(emitter, info, this);
}
virtual CompilerVariable* getattr(IREmitter &emitter, const std::string *attr, bool cls_only) {
return type->getattr(emitter, this, attr, cls_only);
virtual CompilerVariable* getattr(IREmitter &emitter, const OpInfo& info, const std::string *attr, bool cls_only) {
return type->getattr(emitter, info, this, attr, cls_only);
}
virtual void setattr(IREmitter &emitter, const std::string *attr, CompilerVariable *v) {
type->setattr(emitter, this, attr, v);
virtual void setattr(IREmitter &emitter, const OpInfo& info, const std::string *attr, CompilerVariable *v) {
type->setattr(emitter, info, this, attr, v);
}
virtual CompilerVariable* callattr(IREmitter &emitter, const std::string *attr, bool clsonly, const std::vector<CompilerVariable*>& args) {
return type->callattr(emitter, this, attr, clsonly, args);
virtual CompilerVariable* callattr(IREmitter &emitter, const OpInfo& info, const std::string *attr, bool clsonly, const std::vector<CompilerVariable*>& args) {
return type->callattr(emitter, info, this, attr, clsonly, args);
}
virtual CompilerVariable* call(IREmitter &emitter, const std::vector<CompilerVariable*>& args) {
return type->call(emitter, this, args);
CompilerVariable* call(IREmitter &emitter, const OpInfo& info, const std::vector<CompilerVariable*>& args) override {
return type->call(emitter, info, this, args);
}
virtual void print(IREmitter &emitter) {
void print(IREmitter &emitter) override {
type->print(emitter, this);
}
virtual ConcreteCompilerVariable* len(IREmitter &emitter) {
return type->len(emitter, this);
ConcreteCompilerVariable* len(IREmitter &emitter, const OpInfo& info) override {
return type->len(emitter, info, this);
}
virtual CompilerVariable* getitem(IREmitter &emitter, CompilerVariable *slice) {
return type->getitem(emitter, this, slice);
CompilerVariable* getitem(IREmitter &emitter, const OpInfo& info, CompilerVariable *slice) override {
return type->getitem(emitter, info, this, slice);
}
virtual llvm::Value* makeClassCheck(IREmitter &emitter, BoxedClass* cls) {
llvm::Value* makeClassCheck(IREmitter &emitter, BoxedClass* cls) override {
return type->makeClassCheck(emitter, this, cls);
}
virtual BoxedClass* guaranteedClass() {
BoxedClass* guaranteedClass() override {
return type->guaranteedClass();
}
};
......
......@@ -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
......@@ -22,6 +22,7 @@
#include "codegen/compvars.h"
#include "codegen/osrentry.h"
#include "codegen/patchpoints.h"
#include "codegen/type_recording.h"
#include "codegen/irgen.h"
#include "codegen/irgen/irgenerator.h"
......@@ -100,12 +101,6 @@ class IREmitterImpl : public IREmitter {
builder->setEmitter(this);
}
Target getTarget() override {
if (irstate->getEffortLevel() == EffortLevel::INTERPRETED)
return INTERPRETER;
return COMPILATION;
}
IRBuilder* getBuilder() override {
return builder;
}
......@@ -123,6 +118,8 @@ class IREmitterImpl : public IREmitter {
}
llvm::Value* createPatchpoint(const PatchpointSetupInfo* pp, void* func_addr, const std::vector<llvm::Value*> &args) override {
assert(irstate->getEffortLevel() != EffortLevel::INTERPRETED);
std::vector<llvm::Value*> pp_args;
pp_args.push_back(getConstantInt(pp->getPatchpointId(), g.i64));
pp_args.push_back(getConstantInt(pp->totalSize(), g.i32));
......@@ -191,6 +188,34 @@ class IRGeneratorImpl : public IRGenerator {
}
private:
#ifndef NDEBUG
std::unordered_set<AST*> gotten_op_infos;
#endif
OpInfo getOpInfoForNode(AST* ast) {
assert(ast);
#ifndef NDEBUG
assert(gotten_op_infos.count(ast) == 0);
gotten_op_infos.insert(ast);
#endif
EffortLevel::EffortLevel effort = irstate->getEffortLevel();
bool record_types = (effort != EffortLevel::INTERPRETED && effort != EffortLevel::MAXIMAL);
TypeRecorder *type_recorder;
if (record_types) {
type_recorder = getTypeRecorderForNode(ast);
} else {
type_recorder = NULL;
}
return OpInfo(irstate->getEffortLevel(), type_recorder);
}
OpInfo getEmptyOpInfo() {
return OpInfo(irstate->getEffortLevel(), NULL);
}
void createExprTypeGuard(llvm::Value *check_val, AST_expr* node, CompilerVariable* node_value) {
assert(check_val->getType() == g.i1);
......@@ -221,7 +246,7 @@ class IRGeneratorImpl : public IRGenerator {
CompilerVariable *value = evalExpr(node->value);
CompilerVariable *rtn = value->getattr(emitter, &node->attr, false);
CompilerVariable *rtn = value->getattr(emitter, getOpInfoForNode(node), &node->attr, false);
value->decvref(emitter);
return rtn;
}
......@@ -230,7 +255,7 @@ class IRGeneratorImpl : public IRGenerator {
assert(state != PARTIAL);
CompilerVariable *value = evalExpr(node->value);
CompilerVariable *rtn = value->getattr(emitter, &node->attr, true);
CompilerVariable *rtn = value->getattr(emitter, getOpInfoForNode(node), &node->attr, true);
value->decvref(emitter);
return rtn;
}
......@@ -240,7 +265,7 @@ class IRGeneratorImpl : public IRGenerator {
BinOp,
Compare,
};
CompilerVariable* _evalBinExp(CompilerVariable *left, CompilerVariable *right, AST_TYPE::AST_TYPE type, BinExpType exp_type) {
CompilerVariable* _evalBinExp(AST* node, CompilerVariable *left, CompilerVariable *right, AST_TYPE::AST_TYPE type, BinExpType exp_type) {
assert(state != PARTIAL);
assert(left);
......@@ -420,7 +445,7 @@ class IRGeneratorImpl : public IRGenerator {
ConcreteCompilerVariable *boxed_right = right->makeConverted(emitter, right->getBoxType());
llvm::Value* rtn;
bool do_patchpoint = ENABLE_ICBINEXPS && emitter.getTarget() != IREmitter::INTERPRETER;
bool do_patchpoint = ENABLE_ICBINEXPS && (irstate ->getEffortLevel() != EffortLevel::INTERPRETED);
llvm::Value *rt_func;
void* rt_func_addr;
......@@ -436,7 +461,7 @@ class IRGeneratorImpl : public IRGenerator {
}
if (do_patchpoint) {
PatchpointSetupInfo *pp = patchpoints::createBinexpPatchpoint(emitter.currentFunction());
PatchpointSetupInfo *pp = patchpoints::createBinexpPatchpoint(emitter.currentFunction(), getOpInfoForNode(node).getTypeRecorder());
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(boxed_left->getValue());
......@@ -464,7 +489,7 @@ class IRGeneratorImpl : public IRGenerator {
assert(node->op_type != AST_TYPE::Is && node->op_type != AST_TYPE::IsNot && "not tested yet");
CompilerVariable *rtn = this->_evalBinExp(left, right, node->op_type, BinOp);
CompilerVariable *rtn = this->_evalBinExp(node, left, right, node->op_type, BinOp);
left->decvref(emitter);
right->decvref(emitter);
return rtn;
......@@ -478,7 +503,7 @@ class IRGeneratorImpl : public IRGenerator {
assert(node->op_type != AST_TYPE::Is && node->op_type != AST_TYPE::IsNot && "not tested yet");
CompilerVariable *rtn = this->_evalBinExp(left, right, node->op_type, AugBinOp);
CompilerVariable *rtn = this->_evalBinExp(node, left, right, node->op_type, AugBinOp);
left->decvref(emitter);
right->decvref(emitter);
return rtn;
......@@ -495,7 +520,7 @@ class IRGeneratorImpl : public IRGenerator {
assert(left);
assert(right);
CompilerVariable *rtn = _evalBinExp(left, right, node->ops[0], Compare);
CompilerVariable *rtn = _evalBinExp(node, left, right, node->ops[0], Compare);
left->decvref(emitter);
right->decvref(emitter);
return rtn;
......@@ -536,9 +561,9 @@ class IRGeneratorImpl : public IRGenerator {
CompilerVariable *rtn;
if (is_callattr) {
rtn = func->callattr(emitter, attr, callattr_clsonly, args);
rtn = func->callattr(emitter, getOpInfoForNode(node), attr, callattr_clsonly, args);
} else {
rtn = func->call(emitter, args);
rtn = func->call(emitter, getOpInfoForNode(node), args);
}
func->decvref(emitter);
......@@ -559,7 +584,7 @@ class IRGeneratorImpl : public IRGenerator {
ConcreteCompilerVariable *rtn = new ConcreteCompilerVariable(DICT, v, true);
if (node->keys.size()) {
static const std::string setitem_str("__setitem__");
CompilerVariable *setitem = rtn->getattr(emitter, &setitem_str, true);
CompilerVariable *setitem = rtn->getattr(emitter, getEmptyOpInfo(), &setitem_str, true);
for (int i = 0; i < node->keys.size(); i++) {
CompilerVariable *key = evalExpr(node->keys[i]);
CompilerVariable *value = evalExpr(node->values[i]);
......@@ -570,7 +595,7 @@ class IRGeneratorImpl : public IRGenerator {
args.push_back(key);
args.push_back(value);
// TODO could use the internal _listAppend function to avoid incref/decref'ing None
CompilerVariable *rtn = setitem->call(emitter, args);
CompilerVariable *rtn = setitem->call(emitter, getEmptyOpInfo(), args);
rtn->decvref(emitter);
key->decvref(emitter);
......@@ -632,10 +657,10 @@ class IRGeneratorImpl : public IRGenerator {
if (1) {
// Method 1: calls into the runtime getGlobal(), which handles things like falling back to builtins
// or raising the correct error message.
bool do_patchpoint = ENABLE_ICGETGLOBALS && emitter.getTarget() != IREmitter::INTERPRETER;
bool do_patchpoint = ENABLE_ICGETGLOBALS && (irstate ->getEffortLevel() != EffortLevel::INTERPRETED);
bool from_global = irstate->getSourceInfo()->ast->type == AST_TYPE::Module;
if (do_patchpoint) {
PatchpointSetupInfo *pp = patchpoints::createGetGlobalPatchpoint(emitter.currentFunction());
PatchpointSetupInfo *pp = patchpoints::createGetGlobalPatchpoint(emitter.currentFunction(), getOpInfoForNode(node).getTypeRecorder());
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(embedConstantPtr(irstate->getSourceInfo()->parent_module, g.llvm_module_type_ptr));
......@@ -653,7 +678,7 @@ class IRGeneratorImpl : public IRGenerator {
// Method 2 [testing-only]: (ab)uses existing getattr patchpoints and just calls module.getattr()
// This option exists for performance testing because method 1 does not currently use patchpoints.
ConcreteCompilerVariable *mod = new ConcreteCompilerVariable(MODULE, embedConstantPtr(irstate->getSourceInfo()->parent_module, g.llvm_value_type_ptr), false);
CompilerVariable *attr = mod->getattr(emitter, &node->id, false);
CompilerVariable *attr = mod->getattr(emitter, getOpInfoForNode(node), &node->id, false);
mod->decvref(emitter);
return attr;
}
......@@ -729,7 +754,7 @@ class IRGeneratorImpl : public IRGenerator {
CompilerVariable *value = evalExpr(node->value);
CompilerVariable *slice = evalExpr(node->slice);
CompilerVariable *rtn = value->getitem(emitter, slice);
CompilerVariable *rtn = value->getitem(emitter, getOpInfoForNode(node), slice);
value->decvref(emitter);
slice->decvref(emitter);
return rtn;
......@@ -758,7 +783,7 @@ class IRGeneratorImpl : public IRGenerator {
CompilerVariable* operand = evalExpr(node->operand);
if (node->op_type == AST_TYPE::Not) {
ConcreteCompilerVariable *rtn = operand->nonzero(emitter);
ConcreteCompilerVariable *rtn = operand->nonzero(emitter, getOpInfoForNode(node));
operand->decvref(emitter);
llvm::Value* v = rtn->getValue();
......@@ -892,6 +917,7 @@ class IRGeneratorImpl : public IRGenerator {
node->accept(&printer);
printf("; is_partial=%d\n", state == PARTIAL);
}
if (state == PARTIAL) {
guard->branch->setSuccessor(1, curblock);
symbol_table = SymbolTable(guard->st);
......@@ -1011,7 +1037,7 @@ class IRGeneratorImpl : public IRGenerator {
if (irstate->getScopeInfo()->refersToGlobal(name)) {
// TODO do something special here so that it knows to only emit a monomorphic inline cache?
ConcreteCompilerVariable* module = new ConcreteCompilerVariable(MODULE, embedConstantPtr(irstate->getSourceInfo()->parent_module, g.llvm_value_type_ptr), false);
module->setattr(emitter, &name, val);
module->setattr(emitter, getEmptyOpInfo(), &name, val);
module->decvref(emitter);
} else {
CompilerVariable* &prev = symbol_table[name];
......@@ -1031,7 +1057,7 @@ class IRGeneratorImpl : public IRGenerator {
void _doSetattr(AST_Attribute* target, CompilerVariable* val) {
assert(state != PARTIAL);
CompilerVariable *t = evalExpr(target->value);
t->setattr(emitter, &target->attr, val);
t->setattr(emitter, getEmptyOpInfo(), &target->attr, val);
t->decvref(emitter);
}
......@@ -1047,9 +1073,9 @@ class IRGeneratorImpl : public IRGenerator {
ConcreteCompilerVariable *converted_val = val->makeConverted(emitter, val->getBoxType());
bool do_patchpoint = ENABLE_ICSETITEMS && emitter.getTarget() != IREmitter::INTERPRETER;
bool do_patchpoint = ENABLE_ICSETITEMS && (irstate ->getEffortLevel() != EffortLevel::INTERPRETED);
if (do_patchpoint) {
PatchpointSetupInfo *pp = patchpoints::createSetitemPatchpoint(emitter.currentFunction());
PatchpointSetupInfo *pp = patchpoints::createSetitemPatchpoint(emitter.currentFunction(), getEmptyOpInfo().getTypeRecorder());
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(converted_target->getValue());
......@@ -1070,12 +1096,13 @@ class IRGeneratorImpl : public IRGenerator {
void _doUnpackTuple(AST_Tuple* target, CompilerVariable* val) {
assert(state != PARTIAL);
int ntargets = target->elts.size();
ConcreteCompilerVariable *len = val->len(emitter);
// TODO do type recording here?
ConcreteCompilerVariable *len = val->len(emitter, getEmptyOpInfo());
emitter.getBuilder()->CreateCall2(g.funcs.checkUnpackingLength,
getConstantInt(ntargets, g.i64), len->getValue());
for (int i = 0; i < ntargets; i++) {
CompilerVariable *unpacked = val->getitem(emitter, makeInt(i));
CompilerVariable *unpacked = val->getitem(emitter, getEmptyOpInfo(), makeInt(i));
_doSet(target->elts[i], unpacked);
unpacked->decvref(emitter);
}
......@@ -1138,7 +1165,7 @@ class IRGeneratorImpl : public IRGenerator {
AST_FunctionDef *fdef = static_cast<AST_FunctionDef*>(node->body[i]);
CLFunction *cl = this->_wrapFunction(fdef);
CompilerVariable *func = makeFunction(emitter, cl);
cls->setattr(emitter, &fdef->name, func);
cls->setattr(emitter, getEmptyOpInfo(), &fdef->name, func);
func->decvref(emitter);
} else {
RELEASE_ASSERT(node->body[i]->type == AST_TYPE::Pass, "%d", type);
......@@ -1261,7 +1288,7 @@ class IRGeneratorImpl : public IRGenerator {
assert(state != PARTIAL);
assert(val);
ConcreteCompilerVariable* nonzero = val->nonzero(emitter);
ConcreteCompilerVariable* nonzero = val->nonzero(emitter, getOpInfoForNode(node));
assert(nonzero->getType() == BOOL);
val->decvref(emitter);
......
......@@ -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