Permalink
Browse files

merge changes from miura, global variables and other good stuff, bumb…

… the gem version
  • Loading branch information...
Tom Bagby
Tom Bagby committed Dec 24, 2008
1 parent e829dc8 commit 144bb46bded94648aaaf19c4bf686e1417579342
Showing with 155 additions and 12 deletions.
  1. +67 −5 ext/llvm_basicblock.cpp
  2. +34 −2 ext/llvm_module.cpp
  3. +8 −0 ext/llvm_value.cpp
  4. +10 −4 ext/llvmruby.c
  5. +3 −0 ext/llvmruby.h
  6. +1 −1 llvmruby.gemspec
  7. +32 −0 test/test_basic.rb
View
@@ -107,6 +107,11 @@ llvm_builder_cond_br(VALUE self, VALUE rcond, VALUE rtrue_block, VALUE rfalse_bl
BasicBlock *true_block, *false_block;
Data_Get_Struct(rtrue_block, BasicBlock, true_block);
Data_Get_Struct(rfalse_block, BasicBlock, false_block);
+#if defined(USE_ASSERT_CHECK)
+ if (cond->getType() != Type::Int1Ty) {
+ rb_raise(rb_eRuntimeError, "May only branch on boolean predicates!");
+ }
+#endif
Value *branch_instr = builder->CreateCondBr(cond, true_block, false_block);
return Data_Wrap_Struct(cLLVMBranchInst, NULL, NULL, branch_instr);
@@ -126,6 +131,32 @@ llvm_builder_switch(VALUE self, VALUE rv, VALUE rdefault) {
return llvm_instruction_wrap(switch_instr);
}
+VALUE
+llvm_builder_invoke(int argc, VALUE *argv, VALUE self) {
+ DATA_GET_BUILDER
+ if(argc < 3) { rb_raise(rb_eArgError, "Expected at least three argument"); }
+ int num_args = argc - 3;
+
+ Value *callee = LLVM_VAL(argv[0]);
+ BasicBlock *ndest;
+ BasicBlock *udest;
+ std::vector<Value *> vecarg(num_args);
+
+ Data_Get_Struct(argv[1], BasicBlock, ndest);
+ Data_Get_Struct(argv[2], BasicBlock, udest);
+ for (int i = 0; i < num_args; i++) {
+ vecarg[i] = LLVM_VAL(argv[i + 3]);
+ }
+
+ return llvm_value_wrap(builder->CreateInvoke(callee, ndest, udest, vecarg.begin(), vecarg.end()));
+}
+
+VALUE
+llvm_builder_unwind(VALUE self) {
+ DATA_GET_BUILDER
+ return llvm_value_wrap(builder->CreateUnwind());
+}
+
VALUE
llvm_builder_malloc(VALUE self, VALUE rtype, VALUE rsize) {
DATA_GET_BUILDER
@@ -159,22 +190,30 @@ llvm_builder_alloca(VALUE self, VALUE rtype, VALUE rsize) {
}
VALUE
-llvm_builder_load(VALUE self, VALUE rptr) {
+llvm_builder_load(int argc, VALUE *argv, VALUE self) {
DATA_GET_BUILDER
-
+ VALUE rptr;
+ VALUE isVolatile;
Value *ptr;
+
+ rb_scan_args(argc, argv, "11", &rptr, &isVolatile);
Data_Get_Struct(rptr, Value, ptr);
- return Data_Wrap_Struct(cLLVMLoadInst, NULL, NULL, builder->CreateLoad(ptr));
+ return Data_Wrap_Struct(cLLVMLoadInst, NULL, NULL, builder->CreateLoad(ptr, RTEST(isVolatile)));
}
VALUE
-llvm_builder_store(VALUE self, VALUE rv, VALUE rptr) {
+llvm_builder_store(int argc, VALUE *argv, VALUE self) {
DATA_GET_BUILDER
Value *v, *ptr;
+ VALUE rv;
+ VALUE rptr;
+ VALUE isVolatile;
+
+ rb_scan_args(argc, argv, "21", &rv, &rptr, &isVolatile);
Data_Get_Struct(rv, Value, v);
Data_Get_Struct(rptr, Value, ptr);
- return Data_Wrap_Struct(cLLVMStoreInst, NULL, NULL, builder->CreateStore(v, ptr));
+ return Data_Wrap_Struct(cLLVMStoreInst, NULL, NULL, builder->CreateStore(v, ptr, RTEST(isVolatile)));
}
VALUE
@@ -255,8 +294,31 @@ llvm_builder_call(int argc, VALUE* argv, VALUE self) {
Function *callee = LLVM_FUNCTION(argv[0]);
int num_args = argc-1;
Value** args = (Value**)alloca(num_args*sizeof(Value*));
+
+#if defined(USE_ASSERT_CHECK)
+ const FunctionType *FTy =
+ cast<FunctionType>(cast<PointerType>(callee->getType())->getElementType());
+ char message[255];
+ if (!((unsigned)num_args == FTy->getNumParams() ||
+ (FTy->isVarArg() && (unsigned) num_args > FTy->getNumParams()))) {
+ snprintf(message, 255,
+ "Calling a function with bad signature number of argument %d expect %d",
+ num_args, FTy->getNumParams());
+ rb_raise(rb_eRuntimeError, message);
+ }
+#endif
+
for(int i = 0; i < num_args; ++i) {
args[i] = LLVM_VAL(argv[i+1]);
+
+#if defined(USE_ASSERT_CHECK)
+ if (FTy->getParamType(i) != args[i]->getType()) {
+ snprintf(message, 255,
+ "Calling a function with a bad signature in %d argument",
+ i);
+ rb_raise(rb_eRuntimeError, message);
+ }
+#endif
}
return llvm_value_wrap(builder->CreateCall(callee, args, args+num_args));
}
View
@@ -3,6 +3,7 @@
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/System/DynamicLibrary.h"
#include <fstream>
#include <sstream>
@@ -27,7 +28,16 @@ llvm_module_get_or_insert_function(VALUE self, VALUE name, VALUE rtype) {
Module *m = LLVM_MODULE(self);
FunctionType *type = LLVM_FUNC_TYPE(rtype);
- Function *f = cast<Function>(m->getOrInsertFunction(StringValuePtr(name), type));
+ Constant *fn = m->getOrInsertFunction(StringValuePtr(name), type);
+
+#if defined(USE_ASSERT_CHECK)
+ if (isa<Function>(fn) == 0) {
+ rb_raise(rb_eRuntimeError,
+ "cast<Function>(fn) argument of incompatible type !");
+ }
+#endif
+
+ Function *f = cast<Function>(fn);
return llvm_function_wrap(f);
}
@@ -40,14 +50,23 @@ llvm_module_get_function(VALUE self, VALUE name) {
}
VALUE
-llvm_module_global_variable(VALUE self, VALUE rtype, VALUE rinitializer) {
+llvm_module_global_constant(VALUE self, VALUE rtype, VALUE rinitializer) {
Module *m = LLVM_MODULE(self);
Type *type = LLVM_TYPE(rtype);
Constant *initializer = (Constant*)DATA_PTR(rinitializer);
GlobalVariable *gv = new GlobalVariable(type, true, GlobalValue::InternalLinkage, initializer, "", m);
return llvm_value_wrap(gv);
}
+VALUE
+llvm_module_global_variable(VALUE self, VALUE rtype, VALUE rinitializer) {
+ Module *m = LLVM_MODULE(self);
+ Type *type = LLVM_TYPE(rtype);
+ Constant *initializer = (Constant*)DATA_PTR(rinitializer);
+ GlobalVariable *gv = new GlobalVariable(type, false, GlobalValue::InternalLinkage, initializer, "", m);
+ return llvm_value_wrap(gv);
+}
+
VALUE
llvm_module_inspect(VALUE self) {
@@ -94,6 +113,14 @@ VALUE
llvm_execution_engine_get(VALUE klass, VALUE module) {
CHECK_TYPE(module, cLLVMModule);
+#if defined(__CYGWIN__)
+
+ // Load dll Modules for ruby
+ sys::DynamicLibrary::LoadLibraryPermanently("cygwin1.dll");
+ sys::DynamicLibrary::LoadLibraryPermanently("cygruby190.dll");
+
+#endif
+
Module *m = LLVM_MODULE(module);
ExistingModuleProvider *MP = new ExistingModuleProvider(m);
@@ -139,7 +166,12 @@ VALUE
llvm_module_read_bitcode(VALUE self, VALUE bitcode) {
Check_Type(bitcode, T_STRING);
+#if defined(RSTRING_PTR)
+ MemoryBuffer *buf = MemoryBuffer::getMemBufferCopy(RSTRING_PTR(bitcode),RSTRING_PTR(bitcode)+RSTRING_LEN(bitcode));
+#else
MemoryBuffer *buf = MemoryBuffer::getMemBufferCopy(RSTRING(bitcode)->ptr,RSTRING(bitcode)->ptr+RSTRING(bitcode)->len);
+#endif
+
Module *module = ParseBitcodeFile(buf);
delete buf;
return Data_Wrap_Struct(cLLVMModule, NULL, NULL, module);
View
@@ -70,12 +70,20 @@ llvm_value_get_constant(VALUE self, VALUE type, VALUE v) {
VALUE
llvm_value_get_float_constant(VALUE self, VALUE v) {
+#if defined(RFLOAT_VALUE)
+ return llvm_value_wrap(ConstantFP::get(Type::FloatTy, RFLOAT_VALUE(v)));
+#else
return llvm_value_wrap(ConstantFP::get(Type::FloatTy, RFLOAT(v)->value));
+#endif
}
VALUE
llvm_value_get_double_constant(VALUE self, VALUE v) {
+#if defined(RFLOAT_VALUE)
+ return llvm_value_wrap(ConstantFP::get(Type::DoubleTy, RFLOAT_VALUE(v)));
+#else
return llvm_value_wrap(ConstantFP::get(Type::DoubleTy, RFLOAT(v)->value));
+#endif
}
VALUE
View
@@ -48,6 +48,7 @@ VALUE llvm_module_allocate(VALUE);
VALUE llvm_module_initialize(VALUE);
VALUE llvm_module_get_or_insert_function(VALUE, VALUE);
VALUE llvm_module_get_function(VALUE, VALUE);
+VALUE llvm_module_global_constant(VALUE, VALUE, VALUE);
VALUE llvm_module_global_variable(VALUE, VALUE, VALUE);
VALUE llvm_module_external_function(VALUE, VALUE, VALUE);
VALUE llvm_module_read_assembly(VALUE, VALUE);
@@ -98,12 +99,14 @@ VALUE llvm_builder_return(VALUE, VALUE);
VALUE llvm_builder_br(VALUE, VALUE);
VALUE llvm_builder_cond_br(VALUE, VALUE, VALUE, VALUE);
VALUE llvm_builder_switch(VALUE, VALUE, VALUE);
+VALUE llvm_builder_invoke(int, VALUE *, VALUE);
+VALUE llvm_builder_unwind(VALUE, VALUE, VALUE);
VALUE llvm_builder_malloc(VALUE, VALUE, VALUE);
VALUE llvm_builder_free(VALUE, VALUE);
VALUE llvm_builder_alloca(VALUE, VALUE, VALUE);
-VALUE llvm_builder_load(VALUE, VALUE);
-VALUE llvm_builder_store(VALUE, VALUE, VALUE);
+VALUE llvm_builder_load(int, VALUE *, VALUE);
+VALUE llvm_builder_store(int, VALUE *, VALUE);
VALUE llvm_builder_icmp(VALUE, VALUE, VALUE, VALUE);
VALUE llvm_builder_fcmp(VALUE, VALUE, VALUE, VALUE);
VALUE llvm_builder_gep(VALUE, VALUE, VALUE);
@@ -241,6 +244,7 @@ void Init_llvmruby() {
rb_define_method(cLLVMModule, "initialize", llvm_module_initialize, 1);
rb_define_method(cLLVMModule, "get_or_insert_function", llvm_module_get_or_insert_function, 2);
rb_define_method(cLLVMModule, "get_function", llvm_module_get_function, 1);
+ rb_define_method(cLLVMModule, "global_constant", llvm_module_global_constant, 2);
rb_define_method(cLLVMModule, "global_variable", llvm_module_global_variable, 2);
rb_define_method(cLLVMModule, "external_function", llvm_module_external_function, 2);
rb_define_method(cLLVMModule, "write_bitcode", llvm_module_write_bitcode, 1);
@@ -288,11 +292,13 @@ void Init_llvmruby() {
rb_define_method(cLLVMBuilder, "br", llvm_builder_br, 1);
rb_define_method(cLLVMBuilder, "cond_br", llvm_builder_cond_br, 3);
rb_define_method(cLLVMBuilder, "switch", llvm_builder_switch, 2);
+ rb_define_method(cLLVMBuilder, "invoke", llvm_builder_invoke, -1);
+ rb_define_method(cLLVMBuilder, "unwind", llvm_builder_unwind, 0);
rb_define_method(cLLVMBuilder, "malloc", llvm_builder_malloc, 2);
rb_define_method(cLLVMBuilder, "free", llvm_builder_free, 1);
rb_define_method(cLLVMBuilder, "alloca", llvm_builder_alloca, 2);
- rb_define_method(cLLVMBuilder, "load", llvm_builder_load, 1);
- rb_define_method(cLLVMBuilder, "store", llvm_builder_store, 2);
+ rb_define_method(cLLVMBuilder, "load", llvm_builder_load, -1);
+ rb_define_method(cLLVMBuilder, "store", llvm_builder_store, -1);
rb_define_method(cLLVMBuilder, "icmp", llvm_builder_icmp, 3);
rb_define_method(cLLVMBuilder, "fcmp", llvm_builder_fcmp, 3);
View
@@ -63,6 +63,9 @@ extern VALUE cLLVMPassManager;
rb_raise(rb_eTypeError, "wrong argument type: %s given, expected %s", rb_obj_classname(val), rb_class2name(klass));\
}
+
+#define USE_ASSERT_CHECK
+
extern "C" {
VALUE llvm_value_wrap(Value*);
VALUE llvm_user_wrap(User*);
View
@@ -1,7 +1,7 @@
spec = Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.name = "llvmruby"
- s.version = "0.0.5" # Can't require version file on Github
+ s.version = "0.0.6" # Can't require version file on Github
s.summary = "Ruby bindings to LLVM"
s.authors = [ "Thomas Bagby", "Christian Plessl" ]
s.email = [ "tomatobagby@gmail.com", "christian@plesslweb.ch" ]
View
@@ -264,6 +264,17 @@ def test_struct_constants
struct_const = Value.get_struct_constant(struct_type, 2.llvm(int_t), 3.llvm(int_t), 5.llvm(int_t))
assert_kind_of(Value, struct_const)
+ m = LLVM::Module.new('globals')
+ gv = m.global_constant(struct_type, struct_const)
+ assert_kind_of(Value, gv)
+ end
+
+ def test_struct_variable
+ int_t = Type::Int32Ty
+ struct_type = Type.struct([int_t, int_t, int_t])
+ struct_const = Value.get_struct_constant(struct_type, 2.llvm(int_t), 3.llvm(int_t), 5.llvm(int_t))
+ assert_kind_of(Value, struct_const)
+
m = LLVM::Module.new('globals')
gv = m.global_variable(struct_type, struct_const)
assert_kind_of(Value, gv)
@@ -337,4 +348,25 @@ def test_type_to_s
def test_type_type_id
assert_equal IntegerTyID, 2.llvm.type.type_id
end
+
+ def test_invoke_unwind
+ m = LLVM::Module.new("unwind_test_module")
+ type = Type::function(MACHINE_WORD, [])
+ f2 = m.get_or_insert_function("unwind_test2", type)
+ b = f2.create_block.builder
+ b.unwind
+
+ type = Type::function(MACHINE_WORD, [])
+ f = m.get_or_insert_function("unwind_test", type)
+ b = f.create_block.builder
+ nd = f.create_block
+ ud = f.create_block
+ b.invoke(f2, nd, ud)
+ b.set_insert_point(ud)
+ b.return(3.llvm)
+ b.set_insert_point(nd)
+ b.return(1.llvm)
+ ExecutionEngine.get(m)
+ m.write_bitcode("test/foo.bc")
+ end
end

0 comments on commit 144bb46

Please sign in to comment.