Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Build box and arithmetic for other types #20

Merged
merged 8 commits into from Apr 30, 2017

Conversation

Projects
None yet
2 participants
@bollu
Copy link
Contributor

commented Apr 26, 2017

  • Box Float literals
  • addition for int & float

Note that while the IR may seem eccentric at first glance, I'm dividing the different kinds of additions into fine grained calls so I can take advantage of type inference.

Since I have:

define { i32, i64 }* @balloon_add_box_f64_box_f64({ i32, i64 }* %box1, { i32, i64 }* %box2) {
entry:
  %raw1 = call double @unbox_balloon_float({ i32, i64 }* %box1)
  %raw2 = call double @unbox_balloon_float({ i32, i64 }* %box2)
  %sum = fadd double %raw1, %raw2
  %boxed_sum = call { i32, i64 }* @box_balloon_float(double %sum)
  ret { i32, i64 }* %boxed_sum
}

define { i32, i64 }* @balloon_add_box_i64_box_i64({ i32, i64 }* %box1, { i32, i64 }* %box2) {
entry:
  %raw1 = call i64 @unbox_balloon_int({ i32, i64 }* %box1)
  %raw2 = call i64 @unbox_balloon_int({ i32, i64 }* %box2)
  %sum = add i64 %raw1, %raw2
  %boxed_sum = call { i32, i64 }* @box_balloon_int(i64 %sum)
  ret { i32, i64 }* %boxed_sum
}

define { i32, i64 }* @balloon_add_box_box({ i32, i64 }* %box1, { i32, i64 }* %box2) {
entry:
  %tag1 = call i32 @unbox_tag({ i32, i64 }* %box1)
  %tag2 = call i32 @unbox_tag({ i32, i64 }* %box2)
  %int_tag_val = load i32, i32* @balloon_int
  %is_1_int = icmp eq i32 %tag1, %int_tag_val
  %is_2_int = icmp eq i32 %tag2, %int_tag_val
  %int_int_pred = and i1 %is_1_int, %is_2_int
  br i1 %int_int_pred, label %int_int, label %float_float

float_float:                                      ; preds = %entry
  %sum = call { i32, i64 }* @balloon_add_box_f64_box_f64({ i32, i64 }* %box1, { i32, i64 }* %box2)
  ret { i32, i64 }* %sum

int_int:                                          ; preds = %entry
  %sum1 = call { i32, i64 }* @balloon_add_box_i64_box_i64({ i32, i64 }* %box1, { i32, i64 }* %box2)
  ret { i32, i64 }* %sum1
}

define { i32, i64 }* @main() {
init:
  %final_rawmem = call i8* @malloc(i32 ptrtoint ({ i32, i64 }* getelementptr ({ i32, i64 }, { i32, i64 }* null, i32 1) to i32))
  %final = bitcast i8* %final_rawmem to { i32, i64 }*
  %valp = call { i32, i64 }* @box_balloon_int(i64 1)
  %valp1 = call { i32, i64 }* @box_balloon_int(i64 1)
  %sum = call { i32, i64 }* @balloon_add_box_box({ i32, i64 }* %valp, { i32, i64 }* %valp1)
  %stmt_val = load { i32, i64 }, { i32, i64 }* %sum
  store { i32, i64 } %stmt_val, { i32, i64 }* %final
  ret { i32, i64 }* %final
}
  • main may seem insanely wasteful, since there's a bunch of boxing and unboxing that's going on there. However, the cool part is that I'm basically compiling to a mini register based VM, with instructions such as box_int, unbox_int, add_box_box, etc.

  • I can implement high level fusion of operations, such as removing boxing & unboxing between consecutive arithmetic operations as a LLVM pass. This is neat, since I can now gradually lower all my function calls.

  • If I have type information, which I may have in lots of cases, I can raise a call of add_box_box to add_box_int_add_box_int if both the parameters involved are known to be integers. Again, this can be a custom pass called raiseArithOperations or something.

  • The aim is to have a nanopass style compiler that gradually applies high level transformations, and then opens this up to low level optimisations (eg. inlining), which again paves the way to further high level transformations.

@bollu bollu force-pushed the bollu:box-other-primitives branch from da10b53 to 27851c6 Apr 26, 2017

@bollu bollu force-pushed the bollu:box-other-primitives branch from 7a04736 to 262e5be Apr 29, 2017

ref env,
..
} => {
Function::User { ref param_names, ref body, ref env, .. } => {

This comment has been minimized.

Copy link
@polybuildr

polybuildr Apr 30, 2017

Owner

Ah, not wanting these rustfmt changes will require you to rebase on master (or at least copy rustfmt.toml) ensure that it's updated, and then run rustfmt.

This comment has been minimized.

Copy link
@bollu

bollu Apr 30, 2017

Author Contributor

uh, I did rebase over upstream/master

This comment has been minimized.

Copy link
@polybuildr

polybuildr Apr 30, 2017

Owner

That's odd. The rustfmt lint is failing on Travis is failing too.

I think this is your rustfmt version. Mine (and Travis') is currently 0.8.3.

@bollu

This comment has been minimized.

Copy link
Contributor Author

commented Apr 30, 2017

@polybuildr merge?

@polybuildr

This comment has been minimized.

Copy link
Owner

commented Apr 30, 2017

Looked through the code, ran some manual tests, looks good. :D Thanks again for great work, merging!

@polybuildr polybuildr merged commit 705868c into polybuildr:master Apr 30, 2017

1 check passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.