Skip to content

Commit 7128bb2

Browse files
authored
Rework memory options (AssemblyScript#1268)
1 parent 50797ee commit 7128bb2

15 files changed

+145
-27
lines changed

cli/asc.d.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,14 @@ interface CompilerOptions {
9797
noEmit?: boolean;
9898
/** Imports the memory provided as 'env.memory'. */
9999
importMemory?: boolean;
100-
/** Declare memory as shared by settings the max shared memory. */
101-
sharedMemory?: number;
100+
/** Does not export the memory as 'memory'. */
101+
noExportMemory?: boolean;
102+
/** Sets the initial memory size in pages. */
103+
initialMemory?: number;
104+
/** Sets the maximum memory size in pages. */
105+
maximumMemory?: number;
106+
/** Declare memory as shared. Requires maximumMemory. */
107+
sharedMemory?: boolean;
102108
/** Sets the start offset of compiler-generated static memory. */
103109
memoryBase?: number;
104110
/** Imports the function table provided as 'env.table'. */

cli/asc.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,10 @@ exports.main = function main(argv, options, callback) {
272272
const compilerOptions = assemblyscript.newOptions();
273273
assemblyscript.setTarget(compilerOptions, 0);
274274
assemblyscript.setNoAssert(compilerOptions, args.noAssert);
275+
assemblyscript.setExportMemory(compilerOptions, !args.noExportMemory);
275276
assemblyscript.setImportMemory(compilerOptions, args.importMemory);
277+
assemblyscript.setInitialMemory(compilerOptions, args.initialMemory >>> 0);
278+
assemblyscript.setMaximumMemory(compilerOptions, args.maximumMemory >>> 0);
276279
assemblyscript.setSharedMemory(compilerOptions, args.sharedMemory);
277280
assemblyscript.setImportTable(compilerOptions, args.importTable);
278281
assemblyscript.setExportTable(compilerOptions, args.exportTable);

cli/asc.json

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,12 +128,30 @@
128128
"type": "b",
129129
"default": false
130130
},
131-
"sharedMemory": {
131+
"noExportMemory": {
132+
"category": "Features",
133+
"description": "Does not export the memory as 'memory'.",
134+
"type": "b",
135+
"default": false
136+
},
137+
"initialMemory": {
138+
"category": "Features",
139+
"description": "Sets the initial memory size in pages.",
140+
"type": "i",
141+
"default": 0
142+
},
143+
"maximumMemory": {
132144
"category": "Features",
133-
"description": "Declare memory as shared by settings the max shared memory.",
145+
"description": "Sets the maximum memory size in pages.",
134146
"type": "i",
135147
"default": 0
136148
},
149+
"sharedMemory": {
150+
"category": "Features",
151+
"description": "Declare memory as shared. Requires maximumMemory.",
152+
"type": "b",
153+
"default": false
154+
},
137155
"importTable": {
138156
"category": "Features",
139157
"description": "Imports the function table provided as 'env.table'.",

src/compiler.ts

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -202,10 +202,16 @@ export class Options {
202202
target: Target = Target.WASM32;
203203
/** If true, replaces assertions with nops. */
204204
noAssert: bool = false;
205+
/** It true, exports the memory to the embedder. */
206+
exportMemory: bool = true;
205207
/** If true, imports the memory provided by the embedder. */
206208
importMemory: bool = false;
207-
/** If greater than zero, declare memory as shared by setting max memory to sharedMemory. */
208-
sharedMemory: i32 = 0;
209+
/** Initial memory size, in pages. */
210+
initialMemory: u32 = 0;
211+
/** Maximum memory size, in pages. */
212+
maximumMemory: u32 = 0;
213+
/** If true, memory is declared as shared. */
214+
sharedMemory: bool = false;
209215
/** If true, imports the function table provided by the embedder. */
210216
importTable: bool = false;
211217
/** If true, exports the function table. */
@@ -215,9 +221,9 @@ export class Options {
215221
/** If true, generates an explicit start function. */
216222
explicitStart: bool = false;
217223
/** Static memory start offset. */
218-
memoryBase: i32 = 0;
224+
memoryBase: u32 = 0;
219225
/** Static table start offset. */
220-
tableBase: i32 = 0;
226+
tableBase: u32 = 0;
221227
/** Global aliases, mapping alias names as the key to internal names to be aliased as the value. */
222228
globalAliases: Map<string,string> | null = null;
223229
/** Features to activate by default. These are the finished proposals. */
@@ -227,7 +233,7 @@ export class Options {
227233
/** If true, enables pedantic diagnostics. */
228234
pedantic: bool = false;
229235
/** Indicates a very low (<64k) memory limit. */
230-
lowMemoryLimit: i32 = 0;
236+
lowMemoryLimit: u32 = 0;
231237

232238
/** Hinted optimize level. Not applied by the compiler itself. */
233239
optimizeLevelHint: i32 = 0;
@@ -554,15 +560,57 @@ export class Compiler extends DiagnosticEmitter {
554560
}
555561

556562
// set up memory
557-
var isSharedMemory = options.hasFeature(Feature.THREADS) && options.sharedMemory > 0;
563+
var initialPages: u32 = 0;
564+
if (this.options.memoryBase /* is specified */ || this.memorySegments.length) {
565+
initialPages = u32(i64_low(i64_shr_u(i64_align(memoryOffset, 0x10000), i64_new(16))));
566+
}
567+
if (options.initialMemory) {
568+
if (options.initialMemory < initialPages) {
569+
this.error(
570+
DiagnosticCode.Module_requires_at_least_0_pages_of_initial_memory,
571+
null,
572+
initialPages.toString()
573+
);
574+
} else {
575+
initialPages = options.initialMemory;
576+
}
577+
}
578+
var maximumPages = Module.UNLIMITED_MEMORY;
579+
if (options.maximumMemory) {
580+
if (options.maximumMemory < initialPages) {
581+
this.error(
582+
DiagnosticCode.Module_requires_at_least_0_pages_of_maximum_memory,
583+
null,
584+
initialPages.toString()
585+
);
586+
} else {
587+
maximumPages = options.maximumMemory;
588+
}
589+
}
590+
var isSharedMemory = false;
591+
if (options.sharedMemory) {
592+
isSharedMemory = true;
593+
if (!options.maximumMemory) {
594+
this.error(
595+
DiagnosticCode.Shared_memory_requires_maximum_memory_to_be_defined,
596+
null
597+
);
598+
isSharedMemory = false;
599+
}
600+
if (!options.hasFeature(Feature.THREADS)) {
601+
this.error(
602+
DiagnosticCode.Shared_memory_requires_feature_threads_to_be_enabled,
603+
null
604+
);
605+
isSharedMemory = false;
606+
}
607+
}
558608
module.setMemory(
559-
this.options.memoryBase /* is specified */ || this.memorySegments.length
560-
? i64_low(i64_shr_u(i64_align(memoryOffset, 0x10000), i64_new(16)))
561-
: 0,
562-
isSharedMemory ? options.sharedMemory : Module.UNLIMITED_MEMORY,
609+
initialPages,
610+
maximumPages,
563611
this.memorySegments,
564612
options.target,
565-
ExportNames.memory,
613+
options.exportMemory ? ExportNames.memory : null,
566614
isSharedMemory
567615
);
568616

src/diagnosticMessages.generated.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,11 @@ export enum DiagnosticCode {
1111
Operation_is_unsafe = 101,
1212
User_defined_0 = 102,
1313
Feature_0_is_not_enabled = 103,
14-
Function_0_is_possibly_called_virtually_which_is_not_yet_supported = 104,
15-
Low_memory_limit_exceeded_by_static_data_0_1 = 105,
14+
Low_memory_limit_exceeded_by_static_data_0_1 = 104,
15+
Module_requires_at_least_0_pages_of_initial_memory = 105,
16+
Module_requires_at_least_0_pages_of_maximum_memory = 106,
17+
Shared_memory_requires_maximum_memory_to_be_defined = 107,
18+
Shared_memory_requires_feature_threads_to_be_enabled = 108,
1619
Conversion_from_type_0_to_1_requires_an_explicit_cast = 200,
1720
Conversion_from_type_0_to_1_will_require_an_explicit_cast_when_switching_between_32_64_bit = 201,
1821
Type_0_cannot_be_changed_to_type_1 = 202,
@@ -181,8 +184,11 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
181184
case 101: return "Operation is unsafe.";
182185
case 102: return "User-defined: {0}";
183186
case 103: return "Feature '{0}' is not enabled.";
184-
case 104: return "Function '{0}' is possibly called virtually, which is not yet supported.";
185-
case 105: return "Low memory limit exceeded by static data: {0} > {1}";
187+
case 104: return "Low memory limit exceeded by static data: {0} > {1}";
188+
case 105: return "Module requires at least '{0}' pages of initial memory.";
189+
case 106: return "Module requires at least '{0}' pages of maximum memory.";
190+
case 107: return "Shared memory requires maximum memory to be defined.";
191+
case 108: return "Shared memory requires feature 'threads' to be enabled.";
186192
case 200: return "Conversion from type '{0}' to '{1}' requires an explicit cast.";
187193
case 201: return "Conversion from type '{0}' to '{1}' will require an explicit cast when switching between 32/64-bit.";
188194
case 202: return "Type '{0}' cannot be changed to type '{1}'.";

src/diagnosticMessages.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
"Operation is unsafe.": 101,
44
"User-defined: {0}": 102,
55
"Feature '{0}' is not enabled.": 103,
6-
"Function '{0}' is possibly called virtually, which is not yet supported.": 104,
7-
"Low memory limit exceeded by static data: {0} > {1}": 105,
6+
"Low memory limit exceeded by static data: {0} > {1}": 104,
7+
"Module requires at least '{0}' pages of initial memory.": 105,
8+
"Module requires at least '{0}' pages of maximum memory.": 106,
9+
"Shared memory requires maximum memory to be defined.": 107,
10+
"Shared memory requires feature 'threads' to be enabled.": 108,
811

912
"Conversion from type '{0}' to '{1}' requires an explicit cast.": 200,
1013
"Conversion from type '{0}' to '{1}' will require an explicit cast when switching between 32/64-bit.": 201,

src/index.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,28 @@ export function setNoAssert(options: Options, noAssert: bool): void {
5757
options.noAssert = noAssert;
5858
}
5959

60+
/** Sets the `exportMemory` option. */
61+
export function setExportMemory(options: Options, exportMemory: bool): void {
62+
options.exportMemory = exportMemory;
63+
}
64+
6065
/** Sets the `importMemory` option. */
6166
export function setImportMemory(options: Options, importMemory: bool): void {
6267
options.importMemory = importMemory;
6368
}
6469

70+
/** Sets the `initialMemory` option. */
71+
export function setInitialMemory(options: Options, initialMemory: u32): void {
72+
options.initialMemory = initialMemory;
73+
}
74+
75+
/** Sets the `maximumMemory` option. */
76+
export function setMaximumMemory(options: Options, maximumMemory: u32): void {
77+
options.maximumMemory = maximumMemory;
78+
}
79+
6580
/** Sets the `sharedMemory` option. */
66-
export function setSharedMemory(options: Options, sharedMemory: i32): void {
81+
export function setSharedMemory(options: Options, sharedMemory: bool): void {
6782
options.sharedMemory = sharedMemory;
6883
}
6984

tests/compiler.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,12 +165,10 @@ function runTest(basename) {
165165
const stderrString = stderr.toString();
166166
if (typeof expectStderr === "string") expectStderr = [ expectStderr ];
167167
let lastIndex = 0;
168-
let failed = false;
169168
expectStderr.forEach((substr, i) => {
170169
var index = stderrString.indexOf(substr, lastIndex);
171170
if (index < 0) {
172171
console.log("Missing pattern #" + (i + 1) + " '" + substr + "' in stderr at " + lastIndex + "+.");
173-
failedTests.add(basename);
174172
failed = true;
175173
} else {
176174
lastIndex = index + substr.length;

tests/compiler/features/threads.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"asc_flags": [
66
"--runtime none",
77
"--memoryBase 8",
8-
"--sharedMemory 1"
8+
"--maximumMemory 10",
9+
"--sharedMemory"
910
]
1011
}

tests/compiler/features/threads.optimized.wat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
(module
22
(type $none_=>_none (func))
3-
(memory $0 (shared 1 1))
3+
(memory $0 (shared 1 10))
44
(export "memory" (memory $0))
55
(start $~start)
66
(func $features/threads/testAtomic

tests/compiler/features/threads.untouched.wat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
(module
22
(type $none_=>_none (func))
3-
(memory $0 (shared 1 1))
3+
(memory $0 (shared 1 10))
44
(table $0 1 funcref)
55
(global $~lib/ASC_FEATURE_THREADS i32 (i32.const 1))
66
(export "memory" (memory $0))
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"asc_flags": [
3+
"--initialMemory 2",
4+
"--maximumMemory 1"
5+
],
6+
"stderr": [
7+
"AS105: Module requires at least '3' pages of initial memory.",
8+
"AS106: Module requires at least '3' pages of maximum memory."
9+
]
10+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
memory.data((2 << 16) + 1);
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"asc_flags": [
3+
"--sharedMemory"
4+
],
5+
"stderr": [
6+
"AS107: Shared memory requires maximum memory to be defined.",
7+
"AS108: Shared memory requires feature 'threads' to be enabled."
8+
]
9+
}

tests/compiler/memory-config-shared-errors.ts

Whitespace-only changes.

0 commit comments

Comments
 (0)