Commit da069735 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Start adding 'long' support using GMP

parent b2ee75d3
......@@ -101,6 +101,13 @@ apt-get install zsh
sudo apt-get install readline
```
### gmp
`gmp` is a multiprecision library used for implementing Python longs. It's also a dependency of gcc, so if you installed that you should already have it:
```
sudo apt-get install libgmp3-dev
```
# Optional dependencies
There are a number of optional dependencies that the build system knows about, but aren't strictly necessary for building and running Pyston. Most of them are related to developing and debugging:
......
......@@ -141,7 +141,7 @@ COMMON_CXXFLAGS += -DGITREV=$(shell git rev-parse HEAD | head -c 12) -DLLVMREV=$
COMMON_CXXFLAGS += -DDEFAULT_PYTHON_MAJOR_VERSION=$(PYTHON_MAJOR_VERSION) -DDEFAULT_PYTHON_MINOR_VERSION=$(PYTHON_MINOR_VERSION) -DDEFAULT_PYTHON_MICRO_VERSION=$(PYTHON_MICRO_VERSION)
# Use our "custom linker" that calls gold if available
COMMON_LDFLAGS := -B../tools/build_system -L/usr/local/lib -lpthread -ldl -lcurses -lm -lunwind -lz -llzma -L$(DEPS_DIR)/gcc-4.8.2-install/lib64 -lreadline
COMMON_LDFLAGS := -B../tools/build_system -L/usr/local/lib -lpthread -ldl -lcurses -lm -lunwind -lz -llzma -L$(DEPS_DIR)/gcc-4.8.2-install/lib64 -lreadline -lgmp
# Make sure that we put all symbols in the dynamic symbol table so that MCJIT can load them;
# TODO should probably do the linking before MCJIT
COMMON_LDFLAGS += -Wl,-E
......
......@@ -408,7 +408,7 @@ private:
case AST_Num::FLOAT:
return FLOAT;
case AST_Num::LONG:
RELEASE_ASSERT(0, "");
return LONG;
}
abort();
}
......
......@@ -1127,6 +1127,12 @@ ConcreteCompilerVariable* makeFloat(double d) {
return new ConcreteCompilerVariable(FLOAT, llvm::ConstantFP::get(g.double_, d), true);
}
ConcreteCompilerVariable* makeLong(IREmitter& emitter, std::string& n_long) {
llvm::Value* v
= emitter.getBuilder()->CreateCall(g.funcs.createLong, embedConstantPtr(&n_long, g.llvm_str_type_ptr));
return new ConcreteCompilerVariable(LONG, v, true);
}
class KnownClassobjType : public ValuedCompilerType<BoxedClass*> {
private:
BoxedClass* cls;
......@@ -1916,6 +1922,6 @@ ConcreteCompilerVariable* undefVariable() {
}
ConcreteCompilerType* LIST, *SLICE, *MODULE, *DICT, *SET, *FROZENSET;
ConcreteCompilerType* LIST, *SLICE, *MODULE, *DICT, *SET, *FROZENSET, *LONG;
} // namespace pyston
......@@ -29,8 +29,8 @@ class OpInfo;
class CompilerType;
class IREmitter;
extern ConcreteCompilerType* INT, *BOXED_INT, *FLOAT, *BOXED_FLOAT, *VOID, *UNKNOWN, *BOOL, *STR, *NONE, *LIST, *SLICE,
*MODULE, *DICT, *BOOL, *BOXED_BOOL, *BOXED_TUPLE, *SET, *FROZENSET, *CLOSURE, *GENERATOR;
extern ConcreteCompilerType* INT, *BOXED_INT, *LONG, *FLOAT, *BOXED_FLOAT, *VOID, *UNKNOWN, *BOOL, *STR, *NONE, *LIST,
*SLICE, *MODULE, *DICT, *BOOL, *BOXED_BOOL, *BOXED_TUPLE, *SET, *FROZENSET, *CLOSURE, *GENERATOR;
extern CompilerType* UNDEF;
class CompilerType {
......@@ -347,6 +347,7 @@ public:
ConcreteCompilerVariable* makeInt(int64_t);
ConcreteCompilerVariable* makeFloat(double);
ConcreteCompilerVariable* makeBool(bool);
ConcreteCompilerVariable* makeLong(IREmitter& emitter, std::string&);
CompilerVariable* makeStr(std::string*);
CompilerVariable* makeFunction(IREmitter& emitter, CLFunction*, CompilerVariable* closure, bool isGenerator,
const std::vector<ConcreteCompilerVariable*>& defaults);
......
......@@ -737,7 +737,7 @@ private:
else if (node->num_type == AST_Num::FLOAT)
return makeFloat(node->n_float);
else
RELEASE_ASSERT(0, "");
return makeLong(emitter, node->n_long);
}
CompilerVariable* evalRepr(AST_Repr* node, ExcInfo exc_info) {
......
......@@ -114,7 +114,6 @@ def convert(n, f):
if isinstance(n.n, int):
f.write('\x10')
elif isinstance(n.n, long):
assert (-1L<<60) < n.n < (1L<<60)
f.write('\x30')
elif isinstance(n.n, float):
f.write('\x20')
......@@ -158,8 +157,7 @@ def convert(n, f):
elif isinstance(v, int):
f.write(struct.pack(">q", v))
elif isinstance(v, long):
assert (-1L<<60) < v < (1L<<60)
f.write(struct.pack(">q", v))
_print_str(str(v), f)
elif isinstance(v, float):
f.write(struct.pack(">d", v))
elif v is None or isinstance(v, _ast.AST):
......
......@@ -519,10 +519,7 @@ AST_Num* read_num(BufferedReader* reader) {
if (rtn->num_type == AST_Num::INT) {
rtn->n_int = reader->readULL(); // automatic conversion to signed
} else if (rtn->num_type == AST_Num::LONG) {
// Don't really support longs for now...
printf("Warning: converting long literal to int\n");
rtn->num_type = AST_Num::INT;
rtn->n_int = reader->readULL(); // automatic conversion to signed
rtn->n_long = readString(reader);
} else if (rtn->num_type == AST_Num::FLOAT) {
rtn->n_float = reader->readDouble();
} else {
......
......@@ -37,6 +37,7 @@
#include "runtime/generator.h"
#include "runtime/inline/boxing.h"
#include "runtime/int.h"
#include "runtime/long.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
......@@ -171,6 +172,7 @@ void initGlobalFuncs(GlobalState& g) {
GET(createSlice);
GET(createClosure);
GET(createGenerator);
GET(createLong);
GET(getattr);
GET(setattr);
......
......@@ -32,7 +32,7 @@ struct GlobalFuncs {
llvm::Value* boxInt, *unboxInt, *boxFloat, *unboxFloat, *boxStringPtr, *boxCLFunction, *unboxCLFunction,
*boxInstanceMethod, *boxBool, *unboxBool, *createTuple, *createDict, *createList, *createSlice,
*createUserClass, *createClosure, *createGenerator;
*createUserClass, *createClosure, *createGenerator, *createLong;
llvm::Value* getattr, *setattr, *delattr, *delitem, *delGlobal, *print, *nonzero, *binop, *compare, *augbinop,
*unboxedLen, *getitem, *getclsattr, *getGlobal, *setitem, *unaryop, *import, *importFrom, *importStar, *repr,
*isinstance, *yield;
......
......@@ -1376,6 +1376,8 @@ bool PrintVisitor::visit_name(AST_Name* node) {
bool PrintVisitor::visit_num(AST_Num* node) {
if (node->num_type == AST_Num::INT) {
printf("%ld", node->n_int);
} else if (node->num_type == AST_Num::LONG) {
printf("%sL", node->n_long.c_str());
} else if (node->num_type == AST_Num::FLOAT) {
printf("%f", node->n_float);
} else {
......
......@@ -609,6 +609,7 @@ public:
int64_t n_int;
double n_float;
};
std::string n_long;
virtual void accept(ASTVisitor* v);
virtual void* accept_expr(ExprVisitor* v);
......
......@@ -22,11 +22,13 @@
#include "gc/collector.h"
#include "runtime/gc_runtime.h"
#include "runtime/inline/xrange.h"
#include "runtime/list.h"
#include "runtime/long.h"
#include "runtime/objmodel.h"
#include "runtime/set.h"
#include "runtime/types.h"
#include "runtime/util.h"
#include "runtime/list.h"
namespace pyston {
extern "C" Box* trap() {
......@@ -536,6 +538,7 @@ void setupBuiltins() {
builtins_module->giveAttr("object", object_cls);
builtins_module->giveAttr("str", str_cls);
builtins_module->giveAttr("int", int_cls);
builtins_module->giveAttr("long", long_cls);
builtins_module->giveAttr("float", float_cls);
builtins_module->giveAttr("list", list_cls);
builtins_module->giveAttr("slice", slice_cls);
......
......@@ -23,6 +23,7 @@
#include "runtime/inline/boxing.h"
#include "runtime/int.h"
#include "runtime/list.h"
#include "runtime/long.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
......@@ -60,6 +61,7 @@ void force() {
FORCE(createUserClass);
FORCE(createClosure);
FORCE(createGenerator);
FORCE(createLong);
FORCE(getattr);
FORCE(setattr);
......
// 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 "runtime/long.h"
#include <cmath>
#include <gmp.h>
#include <sstream>
#include "codegen/compvars.h"
#include "core/common.h"
#include "core/options.h"
#include "core/stats.h"
#include "core/types.h"
#include "gc/collector.h"
#include "runtime/gc_runtime.h"
#include "runtime/inline/boxing.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
#include "runtime/util.h"
namespace pyston {
BoxedClass* long_cls;
const ObjectFlavor long_flavor(&boxGCHandler, NULL);
extern "C" Box* createLong(const std::string* s) {
BoxedLong* rtn = new BoxedLong(long_cls);
int r = mpz_init_set_str(rtn->n, s->c_str(), 10);
RELEASE_ASSERT(r == 0, "%d: '%s'", r, s->c_str());
return rtn;
}
extern "C" Box* longNew(Box* _cls, Box* val) {
if (!isSubclass(_cls->cls, type_cls))
raiseExcHelper(TypeError, "long.__new__(X): X is not a type object (%s)", getTypeName(_cls)->c_str());
BoxedClass* cls = static_cast<BoxedClass*>(_cls);
if (!isSubclass(cls, long_cls))
raiseExcHelper(TypeError, "long.__new__(%s): %s is not a subtype of long", getNameOfClass(cls)->c_str(),
getNameOfClass(cls)->c_str());
assert(cls->instance_size >= sizeof(BoxedInt));
void* mem = rt_alloc(cls->instance_size);
BoxedLong* rtn = ::new (mem) BoxedLong(cls);
initUserAttrs(rtn, cls);
if (val->cls == int_cls) {
mpz_init_set_si(rtn->n, static_cast<BoxedInt*>(val)->n);
} else if (val->cls == str_cls) {
const std::string& s = static_cast<BoxedString*>(val)->s;
int r = mpz_init_set_str(rtn->n, s.c_str(), 10);
RELEASE_ASSERT(r == 0, "");
} else {
fprintf(stderr, "TypeError: int() argument must be a string or a number, not '%s'\n",
getTypeName(val)->c_str());
raiseExcHelper(TypeError, "");
}
return rtn;
}
Box* longRepr(BoxedLong* v) {
if (!isSubclass(v->cls, long_cls))
raiseExcHelper(TypeError, "descriptor '__repr__' requires a 'long' object but received a '%s'",
getTypeName(v)->c_str());
int space_required = mpz_sizeinbase(v->n, 10) + 2; // basic size
space_required += 1; // 'L' suffix
char* buf = (char*)malloc(space_required);
mpz_get_str(buf, 10, v->n);
strcat(buf, "L");
auto rtn = new BoxedString(buf);
free(buf);
return rtn;
}
Box* longStr(BoxedLong* v) {
if (!isSubclass(v->cls, long_cls))
raiseExcHelper(TypeError, "descriptor '__str__' requires a 'long' object but received a '%s'",
getTypeName(v)->c_str());
char* buf = mpz_get_str(NULL, 10, v->n);
auto rtn = new BoxedString(buf);
free(buf);
return rtn;
}
Box* longMul(BoxedLong* v1, Box* _v2) {
if (!isSubclass(v1->cls, long_cls))
raiseExcHelper(TypeError, "descriptor '__mul__' requires a 'long' object but received a '%s'",
getTypeName(v1)->c_str());
if (!isSubclass(_v2->cls, long_cls))
return NotImplemented;
BoxedLong* v2 = static_cast<BoxedLong*>(_v2);
BoxedLong* r = new BoxedLong(long_cls);
mpz_init(r->n);
mpz_mul(r->n, v1->n, v2->n);
return r;
}
void setupLong() {
long_cls->giveAttr("__name__", boxStrConstant("long"));
long_cls->giveAttr("__new__",
new BoxedFunction(boxRTFunction((void*)longNew, UNKNOWN, 2, 1, false, false), { boxInt(0) }));
long_cls->giveAttr("__mul__", new BoxedFunction(boxRTFunction((void*)longMul, UNKNOWN, 2)));
long_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)longRepr, STR, 1)));
long_cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)longStr, STR, 1)));
long_cls->freeze();
}
}
// 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_RUNTIME_LONG_H
#define PYSTON_RUNTIME_LONG_H
#include <gmp.h>
#include "core/types.h"
#include "runtime/types.h"
namespace pyston {
void setupLong();
extern BoxedClass* long_cls;
extern const ObjectFlavor long_flavor;
class BoxedLong : public Box {
public:
mpz_t n;
BoxedLong(BoxedClass* cls) __attribute__((visibility("default"))) : Box(&long_flavor, cls) {}
};
extern "C" Box* createLong(const std::string* s);
}
#endif
......@@ -28,6 +28,7 @@
#include "core/types.h"
#include "gc/collector.h"
#include "runtime/gc_runtime.h"
#include "runtime/long.h"
#include "runtime/objmodel.h"
#include "runtime/set.h"
......@@ -562,6 +563,7 @@ void setupRuntime() {
// We could have a multi-stage setup process, but that seems overkill for now.
bool_cls = new BoxedClass(object_cls, 0, sizeof(BoxedBool), false);
int_cls = new BoxedClass(object_cls, 0, sizeof(BoxedInt), false);
long_cls = new BoxedClass(object_cls, 0, sizeof(BoxedLong), false);
float_cls = new BoxedClass(object_cls, 0, sizeof(BoxedFloat), false);
function_cls = new BoxedClass(object_cls, offsetof(BoxedFunction, attrs), sizeof(BoxedFunction), false);
instancemethod_cls = new BoxedClass(object_cls, 0, sizeof(BoxedInstanceMethod), false);
......@@ -586,6 +588,7 @@ void setupRuntime() {
SET = typeFromClass(set_cls);
FROZENSET = typeFromClass(frozenset_cls);
BOXED_TUPLE = typeFromClass(tuple_cls);
LONG = typeFromClass(long_cls);
object_cls->giveAttr("__name__", boxStrConstant("object"));
object_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)objectNew, UNKNOWN, 1, 0, true, false)));
......@@ -621,6 +624,7 @@ void setupRuntime() {
setupBool();
setupInt();
setupLong();
setupFloat();
setupStr();
setupList();
......
l = 2L
print l
print type(l)
t = 1L
for i in xrange(150):
t *= l
print t, repr(t)
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