1
0
forked from M-Labs/nac3

Compare commits

...

6 Commits

6 changed files with 94 additions and 17 deletions

View File

@ -3,3 +3,4 @@
#include "irrt/math.hpp"
#include "irrt/ndarray.hpp"
#include "irrt/slice.hpp"
#include "irrt/string.hpp"

View File

@ -0,0 +1,22 @@
#pragma once
#include "irrt/int_types.hpp"
namespace {
template<typename SizeT>
int32_t __nac3_str_eq_impl(const char* str1, SizeT len1, const char* str2, SizeT len2) {
if (str1 == str2) return 1;
if (len1 != len2) return 0;
for (SizeT i = 0; i < len1; ++i) {
if (static_cast<unsigned char>(str1[i]) != static_cast<unsigned char>(str2[i])) {
return 0;
}
}
return 1;
}
} // namespace
extern "C" {
int32_t nac3_str_eq(const char* str1, uint64_t len1, const char* str2, uint64_t len2) {
return __nac3_str_eq_impl<uint64_t>(str1, len1, str2, len2);
}
}

View File

@ -20,6 +20,7 @@ mod list;
mod math;
mod ndarray;
mod slice;
mod string;
#[must_use]
pub fn load_irrt<'ctx>(ctx: &'ctx Context, symbol_resolver: &dyn SymbolResolver) -> Module<'ctx> {

View File

@ -0,0 +1,45 @@
use inkwell::{
values::{BasicValueEnum, CallSiteValue, IntValue, PointerValue},
AddressSpace,
};
use itertools::Either;
use crate::codegen::{CodeGenContext, CodeGenerator};
/// Generates a call to string equality comparison. Returns an `i1` representing whether the strings are equal.
pub fn call_string_eq<'ctx, G: CodeGenerator + ?Sized>(
generator: &G,
ctx: &CodeGenContext<'ctx, '_>,
str1_ptr: PointerValue<'ctx>,
str1_len: IntValue<'ctx>,
str2_ptr: PointerValue<'ctx>,
str2_len: IntValue<'ctx>,
) -> IntValue<'ctx> {
let string_eq_fn = ctx.module.get_function("nac3_str_eq").unwrap_or_else(|| {
let i8_ptr_type = ctx.ctx.i8_type().ptr_type(AddressSpace::default());
let i64_type = ctx.ctx.i64_type();
let i32_type = ctx.ctx.i32_type();
let fn_type = i32_type.fn_type(
&[i8_ptr_type.into(), i64_type.into(), i8_ptr_type.into(), i64_type.into()],
false,
);
ctx.module.add_function("nac3_str_eq", fn_type, None)
});
let result = ctx
.builder
.build_call(
string_eq_fn,
&[
str1_ptr.into(),
ctx.builder.build_int_z_extend(str1_len, ctx.ctx.i64_type(), "").unwrap().into(),
str2_ptr.into(),
ctx.builder.build_int_z_extend(str2_len, ctx.ctx.i64_type(), "").unwrap().into(),
],
"string_eq",
)
.map(CallSiteValue::try_as_basic_value)
.map(|v| v.map_left(BasicValueEnum::into_int_value))
.map(Either::unwrap_left)
.unwrap();
generator.bool_to_i1(ctx, result)
}

View File

@ -135,4 +135,4 @@ extern int32_t run(void);
int main(void) {
run();
}
}

View File

@ -2,29 +2,37 @@
def output_bool(x: bool):
...
def str_eq():
def test_str_eq():
output_bool("" == "")
output_bool("a" == "")
output_bool("a" == "b")
output_bool("b" == "a")
output_bool("a" == "a")
output_bool("a" == "b")
output_bool("test string" == "test string")
output_bool("test string1" == "test string2")
output_bool("Lorem ipsum dolor sit amet" == "Lorem ipsum dolor sit amet")
output_bool("test1" == "test2")
output_bool("123" == "123")
output_bool("123" == "321")
output_bool("abc" == "abcde")
output_bool("a" == "aa")
output_bool(" " == " ")
output_bool(" a " == " a ")
def str_ne():
def test_str_ne():
output_bool("" != "")
output_bool("a" != "")
output_bool("a" != "b")
output_bool("b" != "a")
output_bool("a" != "a")
output_bool("a" != "b")
output_bool("test string" != "test string")
output_bool("test string1" != "test string2")
output_bool("Lorem ipsum dolor sit amet" != "Lorem ipsum dolor sit amet")
output_bool("test1" != "test2")
output_bool("123" != "123")
output_bool("123" != "321")
output_bool("abc" != "abcde")
output_bool("a" != "aa")
output_bool(" " != " ")
output_bool(" a " != " a ")
def run() -> int32:
str_eq()
str_ne()
return 0
test_str_eq()
test_str_ne()
return 0