Skip to content

Commit

Permalink
Adding support for reading integer and float constants.
Browse files Browse the repository at this point in the history
  • Loading branch information
plessl committed Nov 14, 2008
1 parent 277de21 commit cc60d93
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 0 deletions.
62 changes: 62 additions & 0 deletions ext/llvm_value.cpp
Expand Up @@ -101,6 +101,68 @@ llvm_value_get_immediate_constant(VALUE self, VALUE v) {
return llvm_value_wrap(ConstantInt::get(type, (long)v));
}

VALUE
llvm_value_is_constant(VALUE self) {
Value *v;
Data_Get_Struct(self, Value, v);
return isa<Constant>(v) ? Qtrue : Qfalse;
}

VALUE
llvm_value_is_int_constant(VALUE self) {
Value *v;
Data_Get_Struct(self, Value, v);
return isa<ConstantInt>(v) ? Qtrue : Qfalse;
}

VALUE
llvm_value_is_float_constant(VALUE self) {
Value *v;
Data_Get_Struct(self, Value, v);
return isa<ConstantFP>(v) ? Qtrue : Qfalse;
}

VALUE
llvm_value_get_int_constant_value(VALUE self) {
Value *v;
Data_Get_Struct(self, Value, v);
if (ConstantInt *C = dyn_cast<ConstantInt>(v)) {
APInt val = C->getValue();
return LL2NUM(val.getLimitedValue());
} else {
rb_raise(rb_eTypeError, "Argument not an integer constant");
}
}

VALUE
llvm_value_get_float_constant_value(VALUE self) {
Value *v;
Data_Get_Struct(self, Value, v);
if (ConstantFP *C = dyn_cast<ConstantFP>(v)) {
APFloat val = C->getValueAPF();
return rb_float_new(val.convertToFloat());
} else {
rb_raise(rb_eTypeError, "Argument not a float constant");
}
}


VALUE
llvm_value_is_null(VALUE self) {
Value *v;
Data_Get_Struct(self, Value, v);
if (Constant *C = dyn_cast<Constant>(v))
return C->isNullValue() ? Qtrue : Qfalse;
return Qfalse;
}

VALUE
llvm_value_is_undef(VALUE self) {
Value *v;
Data_Get_Struct(self, Value, v);
return isa<UndefValue>(v) ? Qtrue : Qfalse;
}

VALUE
llvm_type_pointer(VALUE self, VALUE rtype) {
Type *type;
Expand Down
16 changes: 16 additions & 0 deletions ext/llvmruby.c
Expand Up @@ -129,6 +129,14 @@ VALUE llvm_value_num_uses(VALUE);
VALUE llvm_value_used_in_basic_block(VALUE, VALUE);
VALUE llvm_value_replace_all_uses_with(VALUE, VALUE);

VALUE llvm_value_is_constant(VALUE self);
VALUE llvm_value_is_int_constant(VALUE self);
VALUE llvm_value_is_float_constant(VALUE self);
VALUE llvm_value_get_int_constant_value(VALUE self);
VALUE llvm_value_get_float_constant_value(VALUE self);
VALUE llvm_value_is_null(VALUE self);
VALUE llvm_value_is_undef(VALUE self);

VALUE llvm_user_get_operand_list(VALUE);
VALUE llvm_user_get_num_operands(VALUE);
VALUE llvm_user_get_operand(VALUE, VALUE);
Expand Down Expand Up @@ -209,6 +217,14 @@ void Init_llvmruby() {
rb_define_method(cLLVMValue, "used_in_basic_block?", llvm_value_used_in_basic_block, 1);
rb_define_method(cLLVMValue, "replace_all_uses_with", llvm_value_replace_all_uses_with, 1);

rb_define_method(cLLVMValue, "is_constant", llvm_value_is_constant, 0);
rb_define_method(cLLVMValue, "is_int_constant", llvm_value_is_int_constant, 0);
rb_define_method(cLLVMValue, "is_float_constant", llvm_value_is_float_constant, 0);
rb_define_method(cLLVMValue, "get_int_constant_value", llvm_value_get_int_constant_value, 0);
rb_define_method(cLLVMValue, "get_float_constant_value", llvm_value_get_float_constant_value, 0);
rb_define_method(cLLVMValue, "is_null", llvm_value_is_null, 0);
rb_define_method(cLLVMValue, "is_undef", llvm_value_is_undef, 0);

rb_define_method(cLLVMUser, "get_operand_list", llvm_user_get_operand_list, 0);
rb_define_method(cLLVMUser, "get_num_operands", llvm_user_get_num_operands, 0);
rb_define_method(cLLVMUser, "get_operand", llvm_user_get_operand, 1);
Expand Down
63 changes: 63 additions & 0 deletions test/test_value.rb
@@ -0,0 +1,63 @@
require 'test/unit'
require 'llvm'

include LLVM

class ValueTests < Test::Unit::TestCase

def setup
@assembly=<<-EOF
; ModuleID = 'constants.o'
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
target triple = "i386-apple-darwin9"
@CONST_PI = constant float 0x400921FA00000000 ; <float*> [#uses=0]
define float @circle_area(float %radius) nounwind {
entry:
%tmp2 = mul float %radius, 0x400921FA00000000 ; <float> [#uses=1]
%tmp4 = mul float %tmp2, %radius ; <float> [#uses=1]
ret float %tmp4
}
define i32 @add_42(i32 %x) nounwind {
entry:
%tmp2 = add i32 %x, 42 ; <i32> [#uses=1]
ret i32 %tmp2
}
EOF

@m = LLVM::Module.read_assembly(@assembly)
end

def test_check_value_is_constant
add42 = @m.get_function("add_42")
assert(add42)
ins = add42.get_basic_block_list[0].get_instruction_list
add_ins = ins[0]
assert_equal(false,add_ins.get_operand(0).is_constant())
assert_equal(true,add_ins.get_operand(1).is_constant())
end

def test_get_integer_constant_values
add42 = @m.get_function("add_42")
assert(add42)
ins = add42.get_basic_block_list[0].get_instruction_list
add_ins = ins[0]
assert(add_ins.get_operand(1).is_constant())
assert(add_ins.get_operand(1).is_int_constant())
assert_equal(42,add_ins.get_operand(1).get_int_constant_value())
end

def test_get_float_constant_values
circle_area = @m.get_function("circle_area")
assert(circle_area)
ins = circle_area.get_basic_block_list[0].get_instruction_list
add_ins = ins[0]
assert_equal(false,add_ins.get_operand(0).is_constant())
assert_equal(true,add_ins.get_operand(1).is_constant())
assert_equal(true,add_ins.get_operand(1).is_float_constant())
assert_in_delta(3.14159, add_ins.get_operand(1).get_float_constant_value(), 2 ** -20)
end

end

0 comments on commit cc60d93

Please sign in to comment.