Skip to content

Commit ca5d9db

Browse files
authored
[Strings] Support the custom section for strings in StringLifting (#7409)
1 parent d262701 commit ca5d9db

File tree

2 files changed

+116
-2
lines changed

2 files changed

+116
-2
lines changed

src/passes/StringLifting.cpp

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "ir/utils.h"
2828
#include "pass.h"
2929
#include "passes/string-utils.h"
30+
#include "support/json.h"
3031
#include "support/string.h"
3132
#include "wasm-builder.h"
3233
#include "wasm.h"
@@ -58,8 +59,6 @@ struct StringLifting : public Pass {
5859
//
5960
// That is, they are imported from module "'" and the basename is the
6061
// actual string. Find them all so we can apply them.
61-
//
62-
// TODO: parse the strings section for non-UTF16 strings.
6362
Name stringConstsModule =
6463
getArgumentOrDefault("string-constants-module", WasmStringConstsModule);
6564
for (auto& global : module->globals) {
@@ -72,6 +71,44 @@ struct StringLifting : public Pass {
7271
}
7372
}
7473

74+
// Imported strings may also be found in the string section.
75+
for (auto& section : module->customSections) {
76+
if (section.name == "string.consts") {
77+
// We found the string consts section. Parse it.
78+
auto copy = section.data;
79+
json::Value array;
80+
array.parse(copy.data());
81+
if (!array.isArray()) {
82+
Fatal()
83+
<< "StringLifting: string.const section should be a JSON array";
84+
}
85+
86+
// We have the array of constants from the section. Find globals that
87+
// refer to it.
88+
for (auto& global : module->globals) {
89+
if (!global->imported() || global->module != "string.const") {
90+
continue;
91+
}
92+
// The index in the array is the basename.
93+
Index index = std::stoi(std::string(global->base.str));
94+
if (index >= array.size()) {
95+
Fatal() << "StringLifting: bad index in string.const section";
96+
}
97+
auto item = array[index];
98+
if (!item->isString()) {
99+
Fatal()
100+
<< "StringLifting: string.const section entry is not a string";
101+
}
102+
if (importedStrings.count(global->name)) {
103+
Fatal()
104+
<< "StringLifting: string.const section tramples other const";
105+
}
106+
importedStrings[global->name] = item->getIString();
107+
}
108+
break;
109+
}
110+
}
111+
75112
auto array16 = Type(Array(Field(Field::i16, Mutable)), Nullable);
76113
auto refExtern = Type(HeapType::ext, NonNullable);
77114
auto externref = Type(HeapType::ext, Nullable);
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
2+
3+
;; Lower first to generate the string.consts custom section, then lift it back.
4+
5+
;; RUN: foreach %s %t wasm-opt -all --string-lowering --string-lifting -S -o - | filecheck %s
6+
7+
(module
8+
;; CHECK: (type $0 (array (mut i16)))
9+
10+
;; CHECK: (type $1 (func (param externref externref) (result i32)))
11+
12+
;; CHECK: (type $2 (func))
13+
14+
;; CHECK: (type $3 (func (param (ref null $0) i32 i32) (result (ref extern))))
15+
16+
;; CHECK: (type $4 (func (param i32) (result (ref extern))))
17+
18+
;; CHECK: (type $5 (func (param externref externref) (result (ref extern))))
19+
20+
;; CHECK: (type $6 (func (param externref (ref null $0) i32) (result i32)))
21+
22+
;; CHECK: (type $7 (func (param externref) (result i32)))
23+
24+
;; CHECK: (type $8 (func (param externref i32) (result i32)))
25+
26+
;; CHECK: (type $9 (func (param externref i32 i32) (result (ref extern))))
27+
28+
;; CHECK: (import "string.const" "0" (global $"string.const_\"bar\"" (ref extern)))
29+
30+
;; CHECK: (import "string.const" "1" (global $"string.const_\"foo\"" (ref extern)))
31+
32+
;; CHECK: (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray (type $3) (param (ref null $0) i32 i32) (result (ref extern))))
33+
34+
;; CHECK: (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint (type $4) (param i32) (result (ref extern))))
35+
36+
;; CHECK: (import "wasm:js-string" "concat" (func $concat (type $5) (param externref externref) (result (ref extern))))
37+
38+
;; CHECK: (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray (type $6) (param externref (ref null $0) i32) (result i32)))
39+
40+
;; CHECK: (import "wasm:js-string" "equals" (func $equals (type $1) (param externref externref) (result i32)))
41+
42+
;; CHECK: (import "wasm:js-string" "compare" (func $compare (type $1) (param externref externref) (result i32)))
43+
44+
;; CHECK: (import "wasm:js-string" "length" (func $length (type $7) (param externref) (result i32)))
45+
46+
;; CHECK: (import "wasm:js-string" "charCodeAt" (func $charCodeAt (type $8) (param externref i32) (result i32)))
47+
48+
;; CHECK: (import "wasm:js-string" "substring" (func $substring (type $9) (param externref i32 i32) (result (ref extern))))
49+
50+
;; CHECK: (func $consts (type $2)
51+
;; CHECK-NEXT: (drop
52+
;; CHECK-NEXT: (string.const "foo")
53+
;; CHECK-NEXT: )
54+
;; CHECK-NEXT: (drop
55+
;; CHECK-NEXT: (string.const "bar")
56+
;; CHECK-NEXT: )
57+
;; CHECK-NEXT: (drop
58+
;; CHECK-NEXT: (string.const "foo")
59+
;; CHECK-NEXT: )
60+
;; CHECK-NEXT: )
61+
(func $consts
62+
;; These strings get lowered into the custom section, then lifted back up,
63+
;; so they do not change. We will see above the imported globals that were
64+
;; created for them (and not cleaned up), two imports from "string.const".
65+
(drop
66+
(string.const "foo")
67+
)
68+
(drop
69+
(string.const "bar")
70+
)
71+
(drop
72+
(string.const "foo")
73+
)
74+
;; TODO: test utf-8 etc.
75+
)
76+
)
77+

0 commit comments

Comments
 (0)