diff --git a/morphisms/.gitignore b/morphisms/.gitignore new file mode 100644 index 0000000..82f5cc4 --- /dev/null +++ b/morphisms/.gitignore @@ -0,0 +1,6 @@ +*.so +posint-dec-to-hex-generated-gcc +posint-dec-to-hex-generated-clang +posint-dec-to-hex-optimal-gcc +posint-dec-to-hex-optimal-clang + diff --git a/morphisms/Makefile b/morphisms/Makefile index 3912ac9..6526bf8 100644 --- a/morphisms/Makefile +++ b/morphisms/Makefile @@ -6,8 +6,26 @@ all: $(TARGETS) lib/libmorph_%.so: src/%.c $(CC) -O3 -shared -o $@ -fPIC -Iinclude $< -test: test.c lib/libmorph_length-prefix.so lib/libmorph_posint.so - $(CC) -O3 -L$(LIB_DIR) -o $@ -Iinclude $< -lmorph_length-prefix -lmorph_posint +posint-dec-to-hex-generated-gcc: posint-dec-to-hex-generated.c + gcc -g -Os -flto -o $@ -Iinclude $< src/length-prefix.c src/posint.c + +posint-dec-to-hex-generated-clang: posint-dec-to-hex-generated.c + clang -g -Os -flto -o $@ -Iinclude $< src/length-prefix.c src/posint.c + +posint-dec-to-hex-optimal-gcc: posint-dec-to-hex-optimal.c + gcc -g -Os -flto -o $@ $< + +posint-dec-to-hex-optimal-clang: posint-dec-to-hex-optimal.c + clang -g -Os -flto -o $@ $< + +code-size-benchmark: posint-dec-to-hex-generated-gcc \ + posint-dec-to-hex-generated-clang \ + posint-dec-to-hex-optimal-gcc \ + posint-dec-to-hex-optimal-clang + INST_COUNT_GEN_GCC=$(shell gdb --batch -ex "file posint-dec-to-hex-generated-gcc" -ex "disassemble main" | wc -l) + INST_COUNT_GEN_CLANG=$(shell gdb --batch -ex "file posint-dec-to-hex-generated-clang" -ex "disassemble main" | wc -l) + INST_COUNT_OPT_GCC=$(shell gdb --batch -ex "file posint-dec-to-hex-optimal-gcc" -ex "disassemble main" | wc -l) + INST_COUNT_OPT_CLANG=$(shell gdb --batch -ex "file posint-dec-to-hex-optimal-clang" -ex "disassemble main" | wc -l) clean: rm $(TARGETS) diff --git a/morphisms/morphism-base/length_prefix.morphism-base b/morphisms/morphism-base/length_prefix.morphism-base index a8c13be..a5d9bd5 100644 --- a/morphisms/morphism-base/length_prefix.morphism-base +++ b/morphisms/morphism-base/length_prefix.morphism-base @@ -1,9 +1,9 @@ morph_string_as_nullterm_to_length_prefix () - [~<ValueDelim '\0'> Char ~ Ascii] ---> [~<LengthPrefix x86.UInt64> Char ~ Ascii] + <Seq~<ValueDelim '\0'> Char ~ Ascii ~ Byte> +--> <Seq~<LengthPrefix x86.UInt64> Char ~ Ascii ~ Byte> @lib/libmorph_length-prefix.so:src/length_prefix.c morph_string_as_length_prefix_to_nullterm () - [~<LengthPrefix x86.UInt64> Char ~ Ascii] ---> [~<ValueDelim '\0'> Char ~ Ascii] + <Seq~<LengthPrefix x86.UInt64> Char ~ Ascii ~ Byte> +--> <Seq~<ValueDelim '\0'> Char ~ Ascii ~ Byte> @lib/libmorph_length-prefix.so:src/length_prefix.c diff --git a/morphisms/morphism-base/posint.morphism-base b/morphisms/morphism-base/posint.morphism-base index af1e3f1..aeb5e37 100644 --- a/morphisms/morphism-base/posint.morphism-base +++ b/morphisms/morphism-base/posint.morphism-base @@ -11,26 +11,26 @@ morph_digit_as_uint8_to_char (Radix:ℤ_16) morph_posint_radix (SrcRadix:ℤ, DstRadix:ℤ) ℕ ~ <PosInt SrcRadix LittleEndian> - ~ [~<LengthPrefix x86.UInt64> <Digit SrcRadix>~x86.UInt64] + ~ <Seq~<LengthPrefix x86.UInt64> <Digit SrcRadix>~x86.UInt64> --> ℕ ~ <PosInt DstRadix LittleEndian> - ~ [~<LengthPrefix x86.UInt64> <Digit DstRadix>~x86.UInt64] + ~ <Seq~<LengthPrefix x86.UInt64> <Digit DstRadix>~x86.UInt64> @lib/libmorph-posint.so:src/posint.c morph_posint_endianness (Radix:ℤ) ℕ ~ <PosInt Radix LittleEndian> - ~ [~<LengthPrefix x86.UInt64> <Digit Radix> ~ x86.UInt64] + ~ <Seq~<LengthPrefix x86.UInt64> <Digit Radix> ~ x86.UInt64> --> ℕ ~ <PosInt Radix BigEndian> - ~ [~<LengthPrefix x86.UInt64> <Digit Radix> ~ x86.UInt64] + ~ <Seq~<LengthPrefix x86.UInt64> <Digit Radix> ~ x86.UInt64> @lib/libmorph-posint.so:src/posint.c morph_posint_endianness (Radix:ℤ) ℕ ~ <PosInt Radix BigEndian> - ~ [~<LengthPrefix x86.UInt64> <Digit Radix> ~ x86.UInt64] + ~ <Seq~<LengthPrefix x86.UInt64> <Digit Radix> ~ x86.UInt64> --> ℕ ~ <PosInt Radix LittleEndian> - ~ [~<LengthPrefix x86.UInt64> <Digit Radix> ~ x86.UInt64] + ~ <Seq~<LengthPrefix x86.UInt64> <Digit Radix> ~ x86.UInt64> @lib/libmorph-posint.so:src/posint.c diff --git a/morphisms/posint-dec-to-hex-generated.c b/morphisms/posint-dec-to-hex-generated.c new file mode 100644 index 0000000..f1aa7cf --- /dev/null +++ b/morphisms/posint-dec-to-hex-generated.c @@ -0,0 +1,82 @@ +#include <stdio.h> +#include <stdint.h> +#include <morphisms/length-prefix.h> +#include <morphisms/posint.h> + +int main() { + uint8_t bufA[1024]; + uint8_t bufB[1024]; + + scanf("%s", bufA); + + // morph to + // ℕ ~ <PosInt 10 BigEndian> ~ [~<LengthPrefix x86.UInt64> <Digit 10> ~ Char ~ Ascii] + { + char const * src = (void*) bufA; + struct LengthPrefixUInt8Array * dst = (void*) bufB; + morph_string_as_nullterm_to_length_prefix( src, dst ); + } + + // morph to + // ℕ ~ <PosInt 10 BigEndian> ~ [~<LengthPrefix x86.UInt64> <Digit 10> ~ ℤ_10 ~ x86.UInt64] + { + struct LengthPrefixUInt8Array * src = (void*) bufB; + struct LengthPrefixUInt64Array * dst = (void*) bufA; + + dst->len = src->len; + for( uint64_t i = 0; i < src->len; ++i ) + morph_digit_as_char_to_uint64( &src->items[i], &dst->items[i] ); + } + + // morph to + // ℕ ~ <PosInt 10 LittleEndian> ~ [~<LengthPrefix x86.UInt64> <Digit 10> ~ ℤ_10 ~ x86.UInt64] + { + uint64_t const radix = 10; + struct LengthPrefixUInt64Array * src = (void*) bufA; + struct LengthPrefixUInt64Array * dst = (void*) bufB; + morph_posint_endianness( radix, src, dst ); + } + + // morph to + // ℕ ~ <PosInt 16 LittleEndian> ~ [~<LengthPrefix x86.UInt64> <Digit 16> ~ ℤ_16 ~ x86.UInt64] + { + uint64_t const src_radix = 10; + uint64_t const dst_radix = 16; + struct LengthPrefixUInt64Array * src = (void*) bufB; + struct LengthPrefixUInt64Array * dst = (void*) bufA; + morph_posint_radix( src_radix, dst_radix, src, dst ); + } + + + // morph to + // ℕ ~ <PosInt 16 LittleEndian> ~ [~<LengthPrefix x86.UInt64> <Digit 10> ~ ℤ_10 ~ x86.UInt64] + { + uint64_t const radix = 16; + struct LengthPrefixUInt64Array * src = (void*) bufA; + struct LengthPrefixUInt64Array * dst = (void*) bufB; + morph_posint_endianness( radix, src, dst ); + } + + // morph to + // ℕ ~ <PosInt 16 BigEndian> ~ [~<LengthPrefix x86.UInt64> <Digit 16> ~ Char ~ Ascii] + { + struct LengthPrefixUInt64Array * src = (void*) bufB; + struct LengthPrefixUInt8Array * dst = (void*) bufA; + + dst->len = src->len; + for( uint64_t i = 0; i < src->len; ++i ) + morph_digit_as_uint64_to_char( &src->items[i], &dst->items[i] ); + } + + // morph to + // ℕ ~ <PosInt 16 BigEndian> ~ [~<ValueDelim '\0'> <Digit 16> ~ Char ~ Ascii] + { + struct LengthPrefixUInt8Array * src = (void*) bufA; + char * dst = (void*) bufB; + morph_string_as_length_prefix_to_nullterm( src, dst ); + } + + printf("%s\n", bufB); + + return 0; +} diff --git a/morphisms/posint-dec-to-hex-optimal.c b/morphisms/posint-dec-to-hex-optimal.c new file mode 100644 index 0000000..7118ae0 --- /dev/null +++ b/morphisms/posint-dec-to-hex-optimal.c @@ -0,0 +1,47 @@ +#include <stdio.h> +#include <stdint.h> + +int main() { + char bufA[1024]; + char bufB[1024]; + + char * in = bufA; + char * out = bufB; + + scanf("%s", in); + + uint64_t value = 0; + while( *in ) { + if( *in >= '0' && *in <= '9' ) { + value *= 10; + value += *in - '0'; + } + else + return -1; + + in++; + } + + uint64_t v = value; + while( v ) { + out ++; + v /= 16; + } + + *out-- = '\0'; + while( value ) { + unsigned digit = value % 16; + if( digit < 10 ) { + *out-- = digit + '0'; + } else if( digit < 16 ) { + *out-- = digit + 'a' - 10; + } else { + return -1; + } + value /= 16; + } + + printf("%s\n", out); + + return 0; +} diff --git a/morphisms/test.c b/morphisms/test.c deleted file mode 100644 index 1346287..0000000 --- a/morphisms/test.c +++ /dev/null @@ -1,55 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <morphisms/length-prefix.h> -#include <morphisms/posint.h> - -int main( int argc, char * argv[] ) { - char * int1 = malloc(4096); - struct LengthPrefixUInt8Array * int2 = malloc(4096); - struct LengthPrefixUInt64Array * int3 = malloc(4096); - struct LengthPrefixUInt64Array * int4 = malloc(4096); - struct LengthPrefixUInt64Array * int5 = malloc(4096); - struct LengthPrefixUInt64Array * int6 = malloc(4096); - struct LengthPrefixUInt8Array * int7 = malloc(4096); - char * int8 = malloc(4096); - - // ℕ ~ <PosInt 10 BigEndian> ~ [~<ValueDelim '\0'> <Digit 10> ~ Char ~ Ascii] - scanf("%s", int1); - - // morph to - // ℕ ~ <PosInt 10 BigEndian> ~ [~<LengthPrefix x86.UInt64> <Digit 10> ~ Char ~ Ascii] - morph_string_as_nullterm_to_length_prefix( int1, int2 ); - - // morph to - // ℕ ~ <PosInt 10 BigEndian> ~ [~<LengthPrefix x86.UInt64> <Digit 10> ~ ℤ_10 ~ x86.UInt64] - int3->len = int2->len; - for( uint64_t i = 0; i < int2->len; ++i ) - morph_digit_as_char_to_uint64( &int2->items[i], &int3->items[i] ); - - // morph to - // ℕ ~ <PosInt 10 LittleEndian> ~ [~<LengthPrefix x86.UInt64> <Digit 10> ~ ℤ_10 ~ x86.UInt64] - morph_posint_endianness( 10, int3, int4 ); - - // morph to - // ℕ ~ <PosInt 16 LittleEndian> ~ [~<LengthPrefix x86.UInt64> <Digit 16> ~ ℤ_16 ~ x86.UInt64] - morph_posint_radix( 10, 16, int4, int5 ); - - // morph to - // ℕ ~ <PosInt 16 BigEndian> ~ [~<LengthPrefix x86.UInt64> <Digit 16> ~ ℤ_16 ~ x86.UInt64] - morph_posint_endianness( 16, int5, int6 ); - - // morph to - // ℕ ~ <PosInt 16 BigEndian> ~ [~<LengthPrefix x86.UInt64> <Digit 16> ~ Char ~ Ascii] - int7->len = int6->len; - for( uint64_t i = 0; i < int6->len; ++i ) - morph_digit_as_uint64_to_char( &int6->items[i], &int7->items[i] ); - - // morph to - // ℕ ~ <PosInt 16 BigEndian> ~ [~<ValueDelim '\0'> <Digit 16> ~ Char ~ Ascii] - morph_string_as_length_prefix_to_nullterm( int7, int8 ); - - printf("%s\n", int8); - - return 0; -} diff --git a/src/main.rs b/src/main.rs index bcbda32..34ddeb8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,8 +11,60 @@ use { std::sync::{Arc, RwLock} }; +/* for a given ladder type `t`, get the corresponding C type + */ +pub fn get_c_repr_type(dict: &mut impl TypeDict, t: laddertypes::TypeTerm, skip_pointer: bool) -> Option<String> { + let lnf = t.normalize().decurry().get_lnf_vec(); + + match lnf.last() { + Some(t) => { + if t == &dict.parse("Byte").expect("parse") + || t == &dict.parse("x86.UInt8").expect("parse") + || t == &dict.parse("<StaticLength 8 Bit>").expect("parse") + { + Some("uint8_t".into()) + } else if t == &dict.parse("x86.UInt16").expect("parse") { + Some("uint16_t".into()) + } else if t == &dict.parse("x86.UInt32").expect("parse") { + Some("uint32_t".into()) + } else if t == &dict.parse("x86.UInt64").expect("parse") { + Some("uint64_t".into()) + } else { + match t { + laddertypes::TypeTerm::App(args) => { + if args[0] == laddertypes::TypeTerm::TypeID(dict.get_typeid(&"LengthPrefix".into()).unwrap()) + { + let item_c_type : String = get_c_repr_type(dict, args[2].clone(), false)?; + match item_c_type.as_str() { + "uint8_t" => Some(format!("LengthPrefixUInt8Array")), + "uint16_t" => Some(format!("LengthPrefixUInt16Array")), + "uint32_t" => Some(format!("LengthPrefixUInt32Array")), + "uint64_t" => Some(format!("LengthPrefixUInt64Array")), + _ => None + } + } + else if args[0] == laddertypes::TypeTerm::TypeID(dict.get_typeid(&"ValueDelim".into()).unwrap()) + { + let c_type = get_c_repr_type(dict, args[2].clone(), false)?; + if skip_pointer { + Some(c_type) + } else { + Some(format!("{} *", c_type)) + } + } else { + None + } + } + _ => None + } + } + } + None => None + } +} + #[derive(Debug)] -struct Morphism { +struct LdmcMorphism { symbol: String, type_args: Vec<(String, String)>, src_type: laddertypes::TypeTerm, @@ -20,6 +72,34 @@ struct Morphism { locations: Vec<String> } +impl LdmcMorphism { + pub fn expected_c_type_signature(&self, dict: &mut impl TypeDict) -> String { + format!("int {} ({} const * restrict src, {} * restrict dst);", + self.symbol, + get_c_repr_type(dict, self.src_type.clone(), true).expect("cant get c-repr type for src type"), + get_c_repr_type(dict, self.dst_type.clone(), true).expect("cant get c-repr type for dst type")) + } + + pub fn generate_call(&self, dict: &mut impl TypeDict) { + let src_c_type = get_c_repr_type(dict, self.src_type.clone(), true).expect("cant get c-repr type for src type"); + let dst_c_type = get_c_repr_type(dict, self.dst_type.clone(), true).expect("cant get c-repr type for dst type"); + + let src_buf = "bufA"; + let dst_buf = "bufB"; + println!( +"{} + {} const * restrict src = {}; + {} * restrict dst = {}; + {} ( src, dst ); +{}", + '{', + src_c_type, src_buf, + dst_c_type, dst_buf, + self.symbol, + '}'); + } +} + /* morphism-base text format: * NAME '(' [TYPE-ARG-NAME ':' KIND] ')' * SRC-TYPE @@ -28,7 +108,7 @@ struct Morphism { */ fn parser( type_dict: Arc<RwLock< BimapTypeDict >> -) -> impl Parser<char, Vec<Morphism>, Error = Simple<char>> { +) -> impl Parser<char, Vec<LdmcMorphism>, Error = Simple<char>> { ident().padded() .then( @@ -57,7 +137,7 @@ fn parser( let src_type = type_dict.parse(&src_type.iter().collect::<String>()).expect("couldnt parse src type"); let dst_type = type_dict.parse(&dst_type.iter().collect::<String>()).expect("couldnt parse dst type"); - Morphism { + LdmcMorphism { symbol, type_args, src_type, @@ -69,40 +149,27 @@ fn parser( } fn main() { - println!("Hello, world!"); - - let src = " - morph_digit_as_char_to_uint8 (Radix:ℤ_16) - <Digit Radix> ~ Char ~ Ascii ~ Byte - --> <Digit Radix> ~ x86.UInt8 ~ Byte - @lib/libmorph_posint.so:src/posint.c - - morph_string_as_nullterm_to_length_prefix () - <Seq~<ValueDelim '\\0'> Char ~ Ascii> - --> <Seq~<LengthPrefix x86.UInt64> Char ~ Ascii> - @lib/libmorph_length-prefix.so:src/length_prefix.c - - morph_string_as_length_prefix_to_nullterm () - <Seq~<LengthPrefix x86.UInt64> Char ~ Ascii> - --> <Seq~<ValueDelim '\\0'> Char ~ Ascii> - @lib/libmorph_length-prefix.so:src/length_prefix.c - "; - let type_dict = Arc::new(RwLock::new(BimapTypeDict::new())); - let result = parser(type_dict.clone()).parse(src); + let src = std::fs::read_to_string( + std::env::args().nth(1).expect("expected file name") + ).expect("read"); + let result = parser(type_dict.clone()).parse(src.clone()); match result { Ok(morphisms) => { println!("parse ok."); - let mut dict = type_dict.write().unwrap(); for m in morphisms { - println!("{}\n {}\n---> \n {}\n", m.symbol, - m.src_type.normalize().sugar(&mut *dict).pretty(&mut *dict, 1), - m.dst_type.normalize().sugar(&mut *dict).pretty(&mut *dict, 1), + println!("{}\n {}\n---> \n {}\n{}\n\n", m.symbol, + m.src_type.clone().sugar(&mut *dict).pretty(&mut *dict, 1), + m.dst_type.clone().sugar(&mut *dict).pretty(&mut *dict, 1), + + m.expected_c_type_signature(&mut *dict), ); + + m.generate_call(&mut *dict); } } Err(errs) => {