-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* PolkVM Package and integer codec * Program parsing * program parse * more tests * memory wip * fix * pvm wip * pvm * fix * fix lint
- Loading branch information
Showing
22 changed files
with
1,009 additions
and
3 deletions.
There are no files selected for viewing
Submodule jamtestvectors
updated
from 15f1b2 to 2a633e
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
{ | ||
"originHash" : "83027e22d1c1e6e15dd98a1719eec3b0aa70fd540013d36d77223e0931d6f7a8", | ||
"pins" : [ | ||
{ | ||
"identity" : "blake2.swift", | ||
"kind" : "remoteSourceControl", | ||
"location" : "https://github.com/tesseract-one/Blake2.swift.git", | ||
"state" : { | ||
"revision" : "29c55c8fe42d6661e5a32cc5bbbad1fff64fd01e", | ||
"version" : "0.2.0" | ||
} | ||
}, | ||
{ | ||
"identity" : "scalecodec.swift", | ||
"kind" : "remoteSourceControl", | ||
"location" : "https://github.com/AcalaNetwork/ScaleCodec.swift.git", | ||
"state" : { | ||
"branch" : "main", | ||
"revision" : "dac3e7161de34c60c82794d031de0231b5a5746e" | ||
} | ||
}, | ||
{ | ||
"identity" : "swift-crypto", | ||
"kind" : "remoteSourceControl", | ||
"location" : "https://github.com/apple/swift-crypto.git", | ||
"state" : { | ||
"revision" : "46072478ca365fe48370993833cb22de9b41567f", | ||
"version" : "3.5.2" | ||
} | ||
}, | ||
{ | ||
"identity" : "swift-log", | ||
"kind" : "remoteSourceControl", | ||
"location" : "https://github.com/apple/swift-log.git", | ||
"state" : { | ||
"revision" : "9cb486020ebf03bfa5b5df985387a14a98744537", | ||
"version" : "1.6.1" | ||
} | ||
}, | ||
{ | ||
"identity" : "swift-syntax", | ||
"kind" : "remoteSourceControl", | ||
"location" : "https://github.com/apple/swift-syntax.git", | ||
"state" : { | ||
"revision" : "4c6cc0a3b9e8f14b3ae2307c5ccae4de6167ac2c", | ||
"version" : "600.0.0-prerelease-2024-06-12" | ||
} | ||
}, | ||
{ | ||
"identity" : "swift-testing", | ||
"kind" : "remoteSourceControl", | ||
"location" : "https://github.com/apple/swift-testing.git", | ||
"state" : { | ||
"branch" : "0.10.0", | ||
"revision" : "69d59cfc76e5daf498ca61f5af409f594768eef9" | ||
} | ||
}, | ||
{ | ||
"identity" : "tuples.swift", | ||
"kind" : "remoteSourceControl", | ||
"location" : "https://github.com/tesseract-one/Tuples.swift.git", | ||
"state" : { | ||
"revision" : "4d2cf7c64443cdf4df833d0bedd767bf9dbc49d9", | ||
"version" : "0.1.3" | ||
} | ||
} | ||
], | ||
"version" : 3 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// swift-tools-version: 6.0 | ||
// The swift-tools-version declares the minimum version of Swift required to build this package. | ||
|
||
import PackageDescription | ||
|
||
let package = Package( | ||
name: "PolkaVM", | ||
platforms: [ | ||
.macOS(.v14), | ||
], | ||
products: [ | ||
.library( | ||
name: "PolkaVM", | ||
targets: ["PolkaVM"] | ||
), | ||
], | ||
dependencies: [ | ||
.package(path: "../Utils"), | ||
.package(url: "https://github.com/apple/swift-testing.git", branch: "0.10.0"), | ||
.package(url: "https://github.com/apple/swift-log.git", from: "1.6.0"), | ||
], | ||
targets: [ | ||
.target( | ||
name: "PolkaVM", | ||
dependencies: [ | ||
"Utils", | ||
.product(name: "Logging", package: "swift-log"), | ||
] | ||
), | ||
.testTarget( | ||
name: "PolkaVMTests", | ||
dependencies: [ | ||
"PolkaVM", | ||
.product(name: "Testing", package: "swift-testing"), | ||
] | ||
), | ||
], | ||
swiftLanguageVersions: [.version("6")] | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
public class Engine { | ||
public init() {} | ||
|
||
public func execute(program: ProgramCode, state: VMState) -> ExitReason { | ||
while true { | ||
guard state.gas > 0 else { | ||
return .outOfGas | ||
} | ||
if let exitReason = step(program: program, state: state) { | ||
return exitReason | ||
} | ||
} | ||
} | ||
|
||
public func step(program: ProgramCode, state: VMState) -> ExitReason? { | ||
let pc = state.pc | ||
guard let skip = program.skip(state.pc) else { | ||
return .halt(.invalidInstruction) | ||
} | ||
guard let inst = InstructionTable.parse(program.code[Int(pc) ..< Int(pc + 1 + skip)]) else { | ||
return .halt(.invalidInstruction) | ||
} | ||
|
||
return inst.execute(state: state, skip: skip) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
public enum ExitReason { | ||
public enum HaltReason { | ||
case trap | ||
case invalidInstruction | ||
} | ||
|
||
case halt(HaltReason) | ||
case panic | ||
case outOfGas | ||
case hostCall(UInt32) | ||
case pageFault(UInt32) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import Foundation | ||
|
||
public protocol Instruction { | ||
static var opcode: UInt8 { get } | ||
|
||
init?(data: Data) | ||
|
||
func execute(state: VMState, skip: UInt32) -> ExitReason? | ||
func executeImpl(state: VMState) -> ExitReason? | ||
|
||
func gasCost() -> UInt64 | ||
func updatePC(state: VMState, skip: UInt32) | ||
} | ||
|
||
extension Instruction { | ||
public func execute(state: VMState, skip: UInt32) -> ExitReason? { | ||
state.consumeGas(gasCost()) | ||
let res = executeImpl(state: state) | ||
if res == nil { | ||
state.updatePC(state.pc + skip + 1) | ||
} | ||
return res | ||
} | ||
|
||
public func gasCost() -> UInt64 { | ||
1 | ||
} | ||
|
||
public func updatePC(state: VMState, skip: UInt32) { | ||
state.increasePC(skip + 1) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import Foundation | ||
|
||
public class InstructionTable { | ||
public static let table: [Instruction.Type?] = { | ||
let insts: [Instruction.Type] = [ | ||
Instructions.Trap.self, | ||
Instructions.Fallthrough.self, | ||
Instructions.Ecalli.self, | ||
Instructions.StoreImmU8.self, | ||
Instructions.StoreImmU16.self, | ||
Instructions.StoreImmU32.self, | ||
] | ||
var table: [Instruction.Type?] = Array(repeating: nil, count: 256) | ||
for i in 0 ..< insts.count { | ||
table[Int(insts[i].opcode)] = insts[i] | ||
} | ||
return table | ||
}() | ||
|
||
public static func parse(_ data: Data) -> (any Instruction)? { | ||
guard data.count >= 1 else { | ||
return nil | ||
} | ||
let opcode = data[data.startIndex] | ||
guard let instType = table[Int(opcode)] else { | ||
return nil | ||
} | ||
return instType.init(data: data) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
import Foundation | ||
import Utils | ||
|
||
public enum Instructions { | ||
static func decodeImmidate(_ data: Data) -> UInt32 { | ||
let len = min(data.count, 4) | ||
if len == 0 { | ||
return 0 | ||
} | ||
var value: UInt32 = 0 | ||
for i in 0 ..< len { | ||
value = value | (UInt32(data[i]) << (8 * i)) | ||
} | ||
let shift = (4 - len) * 8 | ||
// shift left so that the MSB is the sign bit | ||
// and then do signed shift right to fill the empty bits using the sign bit | ||
// and then convert back to UInt32 | ||
return UInt32(bitPattern: Int32(bitPattern: value << shift) >> shift) | ||
} | ||
|
||
static func decodeImmidate2(_ data: Data) -> (UInt32, UInt32)? { | ||
do { | ||
let lA = try Int(data.at(0) & 0b111) | ||
let lX = min(4, lA) | ||
let lY1 = min(4, max(0, data.count - Int(lA) - 1)) | ||
let lY2 = min(lY1, 8 - lA) | ||
let vX = try decodeImmidate(data.at(1 ..< lX)) | ||
let vY = try decodeImmidate(data.at((1 + lA) ..< lY2)) | ||
return (vX, vY) | ||
} catch { | ||
return nil | ||
} | ||
} | ||
|
||
// MARK: Instructions without Arguments | ||
|
||
public struct Trap: Instruction { | ||
public static var opcode: UInt8 { 0 } | ||
|
||
public init(data _: Data) {} | ||
|
||
public func executeImpl(state _: VMState) -> ExitReason? { | ||
.halt(.trap) | ||
} | ||
} | ||
|
||
public struct Fallthrough: Instruction { | ||
public static var opcode: UInt8 { 1 } | ||
|
||
public init(data _: Data) {} | ||
|
||
public func executeImpl(state _: VMState) -> ExitReason? { | ||
nil | ||
} | ||
} | ||
|
||
// MARK: Instructions with Arguments of One Immediate | ||
|
||
public struct Ecalli: Instruction { | ||
public static var opcode: UInt8 { 78 } | ||
|
||
public let callIndex: UInt32 | ||
|
||
public init(data: Data) { | ||
callIndex = Instructions.decodeImmidate(data) | ||
} | ||
|
||
public func executeImpl(state _: VMState) -> ExitReason? { | ||
.hostCall(callIndex) | ||
} | ||
} | ||
|
||
// MARK: Instructions with Arguments of Two Immediates | ||
|
||
public struct StoreImmU8: Instruction { | ||
public static var opcode: UInt8 { 62 } | ||
|
||
public let address: UInt32 | ||
public let value: UInt8 | ||
|
||
public init(data: Data) { | ||
let (x, y) = Instructions.decodeImmidate2(data)! | ||
address = x | ||
value = UInt8(truncatingIfNeeded: y) | ||
} | ||
|
||
public func executeImpl(state: VMState) -> ExitReason? { | ||
if (try? state.memory.write(address: address, value: value)) != nil { | ||
return nil | ||
} | ||
return .pageFault(address) | ||
} | ||
} | ||
|
||
public struct StoreImmU16: Instruction { | ||
public static var opcode: UInt8 { 79 } | ||
|
||
public let address: UInt32 | ||
public let value: UInt16 | ||
|
||
public init(data: Data) { | ||
let (x, y) = Instructions.decodeImmidate2(data)! | ||
address = x | ||
value = UInt16(truncatingIfNeeded: y) | ||
} | ||
|
||
public func executeImpl(state: VMState) -> ExitReason? { | ||
if (try? state.memory.write(address: address, values: value.encode(method: .fixedWidth(2)))) != nil { | ||
return nil | ||
} | ||
return .pageFault(address) | ||
} | ||
} | ||
|
||
public struct StoreImmU32: Instruction { | ||
public static var opcode: UInt8 { 38 } | ||
|
||
public let address: UInt32 | ||
public let value: UInt32 | ||
|
||
public init(data: Data) { | ||
let (x, y) = Instructions.decodeImmidate2(data)! | ||
address = x | ||
value = y | ||
} | ||
|
||
public func executeImpl(state: VMState) -> ExitReason? { | ||
if (try? state.memory.write(address: address, values: value.encode(method: .fixedWidth(4)))) != nil { | ||
return nil | ||
} | ||
return .pageFault(address) | ||
} | ||
} | ||
} |
Oops, something went wrong.