Kim | 19 May 2013 21:24
Picon

Export symbols for dll with clang/mingw on win

Hi guys, just trying to do a simple dll build using clang. The same code 
compiles using mingw gcc with a simple invocation like: g++ -shared -o 
test.dll test.cpp

Here are my arguments and the verbose output. I'm getting some undefined 
symbol errors.

-------------------------------------------------------------------------------------------
C:\Program Files (x86)\LLVM\mingwbuild\bin>clang++ -std=c++11 -shared -v 
-o test.dll test.cpp -I "C:\MinGW\include\sys" -I 
"C:\MinGW\lib\gcc\i686-pc-mingw32\4.8.0\include" -I "C:\MinGW\include" 
-I "C:\MinGW\include\c++" -I "C:\MinGW\include\c++\4.8.0" -I 
"C:\MinGW\include\c++\4.8.0\backward" -I 
"C:\MinGW\include\c++\4.8.0\bits" -I "C:\MinGW\include\c++\4.8.0\debug" 
-I "C:\MinGW\include\c++\4.8.0\decimal" -I 
"C:\MinGW\include\c++\4.8.0\ext" -I 
"C:\MinGW\include\c++\4.8.0\i686-pc-mingw32" -I 
"C:\MinGW\include\c++\4.8.0\tr1" -I "C:\MinGW\include\c++\4.8.0\tr2" -I 
"C:\MinGW\include\c++\4.8.0\profile" -Wl,--verbose
clang version 3.3 (trunk)
Target: i686-pc-mingw32
Thread model: posix
  "C:/Program Files (x86)/LLVM/mingwbuild/bin/clang++.exe" -cc1 -triple 
i686-pc-mingw32 -S -disable-free -main-file-name test.cpp 
-mrelocation-model static -mdisable-fp-elim -fmath-errno 
-mconstructor-aliases -target-cpu pentium4 -v -resource-dir "C:/Program 
Files (x86)/LLVM/mingwbuild/bin\\..\\lib\\clang\\3.3" -I 
"C:\\MinGW\\include\\sys" -I 
"C:\\MinGW\\lib\\gcc\\i686-pc-mingw32\\4.8.0\\include" -I 
"C:\\MinGW\\include" -I "C:\\MinGW\\include\\c++" -I 
(Continue reading)

Pedro Delgado Perez | 18 May 2013 19:17
Picon
Favicon

Re: ASTMatchers: isVirtual and isOverride

Hi,

Ok, Manuel. Thanks for your answers. I'm going to experment with all this.

Traversing the AST is super cheap compared to parsing the C++ code.

Hehehe, ok. It was only curiosity!


Sorry if I'm sounding harsh - I'm more than happy to help with any reasonable questions, but we've already taught you everything you need. In fact, you should have been able to learn all this without us - I myself have learned this mostly through experimentation, reading the documentation and the Clang source code. This is the way you can learn effectively.

Don't worry for this Gabor, you're right. Actually, most of the times I have already thought in some of the answers you give me, but what I want to know if there is a better way to accomplish that. Everybody here have helped me a lot and I'm very thankful for this.

Best regards


El dia 16 may 2013 12:37, Manuel Klimek <klimek-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org> escribió:
On Thu, May 16, 2013 at 12:30 PM, Pedro Delgado Perez <pedro.delgado-Ye0PmE2WaqY@public.gmane.org> wrote:
Hi,
You'll have one process(Decl*) method that does all the common stuff, and overloads for more specific types as needed, e.g. process(FunctionDecl*), which then call the Decl* overload by explicit casting. Have overload resolution work for you.

Ok, I think the best in my case is to have a process method per matcher, so don't take care of this anymore.

Now, I have other two or three questions spinning in my mind.

1. Imagine that I have two files to process in the same execution and both include the same header file. Will that header file's code be processed twice? In this case, how could I avoid this?

Yes. You don't want to avoid this, you want to fix it afterwards by deduplicating your results.
 

2. A matcher finds a CXXConstructorDecl node in a header file (we can call it X.h):
-first: I need to inform the cpp files that include X.h that the header has changed. How can I find that files? Up to now, I was only proccesing one file and searched for the file through Context->getSourceManager().getMainFileID() (That I suppose is the file which have the main method implemented, but I'm not absolutely sure). But now, I need to find another way to find these cpp files.

You'll want to write a matcher that matches all calls to the CXXConstructorDecl. 


3. Is there a way to stop the traversal of the AST in a certain moment when, for instance, I find what I was looking for?

No. Why would you want to do that? Traversing the AST is super cheap compared to parsing the C++ code.
 

Thanks in advance,

Pedro.


El dia 14 may 2013 21:13, Gábor Kozár <kozargabor-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> escribió:
I don't see the problem.
You'll have one process(Decl*) method that does all the common stuff, and overloads for more specific types as needed, e.g. process(FunctionDecl*), which then call the Decl* overload by explicit casting. Have overload resolution work for you.
Gabor


2013/5/14 Pedro Delgado Perez <pedro.delgado-Ye0PmE2WaqY@public.gmane.org>

Ok, what I'm trying to do is not to repeat the same code again and again in different methods (process_matcher1(), process_matcher2()...) For example, matcher1 and matcher2 are treated in the same way except in a little part.  At first, I thought of having a Decl* variable and casting the node result, but I'm not sure if this is a good option. Later, for instance, I need to use the getPreviousDecl() method that you told me and then I'll have to know the class type (or maybe I can cast to Decl* again).

Pedro.

El dia 14 may 2013 20:15, Gábor Kozár <kozargabor-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> escribió:
Hi,
> if (Result.Nodes.getNodeAs<clang::CXXConstructorDecl>("matcher1")) {

I usually do this:
if(const CXXConstructorDecl* ctor = Result.Nodes.getNodeAs<CXXConstructorDecl>("matcher1")) { ... }
> template<typename T>
void process(const T* Node) {

I would recommend against this. Template metaprogramming gives you no advantages here so far as I can see. Use overloading and polymorphism instead.
Gabor


2013/5/14 Pedro Delgado Perez <pedro.delgado-Ye0PmE2WaqY@public.gmane.org>

Hi,

Neither :) Just create an object in main(), and hand a pointer to that object to your callback - then call stuff on it from the match callback.

Ok, ok, that was the problem.

> 1. I create a MatchFinder.
> 2. Then, I add two different matchers to the same callback.
> 3. I call run. 
>
> My questions are:
> 1. How many times is called the run method? Every time the MatchFinder finds a node to match?

Yes, each time either matcher accepts a node.
> 2. The object callback I add to MatchFinder is created more than once? When it is deleted?

You (the user) are the one responsible for creating and destroying the callback object. Usually what we do is allocate it on the stack (and pass it the appropriate arguments, of course), and then pass its address to MatchFinder. MatchFinder doesn't create, copy or delete your callback object, so it is safe to store state in the callback.
> Could you explain better "if the second matcher has no deps on the information collected by matcher1"?

deps = dependencies

Gabor

Thanks for your answers Gabor.

I have decided to follow up the advice of Manuel and I have created a MatchFinder object with all the matchers and a single MatchCallback object. So now, I'm in my run() method and I want to know which matcher was bound. So I think the only way to know this is to ask:

if (Result.Nodes.getNodeAs<clang::CXXConstructorDecl>("matcher1")){
...
}
else if(Result.Nodes.getNodeAs<clang::CXXRecordDecl>("matcher2")){
...
}

Notice that I'm retrieving different classes of nodes (clang::CXXConstructorDecl, clang::CXXRecordDecl...) In spite of this fact, I want to process all the nodes in the same way except from a subtle difference and I was asking myself if there is a better way I can do something like this:

if (Result.Nodes.getNodeAs<clang::CXXConstructorDecl>("matcher1")){
  ...
 process(Result.Nodes.getNodeAs<clang::CXXConstructorDecl>("matcher1"))

}
else if(Result.Nodes.getNodeAs<clang::CXXRecordDecl>("matcher2")){
 ...
 process(Result.Nodes.getNodeAs<clang::CXXRecordDecl>("matcher2"))
}
...


template<typename T>
void process(const T* Node){
...
}

Regards,

Pedro.


El dia 10 may 2013 09:21, Gábor Kozár <kozargabor-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> escribió:
Hi,
> 1. I create a MatchFinder.
> 2. Then, I add two different matchers to the same callback.
> 3. I call run. 
>
> My questions are:
> 1. How many times is called the run method? Every time the MatchFinder finds a node to match?

Yes, each time either matcher accepts a node.
> 2. The object callback I add to MatchFinder is created more than once? When it is deleted?

You (the user) are the one responsible for creating and destroying the callback object. Usually what we do is allocate it on the stack (and pass it the appropriate arguments, of course), and then pass its address to MatchFinder. MatchFinder doesn't create, copy or delete your callback object, so it is safe to store state in the callback.
> Could you explain better "if the second matcher has no deps on the information collected by matcher1"?

deps = dependencies

Gabor


2013/5/8 Pedro Delgado Perez <pedro.delgadoperez-+o0oGDbj3PkxAGwisGp4zA@public.gmane.org>

Hi,

Thanks for all your support. I'm going to respond all your contributions little by little:

You can execute Matcher1 first, and when it returns, you start executing Matcher2. I'm not sure what your problem is exactly. (Of course, this will also mean that you will traverse the whole AST twice, which can potentially be very expensive.)

Ok. What I don't understand quite well is the order in the execution.

1. I create a MatchFinder.
2. Then, I add two different matchers to the same callback.
3. I call run. 

My questions are:
1. How many times is called the run method? Every time the MatchFinder finds a node to match?
2. The object callback I add to MatchFinder is created more than once? When it is deleted? The problem is that I create the object callback with an argument (a constructor method with an argument, not the default constructor) and store it in a variable member. However, when the run method executes, the value of the variable member is lost and I can't understand the problem.


Sorry, missed the comment in one of your more recent emails. So you basically want all matches by matcher1 to be found before all matchers by matcher2. I think the easiest way to do this is just have two MatchFinder classes. Add matcher1 and its callback to the first MatchFinder and call run(). Add matcher2 and its callback to the second MatchFinder and call run() after the first run() returns. You won't have to reparse the file but you will have to traverse the AST twice. There's not much you can do about this given the order you want. However, if the second matcher has no deps on the information collected by matcher1 you could just get away with a single MatchFinder and two callbacks that just store their finds in two vectors which you process after run returns

I'm not sure what order you're interested in but you can create two match callbacks one to use for each matcher. The callbacks will be called in the order the nodes are found in the tree by doing a depth-first pre-order traversal as is usual for RecursiveASTVisitor. If both matchers match a given node, the callbacks are called in the order they are registered. 

What sort of order are you looking for? 

I understand what you have explained until you say "two callbacks". Why could I want to have two different callbacks? Could you explain better "if the second matcher has no deps on the information collected by matcher1"?


What is often faster is to produce a superset of the information needed during the traversal / match phase, and then combine / filter the results after everything's done...
That is a good solution, I suppose. I will have to study my case more in detail to determine whether this fit my problem or not. But, do you store all that information in global variables or in the callback object?


.

You can just count how many times your match callback is called and then print that number after run() returns. 

Again, my problem is that I don't $when the match callback is called. 

I hope I can end up getting the usage of all this with your help.

Pedro.


El dia 08 may 2013 12:10, Gábor Kozár <kozargabor-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> escribió:
Hi,
> Ok, this also helps, but the problem is that I need to print something when all the nodes have been matched. So, is there a way I can check within onStartOfTranslationUnit() method if we have reached the end? I have just found this:

onStartOfTranslationUnit() is - obviously - called at the start of each TU. I.e. this will be called after the previous TU has been completed, i.e. all nodes in it have been matched.
> clang::ast_matchers::MatchFinder::ParsingDoneTestCallback

This is for testing purposes only, it's not recommended to use it.
> So, what you are saying is that I can't control the order the nodes are matched?

No, you can't. You'll have to implement a RecursiveASTVisitor manually if you need this fine control.
> What I'm trying to explain is that I need all the nodes bound with Matcher1 are treated before the execution of nodes bound with Matcher2 starts.

You can execute Matcher1 first, and when it returns, you start executing Matcher2. I'm not sure what your problem is exactly. (Of course, this will also mean that you will traverse the whole AST twice, which can potentially be very expensive.)

Gabor


Hi,

You collect information about the matches into e.g. a vector, and you can use the MatchCallback's onStartOfTranslationUnit to process the previous TU's matches.

Ok, this also helps, but the problem is that I need to print something when all the nodes have been matched. So, is there a way I can check within onStartOfTranslationUnit() method if we have reached the end? I have just found this:

clang::ast_matchers::MatchFinder::ParsingDoneTestCallback

This is the implementation of the class:

class ParsingDoneTestCallback {

  public:
  virtual void run() = 0;
};

Maybe I could redefine the run method. Do you think this may be my solution?

So the matchers run regardless of whether you ever access the bound nodes. What this means is that your run() method will be called for every match, with the appropriate nodes bound to the names you defined. So a MatchResult only contains information about one single match (i.e. a subtree of the AST, if you will). Hope this clears things up.

Um... I'm a bit mixed up at this moment. So, what you are saying is that I can't control the order the nodes are matched? For me that would be a problem because I need to keep an order in the execution. What I'm trying to explain is that I need all the nodes bound with Matcher1 are treated before the execution of nodes bound with Matcher2 starts.

Thanks,

Pedro.

El dia 07 may 2013 22:10, Gábor Kozár <kozargabor-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> escribió:
Hi,
>1. Imagine that I need to print something after all the nodes have been matched. For example, the number of nodes matched. How can I do that? 

You collect information about the matches into e.g. a vector, and you can use the MatchCallback's onStartOfTranslationUnit to process the previous TU's matches.
> How does the 'run' method behave in this case? I mean that I don't know if it retrieves, one by one, all the nodes in applyMatch1 and ,after that, all the nodes in applyMatch2 or it matches one in applyMatch1 and then other in applyMatch2 in each iteration.

So the matchers run regardless of whether you ever access the bound nodes. What this means is that your run() method will be called for every match, with the appropriate nodes bound to the names you defined. So a MatchResult only contains information about one single match (i.e. a subtree of the AST, if you will). Hope this clears things up.
Gabor


Hi again,

Sorry to make so much questions, but I hope a good structure of my tool will save me a lot of time in future.

I'm using something like this in http://clang.llvm.org/docs/LibASTMatchersTutorial.html:


class LoopPrinter : public MatchFinder::MatchCallback {public : virtual void run(const MatchFinder::MatchResult &Result) { if (const ForStmt *FS = Result.Nodes.getNodeAs<clang::ForStmt>("forLoop")) FS->dump(); }};

So, now I have two questions:

1. Imagine that I need to print something after all the nodes have been matched. For example, the number of nodes matched. How can I do that? 

2. Imagine that I have two methods within the run method to separate two kind of nodes I want to bind. Something like this:




class
LoopPrinter : public MatchFinder::MatchCallback {public : virtual void run(const MatchFinder::MatchResult &Result) { applyMatch1();
applyMatch2(); }

void applyMatch1(){
if (const ForStmt *FS = Result.Nodes.getNodeAs<clang::ForStmt>("forLoop__1"))
}

void apply2(){if (const ForStmt *FS = Result.Nodes.getNodeAs<clang::ForStmt>("forLoop_2"))}
};

How does the 'run' method behave in this case? I mean that I don't know if it retrieves, one by one, all the nodes in applyMatch1 and ,after that, all the nodes in applyMatch2 or it matches one in applyMatch1 and then other in applyMatch2 in each iteration. I hope you can understand me because this is very important in my case.

Thanks in advance.

Pedro



El dia 06 may 2013 22:32, "Vane, Edwin" <edwin.vane-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> escribió:

Given your description, I'm not sure matchers are what you want. If you just want to print information on certain types of nodes, you could use a RecursiveASTVisitor for that.

However, if what you're looking for is a little more complex then matchers may be what you want after all.

As for the two classes, you want to use tooling::MatchFinder as shown in the tutorial. The other is just an implementation detail of the match finding code.

newASTConsumer() is a function that's required to be defined for objects passed to newFrontendActionFactory(). You don't need to implement it. It's implemented by MatchFinder. Again, it's an implementation detail you don't need to worry about at this point.

The use of ASTConsumers is not necessary if you're using MatchFinder and ClangTool as described in the tutorial. MatchFinder is an abstraction around RecursiveASTVisitor so all that stuff in RecursiveASTVisitor you'd normally have to use is actually hidden away.

I think you should first decide which route you want to go: MatchFinder or RecursiveASTVisitor. The first question I'd ask is: how hard is it to find the nodes I want to print info on in the AST. If all I want is every for loop that's easy. If I want for loops within member functions of a specific class, that's hard and an excellent use case for ASTMatchers.

-----Original Message-----
From: cfe-dev-bounces-Tmj1lob9twqVc3sceRu5cw@public.gmane.org [mailto:cfe-dev-bounces-Tmj1lob9twqVc3sceRu5cw@public.gmane.org] On
Behalf Of Pedro Delgado Perez
Sent: Monday, May 06, 2013 12:58 PM
To: klimek-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org; kozargabor <at> gmail.com
Cc: cfe-dev-Tmj1lob9twqVc3sceRu5cw@public.gmane.org
Subject: Re: [cfe-dev] ASTMatchers: isVirtual and isOverride

Hi,

I need your help again. Look, in my tool I was trying to use the syntax that's
shown here:

http://clang.llvm.org/docs/LibASTMatchersTutorial.html

Namely I'm referring to this part:

int main(int argc, const char **argv) {
CommonOptionsParser OptionsParser(argc, argv);
ClangTool Tool(OptionsParser.getCompilations(),
OptionsParser.getSourcePathList());

LoopPrinter Printer;
MatchFinder Finder;
Finder.addMatcher(LoopMatcher, &Printer);

return Tool.run(newFrontendActionFactory(&Finder));
}

However, now I want to create a object "Printer" with different features
depending on the arguments provided in command line. So I was thinking on
implement a factory method pattern to create a different LoopPrinter object:
class OptionsFactory {
public:
LoopPrinter getOption() {
if(...)
return LoopPrinter(attribute1, attribute2);
else
return LoopPrinter(attribute1);
}
};

I was searching for a better solution and there are some things that I can't
completely understand.

- Why are there two classes MatchFinder:
http://clang.llvm.org/doxygen/classclang_1_1tooling_1_1MatchFinder.html
http://clang.llvm.org/doxygen/classclang_1_1ast__matchers_1_1MatchFinder.
html

- What the method in ast_matchers:MatchFinder

clang::ASTConsumer
<http://clang.llvm.org/doxygen/classclang_1_1ASTConsumer.html> *

newASTConsumer
<http://clang.llvm.org/doxygen/classclang_1_1ast__matchers_1_1MatchFinder
.html#a4807049e6e39572d19ff127406df3d81> ()

is used for? I see we can 'associate' an ASTConsumer to the Frontend as in:
http://clang.llvm.org/docs/RAVFrontendAction.html

but, is this possible using Matchers? Would it have any sense to create an
ASTConsumer in my class OptionsFactory?

I have improved a lot since you last helped me, but clang is too big!

By the way, do you know how to use CommandLine? I posted a new thread

http://lists.cs.uiuc.edu/pipermail/cfe-dev/2013-May/029473.html

If you know how to solve that problem, please, let me know.

Thanks in advance,

Pedro.


El dia 27 abr 2013 18:39, Manuel Klimek <klimek-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org> escribió:

On Sat, Apr 27, 2013 at 6:36 PM, Gábor Kozár
<kozargabor-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:



2013/4/27 Manuel Klimek <klimek-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>


Just use the empty string for binding and getNodeAs :)


That would potentially lead to confusion when there are more
nodes bound, but the programmer forgot to supply the proper name. In my
suggestion, the parameterless getNodeAs would have an assert to check there is
exactly one node bound (and whose name is the default name).

If you put everything behind constants, I think it'll be easy enough to see
what's happening - and that's a generally good strategy anyway, as you get a
compile error if you mistype...
Thus, I think it'd not add enough value to special case the interface.




2013/4/27 Manuel Klimek <klimek-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>


On Sat, Apr 27, 2013 at 6:28 PM, Gábor Kozár
<kozargabor-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:

Hi,
2013/4/26 Pedro Delgado Perez
<pedro.delgadoperez-+o0oGDbj3PkxAGwisGp4zA@public.gmane.org>


Hehehe... I found the problem with
this. I was binding wrongly the matcher! I used a id in the matcher thas was
different from the id in the function that retrieves the nodes... I think this will be
a typical mistake for newbies...

Ah, yes, that happens a lot to me as well. Now
that I think about it, it might be worthwhile adding a parameterless .bind() and
.getNodeAs<T>() for situations where only one node is bound. Should be fairly
trivial, but also not all that useful...

Just use the empty string for binding and getNodeAs :)



2013/4/26 Pedro Delgado Perez
<pedro.delgadoperez-+o0oGDbj3PkxAGwisGp4zA@public.gmane.org>


Thanks both! Now I can see all this
much clearer and I have the enough knowledge to start out with clang.


You're welcome. Good luck!


2013/4/25 Manuel Klimek <klimek-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>


And btw thanks a lot for all the great user support you're giving
here!


Thank you, I'm happy to help. Clang is a great project!

As soon as the university term is over, I'm also planning on trying to
contribute code-wise, mainly to the Static Analyzer but I guess also on just about
anything that catches my attention. :) I'm quite excited - this is going to be the
first open source project I contribute to.
Gabor







_______________________________________________
cfe-dev mailing list
cfe-dev@...
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Richard Catlin | 18 May 2013 19:15
Picon
Gravatar

Fwd: cling error: no type named 'Interpreter' in namespace 'cling'; did you mean '::cling::Interpreter'?



---------- Forwarded message ----------
From: Richard Catlin <richard.m.catlin-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Date: Sat, May 18, 2013 at 10:10 AM
Subject: Re: [cfe-dev] cling error: no type named 'Interpreter' in namespace 'cling'; did you mean '::cling::Interpreter'?
To: Vassil Vassilev <vvasilev-vJEk5272eHo@public.gmane.org>


Vassil,

I tried to build from source also, but get this error.  I tried both on Lion and Mountain Lion.  I am using the svn repo for llvm, clang.  Here is the error below.  I am attaching the configure log file also.

Any idea?  I am really anxious to try cling, as an LLVM developer.  I use LLVM as the runtime for a DSL.

Thank you.
Richard Catlin

llvm[4]: Compiling ParseDecl.cpp for Debug+Asserts build
llvm[4]: Compiling ParseDeclCXX.cpp for Debug+Asserts build
llvm[4]: Compiling ParseExpr.cpp for Debug+Asserts build
llvm[4]: Compiling ParseExprCXX.cpp for Debug+Asserts build
llvm[4]: Compiling ParseInit.cpp for Debug+Asserts build
llvm[4]: Compiling ParseObjc.cpp for Debug+Asserts build
llvm[4]: Compiling ParseOpenMP.cpp for Debug+Asserts build
llvm[4]: Compiling ParsePragma.cpp for Debug+Asserts build
llvm[4]: Compiling ParseStmt.cpp for Debug+Asserts build
llvm[4]: Compiling ParseTemplate.cpp for Debug+Asserts build
llvm[4]: Compiling ParseTentative.cpp for Debug+Asserts build
llvm[4]: Compiling Parser.cpp for Debug+Asserts build
/Users/rcatlin1/cling-dev/llvm/tools/clang/lib/Parse/Parser.cpp:548:39: error: variable has incomplete type 'clang::DestroyTemplateIdAnnotationsRAIIObj'
  DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(*this);
                                      ^
/Users/rcatlin1/cling-dev/llvm/tools/clang/lib/Parse/../../include/clang/Parse/Parser.h:48:9: note: forward declaration of 'clang::DestroyTemplateIdAnnotationsRAIIObj'
  class DestroyTemplateIdAnnotationsRAIIObj;
        ^
/Users/rcatlin1/cling-dev/llvm/tools/clang/lib/Parse/Parser.cpp:602:39: error: variable has incomplete type 'clang::DestroyTemplateIdAnnotationsRAIIObj'
  DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(*this);
                                      ^
/Users/rcatlin1/cling-dev/llvm/tools/clang/lib/Parse/../../include/clang/Parse/Parser.h:48:9: note: forward declaration of 'clang::DestroyTemplateIdAnnotationsRAIIObj'
  class DestroyTemplateIdAnnotationsRAIIObj;
        ^
2 errors generated.
make[4]: *** [/Users/rcatlin1/cling-dev/build/tools/clang/lib/Parse/Debug+Asserts/Parser.o] Error 1
make[3]: *** [Parse/.makeall] Error 2
make[2]: *** [all] Error 1
make[1]: *** [clang/.makeall] Error 2
make: *** [all] Error 1



On Sat, May 18, 2013 at 6:12 AM, Vassil Vassilev <vvasilev-vJEk5272eHo@public.gmane.org> wrote:
Hi Richard,
  I have filed a bugreport: https://sft.its.cern.ch/jira/browse/ROOT-5212
  Please build cling from source, until that issue is fixed.
Cheers,
Vassil
On 5/17/13 6:18 PM, RichardCatlin wrote:
Subject: error: no type named 'Interpreter' in namespace 'cling'; did you
mean '::cling::Interpreter'?

Hi,

I downloaded the Mac binary.  I get the following error when I run ./cling.

Any help is appreciated.

Regards,
Richard Catlin


SDGL11fd4f1cb:bin rcatlin1$ ./cling
ExecutionContext: use of undefined symbol
'_ZN5cling7runtime8internal21__trigger__cxa_atexitD1Ev'!
ExecutionContext::runStaticInitializersOnce: symbol
'_ZN5cling7runtime8internal21__trigger__cxa_atexitD1Ev' unresolved while
linking static initializer '_GLOBAL__I_a'!
In file included from -:1:
input_line_3:1:45: error: no type named 'Interpreter' in namespace 'cling';
did you mean '::cling::Interpreter'?
namespace cling {namespace runtime { cling::Interpreter
*gCling=(cling::Interpreter*)140734543633080;} }
                                      ~~~~~~~^~~~~~~~~~~
                                             ::cling::Interpreter
Stack dump:
0.      input_line_3:1:45: current parser token 'Interpreter'
1.      input_line_3:1:1: parsing namespace 'cling'
2.      input_line_3:1:18: parsing namespace 'runtime'
Segmentation fault: 11



--
View this message in context: http://clang-developers.42468.n3.nabble.com/cling-tp3198446p4032174.html
Sent from the Clang Developers mailing list archive at Nabble.com.
_______________________________________________
cfe-dev mailing list
cfe-dev-Tmj1lob9twrHfRtnQztjLA@public.gmane.orgu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev



Attachment (configure.log): application/octet-stream, 24 KiB
Attachment (configure.log): application/octet-stream, 24 KiB
_______________________________________________
cfe-dev mailing list
cfe-dev@...
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Faisal Vali | 18 May 2013 18:22
Picon

Implementing DR 712 (odr-use, potential results of an expression)?

Before I return to working on generic lambdas, I thought it might be useful to nail down DR 712 which reworded the definition of odr-use in terms of the potential results of an expression (in order to avoid odr-using a variable that represents a constant expression whenever we can get away with it).  This is relevant to lambdas, because it affects which variables get captured and which don't.


Let me review how I think clang currently handles this (pre-712 resolution  - please correct me where I err). While parsing and semanalyzing expressions, all variables that are usable in constant expressions (and so might not need to be odr-used) are stored in MaybeODRUseExprs (a set container) as DeclRefExprs (DRE).  Then, if an Lvalue-to-Rvalue conversion is performed on the DRE, it is removed from the set above (In UpdateMarkingForLValueToRValue).  Anything left in that set is marked as odr-used by ActOnFinishFullExpr. 


OK, with the above in mind, these are my initial thoughts on how to implement it so that not only do we handle those constant expressions that are lvalue-to-rvalue converted, but also those that are discarded, and also handle the conditional expressions and member-access expressions.

The relevant hooks/callbacks/functions within clang are:
  - UpdateMarkingForLValueToRValue
  - IgnoredValueConversions

A function i intend to write is GetPotentialResultsOfExpression: when passed an Expr* E, returns a vector of its potential results as DeclRefExpr's (and MemberExpr's??); this function should follow from  3.2 para 2.

Now in each hook, GetPotentialResults shall be called, and those expressions shall be removed from the MaybeODRUseExpr.

What are your thoughts on the above preliminary strategy?  I have this sense that Member expressions are going to require some more work, but we'll see...

Also before I proceed any further, I was hoping to get some more clarity on 3.2 para 2 and para 3 - please see my queries below:


Consider the following code:


struct S {
  const int mi;
  constexpr S(int i) : mi(i) { }
};

int f(const int& );
void g(int);
int main() {
  constexpr S r{5};
  constexpr S s{r};
  [](char c) { 
      c = s.mi;  // #1 does this odr-use 's'
      g(s.mi);   //  #2 what about this?
      s.mi;        // #3 and this?
      c ? s.mi : r.mi; // #4 and this?
      g( c ? s.mi : r.mi ); // #5
  };
}

My intial suspicion was that neither s nor r were odr-used in the lambda (because the compiler can figure out the value of 'mi' at its point of use, and use it or discard it) - but then based on Richard's analysis of the example below where he states that s.operator int() is an odr-use of 's', i am now unsure.

Here is my attempt at trying to figure this out (e refers to expression, ex as a potentially-evaluated expression, using the language of 3.2 para 2 and 3)

In #1,
  the variable 's' appears as a potentially evaluated expression and satisfies the requirements for appearing in a constant expression, and it is an object, and it is an element of the set of potential results of an expression 'e' (s.mi) and the lvalue-to-rvalue conversion is applied to that expression so it is not odr-used?  But what if 'e' is deemed to be 's' in 's.mi' - no lvalue-to-rvalue conversion is applied so it should be captured?

OK, I'm going to give up on analyzing the rest, because I feel I'm missing something and am unable to think about this clearly.

Any help or guidance will be appreciated!

 

On Wed, May 15, 2013 at 3:21 PM, Richard Smith <richard-Qo5EllUWu/sqdlJmJB21zg@public.gmane.org> wrote:
On Tue, May 14, 2013 at 9:48 PM, Faisal Vali <faisalv-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:


While we're on the topic, can i ask you to clarify a few capture and constexpr
questions below:

OK, the relevant context is [basic.def.odr]p2 and p3.
 
struct S {
  constexpr S() {}
  constexpr operator int() const { return 0; }
};
void fooS(S s) { }

void fooInt(int i) { }

void f() {
  constexpr S s {};
  auto L = [] (int x) {
      (void) s;  // 1

Here, the 's' expression is a discarded-value expression, and the 's' variable is in the set of potential results of the 's' expression, and 's' satisfies the constraints for appearing in a constant expression, so 's' is not odr-used, so is not captured. We should not require a capture-default here.
 
      fooS(s);  // 2

Here, 's' is implicitly passed to the implicit S::S(const S&) constructor. This is neither an lvalue-to-rvalue conversion nor a discarded-value expression, so 's' is odr-used and we have an error due to the missing capture-default.
 
      fooInt(s); // 3

This is equivalent to 's.operator int()', which again odr-uses 's', so requires a capture-default.
 
  };
}

Should the above be ok in spite of L not having a default capture?
Currently clang errors on all of them individually - is that the right behavior?

Also, how would you want me to start submitting patches for commit - do you want
me to break up the patch into smaller patches? - and if so, do you have any thoughts
on how I might want to break up the functionality per patch?

Smaller patches are definitely better, if you can decompose the functionality into coherent smaller chunks. There are some hints on how to decompose the functionality here (but this division may or may not work for you):


_______________________________________________
cfe-dev mailing list
cfe-dev@...
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
David Chisnall | 18 May 2013 17:00
Picon
Picon
Favicon

Adding -fuse-ld= support to clang

Hi Everyone,

In FreeBSD, we are about to start the process of migrating from (ancient) BFD ld to MCLinker, so we're going
to need support for multiple linkers for a while.  It turns out that gcc already has an option to select
linkers, so I have attempted to remain compatible in the attached patch.  This adds a -fuse-ld={name}
option, which takes a string as an argument.  The toolchains then request a linker and get either
ld.{name}, ld-{name}, or {name} as the linker.  

Does anyone have objections to committing this as-is, or would anyone like to recommend a better approach?

David

Index: include/clang/Basic/DiagnosticDriverKinds.td
===================================================================
--- include/clang/Basic/DiagnosticDriverKinds.td	(revision 182184)
+++ include/clang/Basic/DiagnosticDriverKinds.td	(working copy)
 <at>  <at>  -26,6 +26,8  <at>  <at> 
   "unsupported runtime library '%0' for platform '%1'">;
 def err_drv_invalid_stdlib_name : Error<
   "invalid library name in argument '%0'">;
+def err_drv_invalid_linker_name : Error<
+  "invalid linker name in argument '%0'">;
 def err_drv_invalid_opt_with_multiple_archs : Error<
   "option '%0' cannot be used with multiple -arch options">;
 def err_drv_invalid_output_with_multiple_archs : Error<
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td	(revision 182184)
+++ include/clang/Driver/Options.td	(working copy)
 <at>  <at>  -744,6 +744,8  <at>  <at> 
 def fuse_cxa_atexit : Flag<["-"], "fuse-cxa-atexit">, Group<f_Group>;
 def fuse_init_array : Flag<["-"], "fuse-init-array">, Group<f_Group>, Flags<[CC1Option]>,
   HelpText<"Use .init_array instead of .ctors">;
+def fuse_ld_EQ : Joined<["-", "--"], "fuse-ld=">, Group<f_Group>,
+  HelpText<"The linker to use.">;
 def fverbose_asm : Flag<["-"], "fverbose-asm">, Group<f_Group>;
 def fvisibility_EQ : Joined<["-"], "fvisibility=">, Group<f_Group>,
   HelpText<"Set the default symbol visibility for all global declarations">;
Index: include/clang/Driver/ToolChain.h
===================================================================
--- include/clang/Driver/ToolChain.h	(revision 182184)
+++ include/clang/Driver/ToolChain.h	(working copy)
 <at>  <at>  -136,6 +136,9  <at>  <at> 

   std::string GetFilePath(const char *Name) const;
   std::string GetProgramPath(const char *Name) const;
+  /// Returns the linker path, respecting the -fuse-ld= argument to determine
+  /// the linker suffix or name.
+  std::string GetLinkerPath() const;

   // Platform defaults information

Index: lib/Driver/ToolChain.cpp
===================================================================
--- lib/Driver/ToolChain.cpp	(revision 182184)
+++ lib/Driver/ToolChain.cpp	(working copy)
 <at>  <at>  -132,6 +132,36  <at>  <at> 

 }

+std::string ToolChain::GetLinkerPath() const {
+  if (Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ)) {
+    StringRef Value = A->getValue();
+    // If we're passed -fuse-ld= with no argument, or with the argument ld,
+    // then use whatever the default system linker is.
+    if (Value.empty() || Value == "ld")
+      return GetFilePath("ld");
+    std::string LinkerName = Value.str();
+    std::string LD("ld.");
+    LD += LinkerName;
+    std::string LinkerPath = GetFilePath(LD.c_str());
+    bool Exists;
+    if (!llvm::sys::fs::exists(LinkerPath, Exists) && Exists)
+      return LinkerPath;
+    LD = std::string("ld-") + LinkerName;
+    LinkerPath = GetFilePath(LD.c_str());
+    if (!llvm::sys::fs::exists(LinkerPath, Exists) && Exists)
+      return LinkerPath;
+    LinkerPath = GetFilePath(LinkerName.c_str());
+    if (!llvm::sys::fs::exists(LinkerPath, Exists) && Exists)
+      return LinkerPath;
+    getDriver().Diag(diag::err_drv_invalid_linker_name)
+      << A->getAsString(Args);
+    // Fall through and run the system linker - we could do a hard error here,
+    // but we may as well try and see if it works.
+  }
+  return GetFilePath("ld");
+}
+
+
 std::string ToolChain::GetProgramPath(const char *Name) const {
   return D.GetProgramPath(Name, *this);
 }
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp	(revision 182184)
+++ lib/Driver/Tools.cpp	(working copy)
 <at>  <at>  -5219,8 +5219,7  <at>  <at> 
                               getToolChain().GetFilePath("crtendS.o")));
   }

-  const char *Exec =
-    Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+  const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
   C.addCommand(new Command(JA, *this, Exec, CmdArgs));
 }

 <at>  <at>  -5361,8 +5360,7  <at>  <at> 
                               getToolChain().GetFilePath("crtendS.o")));
   }

-  const char *Exec =
-    Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+  const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
   C.addCommand(new Command(JA, *this, Exec, CmdArgs));
 }

 <at>  <at>  -5612,8 +5610,7  <at>  <at> 

   addProfileRT(ToolChain, Args, CmdArgs, ToolChain.getTriple());

-  const char *Exec =
-    Args.MakeArgString(ToolChain.GetProgramPath("ld"));
+  const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
   C.addCommand(new Command(JA, *this, Exec, CmdArgs));
 }

 <at>  <at>  -5762,7 +5759,7  <at>  <at> 

   addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple());

-  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+  const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
   C.addCommand(new Command(JA, *this, Exec, CmdArgs));
 }

 <at>  <at>  -6247,7 +6244,7  <at>  <at> 
          Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
   }

-  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+  const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
   C.addCommand(new Command(JA, *this, Exec, CmdArgs));
 }

 <at>  <at>  -6430,8 +6427,7  <at>  <at> 

   addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple());

-  const char *Exec =
-    Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+  const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
   C.addCommand(new Command(JA, *this, Exec, CmdArgs));
 }

Index: test/Driver/fuse_ld.c
===================================================================
--- test/Driver/fuse_ld.c	(revision 0)
+++ test/Driver/fuse_ld.c	(working copy)
 <at>  <at>  -0,0 +1,7  <at>  <at> 
+// RUN: rm -f ld.foo
+// RUN: %clang %s -target i386-unknown-freebsd -fuse-ld=foo -### 2>&1 | FileCheck
-check-prefix=MISSING %s
+// RUN: touch ld.foo
+// RUN: %clang %s -B. -target i386-unknown-freebsd -fuse-ld=foo -### 2>&1 | FileCheck
-check-prefix=FOUND %s
+
+// CHECK-MISSING: error: invalid linker name in argument '-fuse-ld=foo'
+// CHECK-FOUND: "./ld.foo"
Jeffrey Walton | 17 May 2013 16:26
Picon

OT: Serebryany paper on MS and TS?

Hi All,

I'm trying to locate Serebryany talk on memory and thread sanitizers.
The link (http://llvm.org/devmtg/2012-11/Serebryany_TSan-MSan.pdf)
appears dead on this MacBook/Firefox combination I'm using.

Would anyone know of an alternate download? Google only returns the
original link (http://www.google.com/#q=Serebryany_TSan-MSan+filetype:pdf)

Jeff
huc1985 | 17 May 2013 04:34
Favicon

How to set the byte alignment of struct?

Hi all!

I'm writing a static checker using clang AST. I want set struct alignment
manually. How to do this?

Thanks!

This is my top level:

    DiagnosticOptions* diagnosticOptions = new DiagnosticOptions;

    llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> diagIDs(new
DiagnosticIDs());

    TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
    DiagnosticsEngine* diagnostics = new DiagnosticsEngine(diagIDs,
diagnosticOptions, DiagsBuffer);

    LangOptions languageOptions;

    FileSystemOptions fileSystemOptions;
    FileManager fileManager(fileSystemOptions);    

    SourceManager* sourceManager = new SourceManager(*diagnostics,
fileManager);

    TargetOptions* targetOptions = new TargetOptions;	
    targetOptions->Triple = llvm::sys::getDefaultTargetTriple();	
    TargetInfo *pTargetInfo =
clang::TargetInfo::CreateTargetInfo(*diagnostics, targetOptions);

    IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts(new
HeaderSearchOptions());

    HeaderSearch headerSearch(HSOpts, fileManager, *diagnostics,
languageOptions, pTargetInfo);

    for (vector<string>::const_iterator it =
filefold.begin();it!=filefold.end();it++)
    {
        (*HSOpts).AddPath(*it,frontend::Quoted,false,false);
    }
    ApplyHeaderSearchOptions(headerSearch, *HSOpts, languageOptions,
pTargetInfo->getTriple());

    //为该源文件创建一个clang的编译器实例
    OwningPtr<CompilerInstance> Clang(new CompilerInstance());

    PreprocessorOptions *preprocessorOptions = new PreprocessorOptions();

    Preprocessor *PP = new Preprocessor(preprocessorOptions, *diagnostics,
languageOptions
        , pTargetInfo, *sourceManager, headerSearch, *(Clang.get()));

    for (int i=0;i<(int)compile_define.size();i++){
        preprocessorOptions->addMacroDef(compile_define[i]);
    }

    FrontendOptions frontendOptions;
    InitializePreprocessor(*PP,  *preprocessorOptions, *HSOpts,
frontendOptions);

    const FileEntry *pFile = fileManager.getFile(file_name);
    sourceManager->createMainFileID(pFile);

    //为该编译器实例初始化。
    Clang->setDiagnostics(diagnostics);
    Clang->getDiagnosticClient().BeginSourceFile(Clang->getLangOpts(),PP);
    Clang->setPreprocessor(PP);
    Clang->setSourceManager(sourceManager);
    Clang->setTarget(pTargetInfo);
    SourceManager &sourceMgr = Clang->getSourceManager();
    Clang->createASTContext();
    Rewriter rewriter;
    rewriter.setSourceMgr(sourceMgr,languageOptions);

    MemoryMonitorASTConsumer consumer(rewriter,
MallocClangReport::GetInstance());
    consumer.mVisitor.SetCheckFunctionName(function);
    consumer.mVisitor.SetCheckFunctionArgumentIndex(arg_index);

    //AST解析
    ParseAST(*PP, &consumer, Clang->getASTContext(),false);

    Clang->getDiagnosticClient().EndSourceFile();

--
View this message in context: http://clang-developers.42468.n3.nabble.com/How-to-set-the-byte-alignment-of-struct-tp4032152.html
Sent from the Clang Developers mailing list archive at Nabble.com.

_______________________________________________
cfe-dev mailing list
cfe-dev <at> cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Bill Wendling | 16 May 2013 20:18
Picon
Favicon

[3.3 Release] Help Needed Fixing Bugs

Hi LLVM-cateers,

The first phase of testing is nearing completion. (Actually, it's pretty much done.) You can find binaries
here as well as the source code if you want to compile your own binaries:

	http://llvm.org/pre-releases/3.3/rc1/

We also have several bugs which have been reported. The umbrella bug report is here:

	http://llvm.org/bugs/show_bug.cgi?id=15999

Now we need your help! You can help us by looking at the bugs listed in the umbrella bug report and seeing if you
can fix them, or if they already are fixed, telling us which patch fixed it.

Secondly, you can download the binaries and start compiling things you're interested in. Any issues you
come across should be listed in the umbrella bug.

Let's make this the best release LLVM has ever had!

Share and enjoy! :-)
-bw
Devchandra L Meetei | 16 May 2013 19:51
Picon

Confusion on interpretations


SUppose if We have
t = 128;
n = 3;
while ( n >= 4 && ((t = 7) & 0x80) == 0 )

why t is 128 after the loop. As we learnt that parentheses has highest priority.
Won't in this case t be 7. why the value is still 128?

--
Warm Regards
--Dev
OpenPegasus Developer/Committer

(\__/)
(='.'=) This is Bunny. Copy and paste bunny
(")_(") to help him gain world domination.
_______________________________________________
cfe-dev mailing list
cfe-dev@...
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
DRC | 16 May 2013 07:32
Picon

Performance disparity between clang/LLVM and GCC when using libjpeg-turbo

Hi.  I maintain libjpeg-turbo, a heavily-accelerated fork of libjpeg for 
x86/x86-64 and ARM systems.  A large part of our speedup comes from 
assembly code, but our Huffman codec relies heavily on C compiler 
optimizations to achieve peak performance.  After upgrading to OS X 
10.8, which uses Clang/LLVM as the default compiler rather than GCC, I 
observed a slowdown of 15-20% when compressing images using 
libjpeg-turbo, and it seems to be due to the compiler having trouble 
optimizing said Huffman codec.  I'll walk you through the steps to 
reproduce the issue:

NOTE:  this is probably reproducible on other platforms, such as Linux, 
as well.  I haven't tested it.

Prerequisites:
-- Xcode 4.5.x installed under /Applications/Xcode.app
-- nasm, automake, autoconf, and apple-gcc42 from MacPorts installed 
under /opt/local
-- artificial.ppm from 
http://www.imagecompression.info/test_images/rgb8bit.zip

xcrun svn co svn://svn.code.sf.net/p/libjpeg-turbo/code/trunk libjpeg-turbo
cd libjpeg-turbo
/opt/local/bin/autoreconf -fiv

mkdir osx.64.clang
cd osx.64.clang
sh ../configure --host x86_64-apple-darwin NASM=/opt/local/bin/nasm 
CC='xcrun clang' CFLAGS=-O4
./tjbench {path_to}/artificial.ppm 95 -rgb -quiet

mkdir osx.64.llvmgcc
cd osx.64.llvmgcc
sh ../configure --host x86_64-apple-darwin NASM=/opt/local/bin/nasm 
CC='xcrun gcc' CFLAGS=-O3
./tjbench {path_to}/artificial.ppm 95 -rgb -quiet

mkdir osx.64.gcc42
cd osx.64.gcc42
sh ../configure --host x86_64-apple-darwin NASM=/opt/local/bin/nasm 
CC=/opt/local/bin/gcc-apple-4.2 CFLAGS=-O3
./tjbench {path_to}/artificial.ppm 95 -rgb -quiet

mkdir osx.32.clang
cd osx.32.clang
sh ../configure --host i686-apple-darwin NASM=/opt/local/bin/nasm 
CC='xcrun clang' CFLAGS='-m32 -O4' LDFLAGS=-m32
./tjbench {path_to}/artificial.ppm 95 -rgb -quiet

mkdir osx.32.llvmgcc
cd osx.32.llvmgcc
sh ../configure --host i686-apple-darwin NASM=/opt/local/bin/nasm 
CC='xcrun gcc' CFLAGS='-m32 -O3' LDFLAGS=-m32
./tjbench {path_to}/artificial.ppm 95 -rgb -quiet

mkdir osx.32.gcc42
cd osx.32.gcc42
sh ../configure --host i686-apple-darwin NASM=/opt/local/bin/nasm 
CC=/opt/local/bin/gcc-apple-4.2 CFLAGS='-O3 -m32' LDFLAGS=-m32
./tjbench {path_to}/artificial.ppm 95 -rgb -quiet

A spreadsheet of my results is attached.  Note that decompression 
performance is generally better across the board with Clang/LLVM, but 
compression performance is generally worse.  Note also that, when using 
the GCC front end to LLVM, the performance is somewhere in the middle, 
so it seems that part of the issue may be in Clang and part of it may be 
in LLVM.

If there are things I can do within the inner loops of jchuff.c to make 
it perform better under Clang/LLVM, I am definitely open to that.

DRC
Attachment (libjpegturbo-1.3.ods): application/vnd.oasis.opendocument.spreadsheet, 13 KiB
_______________________________________________
cfe-dev mailing list
cfe-dev@...
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
NAVEEN CHANDRAKAR | 16 May 2013 06:43

[LLVM-Codegen] Query for stack operations during register allocation pass

Dear All,

In PrologEpilogInserter.cpp -> PEI::replaceFrameIndices()

Currently we've an assert inside this function which assumes stack operations before and after any
function call to be balanced at basic block level.
The assert cond. checked at end of each Basic Block goes as follows

    // If we have evenly matched pairs of frame setup / destroy instructions,
    // make sure the adjustments come out to zero. If we don't have matched
    // pairs, we can't be sure the missing bit isn't in another basic block
    // due to a custom inserter playing tricks, so just asserting SPAdj==0
    // isn't sufficient. See tMOVCC on Thumb1, for example.
    assert((SPAdjCount || SPAdj == 0) &&
           "Unbalanced call frame setup / destroy pairs?");

But in practice we see stack to be balanced at function level. 
My query is, Am i missing some fundamental concept while assuming that stack should be balanced at function
level rather than Basic Block Level.
Is frame balancing at Basic Block level justified ?

This bug is rare as it would happen only in big function arguments (on ARM, MIPS etc.)
eg: On arm if argument size exceeds ((1 << 12) - 1) / 2) ARMFrameLowering::hasReservedCallFrame(), we can
see this issue.

For reference i've created a bug on http://llvm.org/bugs/show_bug.cgi?id=15932 which contains the
problem along with the proposed patch.
However since this would affect all other platforms as well, i wanted your expert opinion about my approach.

PS: I'm awaiting my account creation on phabricator, for time being posting this query on cfe-dev for
discussing the solution approach.

Warm Regards,
Naveen

Gmane