Hello Duncan,
> >> what version of LLVM are you using? I don't think LLVM 2.7
uses a
> >> "indirect call node". However it does use a
"external node", which
> >> is used when a function external to the current module is called.
> >>
> >
> > The "external node" makes sense. However, I am using LLVM
2.8. (See
> > the output from "opt -version") and build it against
Revision 105271
> > in the svn repository. So, can I say that the presence of
"indirect
> > call node" is new in LLVM 2.8?
>
> I couldn't find any code that printed "indirect call node",
and I
> couldn't produce it with a testcase that does an indirect call.
> This is with LLVM 2.8. That's why I asked which version you are
> using. At this point I think you should provide a testcase.
The test code is comprised of three files: example.cpp, string.cpp and
string.h. They are attached later.
I used these commands (in chronic order):
>llvm-g++ -c -emit-llvm string.cpp
>llvm-g++ -c -emit-llvm example.cpp
>llvm-ld string.o example.o
>opt -dot-callgraph a.out.bc
>open -a Graphviz callgraph.dot
Followed are the three files.
- example.cpp
#include "string.h"
int main()
{
String y, z;
String x("Hello World!");
y = x; // strongly update y
z = y; // use y
return 0;
}
- string.cpp
// String.cpp
#include "String.h"
String::String() : capacity(0), length(0), buffer(0)
{
// Nothing else to do
}
String::String(const String& that)
{
length = that.length;
if(that.length > capacity) {
delete [] buffer;
capacity = 1.5 * length;
buffer = new char[capacity];
}
for(int i=0; i<length; ++i) {
buffer[i] = that.buffer[i];
}
}
String::String(const char str[])
{
length = 0;
while(str[length]!='\0') {
++length;
}
capacity = length * 1.5;
buffer = new char[capacity];
for(int i=0; i<length; ++i) {
buffer[i] = str[i];
}
}
String::~String()
{
if(capacity) {
delete [] buffer;
}
}
String& String::operator=(const String& that)
{
length = that.length;
if(that.length > capacity) {
delete [] buffer;
capacity = 1.5 * length;
buffer = new char[capacity];
}
for(int i=0; i<length; ++i) {
buffer[i] = that.buffer[i];
}
return *this;
}
- string.h
#ifndef STRING_H
#define STRING_H
class String {
public:
// Default constructor
String();
// Copy constructor
String(const String& that);
// One argument constructor that takes a character array as the initial
// value for the string
String(const char str[]);
// Destructor
~String();
// Assignment operator
String& operator=(const String& that);
private:
int length;
int capacity;
char* buffer;
};
#endif
Best,
Xiaolong