mirror of
https://github.com/exaloop/codon.git
synced 2025-06-03 15:03:52 +08:00
PyType codegen (WIP)
This commit is contained in:
parent
92f9a274e7
commit
573f3f68c5
@ -660,29 +660,68 @@ void LLVMVisitor::writeToPythonExtension(const PyModule &pymod,
|
|||||||
// Setup LLVM types & constants
|
// Setup LLVM types & constants
|
||||||
auto *i64 = B->getInt64Ty();
|
auto *i64 = B->getInt64Ty();
|
||||||
auto *i32 = B->getInt32Ty();
|
auto *i32 = B->getInt32Ty();
|
||||||
|
auto *i8 = B->getInt8Ty();
|
||||||
auto *ptr = B->getInt8PtrTy();
|
auto *ptr = B->getInt8PtrTy();
|
||||||
auto *pyMethodDefType = llvm::StructType::create("PyMethodDef", ptr, ptr, i32, ptr);
|
auto *pyMethodDefType = llvm::StructType::create("PyMethodDef", ptr, ptr, i32, ptr);
|
||||||
auto *pyObjectType = llvm::StructType::create("PyObject", i64, ptr);
|
auto *pyObjectType = llvm::StructType::create("PyObject", i64, ptr);
|
||||||
|
auto *pyVarObjectType = llvm::StructType::create("PyVarObject", pyObjectType, i64);
|
||||||
auto *pyModuleDefBaseType =
|
auto *pyModuleDefBaseType =
|
||||||
llvm::StructType::create("PyMethodDefBase", pyObjectType, ptr, i64, ptr);
|
llvm::StructType::create("PyMethodDefBase", pyObjectType, ptr, i64, ptr);
|
||||||
auto *pyModuleDefType =
|
auto *pyModuleDefType =
|
||||||
llvm::StructType::create("PyModuleDef", pyModuleDefBaseType, ptr, ptr, i64,
|
llvm::StructType::create("PyModuleDef", pyModuleDefBaseType, ptr, ptr, i64,
|
||||||
pyMethodDefType->getPointerTo(), ptr, ptr, ptr, ptr);
|
pyMethodDefType->getPointerTo(), ptr, ptr, ptr, ptr);
|
||||||
|
std::vector<llvm::Type *> pyNumberMethodsFields(36, ptr);
|
||||||
|
auto *pyNumberMethodsType =
|
||||||
|
llvm::StructType::create(*context, pyNumberMethodsFields, "PyNumberMethods");
|
||||||
|
std::vector<llvm::Type *> pySequenceMethodsFields(10, ptr);
|
||||||
|
auto *pySequenceMethodsType =
|
||||||
|
llvm::StructType::create(*context, pySequenceMethodsFields, "PySequenceMethods");
|
||||||
|
std::vector<llvm::Type *> pyMappingMethodsFields(3, ptr);
|
||||||
|
auto *pyMappingMethodsType =
|
||||||
|
llvm::StructType::create(*context, pyMappingMethodsFields, "PyMappingMethods");
|
||||||
|
std::vector<llvm::Type *> pyAsyncMethodsFields(4, ptr);
|
||||||
|
auto *pyAsyncMethodsType =
|
||||||
|
llvm::StructType::create(*context, pyAsyncMethodsFields, "PyAsyncMethods");
|
||||||
|
auto *pyBufferProcsType = llvm::StructType::create("PyBufferProcs", ptr, ptr);
|
||||||
|
auto *pyTypeObjectType = llvm::StructType::create(
|
||||||
|
"PyTypeObject", pyVarObjectType, ptr, i64, i64, ptr, i64, ptr, ptr, ptr, ptr, ptr,
|
||||||
|
ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, i64, ptr, ptr, ptr, ptr, i64, ptr, ptr,
|
||||||
|
ptr, ptr, ptr, ptr, ptr, ptr, ptr, i64, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr,
|
||||||
|
ptr, ptr, ptr, i32, ptr, ptr, i8);
|
||||||
auto *zero64 = B->getInt64(0);
|
auto *zero64 = B->getInt64(0);
|
||||||
auto *zero32 = B->getInt32(0);
|
auto *zero32 = B->getInt32(0);
|
||||||
|
auto *zero8 = B->getInt8(0);
|
||||||
auto *null = llvm::Constant::getNullValue(ptr);
|
auto *null = llvm::Constant::getNullValue(ptr);
|
||||||
|
auto *pyTypeType = new llvm::GlobalVariable(*M, ptr, /*isConstant=*/false,
|
||||||
|
llvm::GlobalValue::ExternalLinkage,
|
||||||
|
/*Initializer=*/nullptr, "PyType_Type");
|
||||||
|
|
||||||
|
auto allocUncollectable = llvm::cast<llvm::Function>(
|
||||||
|
M->getOrInsertFunction("seq_alloc_uncollectable", ptr, i64).getCallee());
|
||||||
|
allocUncollectable->setDoesNotThrow();
|
||||||
|
allocUncollectable->setReturnDoesNotAlias();
|
||||||
|
allocUncollectable->setOnlyAccessesInaccessibleMemory();
|
||||||
|
|
||||||
|
auto free = llvm::cast<llvm::Function>(
|
||||||
|
M->getOrInsertFunction("seq_free", B->getVoidTy(), ptr).getCallee());
|
||||||
|
free->setDoesNotThrow();
|
||||||
|
|
||||||
|
// Helpers
|
||||||
|
auto pyFunc = [&](Func *func) -> llvm::Constant * {
|
||||||
|
if (!func)
|
||||||
|
return null;
|
||||||
|
auto llvmName = getNameForFunction(func);
|
||||||
|
auto *llvmFunc = M->getFunction(llvmName);
|
||||||
|
seqassertn(llvmFunc, "function {} not found in LLVM module", llvmName);
|
||||||
|
llvmFunc = createPyTryCatchWrapper(llvmFunc);
|
||||||
|
return llvmFunc;
|
||||||
|
};
|
||||||
|
|
||||||
// Handle functions
|
// Handle functions
|
||||||
std::vector<llvm::Constant *> pyMethods;
|
std::vector<llvm::Constant *> pyMethods;
|
||||||
for (auto &pyfunc : pymod.functions) {
|
for (auto &pyfunc : pymod.functions) {
|
||||||
auto llvmName = getNameForFunction(pyfunc.func);
|
|
||||||
auto *llvmFunc = M->getFunction(llvmName);
|
|
||||||
seqassertn(llvmFunc, "function {} not found in LLVM module", llvmName);
|
|
||||||
llvmFunc = createPyTryCatchWrapper(llvmFunc);
|
|
||||||
|
|
||||||
auto *nameVar = new llvm::GlobalVariable(
|
auto *nameVar = new llvm::GlobalVariable(
|
||||||
*M, llvm::ArrayType::get(B->getInt8Ty(), pyfunc.name.length() + 1),
|
*M, llvm::ArrayType::get(i8, pyfunc.name.length() + 1),
|
||||||
/*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
|
/*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
|
||||||
llvm::ConstantDataArray::getString(*context, pyfunc.name), ".pyext_func_name");
|
llvm::ConstantDataArray::getString(*context, pyfunc.name), ".pyext_func_name");
|
||||||
nameVar->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
|
nameVar->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
|
||||||
@ -701,14 +740,14 @@ void LLVMVisitor::writeToPythonExtension(const PyModule &pymod,
|
|||||||
auto *docsConst = null;
|
auto *docsConst = null;
|
||||||
if (pyfunc.doc.empty()) {
|
if (pyfunc.doc.empty()) {
|
||||||
auto *docsVar = new llvm::GlobalVariable(
|
auto *docsVar = new llvm::GlobalVariable(
|
||||||
*M, llvm::ArrayType::get(B->getInt8Ty(), pyfunc.doc.length() + 1),
|
*M, llvm::ArrayType::get(i8, pyfunc.doc.length() + 1),
|
||||||
/*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
|
/*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
|
||||||
llvm::ConstantDataArray::getString(*context, pyfunc.doc), ".pyext_docstring");
|
llvm::ConstantDataArray::getString(*context, pyfunc.doc), ".pyext_docstring");
|
||||||
docsVar->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
|
docsVar->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
|
||||||
docsConst = llvm::ConstantExpr::getBitCast(docsVar, ptr);
|
docsConst = llvm::ConstantExpr::getBitCast(docsVar, ptr);
|
||||||
}
|
}
|
||||||
pyMethods.push_back(llvm::ConstantStruct::get(pyMethodDefType, nameVar, llvmFunc,
|
pyMethods.push_back(llvm::ConstantStruct::get(
|
||||||
flagConst, docsConst));
|
pyMethodDefType, nameVar, pyFunc(pyfunc.func), flagConst, docsConst));
|
||||||
}
|
}
|
||||||
pyMethods.push_back(
|
pyMethods.push_back(
|
||||||
llvm::ConstantStruct::get(pyMethodDefType, null, null, zero32, null));
|
llvm::ConstantStruct::get(pyMethodDefType, null, null, zero32, null));
|
||||||
@ -721,11 +760,11 @@ void LLVMVisitor::writeToPythonExtension(const PyModule &pymod,
|
|||||||
|
|
||||||
// Construct PyModuleDef array
|
// Construct PyModuleDef array
|
||||||
auto *pyObjectConst = llvm::ConstantStruct::get(pyObjectType, B->getInt64(1), null);
|
auto *pyObjectConst = llvm::ConstantStruct::get(pyObjectType, B->getInt64(1), null);
|
||||||
auto *pyModuleDefBaseConst = llvm::ConstantStruct::get(
|
auto *pyModuleDefBaseConst =
|
||||||
pyModuleDefBaseType, pyObjectConst, null, B->getInt64(0), null);
|
llvm::ConstantStruct::get(pyModuleDefBaseType, pyObjectConst, null, zero64, null);
|
||||||
|
|
||||||
auto *nameVar = new llvm::GlobalVariable(
|
auto *nameVar = new llvm::GlobalVariable(
|
||||||
*M, llvm::ArrayType::get(B->getInt8Ty(), pymod.name.length() + 1),
|
*M, llvm::ArrayType::get(i8, pymod.name.length() + 1),
|
||||||
/*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
|
/*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
|
||||||
llvm::ConstantDataArray::getString(*context, pymod.name), ".pyext_module_name");
|
llvm::ConstantDataArray::getString(*context, pymod.name), ".pyext_module_name");
|
||||||
nameVar->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
|
nameVar->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
|
||||||
@ -734,7 +773,7 @@ void LLVMVisitor::writeToPythonExtension(const PyModule &pymod,
|
|||||||
auto *docsConst = null;
|
auto *docsConst = null;
|
||||||
if (!pymod.doc.empty()) {
|
if (!pymod.doc.empty()) {
|
||||||
auto *docsVar = new llvm::GlobalVariable(
|
auto *docsVar = new llvm::GlobalVariable(
|
||||||
*M, llvm::ArrayType::get(B->getInt8Ty(), pymod.doc.length() + 1),
|
*M, llvm::ArrayType::get(i8, pymod.doc.length() + 1),
|
||||||
/*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
|
/*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
|
||||||
llvm::ConstantDataArray::getString(*context, pymod.doc), ".pyext_docstring");
|
llvm::ConstantDataArray::getString(*context, pymod.doc), ".pyext_docstring");
|
||||||
docsVar->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
|
docsVar->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
|
||||||
@ -767,7 +806,171 @@ void LLVMVisitor::writeToPythonExtension(const PyModule &pymod,
|
|||||||
B->CreateRet(B->CreateCall(pyModuleCreate,
|
B->CreateRet(B->CreateCall(pyModuleCreate,
|
||||||
{pyModuleConst, B->getInt32(PYEXT_PYTHON_ABI_VERSION)}));
|
{pyModuleConst, B->getInt32(PYEXT_PYTHON_ABI_VERSION)}));
|
||||||
|
|
||||||
// TODO: Codegen types, methods, etc.
|
for (auto &pytype : pymod.types) {
|
||||||
|
std::vector<llvm::Constant *> numberSlots = {
|
||||||
|
pyFunc(pytype.add), // nb_add
|
||||||
|
pyFunc(pytype.sub), // nb_subtract
|
||||||
|
pyFunc(pytype.mul), // nb_multiply
|
||||||
|
pyFunc(pytype.mod), // nb_remainder
|
||||||
|
pyFunc(pytype.divmod), // nb_divmod
|
||||||
|
pyFunc(pytype.pow), // nb_power
|
||||||
|
pyFunc(pytype.neg), // nb_negative
|
||||||
|
pyFunc(pytype.pos), // nb_positive
|
||||||
|
pyFunc(pytype.abs), // nb_absolute
|
||||||
|
pyFunc(pytype.bool_), // nb_bool
|
||||||
|
pyFunc(pytype.invert), // nb_invert
|
||||||
|
pyFunc(pytype.lshift), // nb_lshift
|
||||||
|
pyFunc(pytype.rshift), // nb_rshift
|
||||||
|
pyFunc(pytype.and_), // nb_and
|
||||||
|
pyFunc(pytype.xor_), // nb_xor
|
||||||
|
pyFunc(pytype.or_), // nb_or
|
||||||
|
pyFunc(pytype.int_), // nb_int
|
||||||
|
null, // nb_reserved
|
||||||
|
pyFunc(pytype.float_), // nb_float
|
||||||
|
pyFunc(pytype.iadd), // nb_inplace_add
|
||||||
|
pyFunc(pytype.isub), // nb_inplace_subtract
|
||||||
|
pyFunc(pytype.imul), // nb_inplace_multiply
|
||||||
|
pyFunc(pytype.imod), // nb_inplace_remainder
|
||||||
|
pyFunc(pytype.ipow), // nb_inplace_power
|
||||||
|
pyFunc(pytype.ilshift), // nb_inplace_lshift
|
||||||
|
pyFunc(pytype.irshift), // nb_inplace_rshift
|
||||||
|
pyFunc(pytype.iand), // nb_inplace_and
|
||||||
|
pyFunc(pytype.ixor), // nb_inplace_xor
|
||||||
|
pyFunc(pytype.ior), // nb_inplace_or
|
||||||
|
pyFunc(pytype.floordiv), // nb_floor_divide
|
||||||
|
pyFunc(pytype.truediv), // nb_true_divide
|
||||||
|
pyFunc(pytype.ifloordiv), // nb_inplace_floor_divide
|
||||||
|
pyFunc(pytype.itruediv), // nb_inplace_true_divide
|
||||||
|
pyFunc(pytype.index), // nb_index
|
||||||
|
pyFunc(pytype.matmul), // nb_matrix_multiply
|
||||||
|
pyFunc(pytype.imatmul), // nb_inplace_matrix_multiply
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<llvm::Constant *> sequenceSlots = {
|
||||||
|
pyFunc(pytype.len), // sq_length
|
||||||
|
null, // sq_concat
|
||||||
|
null, // sq_repeat
|
||||||
|
pyFunc(pytype.getitem), // sq_item
|
||||||
|
null, // was_sq_slice
|
||||||
|
pyFunc(pytype.setitem), // sq_ass_item
|
||||||
|
null, // was_sq_ass_slice
|
||||||
|
pyFunc(pytype.contains), // sq_contains
|
||||||
|
null, // sq_inplace_concat
|
||||||
|
null, // sq_inplace_repeat
|
||||||
|
};
|
||||||
|
|
||||||
|
bool needNumberSlots =
|
||||||
|
std::find_if(numberSlots.begin(), numberSlots.end(),
|
||||||
|
[&](auto *v) { return v != null; }) != numberSlots.end();
|
||||||
|
bool needSequenceSlots =
|
||||||
|
std::find_if(sequenceSlots.begin(), sequenceSlots.end(),
|
||||||
|
[&](auto *v) { return v != null; }) != sequenceSlots.end();
|
||||||
|
|
||||||
|
auto *numberSlotsConst =
|
||||||
|
needNumberSlots ? llvm::ConstantStruct::get(pyNumberMethodsType, numberSlots)
|
||||||
|
: null;
|
||||||
|
auto *sequenceSlotsConst =
|
||||||
|
needSequenceSlots
|
||||||
|
? llvm::ConstantStruct::get(pySequenceMethodsType, sequenceSlots)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
auto *nameVar = new llvm::GlobalVariable(
|
||||||
|
*M, llvm::ArrayType::get(B->getInt8Ty(), pytype.name.length() + 1),
|
||||||
|
/*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
|
||||||
|
llvm::ConstantDataArray::getString(*context, pytype.name), ".pyext_type_name");
|
||||||
|
nameVar->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
|
||||||
|
|
||||||
|
auto *docsConst = null;
|
||||||
|
if (pytype.doc.empty()) {
|
||||||
|
auto *docsVar = new llvm::GlobalVariable(
|
||||||
|
*M, llvm::ArrayType::get(B->getInt8Ty(), pytype.doc.length() + 1),
|
||||||
|
/*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
|
||||||
|
llvm::ConstantDataArray::getString(*context, pytype.doc),
|
||||||
|
".pyext_type_docstring");
|
||||||
|
docsVar->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
|
||||||
|
docsConst = llvm::ConstantExpr::getBitCast(docsVar, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto *refType = cast<types::RefType>(pytype.type);
|
||||||
|
auto *llvmType = getLLVMType(pytype.type);
|
||||||
|
auto *objectType = llvm::StructType::get(pyObjectType, llvmType);
|
||||||
|
auto codonSize =
|
||||||
|
refType
|
||||||
|
? M->getDataLayout().getTypeAllocSize(getLLVMType(refType->getContents()))
|
||||||
|
: 0;
|
||||||
|
auto pySize = M->getDataLayout().getTypeAllocSize(objectType);
|
||||||
|
auto *alloc = llvm::cast<llvm::Function>(
|
||||||
|
M->getOrInsertFunction(pytype.name + ".py_alloc", ptr, ptr, i64).getCallee());
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
auto *entry = llvm::BasicBlock::Create(*context, "entry", alloc);
|
||||||
|
B->SetInsertPoint(entry);
|
||||||
|
|
||||||
|
auto *memory = B->CreateCall(allocUncollectable, pySize);
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
std::vector<llvm::Constant *> typeSlots = {
|
||||||
|
llvm::ConstantStruct::get(
|
||||||
|
pyVarObjectType,
|
||||||
|
llvm::ConstantStruct::get(pyObjectType, B->getInt64(1), pyTypeType),
|
||||||
|
zero64), // PyObject_VAR_HEAD
|
||||||
|
nameConst, // const char *tp_name;
|
||||||
|
B->getInt64(pySize), // Py_ssize_t tp_basicsize;
|
||||||
|
zero64, // Py_ssize_t tp_itemsize;
|
||||||
|
// destructor tp_dealloc;
|
||||||
|
zero64, // Py_ssize_t tp_vectorcall_offset;
|
||||||
|
null, // getattrfunc tp_getattr;
|
||||||
|
null, // setattrfunc tp_setattr;
|
||||||
|
null, // PyAsyncMethods *tp_as_async;
|
||||||
|
pyFunc(pytype.repr), // reprfunc tp_repr;
|
||||||
|
numberSlotsConst, // PyNumberMethods *tp_as_number;
|
||||||
|
sequenceSlotsConst, // PySequenceMethods *tp_as_sequence;
|
||||||
|
null, // PyMappingMethods *tp_as_mapping;
|
||||||
|
pyFunc(pytype.hash), // hashfunc tp_hash;
|
||||||
|
pyFunc(pytype.call), // ternaryfunc tp_call;
|
||||||
|
pyFunc(pytype.str), // reprfunc tp_str;
|
||||||
|
null, // getattrofunc tp_getattro;
|
||||||
|
null, // setattrofunc tp_setattro;
|
||||||
|
null, // PyBufferProcs *tp_as_buffer;
|
||||||
|
zero64, // unsigned long tp_flags;
|
||||||
|
docsConst, // const char *tp_doc;
|
||||||
|
null, // traverseproc tp_traverse;
|
||||||
|
null, // inquiry tp_clear;
|
||||||
|
pyFunc(pytype.cmp), // richcmpfunc tp_richcompare;
|
||||||
|
zero64, // Py_ssize_t tp_weaklistoffset;
|
||||||
|
pyFunc(pytype.iter), // getiterfunc tp_iter;
|
||||||
|
pyFunc(pytype.iternext), // iternextfunc tp_iternext;
|
||||||
|
// PyMethodDef *tp_methods;
|
||||||
|
null, // PyMemberDef *tp_members;
|
||||||
|
// PyGetSetDef *tp_getset;
|
||||||
|
null, // PyTypeObject *tp_base;
|
||||||
|
null, // PyObject *tp_dict;
|
||||||
|
null, // descrgetfunc tp_descr_get;
|
||||||
|
null, // descrsetfunc tp_descr_set;
|
||||||
|
zero64, // Py_ssize_t tp_dictoffset;
|
||||||
|
pyFunc(pytype.init), // initproc tp_init;
|
||||||
|
alloc, // allocfunc tp_alloc;
|
||||||
|
null, // newfunc tp_new;
|
||||||
|
free, // freefunc tp_free;
|
||||||
|
null, // inquiry tp_is_gc;
|
||||||
|
null, // PyObject *tp_bases;
|
||||||
|
null, // PyObject *tp_mro;
|
||||||
|
null, // PyObject *tp_cache;
|
||||||
|
null, // void *tp_subclasses;
|
||||||
|
null, // PyObject *tp_weaklist;
|
||||||
|
null, // destructor tp_del;
|
||||||
|
zero32, // unsigned int tp_version_tag;
|
||||||
|
pyFunc(pytype.del), // destructor tp_finalize;
|
||||||
|
null, // vectorcallfunc tp_vectorcall;
|
||||||
|
B->getInt8(0), // char tp_watched;
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
// set tp_base in module init func
|
||||||
|
|
||||||
writeToObjectFile(filename);
|
writeToObjectFile(filename);
|
||||||
}
|
}
|
||||||
|
@ -105,6 +105,7 @@ struct PyType {
|
|||||||
Func *str = nullptr;
|
Func *str = nullptr;
|
||||||
Func *cmp = nullptr;
|
Func *cmp = nullptr;
|
||||||
Func *iter = nullptr;
|
Func *iter = nullptr;
|
||||||
|
Func *iternext = nullptr;
|
||||||
Func *del = nullptr;
|
Func *del = nullptr;
|
||||||
Func *new_ = nullptr;
|
Func *new_ = nullptr;
|
||||||
Func *init = nullptr;
|
Func *init = nullptr;
|
||||||
|
@ -165,6 +165,14 @@ SEQ_FUNC void *seq_alloc_atomic(size_t n) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SEQ_FUNC void *seq_alloc_uncollectable(size_t n) {
|
||||||
|
#if USE_STANDARD_MALLOC
|
||||||
|
return malloc(n);
|
||||||
|
#else
|
||||||
|
return GC_MALLOC_UNCOLLECTABLE(n);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
SEQ_FUNC void *seq_calloc(size_t m, size_t n) {
|
SEQ_FUNC void *seq_calloc(size_t m, size_t n) {
|
||||||
#if USE_STANDARD_MALLOC
|
#if USE_STANDARD_MALLOC
|
||||||
return calloc(m, n);
|
return calloc(m, n);
|
||||||
|
@ -11,6 +11,11 @@ def seq_alloc(a: int) -> cobj:
|
|||||||
def seq_alloc_atomic(a: int) -> cobj:
|
def seq_alloc_atomic(a: int) -> cobj:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@pure
|
||||||
|
@C
|
||||||
|
def seq_alloc_uncollectable(a: int) -> cobj:
|
||||||
|
pass
|
||||||
|
|
||||||
@nocapture
|
@nocapture
|
||||||
@derives
|
@derives
|
||||||
@C
|
@C
|
||||||
@ -61,6 +66,11 @@ def alloc(sz: int):
|
|||||||
def alloc_atomic(sz: int):
|
def alloc_atomic(sz: int):
|
||||||
return seq_alloc_atomic(sz)
|
return seq_alloc_atomic(sz)
|
||||||
|
|
||||||
|
# Allocates a block of memory via GC that is scanned,
|
||||||
|
# but not collected itself. Should be free'd explicitly.
|
||||||
|
def alloc_uncollectable(sz: int):
|
||||||
|
return seq_alloc_uncollectable(sz)
|
||||||
|
|
||||||
def realloc(p: cobj, newsz: int, oldsz: int):
|
def realloc(p: cobj, newsz: int, oldsz: int):
|
||||||
return seq_realloc(p, newsz, oldsz)
|
return seq_realloc(p, newsz, oldsz)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user