Builtin functions for memory.grow and memory.size
This commit is contained in:
parent
6890c78743
commit
0c23c326ac
@ -385,7 +385,45 @@ func (c *Compiler) compileExpressionWAT(expr Expression) (string, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch fc.Function {
|
||||||
|
case BUILTIN_MEMORY_GROW:
|
||||||
|
if !c.Wasm64 {
|
||||||
|
cast, err := castPrimitiveWAT(Primitive_U64, Primitive_U32)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
wat += cast
|
||||||
|
}
|
||||||
|
|
||||||
|
wat += "memory.grow\n"
|
||||||
|
|
||||||
|
if !c.Wasm64 {
|
||||||
|
cast, err := castPrimitiveWAT(Primitive_I32, Primitive_I64)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
wat += cast
|
||||||
|
}
|
||||||
|
|
||||||
|
return wat, nil
|
||||||
|
case BUILTIN_MEMORY_SIZE:
|
||||||
|
wat += "memory.size\n"
|
||||||
|
|
||||||
|
if !c.Wasm64 {
|
||||||
|
cast, err := castPrimitiveWAT(Primitive_U32, Primitive_U64)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
wat += cast
|
||||||
|
}
|
||||||
|
|
||||||
|
return wat, nil
|
||||||
|
default:
|
||||||
return wat + "call $" + fc.Function + "\n", nil
|
return wat + "call $" + fc.Function + "\n", nil
|
||||||
|
}
|
||||||
case Expression_Unary:
|
case Expression_Unary:
|
||||||
unary := expr.Value.(UnaryExpression)
|
unary := expr.Value.(UnaryExpression)
|
||||||
exprType := expr.ValueType.Value.(PrimitiveType)
|
exprType := expr.ValueType.Value.(PrimitiveType)
|
||||||
|
4
lexer.go
4
lexer.go
@ -113,6 +113,10 @@ type Lexer struct {
|
|||||||
Position uint64
|
Position uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func unknownPosition() TokenPosition {
|
||||||
|
return TokenPosition{SourceFile: "", Position: 0}
|
||||||
|
}
|
||||||
|
|
||||||
func (l *Lexer) error(message string) error {
|
func (l *Lexer) error(message string) error {
|
||||||
return CompilerError{Position: TokenPosition{SourceFile: l.SourceFile, Position: l.LastTokenPosition}, Message: message}
|
return CompilerError{Position: TokenPosition{SourceFile: l.SourceFile, Position: l.LastTokenPosition}, Message: message}
|
||||||
}
|
}
|
||||||
|
@ -9,5 +9,14 @@ void free(u64 address) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
u64 growMemory(u64 numPages) {
|
u64 growMemory(u64 numPages) {
|
||||||
|
i64 value = __builtin_memory_grow(numPages);
|
||||||
|
if(value == -1) {
|
||||||
return 0u64;
|
return 0u64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return __builtin_memory_size();
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 memorySize() {
|
||||||
|
return __builtin_memory_size();
|
||||||
|
}
|
||||||
|
38
validator.go
38
validator.go
@ -14,6 +14,26 @@ type Validator struct {
|
|||||||
CurrentFunction *ParsedFunction
|
CurrentFunction *ParsedFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
BUILTIN_MEMORY_GROW = "__builtin_memory_grow"
|
||||||
|
BUILTIN_MEMORY_SIZE = "__builtin_memory_size"
|
||||||
|
)
|
||||||
|
|
||||||
|
var builtinFunctions map[string]*ParsedFunction = map[string]*ParsedFunction{
|
||||||
|
BUILTIN_MEMORY_GROW: {
|
||||||
|
Name: BUILTIN_MEMORY_GROW,
|
||||||
|
FullName: "builtin." + BUILTIN_MEMORY_GROW,
|
||||||
|
Parameters: []ParsedParameter{{Name: "memory", Type: Type{Type: Type_Primitive, Value: Primitive_U64, Position: unknownPosition()}}},
|
||||||
|
ReturnType: &Type{Type: Type_Primitive, Value: Primitive_I64, Position: unknownPosition()},
|
||||||
|
},
|
||||||
|
BUILTIN_MEMORY_SIZE: {
|
||||||
|
Name: BUILTIN_MEMORY_SIZE,
|
||||||
|
FullName: "builtin." + BUILTIN_MEMORY_SIZE,
|
||||||
|
Parameters: []ParsedParameter{},
|
||||||
|
ReturnType: &Type{Type: Type_Primitive, Value: Primitive_U64, Position: unknownPosition()},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
func isSameType(a Type, b Type) bool {
|
func isSameType(a Type, b Type) bool {
|
||||||
if a.Type != b.Type {
|
if a.Type != b.Type {
|
||||||
return false
|
return false
|
||||||
@ -294,11 +314,14 @@ func (v *Validator) validatePotentiallyVoidExpression(expr *Expression) []error
|
|||||||
case Expression_FunctionCall:
|
case Expression_FunctionCall:
|
||||||
fc := expr.Value.(FunctionCallExpression)
|
fc := expr.Value.(FunctionCallExpression)
|
||||||
|
|
||||||
calledFunc, ok := v.AllFunctions[fc.Function]
|
calledFunc, ok := builtinFunctions[fc.Function]
|
||||||
|
if !ok {
|
||||||
|
calledFunc, ok = v.AllFunctions[fc.Function]
|
||||||
if !ok {
|
if !ok {
|
||||||
errors = append(errors, v.createError("call to undefined function '"+fc.Function+"'", expr.Position))
|
errors = append(errors, v.createError("call to undefined function '"+fc.Function+"'", expr.Position))
|
||||||
return errors
|
return errors
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if fc.Parameters != nil {
|
if fc.Parameters != nil {
|
||||||
paramsErrors := v.validateExpression(fc.Parameters)
|
paramsErrors := v.validateExpression(fc.Parameters)
|
||||||
@ -306,12 +329,18 @@ func (v *Validator) validatePotentiallyVoidExpression(expr *Expression) []error
|
|||||||
errors = append(errors, paramsErrors...)
|
errors = append(errors, paramsErrors...)
|
||||||
return errors
|
return errors
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
params := []*Expression{fc.Parameters}
|
var params []*Expression
|
||||||
if fc.Parameters.Type == Expression_Tuple {
|
if fc.Parameters == nil {
|
||||||
|
params = []*Expression{}
|
||||||
|
} else if fc.Parameters.Type == Expression_Tuple {
|
||||||
|
params = make([]*Expression, len(fc.Parameters.Value.(TupleExpression).Members))
|
||||||
for i := 0; i < len(fc.Parameters.Value.(TupleExpression).Members); i++ {
|
for i := 0; i < len(fc.Parameters.Value.(TupleExpression).Members); i++ {
|
||||||
params[i] = &fc.Parameters.Value.(TupleExpression).Members[i]
|
params[i] = &fc.Parameters.Value.(TupleExpression).Members[i]
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
params = []*Expression{fc.Parameters}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(params) != len(calledFunc.Parameters) {
|
if len(params) != len(calledFunc.Parameters) {
|
||||||
@ -322,12 +351,11 @@ func (v *Validator) validatePotentiallyVoidExpression(expr *Expression) []error
|
|||||||
typeGiven := params[i]
|
typeGiven := params[i]
|
||||||
typeExpected := calledFunc.Parameters[i]
|
typeExpected := calledFunc.Parameters[i]
|
||||||
if !isTypeExpandableTo(*typeGiven.ValueType, typeExpected.Type) {
|
if !isTypeExpandableTo(*typeGiven.ValueType, typeExpected.Type) {
|
||||||
errors = append(errors, v.createError("invalid type for parameter "+strconv.Itoa(i), expr.Position))
|
errors = append(errors, v.createError("invalid type for parameter "+strconv.Itoa(i)+": expected "+typeExpected.Type.String()+", got "+typeGiven.ValueType.String(), expr.Position))
|
||||||
}
|
}
|
||||||
|
|
||||||
expandExpressionToType(typeGiven, typeExpected.Type)
|
expandExpressionToType(typeGiven, typeExpected.Type)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
expr.ValueType = calledFunc.ReturnType
|
expr.ValueType = calledFunc.ReturnType
|
||||||
expr.Value = fc
|
expr.Value = fc
|
||||||
|
Loading…
Reference in New Issue
Block a user