Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F100195154
index.js
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Tue, Jan 28, 23:02
Size
5 KB
Mime Type
text/x-java
Expires
Thu, Jan 30, 23:02 (2 d)
Engine
blob
Format
Raw Data
Handle
23878757
Attached To
rOACCT Open Access Compliance Check Tool (OACCT)
index.js
View Options
// TODO(sven): add flow in here
import
{
isSignature
,
isNumberLiteral
}
from
"@webassemblyjs/ast"
;
import
{
assert
}
from
"mamacro"
;
export
function
moduleContextFromModuleAST
(
m
)
{
const
moduleContext
=
new
ModuleContext
();
assert
(
m
.
type
===
"Module"
);
m
.
fields
.
forEach
(
field
=>
{
switch
(
field
.
type
)
{
case
"Start"
:
{
moduleContext
.
setStart
(
field
.
index
);
break
;
}
case
"TypeInstruction"
:
{
moduleContext
.
addType
(
field
);
break
;
}
case
"Func"
:
{
moduleContext
.
addFunction
(
field
);
break
;
}
case
"Global"
:
{
moduleContext
.
defineGlobal
(
field
);
break
;
}
case
"ModuleImport"
:
{
switch
(
field
.
descr
.
type
)
{
case
"GlobalType"
:
{
moduleContext
.
importGlobal
(
field
.
descr
.
valtype
,
field
.
descr
.
mutability
);
break
;
}
case
"Memory"
:
{
moduleContext
.
addMemory
(
field
.
descr
.
limits
.
min
,
field
.
descr
.
limits
.
max
);
break
;
}
case
"FuncImportDescr"
:
{
moduleContext
.
importFunction
(
field
.
descr
);
break
;
}
case
"Table"
:
{
// FIXME(sven): not implemented yet
break
;
}
default
:
throw
new
Error
(
"Unsupported ModuleImport of type "
+
JSON
.
stringify
(
field
.
descr
.
type
)
);
}
break
;
}
case
"Memory"
:
{
moduleContext
.
addMemory
(
field
.
limits
.
min
,
field
.
limits
.
max
);
break
;
}
}
});
return
moduleContext
;
}
/**
* Module context for type checking
*/
export
class
ModuleContext
{
constructor
()
{
this
.
funcs
=
[];
this
.
funcsOffsetByIdentifier
=
[];
this
.
types
=
[];
this
.
globals
=
[];
this
.
globalsOffsetByIdentifier
=
[];
this
.
mems
=
[];
// Current stack frame
this
.
locals
=
[];
this
.
labels
=
[];
this
.
return
=
[];
this
.
debugName
=
"unknown"
;
this
.
start
=
null
;
}
/**
* Set start segment
*/
setStart
(
index
)
{
this
.
start
=
index
.
value
;
}
/**
* Get start function
*/
getStart
()
{
return
this
.
start
;
}
/**
* Reset the active stack frame
*/
newContext
(
debugName
,
expectedResult
)
{
this
.
locals
=
[];
this
.
labels
=
[
expectedResult
];
this
.
return
=
expectedResult
;
this
.
debugName
=
debugName
;
}
/**
* Functions
*/
addFunction
(
func
/*: Func*/
)
{
// eslint-disable-next-line prefer-const
let
{
params
:
args
=
[],
results
:
result
=
[]
}
=
func
.
signature
||
{};
args
=
args
.
map
(
arg
=>
arg
.
valtype
);
this
.
funcs
.
push
({
args
,
result
});
if
(
typeof
func
.
name
!==
"undefined"
)
{
this
.
funcsOffsetByIdentifier
[
func
.
name
.
value
]
=
this
.
funcs
.
length
-
1
;
}
}
importFunction
(
funcimport
)
{
if
(
isSignature
(
funcimport
.
signature
))
{
// eslint-disable-next-line prefer-const
let
{
params
:
args
,
results
:
result
}
=
funcimport
.
signature
;
args
=
args
.
map
(
arg
=>
arg
.
valtype
);
this
.
funcs
.
push
({
args
,
result
});
}
else
{
assert
(
isNumberLiteral
(
funcimport
.
signature
));
const
typeId
=
funcimport
.
signature
.
value
;
assert
(
this
.
hasType
(
typeId
));
const
signature
=
this
.
getType
(
typeId
);
this
.
funcs
.
push
({
args
:
signature
.
params
.
map
(
arg
=>
arg
.
valtype
),
result
:
signature
.
results
});
}
if
(
typeof
funcimport
.
id
!==
"undefined"
)
{
// imports are first, we can assume their index in the array
this
.
funcsOffsetByIdentifier
[
funcimport
.
id
.
value
]
=
this
.
funcs
.
length
-
1
;
}
}
hasFunction
(
index
)
{
return
typeof
this
.
getFunction
(
index
)
!==
"undefined"
;
}
getFunction
(
index
)
{
if
(
typeof
index
!==
"number"
)
{
throw
new
Error
(
"getFunction only supported for number index"
);
}
return
this
.
funcs
[
index
];
}
getFunctionOffsetByIdentifier
(
name
)
{
assert
(
typeof
name
===
"string"
);
return
this
.
funcsOffsetByIdentifier
[
name
];
}
/**
* Labels
*/
addLabel
(
result
)
{
this
.
labels
.
unshift
(
result
);
}
hasLabel
(
index
)
{
return
this
.
labels
.
length
>
index
&&
index
>=
0
;
}
getLabel
(
index
)
{
return
this
.
labels
[
index
];
}
popLabel
()
{
this
.
labels
.
shift
();
}
/**
* Locals
*/
hasLocal
(
index
)
{
return
typeof
this
.
getLocal
(
index
)
!==
"undefined"
;
}
getLocal
(
index
)
{
return
this
.
locals
[
index
];
}
addLocal
(
type
)
{
this
.
locals
.
push
(
type
);
}
/**
* Types
*/
addType
(
type
)
{
assert
(
type
.
functype
.
type
===
"Signature"
);
this
.
types
.
push
(
type
.
functype
);
}
hasType
(
index
)
{
return
this
.
types
[
index
]
!==
undefined
;
}
getType
(
index
)
{
return
this
.
types
[
index
];
}
/**
* Globals
*/
hasGlobal
(
index
)
{
return
this
.
globals
.
length
>
index
&&
index
>=
0
;
}
getGlobal
(
index
)
{
return
this
.
globals
[
index
].
type
;
}
getGlobalOffsetByIdentifier
(
name
)
{
assert
(
typeof
name
===
"string"
);
return
this
.
globalsOffsetByIdentifier
[
name
];
}
defineGlobal
(
global
/*: Global*/
)
{
const
type
=
global
.
globalType
.
valtype
;
const
mutability
=
global
.
globalType
.
mutability
;
this
.
globals
.
push
({
type
,
mutability
});
if
(
typeof
global
.
name
!==
"undefined"
)
{
this
.
globalsOffsetByIdentifier
[
global
.
name
.
value
]
=
this
.
globals
.
length
-
1
;
}
}
importGlobal
(
type
,
mutability
)
{
this
.
globals
.
push
({
type
,
mutability
});
}
isMutableGlobal
(
index
)
{
return
this
.
globals
[
index
].
mutability
===
"var"
;
}
isImmutableGlobal
(
index
)
{
return
this
.
globals
[
index
].
mutability
===
"const"
;
}
/**
* Memories
*/
hasMemory
(
index
)
{
return
this
.
mems
.
length
>
index
&&
index
>=
0
;
}
addMemory
(
min
,
max
)
{
this
.
mems
.
push
({
min
,
max
});
}
getMemory
(
index
)
{
return
this
.
mems
[
index
];
}
}
Event Timeline
Log In to Comment