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

bollu
Copy link
Contributor

@bollu bollu 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.

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uh, I did rebase over upstream/master

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Contributor Author

bollu commented Apr 30, 2017

@polybuildr merge?

@polybuildr
Copy link
Owner

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants