Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ if (${ENABLE_SANITIZER_UNDEFINED_BEHAVIOR})
endif()

project_options(
# WARNINGS_AS_ERRORS
WARNINGS_AS_ERRORS
# ENABLE_COVERAGE
# ENABLE_CPPCHECK
# ENABLE_CLANG_TIDY
Expand All @@ -74,7 +74,7 @@ project_options(

# TODO: Address all the warning below. This should be only temporary...
target_compile_options(project_warnings
INTERFACE $<$<COMPILE_LANGUAGE:CXX>:-Wno-sign-conversion;-Wno-shorten-64-to-32;-Wno-shadow;-Wno-implicit-fallthrough;-Wno-implicit-int-conversion;-Wno-old-style-cast;-Wno-gnu-zero-variadic-macro-arguments;-Wno-implicit-int-float-conversion;-Wno-deprecated-copy;-Wno-missing-field-initializers>
INTERFACE $<$<COMPILE_LANGUAGE:CXX>:-Wno-sign-conversion;-Wno-shadow;-Wno-implicit-fallthrough;-Wno-old-style-cast;-Wno-deprecated-copy;-Wno-missing-field-initializers;-Wno-null-dereference;-Wno-maybe-uninitialized>
)

check_cxx_source_compiles(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -466,21 +466,21 @@ class LinearScanRegisterAllocation
auto current_value = std::get<mlir::Value>(cur.value);

// Resolve block arguments to their defining operations
if (current_value.isa<mlir::BlockArgument>()) {
if (mlir::isa<mlir::BlockArgument>(current_value)) {
if (auto it = live_interval_analysis.block_input_mappings.find(cur.value);
it != live_interval_analysis.block_input_mappings.end()) {
for (auto mapped_value : it->second) {
ASSERT(!std::holds_alternative<ForwardedOutput>(mapped_value));
if (clobbers_r0(std::get<mlir::Value>(mapped_value))) {
ASSERT(current_value.isa<mlir::BlockArgument>());
ASSERT(mlir::isa<mlir::BlockArgument>(current_value));
current_value = std::get<mlir::Value>(mapped_value);
break;
}
}
}
}

ASSERT(!current_value.isa<mlir::BlockArgument>());
ASSERT(!mlir::isa<mlir::BlockArgument>(current_value));
auto loc = current_value.getLoc();

// Insert: push r{cur_reg}, move r{scratch}, r{cur_reg}, pop r{cur_reg}
Expand Down
12 changes: 11 additions & 1 deletion src/runtime/PyArgParser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include "TypeError.hpp"
#include "vm/VM.hpp"

#include <limits>

namespace py {

template<typename... ArgTypes> struct PyArgsParser
Expand Down Expand Up @@ -56,7 +58,15 @@ template<typename... ArgTypes> struct PyArgsParser
return Err(type_error("'{}' object cannot be interpreted as an integer",
int_obj.unwrap()->type()->name()));
} else {
std::get<Idx>(result) = as<PyInteger>(int_obj.unwrap())->as_i64();
auto value = as<PyInteger>(int_obj.unwrap())->as_i64();
static_assert(sizeof(ExpectedType) <= 8);
if (!fits_in<ExpectedType>(value)) {
return Err(type_error("{} not within range ({}, {})",
value,
std::numeric_limits<ExpectedType>::min(),
std::numeric_limits<ExpectedType>::max()));
}
std::get<Idx>(result) = static_cast<ExpectedType>(value);
}
} else {
[]<bool flag = false>() {
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/PyList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ PyResult<PyObject *> PyList::__mul__(size_t count) const
if (count <= 0) { return PyList::create(); }
std::vector<Value> values;
values.reserve(count * m_elements.size());
for (auto _ : std::views::iota(size_t{ 0 }, count)) {
for ([[maybe_unused]] auto _ : std::views::iota(size_t{ 0 }, count)) {
values.insert(values.end(), m_elements.begin(), m_elements.end());
}

Expand Down
16 changes: 12 additions & 4 deletions src/runtime/PyString.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,11 @@ PyResult<PyString *> PyString::create(const Bytes &bytes, const std::string &enc
if (byte < std::byte{ 128 }) {
result.push_back(static_cast<char>(byte));
} else {
result.push_back(0xc2 + (static_cast<unsigned char>(byte) > 0xbf));
result.push_back((static_cast<char>(byte) & 0x3f) + 0x80);
result.push_back(
static_cast<unsigned char>(0xc2) + static_cast<unsigned char>(byte) > 0xbf);
result.push_back(static_cast<char>(
(static_cast<unsigned char>(byte) & static_cast<unsigned char>(0x3f))
+ static_cast<unsigned char>(0x80)));
}
}
return PyString::create(result);
Expand Down Expand Up @@ -1864,9 +1867,14 @@ PyResult<PyObject *> PyString::translate(PyObject *table) const
if (mapped_cp > 0x110000 || mapped_cp < 0) {
return Err(value_error("character mapping must be in range(0x110000)"));
}
auto el = utf8::utf8chr(mapped_cp.get_ui());
auto mapped_cp_ui = mapped_cp.get_ui();
if (!fits_in<uint32_t>(mapped_cp_ui)) {
return Err(value_error(
"character mapping value {} does not fit in uint32_t", mapped_cp_ui));
}
auto el = utf8::utf8chr(static_cast<uint32_t>(mapped_cp_ui));
if (!el.has_value()) {}
cache[mapped_cp.get_ui()] = *el;
cache[static_cast<uint32_t>(mapped_cp_ui)] = *el;
result.append(*el);
} else if (mapped_value.unwrap()->type()->issubclass(types::str())) {
auto mapped_str = static_cast<const PyString &>(*mapped_value.unwrap()).value();
Expand Down
16 changes: 8 additions & 8 deletions src/runtime/Value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -455,8 +455,8 @@ bool Bytes::operator==(const PyObject *other) const
constexpr unsigned char to_digit_value(char value)
{
if (value >= 0 && value <= 9) { return value; }
if (value >= 'a' && value <= 'z') { return (value - 'a') + 10; }
if (value >= 'A' && value <= 'Z') { return (value - 'A') + 10; }
if (value >= 'a' && value <= 'z') { return static_cast<unsigned char>((value - 'a') + 10); }
if (value >= 'A' && value <= 'Z') { return static_cast<unsigned char>((value - 'A') + 10); }
return 37;
}

Expand Down Expand Up @@ -611,12 +611,6 @@ bool NameConstant::operator==(const NameConstant &other) const
[](const auto &rhs, const auto &lhs) { return rhs == lhs; }, value, other.value);
}

std::ostream &py::operator<<(std::ostream &os, const Tuple &tuple)
{
os << tuple.to_string();
return os;
}

std::string Tuple::to_string() const
{
std::ostringstream os;
Expand All @@ -642,6 +636,12 @@ std::string Tuple::to_string() const

namespace py {

std::ostream &operator<<(std::ostream &os, const Tuple &tuple)
{
os << tuple.to_string();
return os;
}

PyResult<Value> add(const Value &lhs, const Value &rhs, Interpreter &)
{
return std::visit(
Expand Down
6 changes: 5 additions & 1 deletion src/runtime/modules/signal/module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include <csignal>
#include <cstdint>
#include <limits>
#include <variant>

namespace py {
Expand Down Expand Up @@ -83,7 +84,10 @@ PyResult<PyObject *> signal(PyTuple *args, PyDict *kwargs)
previous_handler = std::get<PyObject *>(it->second);
}

if (std::signal(signalnum, sighandler) == SIG_ERR) {
if (signalnum >= NSIG) { return Err(value_error("signal number out of range")); }

static_assert(NSIG < std::numeric_limits<int>::max());
if (std::signal(static_cast<int>(signalnum), sighandler) == SIG_ERR) {
return Err(value_error("error setting signal handler"));
}

Expand Down
11 changes: 10 additions & 1 deletion src/runtime/modules/sre/Pattern.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@
#include "runtime/PyObject.hpp"
#include "runtime/PyTuple.hpp"
#include "runtime/TypeError.hpp"
#include "runtime/ValueError.hpp"
#include "runtime/types/api.hpp"
#include "runtime/types/builtin.hpp"
#include "utilities.hpp"
#include "vm/VM.hpp"
#include <cstdint>
#include <limits>

using namespace py;
using namespace py::sre;
Expand Down Expand Up @@ -49,7 +51,14 @@ PyResult<Pattern *> Pattern::create(PyObject *pattern,
auto el_ = PyObject::from(el);
if (el_.is_err()) { return Err(el_.unwrap_err()); }
if (!el_.unwrap()->type()->issubclass(types::integer())) { TODO(); }
code_vec.push_back(static_cast<const PyInteger &>(*el_.unwrap()).as_size_t());
auto value = static_cast<const PyInteger &>(*el_.unwrap()).as_size_t();
if (!fits_in<uint32_t>(value)) {
return Err(value_error("code value {} does not fit in [{}, {}]",
value,
std::numeric_limits<uint32_t>::min(),
std::numeric_limits<uint32_t>::max()));
}
code_vec.push_back(static_cast<uint32_t>(value));
}

std::optional<bool> isbytes;
Expand Down
4 changes: 2 additions & 2 deletions src/runtime/modules/sre/module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ PyResult<PyObject *> ascii_iscased(PyTuple *args, PyDict *kwargs)

auto ch = character->as_big_int().get_si();
if (ch >= 128) { return Ok(py_false()); }
return Ok(std::isalpha(ch) ? py_true() : py_false());
return Ok(std::isalpha(static_cast<int>(ch)) ? py_true() : py_false());
}

PyResult<PyObject *> ascii_tolower(PyTuple *args, PyDict *kwargs)
Expand All @@ -111,7 +111,7 @@ PyResult<PyObject *> ascii_tolower(PyTuple *args, PyDict *kwargs)

auto ch = character->as_big_int().get_si();
if (ch >= 128) { return Ok(character); }
return PyInteger::create(std::tolower(ch));
return PyInteger::create(std::tolower(static_cast<int>(ch)));
}


Expand Down
6 changes: 3 additions & 3 deletions src/runtime/modules/time/module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ PyModule *time_module()

module->add_symbol(PyString::create("monotonic").unwrap(),
PyNativeFunction::create("monotonic", [](PyTuple *, PyDict *) {
const double ns = std::chrono::duration_cast<std::chrono::nanoseconds>(
auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::steady_clock::now().time_since_epoch())
.count();
return PyFloat::create(ns / std::nano::den);
.count();
return PyFloat::create(static_cast<double>(ns) / std::nano::den);
}).unwrap());

return module;
Expand Down
27 changes: 27 additions & 0 deletions src/utilities.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,30 @@ template<class To, class From> constexpr To bit_cast(const From &from) noexcept
return std::bit_cast<To>(from);
}
#endif


template<typename T>
concept Integral = std::is_integral_v<T>;

template<Integral Target, Integral Source> bool fits_in(Source value)
{
constexpr bool source_is_signed = std::is_signed<Source>::value;
constexpr bool target_is_signed = std::is_signed<Target>::value;

// Case 1: Source is signed, Target is unsigned
if constexpr (source_is_signed && !target_is_signed) {
if (value < 0) { return false; }
// Now we know value is non-negative, safe to cast and compare
return static_cast<std::make_unsigned_t<Source>>(value)
<= std::numeric_limits<Target>::max();
}
// Case 2: Source is unsigned, Target is signed
else if constexpr (!source_is_signed && target_is_signed) {
return value
<= static_cast<std::make_unsigned_t<Target>>(std::numeric_limits<Target>::max());
} else {
// Case 3: Both signed or both unsigned
return value >= std::numeric_limits<Target>::min()
&& value <= std::numeric_limits<Target>::max();
}
}