-
Notifications
You must be signed in to change notification settings - Fork 59
Interpreter: Make function calls and basic instructions working #1753
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
|
||
| } | ||
|
|
||
| struct ObjectAddress { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be called “Pointer?” I don't think “Object” is adding anything.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are instructions like AddressToPointer, thus I didn't pick the name Pointer. But yeah, "object" can be removed from name.
dabrahams
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've only just started with the review, but I must say it's hard to evaluate these diffs, because entities like StackFrame do not show up in the same place.
Sorry! I accidentally moved stackframe down, fixed that. I should have observed that while raising PR itself. |
| } | ||
|
|
||
| /// UInt8 value, if present. | ||
| public var uint8: UInt8? { size == 1 ? UInt8(truncatingIfNeeded: asUInt128) : nil } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| public var uint8: UInt8? { size == 1 ? UInt8(truncatingIfNeeded: asUInt128) : nil } | |
| public var i8: UInt8? { size == 1 ? UInt8(truncatingIfNeeded: asUInt128) : nil } |
Because that's what we call it in instructions
| import IR | ||
|
|
||
| /// The value of a `Builtin` type instance, stripped of type information. | ||
| struct UntypedBuiltinValue { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And now I realize this doesn't represent builtin ptr types I think? IIRC it was my intention that it would; we'd just encode it into the UInt128…
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UntypedBuiltinValue should represent builtin ptr. But encoding to UInt128 might not be possible. As we could have instruction like this:
%i0.0: &[{}] (sink Int) let -> Int = alloc_stack [{}] (sink Int) let -> Int
%i0.1: ptr = address_to_pointer @FunctionDecl(524290)
%i0.2: &ptr = subfield_view %i0.0, 0
%i0.3: &ptr = access [set] %i0.2
store %i0.1, %i0.3
end_access %i0.3
Here thing to note is:
- Address should also be able to represent function id.
- We need to support "function pointers" too.
IDK if Function.ID can be represented in 128 bits.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think Address should represent function IDs. However, the need to represent capture-less lambdas is real and leaves me more and more convinced that we shouldn't try and stuff different types in here.
| if !a.memoryLayout.type.isBuiltin { | ||
| return nil | ||
| } | ||
| let allocIdx = a.memoryAddress.allocation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where did this name come from? We don't use abbrevs. Also it's all type information at an even lower level of abstraction than Allocation.ID which is already too low. What role is the value playing in this context? That's what goes in the name. If you can't do better than to reflect type information, use a single-character name like a.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yeah, this is really a bad habit, mostly coming from work related codebases which normalize the same 😞. Trying to improve on it now!!!
| /// Returns address of subfield denoted by `path` stored in field at `a`. | ||
| mutating func subField(denotedBy path: RecordPath, of a: Address) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
denotedBy is a lot of big words with little semantic value. path is just type information.
| /// Returns address of subfield denoted by `path` stored in field at `a`. | |
| mutating func subField(denotedBy path: RecordPath, of a: Address) | |
| /// Returns the address of `subField` in the object at `origin`. | |
| mutating func address(of subField: RecordPath, in origin: Address) |
My suggestion is imperfect and should eventually be improved. The main reason is that I don't think we know how to talk about or properly name the thing called Address here. There may not be an object there yet. I wonder if it should be called ValueStorage, i.e. the storage for a value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regarding ValueStorage, knowing that Function.ID is also an Address (coming from IR instruction), I am not sure if ValueStorage would be good.
Also, shouldn't we use at instead of in in function name? Then it would match doc summary too.
Sources/Interpreter/Memory.swift
Outdated
|
|
||
| /// Copies `n` bytes from `source` to `destination`. | ||
| public mutating func copy( | ||
| bytes n: Int, from source: Memory.Address, to destination: Memory.Address |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| bytes n: Int, from source: Memory.Address, to destination: Memory.Address | |
| byteCount n: Int, from source: Memory.Address, to destination: Memory.Address |
n is not the bytes. However, you could:
| bytes n: Int, from source: Memory.Address, to destination: Memory.Address | |
| _ n: Int, bytesFrom source: Memory.Address, to destination: Memory.Address |
| _ = x | ||
| case let x as Load: | ||
| _ = x | ||
| let address = address(denotedBy: x.source)!; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This denotedBy label isn't working for me.
| /// Returns address of object denoted by operand, if any. | ||
| func address(denotedBy operand: Operand) -> Address? { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it the address of the object denoted by the operand, or the address denoted by the operand? The name is not consistent with the contract.
Isn't this just the operand, which must denote an address?
| } | ||
|
|
||
| /// The value produced by executing an instruction. | ||
| enum InstructionResult { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having a named type was a good idea. Maybe just an alias?
| /// Returns builtin value referenced by `operand`, if any. | ||
| func toBuiltinValue(_ operand: Operand) -> BuiltinValue? { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't repeat type information in the names of non-types
| /// Returns builtin value referenced by `operand`, if any. | |
| func toBuiltinValue(_ operand: Operand) -> BuiltinValue? { | |
| /// Returns the value of `x` if it has a builtin type, or `nil` if it does not. | |
| func builtinValue(_ x: Operand) -> BuiltinValue? { |
| ) | ||
| } | ||
|
|
||
| /// Store builtin value `v` at address `a`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| /// Store builtin value `v` at address `a`. | |
| /// Stores `v` in memory at `a`. |
| /// Moves the program counter to start of `b`. | ||
| mutating func jumpTo(_ b: Block.ID) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| /// Moves the program counter to start of `b`. | |
| mutating func jumpTo(_ b: Block.ID) { | |
| /// Sets the program counter to the start of `b`. | |
| mutating func jump(to b: Block.ID) { |
Read the swift API guidelines regarding prepositions.
| /// Returns block parameters from operands in `arg`. | ||
| func blockParams(from arg: Call) -> [Address] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand the comment. It probably should not require me to know what block parameters are, since that is the name of the function, except for the abbrev, which you should nix.
I think it returns the addresses of arguments followed by that of the return value space for arg.
arg is a terrible name for a function parameter; of course you're going to pass an argument. Another abbrev. Is it not notionally a function call?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get the sense that perhaps this PR is trying to do too much all at once. Partly I think so because I find myself wanting to make too many corrections.
Would it make sense to break it into smaller units, so we can make a really clean PR and learn from that?
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## interpreter #1753 +/- ##
===============================================
+ Coverage 87.85% 88.14% +0.29%
===============================================
Files 392 393 +1
Lines 24618 24734 +116
===============================================
+ Hits 21627 21803 +176
+ Misses 2991 2931 -60 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Design Changes
InstructionResulttype instead ofAnyupon execution.Unified Memory Representation
Design
Instructions implemented:
Instructions UN-implemented