-
Notifications
You must be signed in to change notification settings - Fork 60
feat: Add TO_<CHAR,STRING>
functions
#1355
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
This commit introduces the `TO_CHAR`, `TO_WCHAR`, `TO_STRING` and `TO_WSTRING` functions, all making use of already existing `X_TO_Y` functions.
@@ -701,12 +702,10 @@ impl AnnotationMapImpl { | |||
|
|||
/// annotates the given statement (using it's `get_id()`) with the given type-name | |||
pub fn annotate(&mut self, s: &AstNode, annotation: StatementAnnotation) { | |||
log::trace!("Annotation: {annotation:?} @ {s:?}"); |
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.
fyi I've previously introduced these trace statements but in hindsight I have to admit they're not as useful as I imagined (i.e. they're waaaaay too bloaty). A better approach would be a more concise representation but that's something I'll address (or not, who knows) when I have the pleasure to debug resolver bugs again :^)
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.
soonTM
END_FUNCTION | ||
|
||
FUNCTION TO_CHAR__STRING : CHAR | ||
VAR_INPUT {ref} |
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.
The {ref}
here is no longer necessary, since aggregate-type arguments are now always passed as pointers. Not blocking, we should probably change these for all occurances in the `stdlib
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.
Lets address this in another PR since I also forgot to remove the code-gen python scripts.
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 am confused, why would Aggregate types be implicitly pass by reference that isn't how it works in Codesys. They are passed by value unless you explicitly pass by reference or use a Reference to or Pointer type.
Changing this would may break alot of existing code that can be converted over from codesys.
In well written code this should not be an issue since in a single task application because it is a bad practice to modify variables that are passed in by value, but this could cause issues with variables that are used across tasks. Aggregate types are not copied atomically as far as I know but after they are copied they are expected to not be mutated outside the function.
Maybe I am missing somthing?
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 would be an implicit reference that the user would not see. I don't know the codesys internal representation but I strongly suspect they would also do something similar for chars and string.
There are multiple reasons to do this but mainly it's because that's what C and llvm usually expect but also compile time performance since the alternative would cause us to preallocate values on the call stack and we previously had compile issues with that. The effect of this is as mentioned transparent for the user in PLC. The C function would however have an additional parameter.
What we do internally to preserve the by value behavior is to actually allocate a new variable on the stack and pass a pointer to that variable
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.
Oh ok, so are you saying there would be a new variables allocated on the heap, and then the value would be copied in to it? Ok I think I am following how that makes sense.
Thank you for the explanation.
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.
Still on the stack, just allocated at runtime because allocating/returning at compile time was very slow during the optimisation passes / binary generation pass
https://llvm.org/docs/LangRef.html#alloca-instruction
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.
Here's some more context on why this is usually needed:
https://stackoverflow.com/questions/11656532/returning-an-array-using-c
Technically it's not required for structs but it made our lives easier there.
Edit: I got something confused here, I gave an example with returns in mind, but these are parameters, the same issues still apply.. we do indeed copy the values before passing them using a memcpy but it's still all on the stack.
https://llvm.org/docs/LangRef.html#llvm-memcpy-intrinsic
This is an equivalant C application with a struct and a string allocated on the stack using this method:
#include<stdio.h>
typedef struct {
int x;
int y;
} MyStruct;
void func(MyStruct* str) {
str->x = 1;
str->y = 2;
}
void stringExample(char* arg) {
sprintf(arg, "Hello, World!");
}
int main() {
MyStruct str;
printf("Before: x : %d y: %d\n", str.x, str.y);
func(&str);
printf("After: x : %d y: %d\n", str.x, str.y);
char helloWorld[14];
stringExample(helloWorld);
printf("%s\n", helloWorld);
return 0;
}
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.
Also for context, I think the graph speaks for itself but the big reduction in compile times (oscat) was due to that internal change https://plc-lang.github.io/metrics/
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.
Here's some more context on why this is usually needed:
https://stackoverflow.com/questions/11656532/returning-an-array-using-c
Technically it's not required for structs but it made our lives easier there.Edit: I got something confused here, I gave an example with returns in mind, but these are parameters, the same issues still apply.. we do indeed copy the values before passing them using a memcpy but it's still all on the stack.
https://llvm.org/docs/LangRef.html#llvm-memcpy-intrinsicThis is an equivalant C application with a struct and a string allocated on the stack using this method:
#include<stdio.h> typedef struct { int x; int y; } MyStruct; void func(MyStruct* str) { str->x = 1; str->y = 2; } void stringExample(char* arg) { sprintf(arg, "Hello, World!"); } int main() { MyStruct str; printf("Before: x : %d y: %d\n", str.x, str.y); func(&str); printf("After: x : %d y: %d\n", str.x, str.y); char helloWorld[14]; stringExample(helloWorld); printf("%s\n", helloWorld); return 0; }
Ooooh I understand now. I never really considered being able to dynamically allocated to the stack. So now that I understand that part. So I am following whar is happing now.
Thank you for the explanation!!! Very much appreciated sorry to derail your PR discussion.
This commit introduces the
TO_CHAR
,TO_WCHAR
,TO_STRING
andTO_WSTRING
functions, all making use of already existingX_TO_Y
functions.EDIT: There's some issue with printf() statements giving incorrect validation errors, which needs to be fixed before this can be merged.