All right, hi. I'm Barish from Intel. I will continue talking about the work. So, we have
seen that the overall location expressions are important. They play a crucial role in debugging.
So here I'm giving you, and I took this, this is a real example. I took this from a, from
a GPU program. It's a location expression, a sequence of the law for operators. And you
may be now a developer who is relatively new to this debugging world. And then you may
be wondering, okay, what does this mean? I mean, I want to learn. So I want to evaluate
this step by step, and I want to understand how the dwarf expressions semantics are. Or you
may be a relatively seasoned developer in this world. But then maybe there's a bug here,
and then you want to debug the expression. You want to understand the details. Or perhaps
you want to optimize it. You want to find a better way of expressing the location. Or perhaps
you are an expert, and you want to introduce a new operator with some other with new semantics
in the dwarf spec. And then you want to define this. You want to experiment with some examples.
You want to test. You want to show this to other people and so on. Well, for this, I present
you to the dwarf evaluator. We can go to, let's see if this is going to work.
Yeah. So this is the repository. And there's one file here, ML. That's, you don't, okay, let me
quit this. Yeah. Yeah. So there's one, there's one ML file. This is written in OCaml. I will just
quit this scroll down. There are some definitions, functions, et cetera, et cetera, et cetera, and
then there are the functions that define the semantics. And then like about here, let's
the end. So in less than, less than 700 lines of code, it's, it's done. The rest is just examples.
So you can just take this, I mean, it's lightweight and concise. So you can just take this one,
just copy and paste. There are some, some OCaml interpreters online. You can just put them
there. You can evaluate inside the browser or you can install it in your terminal and then
work with it. It's not a parser. I will show. I will show. Yeah. So it's implemented in OCaml,
which I think is the second best choice for this purpose. The first one would have been
algal-68, but I don't know how to program it. Yeah. There's also a web playground. I'm going
to show this to you. These are the operators that are currently implemented. It's not the full set,
but I think it's, it's pretty, pretty representative and you can, you can do useful stuff.
So on the left-hand side, we see some snippets from the actual devolve spec version 6.
I don't expect you to read this, of course, but I have highlighted some important places,
and I will show some correspondence with implementation. For instance, here it says a location
names a block of storage and an offset. Well, what this means is that location is a pair of storage
and offset. Here it's, here is the definition. Location is a pair, storage and an integer.
Or it says there are six kinds of storage, memory register, the one in the composite. So memory
register composite. Composite storage consists of a possibly empty series of continues pieces.
Well, composite storage has a list of pieces and so on. So with the spec, the verbal English version
of the spec versus the code. I hope that there will, there will be a nice correspondence to,
to show how, how this is defined. Some more examples, again from the spec,
the expressions operate on a stack of entries. Each of which may be either a value or location.
Now, a stack element is either a value or a location. And then there is this evolve function,
which takes an operator, stack and the context. Okamol is valid, it's typed and types are
inferred. It's not explicit written here, but the inferred type for this argument,
stack argument is a list of stack elements, which is just a stack. Again, taking a look at the definition
of DWOp Adder. It says, well, takes an Ad, takes an operant, which is address in the default
address space. And the corresponding memory location is pushed onto the stack. Well, let's take
a look at how it's defined. Default address space is map 0, 0 is the default index. And then with
the given address, which happens now, happens to be the offset, we push a location onto the stack.
Or for the REC operators, a location that names the storage associated with the designated
register with an offset of 0 is formed and pushed on the stack. Exactly what's happening here,
furnishes for REC one. We form a location for REC one with offset 0 and push it on top of the stack.
A few more examples. Well, DWOp top duplicates the entry. Here, the pattern matching
feature of a cable disiting excellent. So we do a pattern matching on the stack. We expect an
element on the top with rest of the stack, which is now a stack prime. And then we duplicate it,
E1, the element E1 followed by E1 again, followed by rest of the stack. Or for rotation,
says there are three stack entries. Well, then the stack has to be E1, an element followed by another,
followed by the rest. And then we rotate them and then give the give the new state of the stack.
Relational operators, again, I don't expect you to read, but what it says is that, well, we push the
constant value one or zero depending on the operation. Well, here is the definition,
we expect E1 and E2 and then they have to be values, so that we can compare them. And then depending
on the result of comparison, we either push value one or value zero. Here is how you can use it.
Um, for this I want to give a demo. I start your camera, yeah, interpreter and then I load the file.
And then I can say for instance, I want to evaluate the work list of the work operators. So let me push
um, three, let me push four and then I'm going to multiply. I want to evaluate this in an in the
empty stack initially and in an empty context. So I do that and I get the result. Okay, so this is how
it's not a parser, this is how you can use it. This is an actual example, again from the spec,
an example for for the pick operator. Well, here is what I did. I want to, I want a DW pick
two evaluated in this initial stack, 17, 29, 1000 and then I get this as the result.
Um, another example, again, actual example from the stack, this time it relates to a
location. Um, so composite location is being formed with these operators. What I did is that
well, frame frame base register, I mean it's ABI dependent, so I just said, okay, let's let's
say register nine is frame base. And then I evaluate in a context where we need to define our
register zero and register nine and then I get this composite with three pieces. Well,
the first part is first four bytes reciting register zero, so byte zero until four registers zero.
Middle four bytes are unavailable, unavailable and the last four bytes are in memory 12 bytes
before the frame base. So last four bytes, they are in memory and the value 30 which is 12 bytes
below the frame base. This is the text which gives which defines piece operators, which defines
the piece operations and there is also definition of compatibility rules for the world version five.
There are three rules. Now, if you look at the, look at the code well, we have three
compatibility rules. The point I'm trying to make here is that for some people looking at this
maybe easier to understand and the purpose is to help these people.
There's a web playground. This was contributed by Scott Lindner from AMD, so full credits goes to him.
And I thank him very much. In the web playground, you can do step by step.
So here you type the context, you type the expression and then it evaluates. Here's an example.
In the AMD context, I'm going to evaluate DWOP lit 5 DWOP lit 8 DWOP plus DWOP lit 3 and then let's say multiply.
And then I evaluate. This shows you the state of step by step. So here's the state of the
stack and then we evaluate this. We get this stack state and so on until and we end up with the value.
In the web, let's try it again. So I should have opened this already.
I'm going to show you another example. The same example from the actual spec,
but done in the web playground. What we see, here's the same example.
The expression there and when I evaluate again, it goes step by step and then we end up with a location on
top of the stack. This is the result. I just cut it from there and then again you can see the
correspondence between what the spec explains and what we end up with. This is a composite location.
There's actually a DWOP issue where which defines a new operator. Overlay.
I'm finishing and here there are some examples and here you would see links like this.
You can just open it, evaluate it and you can see what the example is named. So this is another
use case where such a tool could be useful.
I present to you, I present to you the Wurf evaluator. To learn or teach, to understand the
Wurf expressions, I think it's useful. I want to thank my managers for allowing me the time to work on this.
There are some notices and disclaimers. Thank you for reading and with that I conclude.
Why is not in GDP? So the goal here is that it's lightweight. You just take it and we're
not having to go into the details of a full-fledged compiler or a debugger you can just run it and
experiment with it easily. Thank you.