I have been seeing code like this in submissions at leetcode.com and I don't understand it. My unfamiliarity with the syntax has made it hard to search for an explanation.
static const int _ = []() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
return 0;
}()
I gather that the I/O calls are an effort to increase execution speed. What I am not grasping is the syntax- is this a function definition, or a lambda expression? How is this code ever executed?
This is lambda syntax, so what they're doing is creating a c++ lambda which performs the code above and evaluates it, then stores the result as a static const int. More information here: https://en.cppreference.com/w/cpp/language/lambda
My best guess is that this function will be evaluated first before main is called as static const values are initialized prior to starting the program. It seems like a hacky version of a state initializer for stdio.
Related
PROBLEM:
I currently have a traditional module instrumentation pass that
inserts new function calls into a given IR according to some logic
(inserted functions are external from a small lib that is later linked
to given program). Running experiments, my overhead is from
the cost of executing a function call to the library function.
What I am trying to do:
I would like to inline these function bodies into the IR of
the given program to get rid of this bottleneck. I assume an intrinsic
would be a clean way of doing this, since an intrinsic function would
be expanded to its function body when being lowered to ASM (please
correct me if my understanding is incorrect here, this is my first
time working with intrinsics/LTO).
Current Status:
My original library call definition:
void register_my_mem(void *user_vaddr){
... C code ...
}
So far:
I have created a def in: llvm-project/llvm/include/llvm/IR/IntrinsicsX86.td
let TargetPrefix = "x86" in {
def int_x86_register_mem : GCCBuiltin<"__builtin_register_my_mem">,
Intrinsic<[], [llvm_anyint_ty], []>;
}
Added another def in:
otwm/llvm-project/clang/include/clang/Basic/BuiltinsX86.def
TARGET_BUILTIN(__builtin_register_my_mem, "vv*", "", "")
Added my library source (*.c, *.h) to the compiler-rt/lib/test_lib
and added to CMakeLists.txt
Replaced the function insertion with trying to insert the intrinsic
instead in: llvm/lib/Transforms/Instrumentation/myModulePass.cpp
WAS:
FunctionCallee sm_func =
curr_inst->getModule()->getOrInsertFunction("register_my_mem",
func_type);
ArrayRef<Value*> args = {
builder.CreatePointerCast(sm_arg_val, currType->getPointerTo())
};
builder.CreateCall(sm_func, args);
NEW:
Intrinsic::ID aREGISTER(Intrinsic::x86_register_my_mem);
Function *sm_func = Intrinsic::getDeclaration(currFunc->getParent(),
aREGISTER, func_type);
ArrayRef<Value*> args = {
builder.CreatePointerCast(sm_arg_val, currType->getPointerTo())
};
builder.CreateCall(sm_func, args);
Questions:
If my logic for inserting the intrinsic functions shouldnt be a
module pass, where do i put it?
Am I confusing LTO with intrinsics?
Do I put my library function definitions into the following files as mentioned in
http://lists.llvm.org/pipermail/llvm-dev/2017-June/114322.html as for example EmitRegisterMyMem()?
clang/lib/CodeGen/CodeGenFunction.cpp - define llvm::Instrinsic::ID
clang/lib/CodeGen/CodeGenFunction.h - declare llvm::Intrinsic::ID
My LLVM compiles, so it is semantically correct, but currently when
trying to insert this function call, LLVM segfaults saying "Not a valid type for function argument!"
I'm seeing multiple issues here.
Indeed, you're confusing LTO with intrinsics. Intrinsics are special "functions" that are either expanded into special instructions by a backend or lowered to library function calls. This is certainly not something you're going to achieve. You don't need an intrinsic at all, you'd just need to inline the function call in question: either by hands (from your module pass) or via LTO, indeed.
The particular error comes because you're declaring your intrinsic as receiving an integer argument (and this is how the declaration would look like), but:
asking the declaration of variadic intrinsic with invalid type (I'd assume your func_type is a non-integer type)
passing pointer argument
Hope this makes an issue clear.
See also: https://llvm.org/docs/LinkTimeOptimization.html
Thanks you for clearing up the issue #Anton Korobeynikov.
After reading your explanation, I also believe that I have to use LTO to accomplish what I am trying to do. I especially found this link very useful: https://llvm.org/docs/LinkTimeOptimization.html. It seems that I am now on a right path.
I got the following code snipped.
bool parseTool() {
string name;
string version;
static /*!!*/ AttrMap attrMap = {
{"name", Attr([&](const string &val)->bool{name = val;return true;})},
{"version", Attr([&](const string &val)->bool{version = val;return true;})},
};
return parseAttributes(attrMap);
}
The attrMap is declared static and lambda functions capture variables from the stack of the parseTool.
Compilation produces no errors and executable runs happily, up to some point, when it starts producing trash. Of course, removing 'static' fixes the 'trash' issue (probably making name and version static will fix it too, but i have not tried it). I do not understand what does compiler capture in this case when the static attrMap is initialized.
The question is, why did not compiler complain about it? Is there anything in the standard which would mark this case (I could not find one)? What does compiler do there?
I was running gcc-7.2.8 with -std=c++17 on linux.
The compiler has no way of knowing that the references you are capturing will no longer be valid the next time the lambda is called or even if the lamda will ever be called again.
The code you have posted is dangerous and likely to fail but is perfectly valid according to the standard so the compiler is free to accept it without warnings.
To fix it capture the variables by value or make the lambda not static. Making the lambda static probably doesn't make much sense as creating a lambda probably isn't expensive in most implementations and depending how the lambda is used may be inlined away completely.
I'm doing a simple tutorial based around threads. In this exercise I am supposed to get threads to wait for each other.
I have copied the example code verbatim with the exception that I'm not using namespace std; and am instead writing in std::each time I need it.
The error in question corresponds to the line:
if (condition.wait_for(std::unique_lock<std::mutex>(mut), std::chrono::seconds(3)))
Intellisense tells me that "the expression must have bool type (or be convertible to bool)" but I looked up the documentation on condition.wait_for and it can return std::cv_status::timeout, std::cv_status::no_timeout as well as true and false. When I go to build, it thinks it can only return std::cv_status.
It should work right? Does it require the third parameter? The example I'm following doesn't use one.
As Bo says, there are 2 versions of the function. I'm going to assume there was a typo in the example and it meant to use the version of the function with three parameters, here's some working code, I don't know if it works in the same way as the example intended.
if (condition.wait_for(std::unique_lock<std::mutex>(mut), std::chrono::seconds(3), [] {return true; }))
I was looking over some example functions and methods (I'm currently in a C++ class), and I noticed that there were a few functions that, rather than being void, they were something like
int myFunction() {
// ...;
return 0;
}
Where the ellipses is obviously some other statement. Why are they returning zero? What's the point of returning a specific value every time you run a function?
I understand that main() has to be int (at least according to the standards) because it is related (or is?) the exit code and thus works with the operating system. However, I can't think of a reason a non-main function would do this.
Is there any particular reason why someone might want to do this, as opposed to simply making a void function?
If that's really what they're doing, returning 0 regardless of what the function does, then it's entirely pointless and they shouldn't be doing it.
In the C world, an int return type is a convention so that you can return your own "error code", but not only is this not idiomatic C++ but if, again, your programmer is always returning 0, then it's entirely silly.
Specifically:
I understand that main() has to be int (at least according to the standards) because it is related (or is?) the exit code and thus works with the operating system. However, I can't think of a reason a non-main function would do this.
I agree.
There's a common convention of int functions returning 0 for success and some non-zero error code for failure.
An int function that always returns 0 might as well be a void function if viewed in isolation. But depending on the context, there might be good reasons to make it compatible with other functions that returning meaningful results. It could mean that the function's return type won't have to be changed if it's later modified so it detects errors -- or it might be necessary for its declaration to be compatible with other int-returning functions, if it's used as a callback or template argument.
I suggest examining other similar functions in the library or program.
It's a convention, particularly among C programmers, to return 0 if the function did not experience any errors and return a nonzero value if there was an error.
This has carried over into C++, and although it's less common and less of a convention due to exception handling and other more object-oriented-friendly ways of handling errors, it does come up often enough.
One more issue that was not touched by other answers. Within the ellipses may be another return statement:
int myFunction() {
// ...;
if (error)
return code;
// ...;
return 0;
}
in which case myFunction is not always returning 0, but rather only when no error has occurred. Such return statements are often preferred over more structured but more verbose if/else code blocks, and may often be disguised within long, sloppy code.
Most of the time function like this should be returning void.
Another possibility is that this function is one of a series of closed-related functions that have the same signature. The return int value may signal the status, say returning 0 for success, and a few of these functions always succeed. To change the signature may break the consistency, or would make the function unusable as function objects since the signature does not match.
Is there any particular reason why someone might want to do this, as opposed to simply making a void function?
Why does your mother cut the ends off the roast before putting it in the oven? Answer: Because that's what her grandmother did. However, her grandmother did that for a simple reason: Her roast pan wasn't big enough to hold a full-sized roast.
I work with a simulation tool that in its earliest incarnations required that all functions callable by the simulation engine must return a success status: 0=success, non-zero=failure. Functions that could never fail were coded to always returned zero. The simulation engine has been able to accommodate functions that return void for a long, long, time. That returning an integer success code was the required behavior from some previous millennium hasn't stopped cargo cult programmers from carrying this behavior of writing functions that always returning zero forward to the current day.
In certain programming languages you find procedures and functions. In C, C++ and similar languages you don't. Rather you only have functions.
In practice, a procedure is a part of a program that performs a certain task. A function on the other hand is like a procedure but the function can return an answer back.
Since C++ has only functions, how would you create a procedure? That's when you would either create a void function or return any value you like to show that the task is complete. It doesn't have to be 0. You can even return a character if you like to.
Take for example, the cout statement. It just outputs something but not return anything. This works like a procedure.
Now consider a math function like tan(x). It is meant to use x and return an answer back to the program that called it. In this case, you cannot return just anything. You must return the value of the TAN operation.
So if you need to write your own functions, you must return a value based on what you're doing. If there's nothing to return, you may just write a void function or return a dummy value like 0 or anything else.
In practice though, it's common to find functions returning 0 to indicate that 'all went off well' but this is not necessarily a rule.
here's an example of a function I would write, which returns a value:
float Area ( int radius)
{
float Answer = 3.14159 * radius * radius;
return Answer;
}
This takes the radius as a parameter and returns the calculated answer (area). In this case you cannot just say return 0.
I hope this is clear.
I have several functions in a program I'm writing that use a value I need to calculate with a very slow function. This value will change every time the program is rerun, so I can't just store a static value. Below is an example.
void this_gets_called_frequently()
{
static int value = slow_function();
//do stuff with the above value
}
My main problem here is not one of the program not working, rather of neatness. I don't really want to initialise a global variable and store the value in that, since it is not going to change once calculated. Would using the static keyword in the manner shown above only call the function above to be calculated once? Would a const keyword added in there help?
Thanks everyone, this was answered perfectly!
Yes, an initialization of local static variable will happen at most once (although I recall some compiler versions could have problems with multithreading here).
const is not required, in this case it's mostly a matter of readability and taste.
Would using the static keyword in the manner shown above only call the function above to be calculated once?
Yes, on the first invocation of this_gets_called_frequently
Would a const keyword added in there help?
No. But add const for documentation value.
Use may use the thread local variables from C++11, if they are available in your compiler. If you are on Windows, you can use similar TlsAlloc API. It is there since the dawn of Win32.