poke-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 07/12] libpoke: Add `__pkl_unsafe_string_set` builtin


From: Mohammad-Reza Nabipoor
Subject: [PATCH 07/12] libpoke: Add `__pkl_unsafe_string_set` builtin
Date: Wed, 26 May 2021 02:51:10 +0430

The new builtin is an unsafe operation that modifies the content of
a string. This is useful for creating new string out of a bunch of
smaller strings. One can allocate the whole string once and then
modify the sub-parts accordingly.

2021-05-22  Mohammad-Reza Nabipoor  <mnabipoor@gnu.org>

        * libpoke/pvm.jitter (strset): New instruction.
        (wrapped-functions): Add `memcpy`.
        * libpoke/pkl-insn.def (STRSET): Likewise.
        * libpoke/pkl-gen.c (pkl_gen_ps_comp_stmt): Emit code.
        * libpoke/pkl-lex.l: Recognize `BUILTIN_UNSAFE_STRING_SET`.
        * libpoke/pkl-tab.y: Define token `BUILTIN_UNSAFE_STRING_SET`.
        (comp_stmt): New rule.
        * libpoke/pkl-ast.h (PKL_AST_BUILTIN_UNSAFE_STRING_SET): Define.
        * libpoke/pkl-rt.pk (__pkl_unsafe_string_set): New function.
        * testsuite/poke.pkl/unsafe-string-set-1.pk: New test.
        * testsuite/poke.pkl/unsafe-string-set-2.pk: Likewise.
        * testsuite/poke.pkl/unsafe-string-set-3.pk: Likewise.
        * testsuite/poke.pkl/unsafe-string-set-4.pk: Likewise.
        * testsuite/poke.pkl/unsafe-string-set-5.pk: Likewise.
        * testsuite/poke.pkl/unsafe-string-set-diag-1.pk: Likewise.
        * testsuite/poke.pkl/unsafe-string-set-diag-2.pk: Likewise.
        * testsuite/Makefile.am (EXTRA_DIST): Add new tests.
---
 ChangeLog                                     | 20 +++++++++++
 libpoke/pkl-ast.h                             |  1 +
 libpoke/pkl-gen.c                             |  7 ++++
 libpoke/pkl-insn.def                          |  1 +
 libpoke/pkl-lex.l                             |  2 ++
 libpoke/pkl-rt.pk                             |  3 ++
 libpoke/pkl-tab.y                             |  2 ++
 libpoke/pvm.jitter                            | 36 +++++++++++++++++++
 testsuite/Makefile.am                         |  7 ++++
 testsuite/poke.pkl/unsafe-string-set-1.pk     |  6 ++++
 testsuite/poke.pkl/unsafe-string-set-2.pk     |  9 +++++
 testsuite/poke.pkl/unsafe-string-set-3.pk     |  3 ++
 testsuite/poke.pkl/unsafe-string-set-4.pk     |  7 ++++
 testsuite/poke.pkl/unsafe-string-set-5.pk     |  3 ++
 .../poke.pkl/unsafe-string-set-diag-1.pk      |  5 +++
 .../poke.pkl/unsafe-string-set-diag-2.pk      |  5 +++
 16 files changed, 117 insertions(+)
 create mode 100644 testsuite/poke.pkl/unsafe-string-set-1.pk
 create mode 100644 testsuite/poke.pkl/unsafe-string-set-2.pk
 create mode 100644 testsuite/poke.pkl/unsafe-string-set-3.pk
 create mode 100644 testsuite/poke.pkl/unsafe-string-set-4.pk
 create mode 100644 testsuite/poke.pkl/unsafe-string-set-5.pk
 create mode 100644 testsuite/poke.pkl/unsafe-string-set-diag-1.pk
 create mode 100644 testsuite/poke.pkl/unsafe-string-set-diag-2.pk

diff --git a/ChangeLog b/ChangeLog
index 951da58f..5f628514 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2021-05-22  Mohammad-Reza Nabipoor  <mnabipoor@gnu.org>
+
+       * libpoke/pvm.jitter (strset): New instruction.
+       (wrapped-functions): Add `memcpy`.
+       * libpoke/pkl-insn.def (STRSET): Likewise.
+       * libpoke/pkl-gen.c (pkl_gen_ps_comp_stmt): Emit code.
+       * libpoke/pkl-lex.l: Recognize `BUILTIN_UNSAFE_STRING_SET`.
+       * libpoke/pkl-tab.y: Define token `BUILTIN_UNSAFE_STRING_SET`.
+       (comp_stmt): New rule.
+       * libpoke/pkl-ast.h (PKL_AST_BUILTIN_UNSAFE_STRING_SET): Define.
+       * libpoke/pkl-rt.pk (__pkl_unsafe_string_set): New function.
+       * testsuite/poke.pkl/unsafe-string-set-1.pk: New test.
+       * testsuite/poke.pkl/unsafe-string-set-2.pk: Likewise.
+       * testsuite/poke.pkl/unsafe-string-set-3.pk: Likewise.
+       * testsuite/poke.pkl/unsafe-string-set-4.pk: Likewise.
+       * testsuite/poke.pkl/unsafe-string-set-5.pk: Likewise.
+       * testsuite/poke.pkl/unsafe-string-set-diag-1.pk: Likewise.
+       * testsuite/poke.pkl/unsafe-string-set-diag-2.pk: Likewise.
+       * testsuite/Makefile.am (EXTRA_DIST): Add new tests.
+
 2021-05-22  Mohammad-Reza Nabipoor  <mnabipoor@gnu.org>
 
        * libpoke/pvm.jitter (return): s/jitter_int/jitter_uint/.
diff --git a/libpoke/pkl-ast.h b/libpoke/pkl-ast.h
index 803e34f8..550b9f48 100644
--- a/libpoke/pkl-ast.h
+++ b/libpoke/pkl-ast.h
@@ -1448,6 +1448,7 @@ pkl_ast_node pkl_ast_make_incrdecr (pkl_ast ast,
 #define PKL_AST_BUILTIN_VM_SET_OMAPS 38
 #define PKL_AST_BUILTIN_VM_OMODE 39
 #define PKL_AST_BUILTIN_VM_SET_OMODE 40
+#define PKL_AST_BUILTIN_UNSAFE_STRING_SET 41
 
 struct pkl_ast_comp_stmt
 {
diff --git a/libpoke/pkl-gen.c b/libpoke/pkl-gen.c
index 7e462cee..19d7fb9e 100644
--- a/libpoke/pkl-gen.c
+++ b/libpoke/pkl-gen.c
@@ -845,6 +845,13 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_ps_comp_stmt)
           pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSHVAR, 0, 0);
           pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_POPOM);
           break;
+        case PKL_AST_BUILTIN_UNSAFE_STRING_SET:
+          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSHVAR, 0, 0);
+          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSHVAR, 0, 1);
+          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSHVAR, 0, 2);
+          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_STRSET);
+          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_DROP);
+          break;
         default:
           assert (0);
         }
diff --git a/libpoke/pkl-insn.def b/libpoke/pkl-insn.def
index 444020d6..3b059dbd 100644
--- a/libpoke/pkl-insn.def
+++ b/libpoke/pkl-insn.def
@@ -235,6 +235,7 @@ PKL_DEF_INSN(PKL_INSN_NEC,"","nec")
 
 PKL_DEF_INSN(PKL_INSN_SCONC,"","sconc")
 PKL_DEF_INSN(PKL_INSN_STRREF,"","strref")
+PKL_DEF_INSN(PKL_INSN_STRSET,"","strset")
 PKL_DEF_INSN(PKL_INSN_SUBSTR,"","substr")
 PKL_DEF_INSN(PKL_INSN_MULS,"","muls")
 
diff --git a/libpoke/pkl-lex.l b/libpoke/pkl-lex.l
index cfe30f0c..55ba36cd 100644
--- a/libpoke/pkl-lex.l
+++ b/libpoke/pkl-lex.l
@@ -303,6 +303,8 @@ S ::
    if (yyextra->bootstrapped) REJECT; return BUILTIN_VM_OPPRINT; }
 "__PKL_BUILTIN_VM_SET_OPPRINT__" {
    if (yyextra->bootstrapped) REJECT; return BUILTIN_VM_SET_OPPRINT; }
+"__PKL_BUILTIN_UNSAFE_STRING_SET__" {
+   if (yyextra->bootstrapped) REJECT; return BUILTIN_UNSAFE_STRING_SET; }
 
 "uint<"         { return UINTCONSTR; }
 "int<"          { return INTCONSTR; }
diff --git a/libpoke/pkl-rt.pk b/libpoke/pkl-rt.pk
index a272d045..033636e0 100644
--- a/libpoke/pkl-rt.pk
+++ b/libpoke/pkl-rt.pk
@@ -58,6 +58,9 @@ fun vm_set_omaps = (int<32> omaps) void: 
__PKL_BUILTIN_VM_SET_OMAPS__;
 fun vm_omode = int<32>: __PKL_BUILTIN_VM_OMODE__;
 fun vm_set_omode = (int<32> omode) void: __PKL_BUILTIN_VM_SET_OMODE__;
 
+fun __pkl_unsafe_string_set = (string dst, uint<64> index, string str) void:
+  __PKL_BUILTIN_UNSAFE_STRING_SET__;
+
 var ENDIAN_LITTLE = 0;
 var ENDIAN_BIG = 1;
 
diff --git a/libpoke/pkl-tab.y b/libpoke/pkl-tab.y
index 95c02cb4..7713191b 100644
--- a/libpoke/pkl-tab.y
+++ b/libpoke/pkl-tab.y
@@ -438,6 +438,7 @@ token <integer> UNION    _("keyword `union'")
 %token BUILTIN_VM_OMAPS BUILTIN_VM_SET_OMAPS
 %token BUILTIN_VM_OMODE BUILTIN_VM_SET_OMODE
 %token BUILTIN_VM_OPPRINT BUILTIN_VM_SET_OPPRINT
+%token BUILTIN_UNSAFE_STRING_SET
 
 /* Compiler builtins.  */
 
@@ -2106,6 +2107,7 @@ builtin:
         | BUILTIN_VM_SET_OMODE { $$ = PKL_AST_BUILTIN_VM_SET_OMODE; }
         | BUILTIN_VM_OPPRINT { $$ = PKL_AST_BUILTIN_VM_OPPRINT; }
         | BUILTIN_VM_SET_OPPRINT { $$ = PKL_AST_BUILTIN_VM_SET_OPPRINT; }
+        | BUILTIN_UNSAFE_STRING_SET { $$ = PKL_AST_BUILTIN_UNSAFE_STRING_SET; }
         ;
 
 stmt_decl_list:
diff --git a/libpoke/pvm.jitter b/libpoke/pvm.jitter
index 176fad7d..60b19ee2 100644
--- a/libpoke/pvm.jitter
+++ b/libpoke/pvm.jitter
@@ -112,6 +112,7 @@ wrapped-functions
   srandom
   secure_getenv
   gettime
+  memcpy
 end
 
 #wrapped-globals
@@ -4157,6 +4158,41 @@ instruction strref () # ( STR ULONG -- STR ULONG VAL )
   end
 end
 
+# Instruction: strset
+#
+# Given a string STR, an index FROM and a string NEWSTR, copy the content
+# of NEWSTR to STR at index FROM.
+#
+# Index is zero-based.
+#
+# If FROM >= the size of the string, or if FROM+len(NEWSTR) > the size
+# of the string, raise the PVM_E_OUT_OF_BOUNDS exception.
+#
+# Stack: ( STR ULONG NEWSTR -- STR )
+# Exceptions: PVM_E_OUT_OF_BOUNDS
+
+instruction strset ()
+  branching # because of PVM_RAISE_DIRECT
+  code
+    pvm_val newstr = JITTER_TOP_STACK ();
+    uint64_t from = PVM_VAL_ULONG (JITTER_UNDER_TOP_STACK ());
+    pvm_val str;
+    size_t slen, nslen = strlen (PVM_VAL_STR (newstr));
+
+    JITTER_DROP_STACK ();
+    JITTER_DROP_STACK ();
+    str = JITTER_TOP_STACK ();
+    slen = strlen (PVM_VAL_STR (str));
+
+    if (from > slen || from + nslen > slen)
+      PVM_RAISE_DFL (PVM_E_OUT_OF_BOUNDS);
+
+    /* Using `strncpy` will emit a false compiler warning
+       (-Wstringop-overflow=).  */
+    memcpy (PVM_VAL_STR (str) + from, PVM_VAL_STR (newstr), nslen);
+  end
+end
+
 # Instruction: substr
 #
 # Given a string and two indices FROM and TO conforming a semi-open
diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am
index 135688bf..afe35442 100644
--- a/testsuite/Makefile.am
+++ b/testsuite/Makefile.am
@@ -1938,6 +1938,13 @@ EXTRA_DIST = \
   poke.pkl/units-diag-1.pk \
   poke.pkl/units-diag-2.pk \
   poke.pkl/units-diag-3.pk \
+  poke.pkl/unsafe-string-set-1.pk \
+  poke.pkl/unsafe-string-set-2.pk \
+  poke.pkl/unsafe-string-set-3.pk \
+  poke.pkl/unsafe-string-set-4.pk \
+  poke.pkl/unsafe-string-set-5.pk \
+  poke.pkl/unsafe-string-set-diag-1.pk \
+  poke.pkl/unsafe-string-set-diag-2.pk \
   poke.pkl/uu-file-1.pk \
   poke.pkl/uu-line-1.pk \
   poke.pkl/vm-oacutoff-1.pk \
diff --git a/testsuite/poke.pkl/unsafe-string-set-1.pk 
b/testsuite/poke.pkl/unsafe-string-set-1.pk
new file mode 100644
index 00000000..69a241d2
--- /dev/null
+++ b/testsuite/poke.pkl/unsafe-string-set-1.pk
@@ -0,0 +1,6 @@
+/* { dg-do run } */
+
+/* { dg-command {var s = "Hello, Jose!"} } */
+/* { dg-command {__pkl_unsafe_string_set (s, 7, "Luca")} } */
+/* { dg-command {s} } */
+/* { dg-output "Hello, Luca!" } */
diff --git a/testsuite/poke.pkl/unsafe-string-set-2.pk 
b/testsuite/poke.pkl/unsafe-string-set-2.pk
new file mode 100644
index 00000000..5c512ac7
--- /dev/null
+++ b/testsuite/poke.pkl/unsafe-string-set-2.pk
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+
+/* { dg-command {var s = "Poke"} } */
+/* { dg-command {__pkl_unsafe_string_set (s, 0, "")} } */
+/* { dg-command {s} } */
+/* { dg-output {"Poke"} } */
+/* { dg-command {__pkl_unsafe_string_set (s, 1, "")} } */
+/* { dg-command {s} } */
+/* { dg-output {\n"Poke"} } */
diff --git a/testsuite/poke.pkl/unsafe-string-set-3.pk 
b/testsuite/poke.pkl/unsafe-string-set-3.pk
new file mode 100644
index 00000000..cd9848c0
--- /dev/null
+++ b/testsuite/poke.pkl/unsafe-string-set-3.pk
@@ -0,0 +1,3 @@
+/* { dg-do run } */
+
+/* { dg-command {__pkl_unsafe_string_set ("Jose", 0, "Luca")} } */
diff --git a/testsuite/poke.pkl/unsafe-string-set-4.pk 
b/testsuite/poke.pkl/unsafe-string-set-4.pk
new file mode 100644
index 00000000..999f6e8d
--- /dev/null
+++ b/testsuite/poke.pkl/unsafe-string-set-4.pk
@@ -0,0 +1,7 @@
+/* { dg-do run } */
+
+var s = "Earth";
+
+/* { dg-command {__pkl_unsafe_string_set (s, s'length, "")} } */
+/* { dg-command {s} } */
+/* { dg-output "Earth" } */
diff --git a/testsuite/poke.pkl/unsafe-string-set-5.pk 
b/testsuite/poke.pkl/unsafe-string-set-5.pk
new file mode 100644
index 00000000..795effa1
--- /dev/null
+++ b/testsuite/poke.pkl/unsafe-string-set-5.pk
@@ -0,0 +1,3 @@
+/* { dg-do run } */
+
+/* { dg-command {__pkl_unsafe_string_set ("", 0, "")} } */
diff --git a/testsuite/poke.pkl/unsafe-string-set-diag-1.pk 
b/testsuite/poke.pkl/unsafe-string-set-diag-1.pk
new file mode 100644
index 00000000..d3f35ed5
--- /dev/null
+++ b/testsuite/poke.pkl/unsafe-string-set-diag-1.pk
@@ -0,0 +1,5 @@
+/* { dg-do run } */
+
+var s = "Earth";
+
+__pkl_unsafe_string_set(s, 2, "Mars");  /* { dg-output "unhandled out of 
bounds exception" } */
diff --git a/testsuite/poke.pkl/unsafe-string-set-diag-2.pk 
b/testsuite/poke.pkl/unsafe-string-set-diag-2.pk
new file mode 100644
index 00000000..65dcf2fe
--- /dev/null
+++ b/testsuite/poke.pkl/unsafe-string-set-diag-2.pk
@@ -0,0 +1,5 @@
+/* { dg-do run } */
+
+var s = "Mars";
+
+__pkl_unsafe_string_set(s, 0, "Earth");  /* { dg-output "unhandled out of 
bounds exception" } */
-- 
2.31.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]