diff --git a/compiler/wasm32/aasmcpu.pas b/compiler/wasm32/aasmcpu.pas index b6698e9b22..67471290ef 100644 --- a/compiler/wasm32/aasmcpu.pas +++ b/compiler/wasm32/aasmcpu.pas @@ -108,8 +108,10 @@ uses FValueStack: TWasmValueStack; FCtrlStack: TWasmControlStack; FGetLocalType: TGetLocalTypeProc; + FFuncType: TWasmFuncType; + FEndFunctionReached: Boolean; public - constructor Create(AGetLocalType: TGetLocalTypeProc); + constructor Create(AGetLocalType: TGetLocalTypeProc; AFuncType: TWasmFuncType); destructor Destroy; override; procedure PushVal(vt: TWasmBasicType); @@ -500,11 +502,14 @@ uses { TWasmValidationStacks } - constructor TWasmValidationStacks.Create(AGetLocalType: TGetLocalTypeProc); + constructor TWasmValidationStacks.Create(AGetLocalType: TGetLocalTypeProc; AFuncType: TWasmFuncType); begin + FEndFunctionReached:=False; FGetLocalType:=AGetLocalType; FValueStack:=TWasmValueStack.Create; FCtrlStack:=TWasmControlStack.Create; + FFuncType:=AFuncType; + PushCtrl(a_block,[],[]); end; destructor TWasmValidationStacks.Destroy; @@ -534,7 +539,7 @@ uses function TWasmValidationStacks.PopVal(expect: TWasmBasicType): TWasmBasicType; begin Result:=wbt_Unknown; - Result:=PopVal; + Result:=PopVal(); if (Result<>expect) and (Result<>wbt_Unknown) and (expect<>wbt_Unknown) then internalerror(2024013105); end; @@ -643,6 +648,8 @@ uses frame: TWasmControlFrame; n: TCGInt; begin + if FEndFunctionReached then + internalerror(2024022602); case a.opcode of a_nop: ; @@ -1110,6 +1117,13 @@ uses PopVals(label_types(FCtrlStack[n])); PushVals(label_types(FCtrlStack[n])); end; + a_return: + begin + PopVals(FFuncType.results); + Unreachable; + end; + a_end_function: + FEndFunctionReached:=True; else internalerror(2024030502); end; diff --git a/compiler/wasm32/cpupi.pas b/compiler/wasm32/cpupi.pas index c87a733dfe..6e99ccddf2 100644 --- a/compiler/wasm32/cpupi.pas +++ b/compiler/wasm32/cpupi.pas @@ -36,6 +36,9 @@ interface tcpuprocinfo=class(tcgprocinfo) private + FFuncType: TWasmFuncType; + FLocals: array of TWasmBasicType; + FParametersCount: Integer; FFirstFreeLocal: Integer; FAllocatedLocals: array of TWasmBasicType; FGotoTargets: TFPHashObjectList; @@ -47,6 +50,7 @@ interface { used for allocating locals during the postprocess_code stage (i.e. after register allocation) } function AllocWasmLocal(wbt: TWasmBasicType): Integer; + function GetLocalType(localidx: Integer): TWasmBasicType; public { label to the nearest local exception handler } CurrRaiseLabel : tasmlabel; @@ -423,6 +427,16 @@ implementation SetLength(FAllocatedLocals,Length(FAllocatedLocals)+1); FAllocatedLocals[High(FAllocatedLocals)]:=wbt; result:=High(FAllocatedLocals)+FFirstFreeLocal; + + SetLength(FLocals,Length(FLocals)+1); + FLocals[High(FLocals)]:=wbt; + end; + + function tcpuprocinfo.GetLocalType(localidx: Integer): TWasmBasicType; + begin + if (localidxHigh(FLocals)) then + internalerror(2024022601); + result:=FLocals[localidx]; end; constructor tcpuprocinfo.create(aparent: tprocinfo); @@ -889,9 +903,14 @@ implementation local:=nil; first:=true; l:=ttgwasm(tg).localvars.first; - FFirstFreeLocal:=Length(findfirst_tai_functype(aktproccode).functype.params); + FFuncType:=findfirst_tai_functype(aktproccode).functype; + FLocals:=Copy(FFuncType.params); + FParametersCount:=Length(FLocals); + FFirstFreeLocal:=FParametersCount; while Assigned(l) do begin + SetLength(FLocals,Length(FLocals)+1); + FLocals[High(FLocals)]:=l.typ; local:=tai_local.create(l.typ); local.first:=first; first:=false; @@ -944,6 +963,23 @@ implementation end; end; + procedure validate_code; + var + vs: TWasmValidationStacks; + hp: tai; + begin + vs:=TWasmValidationStacks.Create(@GetLocalType,FFuncType); + + hp:=tai(aktproccode.first); + while assigned(hp) do + begin + if hp.typ=ait_instruction then + vs.Validate(taicpu(hp)); + hp:=tai(hp.next); + end; + vs.Free; + end; + var localslist: TAsmList; labels_resolved, has_goto: Boolean; @@ -967,6 +1003,10 @@ implementation insert_localslist(aktproccode,localslist); localslist.Free; +{$ifdef DEBUG_WASM_VALIDATION} + validate_code; +{$endif DEBUG_WASM_VALIDATION} + inherited postprocess_code; end;