Add builtins for compound assignment operators. (#5335)

Provide builtins for compound assignments instead of defining them in
the prelude as a use of a binary operator and an assignment. This allows
us to lower compound assignment directly to LLVM operations instead of
producing a function call. In the short term this also allows us to
define a type-generic compound assignment in the prelude.
This commit is contained in:
Richard Smith
2025-04-21 20:38:11 +00:00
committed by GitHub
parent 2bdea71c25
commit b5ae988a08
39 changed files with 1373 additions and 312 deletions
+3 -3
View File
@@ -33,7 +33,7 @@ fn F() -> i32 {
// CHECK:STDOUT: %Convert.specific_fn: <specific function> = specific_function %Convert.956, @Convert.2(%int_32) [concrete]
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %int_0.5c6, %Convert.specific_fn [concrete]
// CHECK:STDOUT: %int_0.6a9: %i32 = int_value 0 [concrete]
// CHECK:STDOUT: %ptr: type = ptr_type %i32 [concrete]
// CHECK:STDOUT: %ptr.235: type = ptr_type %i32 [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -83,9 +83,9 @@ fn F() -> i32 {
// CHECK:STDOUT: }
// CHECK:STDOUT: %n: ref %i32 = bind_name n, %n.var
// CHECK:STDOUT: %n.ref: ref %i32 = name_ref n, %n
// CHECK:STDOUT: %addr.loc13_13: %ptr = addr_of %n.ref
// CHECK:STDOUT: %addr.loc13_13: %ptr.235 = addr_of %n.ref
// CHECK:STDOUT: %.loc13_12: ref %i32 = deref %addr.loc13_13
// CHECK:STDOUT: %addr.loc13_11: %ptr = addr_of %.loc13_12
// CHECK:STDOUT: %addr.loc13_11: %ptr.235 = addr_of %.loc13_12
// CHECK:STDOUT: %.loc13_10.1: ref %i32 = deref %addr.loc13_11
// CHECK:STDOUT: %.loc13_10.2: %i32 = bind_value %.loc13_10.1
// CHECK:STDOUT: return %.loc13_10.2
+10 -10
View File
@@ -35,7 +35,7 @@ fn F() -> i32 {
// CHECK:STDOUT: %Convert.specific_fn: <specific function> = specific_function %Convert.956, @Convert.2(%int_32) [concrete]
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %int_0.5c6, %Convert.specific_fn [concrete]
// CHECK:STDOUT: %int_0.6a9: %i32 = int_value 0 [concrete]
// CHECK:STDOUT: %ptr: type = ptr_type %i32 [concrete]
// CHECK:STDOUT: %ptr.235: type = ptr_type %i32 [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -85,21 +85,21 @@ fn F() -> i32 {
// CHECK:STDOUT: }
// CHECK:STDOUT: %n: ref %i32 = bind_name n, %n.var
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %p.patt: %ptr = binding_pattern p
// CHECK:STDOUT: %.loc13_3: %ptr = var_pattern %p.patt
// CHECK:STDOUT: %p.patt: %ptr.235 = binding_pattern p
// CHECK:STDOUT: %.loc13_3: %ptr.235 = var_pattern %p.patt
// CHECK:STDOUT: }
// CHECK:STDOUT: %p.var: ref %ptr = var p
// CHECK:STDOUT: %p.var: ref %ptr.235 = var p
// CHECK:STDOUT: %n.ref: ref %i32 = name_ref n, %n
// CHECK:STDOUT: %addr: %ptr = addr_of %n.ref
// CHECK:STDOUT: %addr: %ptr.235 = addr_of %n.ref
// CHECK:STDOUT: assign %p.var, %addr
// CHECK:STDOUT: %.loc13_13: type = splice_block %ptr [concrete = constants.%ptr] {
// CHECK:STDOUT: %.loc13_13: type = splice_block %ptr [concrete = constants.%ptr.235] {
// CHECK:STDOUT: %int_32.loc13: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc13: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %ptr: type = ptr_type %i32.loc13 [concrete = constants.%ptr]
// CHECK:STDOUT: %ptr: type = ptr_type %i32.loc13 [concrete = constants.%ptr.235]
// CHECK:STDOUT: }
// CHECK:STDOUT: %p: ref %ptr = bind_name p, %p.var
// CHECK:STDOUT: %p.ref: ref %ptr = name_ref p, %p
// CHECK:STDOUT: %.loc15_11: %ptr = bind_value %p.ref
// CHECK:STDOUT: %p: ref %ptr.235 = bind_name p, %p.var
// CHECK:STDOUT: %p.ref: ref %ptr.235 = name_ref p, %p
// CHECK:STDOUT: %.loc15_11: %ptr.235 = bind_value %p.ref
// CHECK:STDOUT: %.loc15_10.1: ref %i32 = deref %.loc15_11
// CHECK:STDOUT: %.loc15_10.2: %i32 = bind_value %.loc15_10.1
// CHECK:STDOUT: return %.loc15_10.2
+18 -18
View File
@@ -39,7 +39,7 @@ var a: i32* = a_ref;
// CHECK:STDOUT: %Convert.specific_fn: <specific function> = specific_function %Convert.956, @Convert.2(%int_32) [concrete]
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %int_0.5c6, %Convert.specific_fn [concrete]
// CHECK:STDOUT: %int_0.6a9: %i32 = int_value 0 [concrete]
// CHECK:STDOUT: %ptr: type = ptr_type %i32 [concrete]
// CHECK:STDOUT: %ptr.235: type = ptr_type %i32 [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -69,16 +69,16 @@ var a: i32* = a_ref;
// CHECK:STDOUT: }
// CHECK:STDOUT: %a_orig: ref %i32 = bind_name a_orig, %a_orig.var
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %a_ref.patt: %ptr = binding_pattern a_ref
// CHECK:STDOUT: %.loc5_1: %ptr = var_pattern %a_ref.patt
// CHECK:STDOUT: %a_ref.patt: %ptr.235 = binding_pattern a_ref
// CHECK:STDOUT: %.loc5_1: %ptr.235 = var_pattern %a_ref.patt
// CHECK:STDOUT: }
// CHECK:STDOUT: %a_ref.var: ref %ptr = var a_ref
// CHECK:STDOUT: %.loc5_15: type = splice_block %ptr [concrete = constants.%ptr] {
// CHECK:STDOUT: %a_ref.var: ref %ptr.235 = var a_ref
// CHECK:STDOUT: %.loc5_15: type = splice_block %ptr [concrete = constants.%ptr.235] {
// CHECK:STDOUT: %int_32.loc5: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc5: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %ptr: type = ptr_type %i32.loc5 [concrete = constants.%ptr]
// CHECK:STDOUT: %ptr: type = ptr_type %i32.loc5 [concrete = constants.%ptr.235]
// CHECK:STDOUT: }
// CHECK:STDOUT: %a_ref: ref %ptr = bind_name a_ref, %a_ref.var
// CHECK:STDOUT: %a_ref: ref %ptr.235 = bind_name a_ref, %a_ref.var
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
@@ -92,7 +92,7 @@ var a: i32* = a_ref;
// CHECK:STDOUT: %.loc4: init %i32 = converted %int_0, %int.convert_checked [concrete = constants.%int_0.6a9]
// CHECK:STDOUT: assign file.%a_orig.var, %.loc4
// CHECK:STDOUT: %a_orig.ref: ref %i32 = name_ref a_orig, file.%a_orig
// CHECK:STDOUT: %addr: %ptr = addr_of %a_orig.ref
// CHECK:STDOUT: %addr: %ptr.235 = addr_of %a_orig.ref
// CHECK:STDOUT: assign file.%a_ref.var, %addr
// CHECK:STDOUT: return
// CHECK:STDOUT: }
@@ -102,12 +102,12 @@ var a: i32* = a_ref;
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete]
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete]
// CHECK:STDOUT: %ptr: type = ptr_type %i32 [concrete]
// CHECK:STDOUT: %ptr.9e1: type = ptr_type %i32 [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Implicit.a_orig = import_ref Implicit//default, a_orig, unloaded
// CHECK:STDOUT: %Implicit.a_ref: ref %ptr = import_ref Implicit//default, a_ref, loaded
// CHECK:STDOUT: %Implicit.a_ref: ref %ptr.9e1 = import_ref Implicit//default, a_ref, loaded
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [concrete] {
// CHECK:STDOUT: .Int = %Core.Int
// CHECK:STDOUT: import Core//prelude
@@ -126,22 +126,22 @@ var a: i32* = a_ref;
// CHECK:STDOUT: %default.import = import <none>
// CHECK:STDOUT: %Core.import = import Core
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %a.patt: %ptr = binding_pattern a
// CHECK:STDOUT: %.loc4_1: %ptr = var_pattern %a.patt
// CHECK:STDOUT: %a.patt: %ptr.9e1 = binding_pattern a
// CHECK:STDOUT: %.loc4_1: %ptr.9e1 = var_pattern %a.patt
// CHECK:STDOUT: }
// CHECK:STDOUT: %a.var: ref %ptr = var a
// CHECK:STDOUT: %.loc4_11: type = splice_block %ptr [concrete = constants.%ptr] {
// CHECK:STDOUT: %a.var: ref %ptr.9e1 = var a
// CHECK:STDOUT: %.loc4_11: type = splice_block %ptr [concrete = constants.%ptr.9e1] {
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %ptr: type = ptr_type %i32 [concrete = constants.%ptr]
// CHECK:STDOUT: %ptr: type = ptr_type %i32 [concrete = constants.%ptr.9e1]
// CHECK:STDOUT: }
// CHECK:STDOUT: %a: ref %ptr = bind_name a, %a.var
// CHECK:STDOUT: %a: ref %ptr.9e1 = bind_name a, %a.var
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %a_ref.ref: ref %ptr = name_ref a_ref, imports.%Implicit.a_ref
// CHECK:STDOUT: %.loc4: %ptr = bind_value %a_ref.ref
// CHECK:STDOUT: %a_ref.ref: ref %ptr.9e1 = name_ref a_ref, imports.%Implicit.a_ref
// CHECK:STDOUT: %.loc4: %ptr.9e1 = bind_value %a_ref.ref
// CHECK:STDOUT: assign file.%a.var, %.loc4
// CHECK:STDOUT: return
// CHECK:STDOUT: }