 Hello, I want to start this presentation. Can you hear me well? Thanks. I want to start this presentation with a simple question. Do you know that in a Linux system, only the kernel and the browser has much more lines of codes than the compiler that was used to build those tools? How many lines of code do you think that a compiler usually has? In this case, GCC compiler. I was in the other presentation, and it was a nice graph about we have more than 25 millions lines of code today in the kernel. So any guess for GCC compiler? GCC compiler is around 50 millions lines of code. Last night, I ran a simple test for a git analysis of the repository. I cloned it straightforward, git clone. Do the analysis. And this was a nice graph with matplotlib that was generated. Sorry, git ingenieplot. And it came to me the reason of why I started this presentation with this graph. A week ago, I was reading this article, how much does a compiler cost? And it's a nice blog talking about the importance of a compiler in today's world. How much a compiler can affect our lives and how much a compiler can transcend to the performance, security, and functionality of the software that we build every day. The tool that I use with git stats. On the graph, we can see that every year, the lines of code, yes, there was a cleanup. Yes. At some point, yes. There is always a bot in the graph. I know that. But the numbers of lines of code that we have seen in the last, I don't know, four or five years has been amazing in terms of how much increment on lines of code commits a new feature unimplemented for our compilers every year. I'm not going to show all the patches that are outside. I'm just going to try to show you some of the useful tools that the compiler and the being-utils or GLC already have by now in the last two, three years. And this is a story that I want to connect with you in terms of my personal story. Before being a compiler developer and linker developer, where it's the two communities that I work more, I used to work in a hardware store with my parents. And it was nice that every carpenter or every hardware came to me and said, hey, I need a tool for this kind of activity. So I needed to look in the catalog and search for the best tool that fulfills the needs for that person. Little is the same of what we have here. I was looking for a definition of a tool change. The tool change is a bunch of tools that we give to the software developers so that they can build much more complex system and launch it to our world in different ways. We have seen since today keynotes how Linux exchanges the world in terms of graphics, data analytics, big data, and more things. So what is a tool change today? We know GCC. We know G-Lipsy. But there are much more stops. We need to have a debugger. Without a debugger, it's almost impossible to think that we can go and develop. We need to have a linker. Once the process is running on our operating system, we need to link the libraries that we're going to be using. The assembly or disassembly. In this case, it's a GNU gas that we have. The binary utilities. GNU being utils. Emulator libraries. The standard C library. Whether we like it or not, it's there. And yes, there are much more options. And we love G-Lipsy because it's always there for us. Otherwise, we will be having to develop the sign and co-sign by ourselves every time that we need it. And of course, yes, the compiler is the first one that we use mostly. So what have we built with these tools? Almost the world. We have built operating system kernel, image processing libraries, web server-side script language. PHP is built with GCC by definition. We built OpenCB. We built the kernel. You name it. There are many projects that are de facto compiler right now. And yes, I have very good friends in Clank, C-Lank, and LLBM. Yes. And as Greg said one day, we love the fact that there are much more people trying to develop another tool change. It forces us to be better as a community and also give us the capability to have much more options. We love the idea. We are friends, the two communities. So the first tool that I want to talk to you, it's about security. In the morning, Ariane was talking about security de facto. There is no way that we can argue with customers to say, well, I can give you good density or good performance, but security is going to be a luck. No way. Nobody wants to be attacked today by anything. First of the tools that I want to present to you is FC protection. There are many kinds of security vulnerabilities. We have seen security vulnerabilities in terms of hardware. I will not talk about those kind of things. I will need an entire slot of speech for that. But the kind of attacks that I will talk to you, it's about the return-oriented programming and call jam-oriented programming. Those are very horrible kind of vulnerabilities. Well, GCC-8 helps to fix those kind of things. This is a very simple Aero-P attack. For those that have never seen an Aero-P attacks, voila, this is a picture of an Aero-P attack. We will have a simple main with a simple function echo. And there is a secret function. Yes, I know. It's very simple. It's just for academic purpose. Nobody does this. Nobody calls a function a secret function. In the object, there will be very easy to attack. That function is like, come on, attack me. But it's just for academic purpose. So we will have a scan of a buffer. Whose size is 20? Yes, good. But with the scan, which is, by the way, when you compile it, the compiler by itself say, please don't use this thing. I mean, there are better things to read from the user space at a scan. This is a cool security, an entire hole in security. And we will see why for some of the audiences that have never seen an Aero-P attack. So if I run this pretty beautiful simple line to execute, I use Python just for the, I don't want to type too many times the same character. But what I'm going to do is print A 32 times. The 32 came out because 28 plus 4 is the 32 bits that are necessary to put my specific address where I want to go into the space of memory that I want to overlap and rewrite instead of the current return address that I used to have. That is the core of the return-oriented programming. The basis of that is the buffer overflow. So what I'm going to do is pass that string plus, at the end, another address, which in this case is the address of secret function. How do I know? Because with a simple object DOM, it was pretty easy to me to say, oh, secret function. So I need to go there. So hit number one, never put your secret function. And I pass that to my bold binary. So yeah, it's going to be very easy if you execute that into your Linux system. The only thing that I had to do was compile with minus M32. In M64, it's way much more complicated. It's possible to do the same thing, but for academic purpose, it's way much more complicated. On the slides that I will upload at the end of the presentation, there is the link of the source code that you can use and follow the same approach. So yeah, it put the 32 bytes in this bunch of As. And at the end, the address that I want to pass. And it will print, as we saw in the previous code. Congratulations, you have entered to the secret function. Nobody calls that function. Yet I'm able to do that. And you might say, well, that is not an AeroP attack. Yes, I know. But it's just the basic to understand how does it work. We can pass, instead of a simple address of a function that I want to execute, I can put much more execution things that I want that CPU to do. For example, in this case, I'm passing to E and X, the value of 10, and then returning. The point here of an AeroP attack is I can overwrite instead of going to the current flow that I used to have to wherever I want to go. And there are good friends over there that put shellcode database for static cases. So if you go to that web page, you will have Beam Bash or shell, or you name it. There are many kind of examples that you can use. And instead of passing the address of another function that you want to call, you can actually point to an binary that you want to execute. And you can get root privilege access to your system. You can do many harmful things with these kind of attacks. These are called gadgets. Well, GCC introduced a new option for these. FC protection, full branch return, and none. These kind of technology, it's based on something that we call control flow and force technology for a shorter name, set technology, which the good thing is that I think that will be available by this year in terms of CPU architecture. And there are two kinds of approaches for set technology. One we will see is a new instruction, and the other one is a shadow stack. How does it work, this kind of thing? The FC protection checks for a Bali-target address. And these will try to have an instrumentation inside your code and do two kind of things. In this case, it's preventing from the current return that you're trying to access, which detects that it's malicious, to the actual, that you're supposed to be going in that point. So I like this picture. Imagine that you have a single stack pointer and a program counter. So the program counter goes into the read or the scan. It has a stack pointer plus 20, and we have enough 20 spaces. And we start to write hello world at this point. And suddenly, we put, instead of the 804 or 8004 to 8001. So the stack pointer will go into here, the read, which is the next program counter where it will go, check the address of here, and will go straight forward to 8001. That is a picture of how does the return harm could happen into your binary. What this technology is trying to do, it's preventing the flow control to do an expected target. The text that, hey, wait a minute. You're supposed to go to 1004, and now you're going to 8001. How does it work in terms? Well, first of all, let's check what are the full options that we have. Full branch return and none. The value branch tells a compiler to implement checking on the branch, indirect branch instructions, for example, call or jumps instructions. The value return implements checking from a function. And the value full, it's going to be both of them, on the function and on the branch by definition. The value none will turn off this kind of implementation. It's put it just in case somebody wants to disable for debugging. The control flow technology, the set technology, it will have two things. The shadow stack and indirect branch prediction, indirect branch tracking, or IBT. The shadow stack will work in the next way. We will have a stack that will have a red address, and that red address is going to make, for example, in the stack a call to another function, or another jump, or another branch, or another whatever you prefer. At the end of the execution, we will have two return address, one in the new shadow stack and one in the another stack that it was supposed to have in the original place. We are creating a different kind of a stack, which is called the shadow stack, to compare the two return address. If, in this case, the vulnerability over a rope happens, it will detect comparing and saying, wait a minute, you're supposed to come back to this red address. Now you're telling me that you're coming to a different one. By having two stacks, we'll be able to detect if something in the execution, in the second stack, after the call jump, or whatever branch you prefer to jump, was doing some malicious code by both Herbal Flow, Aeropy Attack, or something else. So we will have two stacks, and we will save the two address in two places to say, OK, if there is a difference, something is screwed. Something is completely wrong, and I will award the execution of this point. The other thing is the indirect branch tracking. It literally adds a new instruction at the end of the branch. To check that the return code, it's actually go where it's supposed to go. And you might be wondering, wait a minute, what happened with my Haswell, Westmere, or any other hardware that is not with this instruction? Doesn't matter. If you execute this thing now, it will give you another operation. It's not harmful. We will need to wait for the real hardware to have that specific instruction. But to be honest, with the shadow stack, it's good enough for now. More information about this last year, and this is what we are trying to do in the tool change community. Last year, we joined to the Linux Plumbers for the very first time. And it was the moment that my friend HILU do a presentation about the set technology and into the Linux Plumbers. This year, there will be another micro-conference for tool change so that we can collaborate even more the two communities. Let's go for performance. Flop interchange. Well, I like this flag, especially. The flock interchange, it's kind of an optimization for the nested force that we have. It's by default enabled with minus O3, and you might be at the point. Victor, you were in the embedded Linux conference. We barely use minus O2. We mostly use minus OS because we want to do our binary small instead of faster. It was, and correct me if I'm wrong, that was true 10 years ago. Today, embedded, it's not only about size, but also about a speed. So let's take the first example. Imagine that you have a two-force, one of the, in this case, y is going to 100, and x is going to 1,000. Increasingly, increasingly, increasingly, increasingly, increasingly, going forward, forward, forward. And we will talk about doing a multiplication of x by y and assign it to the value that we have in this case, OK? What we want in software is this. What the actually hardware, it's going to be a little bit different. And we need to be aware of how does a loop stick. You might be wondering, well, if I do these one side or the other, it shouldn't affect to me. Actually, it does. We have a CPU, and we have a cache memory, and the main memory. Suppose that we have to go to the main memory for the real data to the cache memory as a beginning. What we are going to be reading with this approach is going to be k00, 1020, and 30. We read the memory by a bunch of data instead of like a line. So we will have, first, the CPU is going to have in cache these first lines from the main memory. And OK, it's nice. I have k0. Wait a minute. Now I need k1.0. So it's not in my cache line. I have to go for another cache line. So I have to go to the main memory, bring it back a different one, and discard this one. I spend CPU time going to the main memory, bringing it up to the cache, and not using just for one single unit. Memory facts. When the processor access to an array element, for the first time, it retrieves an entire cache line of data from the main memory to the cache. If the rest of the data is not used, sorry, if the rest of the data will be used soon, this is a major performance bust. So the most amount of memory that we use in the cache that was bringing it from the main memory, the best that is for us, because we spend time, power, and anything going to the main memory and bringing it to the cache. So it's better that we use that amount of data. If, on the other hand, we only use very few in the, like in my example, only one of the elements from the line that I used to have, it's a performance lost. So when we apply the F loop interchange flag, the code is transformed. And now we have x1000 here and y to the 100. So the approach is different. Now it's going to be k0, k01, k02, k03, and there it goes to the k, to the k, almost 1000. So what happened in hardware is that now I am able to access to k00, k01, k02, k03, which is in the same cache line that I have over here. So I don't have to discard of this cache line, go back to the main memory and come back to cache 2. I can use much more of my memory that I have in my cache instead of going that many times to the main memory. So highly recommended to use this F loop interchange. It's one of the main reasons why it also with minus o3 in GCC give a very good performance. Not everything it's about vectorization, also about the way that how do we access to memory cares. Got hoisting optimizations. Partial redundancy elimination, PRE. At this flag I see it's going to check my code and tell me where did I was very dumb and didn't realize that it couldn't be better. I joke with my students, I forgot to mention, I give compilers basics on university at hometown. And I joke sometimes the compilers are a little bit more smart than me, smarter than me, sometimes, just sometimes. This is one of the cases. Eliminates unnecessary codes that it's not being executed. Let's take this very simple example. And I did it yesterday for just academic purpose. Don't judge me. I know that I suck at coding. So let's go. We have a test function in A, B, C, and G. We defined D and E as any integers. We check if A, anything different than zero, we go into this path or this branch. Else we go to another branch in this case. And D, it's going to be B minus E. It's going to be B multiplied by C. I can see that if I calculate one time, I can reuse in the other case, plus G. And the end, the return is going to be the value that I have even for D that will diverge according to A plus E, which will be only accessible in the case of the else. If I go into this one, it's going to be zero. If I defined it here before or anything else. And I'm going to pass one, two, three, four, not because it's important for the code, because it was very easy for me to put it there when I was coding yesterday. Well, F code hosting, it's on minus O2 optimization level. Remember, for compilers, I forgot to mention, the optimization is like an onion. We have layers. So O0, it's no optimization. O1 is just the very beginning of optimization. O2 will be O1 plus something else. O3 will be O1, O2 plus something else. And that's the limit. We don't add O4. There was a discussion in the GNU compiler list and say, do we need an O4? And we say, no, no, no, O3 is good enough. We don't want to have that more layers, not a cake. Also, this flag, it's important to mention that it's in minus OS, okay? So it's also possible to use these for doing a small, OS stands for small binaries that we want to generate. So these are the object dumps of the same test function executed in my Linux system. And let's go straight forward. In this case, with GCC hosting minus O1, which will avoid the use of that specific flag, I'm doing, in this case, two times the multiplication, doing a comparison, and then doing the addition, okay? I'm sorry, the comparison is here. And then doing the addition of this case, at the addition that we see at the end of D plus E. In this case, with hoisting minus O2, we are just doing one single multiplication and the addition over here. We are reducing the amount of times that we are doing the multiplication by definition and doing way much more or less comparison, okay? So hoisting is gonna transform, first of all, yes, it transformed the code that I'm going to pass to the CPU and it also eliminates redundancy in terms of how many instruction the CPU needs to generate. The compiler is the last defense against bad code to the actual CPU. CPU are not that smart. They will only execute in every time that a scheduler deploy a process, all the code that we want. So it's the responsibility of the compiler to provide the best code to the CPU. This is another one, and this is not for the compiler. This is for the DG Lib C. I was joking before about whether we like it or not, G Lib C. G Lib C is one of the heroes that we have in our back supporting us every day. It has all the sine, cosine, mathematical things, POWs, all the things that we will not be willing to do every day, it's there, right? One of the optimization that happened in the last G Lib C, it was introduced in November, December of last year, is the optimization for sine and cosine. I'm not a mathematical guy, so I don't know who needs sine and cosine at the same time, but there is a function for that. No, trust me, I didn't want to ask in the community so they will throw me potatoes, but yes, there are somebody outside in the industry that needs sine and cosine at the same time. And what is happening right now, it's instead of doing the approach by difficult assembly instructions, and you can see the patches, I put the links in the presentation, the elimination that HLU did for sine and cosine before this optimization to after this optimization, it's huge, it's huge, right? And he's not using vectorization or, yes, he's doing function, fuse multiplication addition, but the reason why he's doing fuse multiplication addition is because he's using the Taylor approximation. So now sine and cosine from G Lib C to 2.29 is gonna use Taylor approximation for going into them to know exactly the value that I'm asking for. I passed to the sine and cosine function the angle that I want to, or the radian variable that I want to calculate for sine and cosine. He needs to, he needs to returns to me the value of sine and cosine. That's the only job that has to do. Well, and now instead of doing with heavy mathematical things, it's gonna go with Taylor approximation, which is to be completely honest, divisions, multiplications, nothing that complicated, okay? And there are good papers outside that proves that actually this is a very close to what we used to have. Remember, Taylor approximation or polynomial P algorithm approximation, it's, I'm gonna try to be as close as possible to a function, which in this case is sine of X, using this kind of polynomial approach, the larger that the polynomial becomes, the closer that it goes to the sine of this in this case. There are some advantages of having this kind of improvement for the polynomial method. The memory requires necessary to implement, it's quite a small. So the amount of memory reduced by this improvement, the numbers for the performance improvement are on the patch, but goes around, for example, in terms of performance of execution from 20 to 40% in the micro benchmark that was rented, because yes, we have to prove that it has a performance improvement when we accept the patch. So Hulu, who is the guy to send this patch, put it on the commit, how many, the amount of performance that was gained because of these. Only requirement application addition and subtraction of floating points numbers, which is not very much CPU cycles. It's part of, I put on the presentation will be the link of where is the library that is doing this thing. But yeah, before going to the developer experience, this is one of the core things that we don't see every day, but it's there for us, right? So the first call of action is trying your operating system or in your deployment to use the latest technology that we as a tool change community deploy for you. There is a very hard work for doing that and that you can use it. The developer experience, I definitely like this one. It's my favorite in all the presentation. Had somebody realized that since the latest GCC, they defined that, hey, you don't know how to spell color. So I'm going to show you that it's color, not color, GCC detects that. And the amount of job that has to happen in the back end of GCC, it's huge. Just for us to let us know that we're spelling wrong. Sorry? Yeah. Yes, in this case, yes, I spell the decoration for this one. So the smarter fixed skins, it's included by definition in all the GCC. I mean, only, I don't know any distribution right now that remove these flux when providing the compiler. If it's providing, for example, Fedora, it's using this one. And I think that Ubuntu is also enabled in the latest version. Well, even, and you might be saying, well, that case is very simple. I mean, it's a simple typo and things like that. No, it goes way much more on typos. And for a small project for a simple few thousand of lines of codes, no more than 100, it's fine. But what happened when our, how many lines of code usually a production system based on C has? More than 100, more than 200. Increasing the lines of code in C is very simple. Very simple, right? You blink one day, you wake up the next weekend, boom, 200 lines of codes, right? Well, if diagnostic generation patch, make the patch for you. So even if you have a huge warning errors, whatever you want, run that flag and it will generate the patch for you. So you can get AM, the file, and fix all the things that you have wrong in your code, okay? So yes, come back to the font that we used to have. Can I just literally hit randomly something and the compiler will fix it for me? Yes, we arrive to the point in the future when the compiler can fix it for you. You just need to apply the patch. The next steps that we're talking in the communities, should we put a flag that say apply the patch for me? Or, now if diagnostic, it's another one, we've put a format, where it possible to select a different kind of format that we want to print. Format is text or JSON. And the reason why we added JSON as a format example for our case is because it's easy for later to post-process, right? Imagine this developer system into your teams or for your personal experience where you have warnings and instead of going one by one, you can create an smart algorithm that select them or cluster them or give you a, goes into a dashboard, anything you want. The old days where I sit in my computer, develop the code and magically after fairs comes to my mind and happened the magic is not longer what we do every day. It's a continuous integration, continuous deployment system that we have to deliver to customers in less than a month. How many months do we have for deploying an IoT system? Around three, things like that. Means really fast amount of time that we need to spend for deploying. So if we say gccdiagnostic.c in this case, this C example has some mistake and we run fdiagnostic format JSON, it will generate the JSON format in a different approach than just in the text. If I pass that through a JSON reader, for me it's way much more easy to read and for another tool to classify your cluster and things like that. Oh, and maybe the last one. I don't know how much time do we have but the last one is F3 switch conversion. We have a simple full function with switches two, three, four, five, six and the variable how it's gonna be later assigned it to 205, 305, 405, five. As a human, we can easily see that, hey, wait a minute, it's two multiplied by 100 and not five. Well, now the compiler can detect that. This is a snippet of the code of the test case that was added to the compiler in GCC night and now it transformed that into this linear function. 100 multiplied by half plus five, for this example. If I change instead of five to eight, it will detect eight, okay? So it's not hard coded, it's just for this example. And these are the object dumps because in the beginning when I realized that and in the main list, I didn't believe it. So I have to test it by myself. It's too pretty cool to be real. So yes, the full function, this is the full function without using that one, that flag, in this case, the F3 switch conversion. It's a lot of jumps, movements, jumps, additions. And this is if I add this flag. If I add this flag, I will do a multiplication and an addition. Here you will see the I mole and the I and the F exactly as I describe it here. Yeah, that's a great question. The part of generic in this term is, it has to have at least this kind of approach. We have to have an element that will be, an element that will try to take a variable plus here could be an addition, multiplication, deviation and things like that. It tries to be as much generic as possible. Remember, in the tree of the compiler, we have the lexical analyzer, the syntax analyzer, the semantic analyzer, then we generate intermediate code and then composite optimization. This is the part when the compiler sits and say, what can I do in this term? So it's as generic as we try to do it. It's not perfect, but we're trying to improve it. So yeah, as you can see, it's pretty magic in terms of, hey, I used to have this bunch of instruction that was going to be passed to the CPU and now I'm all in that and detects the logic that I maybe didn't realize myself because if I would be able to realize myself, I will not code this switch in the first place, okay? And there are more, okay? There are much more things that we can do with the latest technology. For example, FNL Diagnostic Showline numbers, pretty easy for debugging. A warning for allocation, learning and that and you put an equal here and you can pass the number. So imagine that for your embedded application, you want to check if I have an allocation more than a specific lines of, a specific amount of bytes. I will be able to do, to detect those ones with WL of larger than equal to 1024 or 2048, things like that, okay? There is also a pretty system, new system calls in JLFC 229, get CPU, get CPU will print me the CPU and the NUMA node where my application is standing. So I'm pretty sure that for embedded also for servers that it's pretty useful. If I'm able to know where am I standing? Remember, this is a wrapper that used to be in the kernel. Yes, now it's a system call, okay? If you Google search for get CPU, yes, it will find out that it has been in Man Linux page years ago in kernel space. Now we have a pretty an amazing system call that we can use in user space, okay? I want to close this part with this picture, taking advantage that we are in San Diego and there is a nice front water close to us with nice boats, I like boats by the way. GCC, JLFC, Bing Utils and all the tool change team together, we want to say that we are happy to produce more tools for you so that you can propel the software development that you do every day. And of course the LLVM and C-Line community is more than happy to develop those kind of tools so that you can create way much more things. Use the latest version, find box in our approaches for optimization, complain to us and say, hey, could you please do it this more generic? Yes, I can try to do it much more generic. Or have you think about this warning? Today in the morning somebody called me and say, we are friends many years ago and we say, is there any way that we can make much more easy to get the profiling information from the kernel on boot time from the debugger? And I was like, hmm, I don't know, could be a nice plugin, but I haven't thought about it. So when I came back, I might talk with some of my friends on the clean or Hulu about that kind of plugin. We are here to communicate to you that we can listen your needs based on your daily jobs that you have. Example of that operating system that I'm part of the community, is the Clay Linux operating system project. We have much more information on these webpages about GCC7, GCC8, all these examples are over there in code and with much more details. And there will be a GCC9, GNPC3229 tool change block also over there in that webpage. So all the code, all the comments, all the things that I present in there are a summary of these three blocks that will be public. The last one will be public in a few weeks, maybe two weeks. That's a backup, that's supposed to be say thank you. Yeah, that's a backup, thank you. I don't know how much time do we have, do we have time for questions? Yes, can you let me pass the microphone because I have problems hearing, sorry. Yeah, thank you. Oh yeah, that's a good question. So, Code Hoisting tried to, for example, detect these kind of uses of multiplication and assign to a variable and a split into maybe two or more but using less amount of variable. In, yeah, less amount of reuse as much variable. For example, in this case we'll say B multiplied by C will be assigned to D and replace these one by D in the case detecting that one it's always going to be in one, in that case. Detect that one is going to be not passing by a common line interface and go straight forward. That is the approach for that one. For the other one, I haven't tested much. The other kind of reducing of code that you mentioned. So, okay. Yeah, I will need to do that experiments because I didn't test Code Hoisting in that approach in a four or taken out of a four loop. I realize that it reduced the amount of code in my case or change it but I was not aware of that. Thank you. I will investigate about it. Yeah, can you? Yeah, I'm going to pass you the microphone. It's way much better. So, when you have an architecture that uses a register for return address like ARM, so you have LR register to keep return address, yeah. FCF protection, does it take into account scenarios or architectures which use register to hold return address? And I need to talk to you about how set it's going to be. Right, so in that case, that return address ultimately goes on the stack if there's nested function calls. So, if a function calls. Oh, for the nested. Yeah. Yeah. So, the set of a stack and the branch and the extra instruction to be the only solution. So, it will have a stack and double a stack and double a stack and double a stack, yeah. And if not, it doesn't work. Things, the return address instruction at the end of the branch that you have. Thanks. Yeah. Any other question? Oh, yeah. Yeah, yeah, it's good log. Good log, we're trying to convince him with that part. The set technology is the first step on that to having the IVT instruction to detect these kind of errors for for security but limit is the first, one of the first approaches. The set technology will be enabled for Sion and other ones at the end. I think, don't take me by heart reading but it's supposed to be in this year, posted. Well, but for that case, the problem is how long do you go to the, how deep do you go? But that is the problem as well. How do you lock it down as before? Yeah, because in the very simple example that we have over here with the hello word, yes, we said a stack pointer minus 20 but how do we know that it's not minus 40, minus 400? Any other question? If not, thank you so much for your time. Really appreciate it.