#include "llvmruby.h" extern VALUE cLLVMBasicBlock; extern VALUE cLLVMBuilder; extern "C" { VALUE llvm_basic_block_wrap(BasicBlock* bb) { return Data_Wrap_Struct(cLLVMBasicBlock, NULL, NULL, bb); } VALUE llvm_basic_block_size(VALUE self) { BasicBlock *bb = LLVM_BASIC_BLOCK(self); return INT2NUM(bb->size()); } VALUE llvm_basic_block_get_instruction_list(VALUE self) { BasicBlock *bb = LLVM_BASIC_BLOCK(self); VALUE ins_array = rb_ary_new(); BasicBlock::iterator ins = bb->begin(); while(ins != bb->end()) { Instruction *i = ins++; rb_ary_push(ins_array, llvm_instruction_wrap(i)); } return ins_array; } VALUE llvm_basic_block_builder(VALUE self) { BasicBlock* bb; Data_Get_Struct(self, BasicBlock, bb); IRBuilder<> *builder = new IRBuilder<>(bb); return Data_Wrap_Struct(cLLVMBuilder, NULL, NULL, builder); } #define DATA_GET_BUILDER IRBuilder<> *builder; Data_Get_Struct(self, IRBuilder<>, builder); #define DATA_GET_BLOCK BasicBlock *bb; CHECK_TYPE(rbb, cLLVMBasicBlock); Data_Get_Struct(rbb, BasicBlock, bb); VALUE llvm_builder_set_insert_point(VALUE self, VALUE rbb) { DATA_GET_BUILDER DATA_GET_BLOCK builder->SetInsertPoint(bb); return self; } VALUE llvm_builder_bin_op(VALUE self, VALUE rbin_op, VALUE rv1, VALUE rv2) { Check_Type(rbin_op, T_FIXNUM); //CHECK_TYPE(rv1, cLLVMValue); //CHECK_TYPE(rv2, cLLVMValue); DATA_GET_BUILDER Instruction::BinaryOps bin_op = (Instruction::BinaryOps)FIX2INT(rbin_op); Value *v1, *v2; Data_Get_Struct(rv1, Value, v1); Data_Get_Struct(rv2, Value, v2); Value *res = builder->CreateBinOp(bin_op, v1, v2); return llvm_value_wrap(res); } VALUE llvm_builder_phi(VALUE self, VALUE type) { CHECK_TYPE(type, cLLVMType); DATA_GET_BUILDER PHINode *v = builder->CreatePHI(LLVM_TYPE(type)); return Data_Wrap_Struct(cLLVMPhi, NULL, NULL, v); } VALUE llvm_phi_add_incoming(VALUE self, VALUE val, VALUE rbb) { CHECK_TYPE(val, cLLVMValue); DATA_GET_BLOCK PHINode *phi = LLVM_PHI(self); phi->addIncoming(LLVM_VAL(val), bb); return self; } VALUE llvm_builder_return(VALUE self, VALUE rv) { //CHECK_TYPE(rv, cLLVMValue); DATA_GET_BUILDER return llvm_value_wrap(builder->CreateRet(LLVM_VAL(rv))); } VALUE llvm_builder_br(VALUE self, VALUE rblock) { DATA_GET_BUILDER BasicBlock *bb; Data_Get_Struct(rblock, BasicBlock, bb); Value *branch_instr = builder->CreateBr(bb); return Data_Wrap_Struct(cLLVMBranchInst, NULL, NULL, branch_instr); } VALUE llvm_builder_cond_br(VALUE self, VALUE rcond, VALUE rtrue_block, VALUE rfalse_block) { DATA_GET_BUILDER Value *cond; Data_Get_Struct(rcond, Value, cond); BasicBlock *true_block, *false_block; Data_Get_Struct(rtrue_block, BasicBlock, true_block); Data_Get_Struct(rfalse_block, BasicBlock, false_block); Value *branch_instr = builder->CreateCondBr(cond, true_block, false_block); return Data_Wrap_Struct(cLLVMBranchInst, NULL, NULL, branch_instr); } VALUE llvm_builder_switch(VALUE self, VALUE rv, VALUE rdefault) { DATA_GET_BUILDER BasicBlock *deflt; Data_Get_Struct(rdefault, BasicBlock, deflt); Value *v; Data_Get_Struct(rv, Value, v); Value* switch_instr = builder->CreateSwitch(v, deflt); return Data_Wrap_Struct(cLLVMSwitchInst, NULL, NULL, switch_instr); } VALUE llvm_builder_malloc(VALUE self, VALUE rtype, VALUE rsize) { DATA_GET_BUILDER const Type *type; Data_Get_Struct(rtype, Type, type); Value *size = ConstantInt::get(Type::Int32Ty, FIX2INT(rsize)); Value *v = builder->CreateMalloc(type, size); return llvm_value_wrap(v); } VALUE llvm_builder_free(VALUE self, VALUE rptr) { DATA_GET_BUILDER Value *v = LLVM_VAL(rptr); builder->CreateFree(v); return Qtrue; } VALUE llvm_builder_alloca(VALUE self, VALUE rtype, VALUE rsize) { DATA_GET_BUILDER const Type* type; Data_Get_Struct(rtype, Type, type); Value *size = ConstantInt::get(Type::Int32Ty, FIX2INT(rsize)); Value *v = builder->CreateAlloca(type, size); return llvm_value_wrap(v); } VALUE llvm_builder_load(VALUE self, VALUE rptr) { DATA_GET_BUILDER Value *ptr; Data_Get_Struct(rptr, Value, ptr); return llvm_value_wrap(builder->CreateLoad(ptr)); } VALUE llvm_builder_store(VALUE self, VALUE rv, VALUE rptr) { DATA_GET_BUILDER Value *v, *ptr; Data_Get_Struct(rv, Value, v); Data_Get_Struct(rptr, Value, ptr); return llvm_value_wrap(builder->CreateStore(v, ptr)); } VALUE llvm_builder_icmp(VALUE self, VALUE pred, VALUE lhs, VALUE rhs) { DATA_GET_BUILDER CmpInst::Predicate p = (CmpInst::Predicate)FIX2INT(pred); Value *v = builder->CreateICmp(p, LLVM_VAL(lhs), LLVM_VAL(rhs)); return llvm_value_wrap(v); } VALUE llvm_builder_fcmp(VALUE self, VALUE pred, VALUE lhs, VALUE rhs) { DATA_GET_BUILDER CmpInst::Predicate p = (CmpInst::Predicate)FIX2INT(pred); Value *v = builder->CreateFCmp(p, LLVM_VAL(lhs), LLVM_VAL(rhs)); return llvm_value_wrap(v); } VALUE llvm_builder_gep(VALUE self, VALUE rptr, VALUE ridx) { DATA_GET_BUILDER Value *ptr, *idx; Data_Get_Struct(rptr, Value, ptr); Data_Get_Struct(ridx, Value, idx); return llvm_value_wrap(builder->CreateGEP(ptr, idx)); } VALUE llvm_builder_struct_gep(VALUE self, VALUE rptr, VALUE ridx) { DATA_GET_BUILDER Value *ptr; Data_Get_Struct(rptr, Value, ptr); return llvm_value_wrap(builder->CreateStructGEP(ptr, FIX2INT(ridx))); } VALUE llvm_builder_cast(VALUE self, VALUE rop, VALUE rv, VALUE rdest_ty) { DATA_GET_BUILDER Instruction::CastOps op = (Instruction::CastOps)FIX2INT(rop); Value *v; Data_Get_Struct(rv, Value, v); Type *dest_ty; Data_Get_Struct(rdest_ty, Type, dest_ty); return llvm_value_wrap(builder->CreateCast(op, v, dest_ty)); } VALUE llvm_builder_int_to_ptr(VALUE self, VALUE ri, VALUE rtype) { DATA_GET_BUILDER Value *i; Data_Get_Struct(ri, Value, i); const Type* type; Data_Get_Struct(rtype, Type, type); return llvm_value_wrap(builder->CreateIntToPtr(i, type)); } VALUE llvm_builder_int_cast(VALUE self, VALUE i, VALUE type, VALUE sign) { DATA_GET_BUILDER bool isSigned = (sign != Qnil && sign != Qfalse); return llvm_value_wrap(builder->CreateIntCast(LLVM_VAL(i), LLVM_TYPE(type), isSigned)); } VALUE llvm_builder_call(int argc, VALUE* argv, VALUE self) { DATA_GET_BUILDER Function *callee = LLVM_FUNCTION(argv[0]); int num_args = argc-1; Value** args = (Value**)alloca(num_args*sizeof(Value*)); for(int i = 0; i < num_args; ++i) { args[i] = LLVM_VAL(argv[i+1]); } return llvm_value_wrap(builder->CreateCall(callee, args, args+num_args)); } VALUE llvm_builder_insert_element(VALUE self, VALUE rv, VALUE rnv, VALUE ridx) { DATA_GET_BUILDER Value *v, *nv, *idx; Data_Get_Struct(rv, Value, v); Data_Get_Struct(rnv, Value, nv); Data_Get_Struct(ridx, Value, idx); return llvm_value_wrap(builder->CreateInsertElement(v, nv, idx)); } VALUE llvm_builder_extract_element(VALUE self, VALUE rv, VALUE ridx) { DATA_GET_BUILDER Value *v, *idx; Data_Get_Struct(rv, Value, v); Data_Get_Struct(ridx, Value, idx); return llvm_value_wrap(builder->CreateExtractElement(v, idx)); } VALUE llvm_builder_get_global(VALUE self) { GlobalVariable *g = new GlobalVariable(Type::Int64Ty, false, GlobalValue::ExternalLinkage, 0, "shakalaka"); return llvm_value_wrap(g); } VALUE llvm_builder_create_global_string_ptr(VALUE self, VALUE str) { DATA_GET_BUILDER Value *v = builder->CreateGlobalStringPtr(StringValuePtr(str)); return llvm_value_wrap(v); } }