Method to create LLVM IR - clang

I am creating clang tool and I want to generate LLVM IR from clang AST. I am aware of -emit-llvm option that I can use to get *.ll file, but is there way to generate IR inside code? Some method that I can call that takes clang AST or AST context and returns llvm::Module? I cannot find any example that shows this.
Edited:
So I tried using CodeGenAction for this, but I can't get it to work. I end up with unresolved external symbol error. Am I missing something?
#include <clang/CodeGen/CodeGenAction.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Frontend/CompilerInvocation.h>
#include <clang/Basic/DiagnosticOptions.h>
#include <clang/Frontend/TextDiagnosticPrinter.h>
#include <llvm/ADT/IntrusiveRefCntPtr.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/LLVMContext.h>
using namespace std;
clang::CodeGenAction * getAction(void)
{
// Path to the C file
string inputPath = "test.c";
// Arguments to pass to the clang frontend
vector<const char *> args;
args.push_back(inputPath.c_str());
// The compiler invocation needs a DiagnosticsEngine so it can report problems
clang::DiagnosticOptions opt = clang::DiagnosticOptions();
clang::TextDiagnosticPrinter *DiagClient = new clang::TextDiagnosticPrinter(llvm::errs(), &opt);
llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID(new clang::DiagnosticIDs());
clang::DiagnosticsEngine Diags(DiagID, &opt, DiagClient);
// Create the compiler invocation
clang::CompilerInvocation* CI(new clang::CompilerInvocation());
clang::CompilerInvocation::CreateFromArgs(*CI, &args[0], &args[0] + args.size(), Diags);
// Create the compiler instance
clang::CompilerInstance Clang;
Clang.setInvocation(CI);
// Get ready to report problems
Clang.createDiagnostics(&Diags.getDiagnosticOptions());
if (!Clang.hasDiagnostics())
return NULL;
// Create an action and make the compiler instance carry it out
clang::CodeGenAction *Act = new clang::EmitLLVMOnlyAction(&llvm::getGlobalContext());
if (!Clang.ExecuteAction(*Act))
return NULL;
return Act;
}
int main(void)
{
clang::CodeGenAction* Act = getAction();
// Grab the module built by the EmitLLVMOnlyAction
std::unique_ptr<llvm::Module> module = Act->takeModule();
// Print all functions in the module
for (llvm::Module::FunctionListType::iterator i = module->getFunctionList().begin(); i != module->getFunctionList().end(); ++i)
printf("%s\n", i->getName().str().c_str());
return 0;
}
Errors I got during linking:
LNK1120: 2 unresolved externals
LNK2001: unresolved external symbol "public: __thiscall clang::EmitLLVMOnlyAction::EmitLLVMOnlyAction(class llvm::LLVMContext *)" (??0EmitLLVMOnlyAction#clang##QAE#PAVLLVMContext#llvm###Z)
LNK2001: unresolved external symbol "public: class std::unique_ptr<class llvm::Module,struct std::default_delete<class llvm::Module> > __thiscall clang::CodeGenAction::takeModule(void)" (?takeModule#CodeGenAction#clang##QAE?AV?$unique_ptr#VModule#llvm##U?$default_delete#VModule#llvm###std###std##XZ)

In clang the code generation happens in the CodeGenModule class. There you can get the current module through llvm::Module & getModule () const. CodeGenModule handles code generation on module level while CodeGenFunction does this for a particular function. There you find Emit* functions for each node of the AST.

Related

Is there a way to register types from gobject introspection?

I'm currently experimenting with the gobject-introspection library. One thing I would like to do is to be able to register types (classes in particular) from the information I can obtain. Specifically so I can get a GLib.Type which I can then use to instantiate a class with GLib.Object.new
I have successfully loaded a namespace from a typelib, and I can get information about the classes etc in the namespace, but I am uncertain how to move on from there?
static void main(string[] args){
var rep = GI.Repository.get_default();
rep.require("Gtk", null, 0);
var oinfo = (GI.ObjectInfo)rep.find_by_name("Gtk", "Button");
}
from oinfo i can now easily obtain the name, etc. of the class, I have all the metadata there, as far as I can tell. But suppose I can not reference the type like: typeof(Gtk.Button) or otherwise directly refer to it in the code, how to I register this type with the type system so that I may instantiate it?
Right, so I have solved this myself, after a LOT of tinkering. But after all it turned out not to be so difficult. The most involved way to do this is using a shared library that has just been compiled, so my example will involve that:
First, lets create a shared library containing just one class in one file:
namespace TestLib{
public class TestBase : Object{
private static int counter = 0;
public int count{
get{
return ++counter;
}
}
}
}
This needs to be compiled to a shared library file
valac --library=TestLib -H TestLib-1.0.h --gir=TestLib-1.0.gir TestLib.vala -X -fPIC -X -shared -o TestLib.so
Then use the gir compiler and generate the typelib
g-ir-compiler --shared-library=TestLib TestLib-1.0.gir -o TestLib-1.0.typelib
Then we write the program we want to run:
using GI;
namespace TestRunner{
static int main(string[] args){
var namesp = "TestLib"; //set the name of the namespace we want to load
var rep = Repository.get_default(); //Obtain default repository
rep.require_private(".", namesp, null, 0); //load namespace info from the current folder (this assumes the typelib is here)
var rtinfo = (RegisteredTypeInfo)rep.find_by_name(namesp, "TestBase"); //retrieves the BaseInfo of any type in the "TestLib" namespace called "TestBase" and casts it
var type = rtinfo.get_g_type(); //Calls the get type, registrering the type with the type system, so now it can be used as we wish
var objt = Object.new(type); //object is instantiated, and we can use it
Value val = Value(typeof(int));
objt.get_property("count", ref val);
message(val.get_int().to_string());
objt.get_property("count", ref val);
message(val.get_int().to_string());
message("type is: %s".printf(type.name()));
return 0;
}
}
Then we compile this program: valac TestLib.vapi TestRunner.vala -X TestLib.so -X -I. -o testintro --pkg=gobject-introspection-1.0
And before we run it, we will remember to add this dir to the path, so the program knows where to find the shared library: export LD_LIBRARY_PATH=.
finally we run the new program: ./testintro
And we should see:
** Message: 22:45:18.556: TestRunner.vala:9: Chosen namespace is: TestLib
** Message: 22:45:18.556: TestRunner.vala:24: 1
** Message: 22:45:18.556: TestRunner.vala:28: 2
** Message: 22:45:18.556: TestRunner.vala:30: type is: TestLibTestBase

pragma solidity - compilation error in jpmorganchase cakeshop

I am running a simple code from SimpleStorage example and just added few lines on top of it which I was using for my other contracts. The contract compiles fine from truffle. But on the Cakeshop Integrated IDE it shows compilation error.
pragma solidity ^0.4.24;
pragma experimental ABIEncoderV2;
contract SimpleStorage {
uint public storedData;
event Change(string message, uint newVal);
function SimpleStorage(uint initVal) {
Change("initialized", initVal);
storedData = initVal;
}
function set(uint x) {
Change("set", x);
storedData = x;
}
function get() constant returns (uint retVal) {
return storedData;
}
}
It should compile on the cakeshop web UI as it compiles on local machine
Utilizing Remix, it seems the following could be potential issues with your contract:
You are using the Contract name for the constructor. You should use the constructor keyword instead.
All of your functions are missing visibility modifiers. Consider adding the public modifier to each function including the constructor.
Events should be invoked using the emit keyword. Example: emit Change("set", x);

How to communicate from pure C (.c files) SDK to IOS (obj-C, .m files) framework?

Preface: I have little experience with C integration in iOS, feel free to correct me on any misinterpretations I have about this.
I have a project that has a custom 2-tier "SDK" both written in C. The coreSDK makes method calls to the deviceSDK which communicates with the ios framework to execute hardware actions (ie. enable camera) or retrieve device information (ie. path to NSDocumentDirectory).
Unfortunately, due to the infrastructure, both SDK file extensions use (.h) and (.c) and cannot be changed to (.m) as some sources recommended. According to what I've read, I can create C-callbacks to the ObjC methods but that's only really viable for singletons, and the C-callback needs to be within the scope of the (.m) file.
I have tried creating a wrapper class in ObjC such that it has a C-callback from which the deviceSDK calls to, but when including the header(.h) for that (.m), the compiler seems to crash. If my understanding is correct, it's because the C-compiler cannot interpret the ObjC language contained in the (.m).
I believe theoretically is possible to write iOS apps in pure C with ObjC runtime, but ideally would rather not go down that route as what I've seen is absurdly complicated.
An example workflow
ViewController.m method calls to coreSDK method (.c)
coreSDK method calls to deviceSDK method (.c)
deviceSDK needs to retrieve (for example) NSDocumentDirectory (or enable camera)
How can I achieve this?
Code examples would be most comprehensive and appreciated.
Thanks!
These are some(not all) references I've already looked into...
How to write ios app purely in c
Pure C function calling Objective-C method
C function calling objective C functions
Using native objective-c method for C callbacks
Callback methods from C to Objective-C
Mixing C functions in an Objective-C class
How to call an Objective-C method from a C method
How to use pure C files in an objective-C project
Edit: 2016-07-21
To clarify the issue, I'm having trouble making calls from C methods in (.c) files to ObjC methods in (.m) files, or figuring out an alternative means to retrieve information such as (for example) NSDocumentsDirectory in ObjC (.m files) and passing back to C in (.c) files.
Example Code: Of course it's incorrect but it's along the lines of my expectations or what I'm hoping to achieve.
//GPS.h
#include "GPSWrapper.h"
STATUS_Code GPSInitialize(void);
//GPS.c
#include "GPS.h"
STATUS_Code GPSInitialize(void) {
GPS_cCallback();
}
//GPSWrapper.h
#import <Foundation/Foundation.h>
#interface GPSWrapper: NSObject
- (void) testObjC;
#end
//GPSWrapper.m
#import "GPSWrapper.h"
static id refToSelf = nil;
#implementation GPSWrapper
- (void) testObjC {
// just an example of a ObjC method call
NSString *documentsDirectory = [paths objectAtIndex:0];
NSLog(documentsDirectory);
}
#end
static void GPS_cCallback() {
[refToSelf testObjC];
}
This line #include "GPSWrapper.h" in your example is the problem. You can't include a header that has ObjC syntax in a file that's being compiled as C. Any interface to the ObjC side that's being included in your C code needs to be broken out into its own header that contains only valid C. Here's a demo of what you need:
First, header and implementation file for the C-only stuff.
// CUtils.h
// OCFromC
#ifndef CUtils_h
#define CUtils_h
#include <stdio.h>
void doThatThingYouDo();
void doThatThingWithThisObject(const void * objRef);
#endif /* CUtils_h */
// CUtils.c
// OCFromC
// Proof that this is being compiled without ObjC
#ifdef __OBJC__
#error "Compile this as C, please."
#endif
#include "CUtils.h"
#include "StringCounterCInterface.h"
void doThatThingYouDo()
{
printf("%zu\n", numBytesInUTF32("Calliope"));
}
void doThatThingWithThisObject(const void * objRef)
{
size_t len = numBytesInUTF32WithRef(objRef, "Calliope");
printf("%zu\n", len);
}
Note that second function; if you need to, you can pass around an object reference in C land, as long as it's cloaked in a void *. There's also some casting that needs to be done for memory management. More on that below.
This is the exciting ObjC class we'll be using:
// StringCounter.h
// OCFromC
#import <Foundation/Foundation.h>
#interface StringCounter : NSObject
- (size_t)lengthOfBytesInUTF32:(const char *)s;
#end
// StringCounter.m
// OCFromC
#import "StringCounter.h"
#implementation StringCounter
- (size_t)lengthOfBytesInUTF32:(const char *)s
{
NSString * string = [NSString stringWithUTF8String:s];
return [string lengthOfBytesUsingEncoding:NSUTF32StringEncoding];
}
#end
Now, this is the important part. This is a header file that declares C functions. The header itself contains no ObjC, so it can be included in CUtils.c as you saw above.
// StringCounterCInterface.h
// OCFromC
#ifndef StringCounterCInterface_h
#define StringCounterCInterface_h
// Get size_t definition
#import <stddef.h>
size_t numBytesInUTF32(const char * s);
size_t numBytesInUTF32WithRef(const void * scRef, const char *s);
#endif /* StringCounterCInterface_h */
This is the connection point. Its implementation file is compiled as ObjC, and it contains the definitions of those functions just declared. This file imports the interface of StringCounter, and so the functions can use methods from that class:
// StringCounterCInterface.m
// OCFromC
#ifndef __OBJC__
#error "Must compile as ObjC"
#endif
#import "StringCounterCInterface.h"
#import "StringCounter.h"
size_t numBytesInUTF32(const char * s)
{
StringCounter * sc = [StringCounter new];
// Or, use some "default" object in static storage here
return [sc lengthOfBytesInUTF32:s];
}
size_t numBytesInUTF32WithRef(const void * objRef, const char * s)
{
StringCounter * sc = (__bridge_transfer StringCounter *)objRef;
return [sc lengthOfBytesInUTF32:s];
}
Now, in main or wherever you like you can exercise those functions from CUtils:
// main.m
// OCFromC
#import <Foundation/Foundation.h>
#import "StringCounter.h"
#import "CUtils.h"
int main(int argc, const char * argv[]) {
#autoreleasepool {
doThatThing();
// Create an object reference
StringCounter * sc = [StringCounter new];
// Tell ARC that I know this is dangerous, trust me,
// pass this reference along.
const void * scRef = (__bridge_retained void *)sc;
doThatThingWithThisObject(scRef);
}
return 0;
}
The bridging cast, along with its counterpart in StringCounterCInterface.m, lets you move an ObjC object through areas where ARC cannot go. It bumps the object's retain count before it is hidden in the void *, so that it will not be accidentally deallocated before you can __bridge_transfer it back to ObjC land.
One final note: If you are going to be passing object references around in C a lot, you might consider doing typedef void * StringCounterRef; and changing the signatures of everything appropriately.

using llvm RecursiveASTVisitor for Objective C and iOS

I would like to use clang to preprocess objective C files from an iOS app. I looked over the source code and am trying to implement a pre-processor based on the RecursiveASTVisitor class. However, I seem to be running into many issues that I cannot resolve. I developed a preprocessor to add a "Enter" call at the beginning of each method and an "Exit" call at the end. I also added an "Exit" call before each return statement. I am using the following code to do the instrumentation:
class ExampleVisitor : public RecursiveASTVisitor<ExampleVisitor> {
private:
ASTContext *astContext; // used for getting additional AST info
std::string funcName;
public:
explicit ExampleVisitor(CompilerInstance *CI)
: astContext(&(CI->getASTContext())) // initialize private members
{
rewriter.setSourceMgr(astContext->getSourceManager(), astContext->getLangOpts());
}
virtual bool VisitObjCMethodDecl(ObjCMethodDecl *ND) {
funcName = ND->getDeclName().getAsString();
errs() << "Testing function: " << funcName << "\n";
if (ND->hasBody()) {
rewriter.InsertText(ND->getBody()->getSourceRange().getBegin().getLocWithOffset(1), "\nEnter(\""+funcName+"\");\n");
rewriter.InsertText(ND->getBody()->getSourceRange().getEnd(),"Exit(\""+funcName+"\");\n");
}
return true;
}
virtual bool VisitReturnStmt(ReturnStmt *ret) {
rewriter.InsertText(ret->getSourceRange().getBegin(), "\nExit(\""+funcName+"\");\n");
errs() << "** Rewrote ReturnStmt\n";
return true;
}
virtual ~ExampleVisitor() {}
};
class ExampleASTConsumer : public ASTConsumer {
private:
ExampleVisitor *visitor; // doesn't have to be private
public:
// override the constructor in order to pass CI
explicit ExampleASTConsumer(CompilerInstance *CI)
: visitor(new ExampleVisitor(CI)) // initialize the visitor
{ }
// override this to call our ExampleVisitor on the entire source file
virtual void HandleTranslationUnit(ASTContext &Context) {
/* we can use ASTContext to get the TranslationUnitDecl, which is
a single Decl that collectively represents the entire source file */
visitor->TraverseDecl(Context.getTranslationUnitDecl());
}
};
The code compiles. I created a command line executable "instrument". I then used the following command to run this on a simple Objective C program generated by Xcode:
instrument AppDelegate.m --
I run into two problems. First, I get the error: 'UIKit/UIKit.h' file not found. This is one of the includes generated by Xcode. Second, I'm seeing only some of the return statements being processed in the file. Can someone give me some insights into what is happening?
I'm using the 3.7.0 version of llvm.

Do C++ Templates play nicely with VCL classes?

I'm trying to use C++ Template 'mixins' to create some new VCL components with shared additional functionality. Example...
template <class T> class Mixin : public T
{
private:
typedef T inherited;
// ...additional methods
public:
Mixin(TComponent *owner) : inherited(owner)
{
// .. do stuff here
};
};
Used like this:
class MyLabel : public Mixin<TLabel>
{
....
}
class MyEdit : public Mixin<TEdit>
{
....
}
Now, everything compiles fine, and the mixin stuff seems to work - until I try and save the component to a stream using TStream->WriteComponent, where the inherited properties (eg TLabel.Width/Height/etc.) don't get written. This is even with a 'null' mixin like the one shown above.
My code works fine when just deriving classes directly from TForm, TEdit, etc - and the class is correctly registered with the streaming system.
The quick/simple answer is: no; when dealing with a template, the compiler won't generate the proper descriptors to make streaming working. However, since this has come up before, I peeked under the cover to find out what's missing. And what I found is that it's almost there. So here's a little more information.
Upfront the compiler will never treat a template-based type as a Delphi. For example, do something like this:
void testing()
{
__classid(Mixin<Stdctrls::TLabel>); // Error Here
}
... and you'll see the error
"Error E2242 test.cpp 53: __classid requires Delphi style class type (i.e. class marked __declspec(delphiclass) or derived from System::TObject) in function testing()"
This basically says the compiler does not consider this type/class as compatible with Delphi-classes [i.e. those that derive from TObject]. Internally there's just a flag on the symbol that says whether the type is delphi-compatible or not. And I noticed that I could trick the compiler into marking the type as delphi-style if I forced it to walk up the hierarchy.. which is something it has to do if I create an instance of the object. So, with this hack the error goes away:
void testing()
{
typedef Mixin<Stdctrls::TLabel> __ttype;
std::auto_ptr<__ttype> c2(new __ttype(0));
__classid(Mixin<Stdctrls::TLabel>); // No more errors here
}
But much nicer was actually to use the __declspec(delphiclass) directly on the template, as in:
template <class T>
class __declspec(delphiclass) Mixin : public T {
private:
int i;
typedef T inherited;
public:
__fastcall Mixin(TComponent *owner) : inherited(owner) {};
};
So now that the compiler treats the type as a delphi-style class without hacks, I peeked a little more and found the issue you're probably running into: Delphi classes have the TTypeData.PropCount field - http://docwiki.embarcadero.com/VCL/en/TypInfo.TTypeData - which is a sum of the class' properties, including those of its base classes. Due to the way the various pieces of information are computed, the compiler writes out a '0' for that field when a template is involved:(
You can see this by printing out the PropCount, as in:
#include <Stdctrls.hpp>
#include <cstdio>
#include <memory>
#include <utilcls.h>
class TCppComp : public Classes::TComponent {
int i;
public:
__fastcall TCppComp(TComponent* owner): Classes::TComponent(owner) {};
__published:
__property int AAAA = {read=i, write=i};
};
template <class T>
class __declspec(delphiclass) Mixin : public T {
private:
int i;
typedef T inherited;
public:
__fastcall Mixin(TComponent *owner) : inherited(owner) {};
};
typedef Mixin<TCppComp> TMixinComp;
void showProps(TClass meta) {
PTypeInfo pInfo = PTypeInfo(meta->ClassInfo());
int Count = GetPropList(pInfo, tkAny, NULL);
TAPtr<PPropInfo> List(new PPropInfo[Count]);
std::printf("Class: %s - Total Props:%d\n",
AnsiString(pInfo->Name).c_str(), Count);
GetPropList(pInfo, tkAny, *(reinterpret_cast<PPropList*>(&List)));
for (int i = 0; i < Count; i++) {
AnsiString propName(List[i]->Name);
std::printf("\t%s\n", propName.c_str());
}
}
void test() {
showProps(__classid(TCppComp));
showProps(__classid(TMixinComp));
}
int main() {
test();
return 0;
}
When run the above prints:
Class: TCppComp - Total Props:3
AAAA
Name
Tag
Class: #%Mixin$8TCppComp% - Total Props:0
IOW, Mixin shows up with '0' published properties while its base type has 3:(
I suspect the streaming system relies on this count and that's why inherited properties are not being written out in your setup.
I considered tweaking the generated descriptors at runtime but since we write them to _TEXT it's bound to trigger DEP.
I'll look at the logic that computes the PropCount to see if there's some way to get it to compute the correct number. If time allows, please do open a QC for this: now that I've peek underneath, I believe it would not require much effort to get this working as expected.
Cheers,
Bruneau
PS: In my sample I even had the Mixin publish a property and the compiler generated the correct descriptor for that property; however, the total count was still zero.

Resources