From 889d007686e2464508c097664d07b81edf6e289c Mon Sep 17 00:00:00 2001 From: Alexander Wood Date: Sat, 4 May 2024 18:01:21 +0100 Subject: [PATCH] add New and InvokeSpecial --- h2jvm.cabal | 2 +- src/JVM/Data/Abstract/Instruction.hs | 4 ++++ src/JVM/Data/Analyse/StackMap.hs | 2 ++ src/JVM/Data/Convert/Instruction.hs | 8 ++++++++ 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/h2jvm.cabal b/h2jvm.cabal index 75dc205..bc98026 100644 --- a/h2jvm.cabal +++ b/h2jvm.cabal @@ -21,7 +21,7 @@ name: h2jvm -- PVP summary: +-+------- breaking API changes -- | | +----- non-breaking API additions -- | | | +--- code changes with no API change -version: 0.5.4.7 +version: 0.5.4.8 -- A short (one-line) description of the package. synopsis: diff --git a/src/JVM/Data/Abstract/Instruction.hs b/src/JVM/Data/Abstract/Instruction.hs index 08f3233..c7a77f3 100644 --- a/src/JVM/Data/Abstract/Instruction.hs +++ b/src/JVM/Data/Abstract/Instruction.hs @@ -36,6 +36,7 @@ data Instruction' label | InvokeInterface ClassInfoType Text MethodDescriptor | InvokeVirtual ClassInfoType Text MethodDescriptor | InvokeDynamic BootstrapMethod Text MethodDescriptor + | InvokeSpecial ClassInfoType Text MethodDescriptor | ILoad U1 | IStore U1 | Label label @@ -47,6 +48,7 @@ data Instruction' label | Goto label | CheckCast ClassInfoType | Return + | New ClassInfoType deriving (Show, Eq, Ord, Functor, Generic, Data) instance (Pretty label) => Pretty (Instruction' label) where @@ -65,6 +67,7 @@ instance (Pretty label) => Pretty (Instruction' label) where pretty (InvokeInterface c n d) = "invokeinterface" <+> pretty c <> "." <> pretty n <> pretty d pretty (InvokeVirtual c n d) = "invokevirtual" <+> pretty c <> "." <> pretty n <> pretty d pretty (InvokeDynamic b n d) = "invokedynamic" <+> pretty b <> "." <> pretty n <> pretty d + pretty (InvokeSpecial c n d) = "invokespecial" <+> pretty c <> "." <> pretty n <> pretty d pretty (ILoad x) = "iload" <+> pretty x pretty (IStore x) = "istore" <+> pretty x pretty (Label l) = ":" <> pretty l @@ -76,6 +79,7 @@ instance (Pretty label) => Pretty (Instruction' label) where pretty (Goto l) = "goto" <+> pretty l pretty (CheckCast c) = "checkcast" <+> pretty c pretty Return = "return" + pretty (New c) = "new" <+> pretty c jumpTarget :: Instruction' label -> Maybe label jumpTarget (IfEq l) = Just l diff --git a/src/JVM/Data/Analyse/StackMap.hs b/src/JVM/Data/Analyse/StackMap.hs index 28ad0e9..1db7ff8 100644 --- a/src/JVM/Data/Analyse/StackMap.hs +++ b/src/JVM/Data/Analyse/StackMap.hs @@ -104,12 +104,14 @@ analyseBlockDiff current block = foldl' (flip analyseInstruction) current (takeW analyseInstruction (InvokeVirtual _ _ md) ba = ba{stack = (StackEntry <$> maybeToList (returnDescriptorType md.returnDesc)) <> drop (1 + length md.params) ba.stack} analyseInstruction (InvokeInterface _ _ md) ba = ba{stack = (StackEntry <$> maybeToList (returnDescriptorType md.returnDesc)) <> drop (length md.params) ba.stack} analyseInstruction (InvokeDynamic _ _ md) ba = ba{stack = (StackEntry <$> maybeToList (returnDescriptorType md.returnDesc)) <> drop (1 + length md.params) ba.stack} + analyseInstruction (InvokeSpecial _ _ md) ba = ba{stack = (StackEntry <$> maybeToList (returnDescriptorType md.returnDesc)) <> drop (1 + length md.params) ba.stack} analyseInstruction (PutStatic{}) ba = ba{stack = tail ba.stack} analyseInstruction (GetField _ _ ft) ba = ba{stack = StackEntry ft : tail ba.stack} analyseInstruction (GetStatic _ _ ft) ba = ba{stack = StackEntry ft : ba.stack} analyseInstruction (PutField{}) ba = ba{stack = tail $ tail ba.stack} analyseInstruction (Goto _) ba = ba analyseInstruction (LDC l) ba = ba{stack = StackEntry (ldcEntryToFieldType l) : ba.stack} + analyseInstruction (New t) ba = ba{stack = StackEntry (classInfoTypeToFieldType t) : ba.stack} frameDiffToSMF :: (HasCallStack) => Frame -> BasicBlock -> StackMapFrame frameDiffToSMF f1@(Frame locals1 stack1) bb = do diff --git a/src/JVM/Data/Convert/Instruction.hs b/src/JVM/Data/Convert/Instruction.hs index 3cc0deb..fb5097a 100644 --- a/src/JVM/Data/Convert/Instruction.hs +++ b/src/JVM/Data/Convert/Instruction.hs @@ -77,6 +77,7 @@ instructionSize (Abs.InvokeStatic{}) = 3 instructionSize (Abs.InvokeVirtual{}) = 3 instructionSize (Abs.InvokeInterface{}) = 5 instructionSize (Abs.InvokeDynamic{}) = 5 +instructionSize (Abs.InvokeSpecial{}) = 3 instructionSize (Abs.Label _) = 0 instructionSize (Abs.LDC _) = 2 instructionSize (Abs.PutStatic{}) = 3 @@ -87,6 +88,7 @@ instructionSize (Abs.CheckCast _) = 3 instructionSize Abs.Return = 1 instructionSize Abs.Dup = 1 instructionSize (Abs.Goto _) = 3 +instructionSize (Abs.New _) = 3 convertInstructions :: (CodeConverterEff r) => [Abs.Instruction] -> Sem r [Raw.Instruction] convertInstructions xs = do @@ -196,6 +198,9 @@ convertInstruction (OffsetInstruction instOffset o) = Just <$> convertInstructio idx <- findIndexOf (CPInterfaceMethodRefEntry (MethodRef c n m)) let count = countArguments m pure (Raw.InvokeInterface idx (fromIntegral count)) + convertInstruction (Abs.InvokeSpecial c n m) = do + idx <- findIndexOf (CPMethodRefEntry (MethodRef c n m)) + pure (Raw.InvokeSpecial idx) convertInstruction (Abs.LDC ldc) = do idx <- findIndexOf @@ -237,3 +242,6 @@ convertInstruction (OffsetInstruction instOffset o) = Just <$> convertInstructio convertInstruction (Abs.IfLe offset) = Raw.IfLe <$> mustBeResolved instOffset offset convertInstruction (Abs.Goto offset) = Raw.Goto <$> mustBeResolved instOffset offset convertInstruction (Abs.Label _) = error "unreachable" + convertInstruction (Abs.New t) = do + idx <- findIndexOf (CPClassEntry t) + pure (Raw.New idx)