mem: Steps 5-7 — context-identifier rebind + interp ctx bootstrap

Step 5 — `context` resolves through `current_ctx_ref`. The compile-time
emit of the default GPA into the `context` global is gone; entry points
already bind `current_ctx_ref` to `&__sx_default_context` and every
sx-to-sx call forwards it. `allocViaContext` sources from
`current_ctx_ref` too. `matchContextAllocCall` is kept as a comptime
escape hatch: the ct_module spun up by `evalComptimeString` doesn't get
the full Allocator/CAllocator/Context type registration so the protocol-
dispatch chain wouldn't run in the interp; codegen also wins from the
direct libc malloc/free.

Step 6 — `push Context.{...}` stack-discipline rewrite. Allocates a
fresh `Context` slot, binds `current_ctx_ref` to it for the body's
lexical scope, restores on exit. No global, no walk.

Step 7 — interp parity. `defaultContextValue()` builds the Context
aggregate (CAllocator thunks for alloc/dealloc, null data) on demand.
`interp.call` bootstraps slot_ptr(0) when an entry function with
implicit ctx is called sans args; `materializeCtxArg` dereferences the
caller's slot_ptr into the aggregate at every sx-to-sx call boundary so
the callee's `load(ref_0)` lands on the value; `load` of an aggregate
is a passthrough. `.global_addr` of `__sx_default_context` returns the
aggregate directly so exported entries' first-line `global_addr(...)`
runs cleanly in `#run`.

`ct_lowering` inherits `implicit_ctx_enabled` + `has_implicit_ctx` so
functions lowered into the ct module carry ctx like their main-module
twins.

152/152 example tests pass. Snapshots regen.
This commit is contained in:
agra
2026-05-25 09:10:04 +03:00
parent 92c6b47f12
commit 4bf5908792
14 changed files with 440 additions and 966 deletions

View File

@@ -164,6 +164,37 @@ pub const Interpreter = struct {
self.hooks.deinit();
}
// ── Implicit Context ──────────────────────────────────────────
/// Build the default Context aggregate for top-level interp calls.
/// Mirrors the static `__sx_default_context` LLVM global: a Context
/// whose `allocator` field is the stateless CAllocator inline-protocol
/// value (alloc/dealloc thunks bottom out at libc malloc/free).
fn defaultContextValue(self: *Interpreter) Value {
const tbl_ptr: *const @import("types.zig").TypeTable = &self.module.types;
const tbl = @constCast(tbl_ptr);
const alloc_thunk_name = tbl.internString("__thunk_CAllocator_Allocator_alloc");
const dealloc_thunk_name = tbl.internString("__thunk_CAllocator_Allocator_dealloc");
var alloc_fn: Value = .null_val;
var dealloc_fn: Value = .null_val;
for (self.module.functions.items, 0..) |func, i| {
if (func.name == alloc_thunk_name) alloc_fn = .{ .func_ref = FuncId.fromIndex(@intCast(i)) };
if (func.name == dealloc_thunk_name) dealloc_fn = .{ .func_ref = FuncId.fromIndex(@intCast(i)) };
}
const allocator_fields = self.alloc.alloc(Value, 3) catch unreachable;
allocator_fields[0] = .null_val; // CAllocator receiver — stateless
allocator_fields[1] = alloc_fn;
allocator_fields[2] = dealloc_fn;
const allocator_val: Value = .{ .aggregate = allocator_fields };
const ctx_fields = self.alloc.alloc(Value, 2) catch unreachable;
ctx_fields[0] = allocator_val;
ctx_fields[1] = .null_val;
return .{ .aggregate = ctx_fields };
}
// ── Heap operations ────────────────────────────────────────────
fn heapAlloc(self: *Interpreter, size: usize) Value.HeapPtr {
@@ -367,9 +398,23 @@ pub const Interpreter = struct {
var frame = Frame.initSized(self.alloc, total_refs);
defer frame.deinit();
// Bind parameters as initial refs (indices 0..N-1)
// Implicit-context bootstrap: when an entry point with implicit
// ctx is called without an explicit ctx arg, materialise the
// default context in a fresh slot and bind slot_ptr(0) to ref 0.
// This is the interp-side equivalent of FFI-inbound wrappers
// installing `&__sx_default_context` at function entry.
var skip_first: u32 = 0;
if (func.has_implicit_ctx and args.len + 1 == func.params.len) {
const ctx_val = self.defaultContextValue();
const slot = frame.allocSlot(self.alloc);
frame.storeSlot(slot, ctx_val);
frame.setRef(0, .{ .slot_ptr = slot });
skip_first = 1;
}
// Bind parameters as initial refs (indices skip_first..N-1)
for (args, 0..) |arg, i| {
frame.setRef(@intCast(i), arg);
frame.setRef(@intCast(i + skip_first), arg);
}
// Start at the entry block (index 0)
@@ -536,6 +581,10 @@ pub const Interpreter = struct {
}
return .{ .value = slot_val };
},
// The implicit __sx_ctx arrives as an aggregate after
// materializeCtxArg dereferences the caller's slot_ptr.
// `load(ref_0)` then naturally yields the Context value.
.aggregate => return .{ .value = ptr },
else => return error.CannotEvalComptime,
}
},
@@ -667,6 +716,14 @@ pub const Interpreter = struct {
// its own slot table and read garbage.
args[i] = self.materializeForCall(frame, frame.getRef(ref));
}
// The implicit __sx_ctx is logically a `*Context` but the
// interp can't dereference cross-frame slot_ptrs. Materialise
// args[0] to the loaded Context aggregate so the callee can
// treat its slot 0 as the value directly.
const callee_func = self.module.getFunction(c.callee);
if (callee_func.has_implicit_ctx and args.len >= 1) {
args[0] = self.materializeCtxArg(frame, args[0]);
}
const result = try self.call(c.callee, args);
return .{ .value = result };
},
@@ -1020,8 +1077,18 @@ pub const Interpreter = struct {
const val = try self.getGlobal(gid);
return .{ .value = val };
},
.global_addr => {
// Address-of-global not meaningful in interpreter
.global_addr => |gid| {
// The implicit-context default global is the only global
// whose address sees runtime use. Return the Context
// aggregate directly so `load(args[0])` yields it via the
// aggregate-passthrough branch of the `.load` handler.
if (gid.index() < self.module.globals.items.len) {
const global = &self.module.globals.items[gid.index()];
const name = self.module.types.getString(global.name);
if (std.mem.eql(u8, name, "__sx_default_context")) {
return .{ .value = self.defaultContextValue() };
}
}
return error.CannotEvalComptime;
},
.func_ref => |fid| {
@@ -1114,7 +1181,11 @@ pub const Interpreter = struct {
const args = self.alloc.alloc(Value, ci.args.len) catch return error.CannotEvalComptime;
defer self.alloc.free(args);
for (ci.args, 0..) |ref, i| {
args[i] = frame.getRef(ref);
args[i] = self.materializeForCall(frame, frame.getRef(ref));
}
const target = self.module.getFunction(fid);
if (target.has_implicit_ctx and args.len >= 1) {
args[0] = self.materializeCtxArg(frame, args[0]);
}
const result = try self.call(fid, args);
return .{ .value = result };
@@ -1232,6 +1303,17 @@ pub const Interpreter = struct {
/// emitted by `struct_gep` / `index_gep`) into the resolved parent value.
/// Slot indices are frame-local; a slice passed across a call would otherwise
/// read its data_ptr out of the callee's slot table.
/// Resolve the implicit __sx_ctx arg to its loaded Context value so
/// callees can treat their own slot 0 as the aggregate directly
/// (no cross-frame slot_ptr indirection).
fn materializeCtxArg(self: *Interpreter, frame: *Frame, val: Value) Value {
_ = self;
return switch (val) {
.slot_ptr => |slot| frame.loadSlot(slot),
else => val,
};
}
fn materializeForCall(self: *Interpreter, frame: *Frame, val: Value) Value {
switch (val) {
.aggregate => |fields| {

View File

@@ -1014,11 +1014,6 @@ pub const Lowering = struct {
}
}
// Auto-initialize context with default GPA at the start of main()
if (std.mem.eql(u8, name, "main")) {
self.emitDefaultContextInit();
}
// Lower the function body (set target_type to return type for implicit returns)
const saved_target = self.target_type;
self.target_type = if (ret_ty != .void) ret_ty else null;
@@ -1907,6 +1902,18 @@ pub const Lowering = struct {
.enum_tag => |et| break :blk self.builder.constInt(@intCast(et.tag), et.ty),
}
}
// `context` resolves to a load through the lowering's
// current `__sx_ctx` pointer. Every sx function (and
// every `push Context.{...}` body) sets `current_ctx_ref`
// to a `*Context` it owns, so this is one indirection.
if (self.implicit_ctx_enabled and std.mem.eql(u8, id.name, "context")) {
if (self.current_ctx_ref != Ref.none) {
const ctx_ty = self.module.types.findByName(self.module.types.internString("Context")) orelse {
break :blk self.emitError("context", node.span);
};
break :blk self.builder.load(self.current_ctx_ref, ctx_ty);
}
}
// Check globals (#run constants)
if (self.global_names.get(id.name)) |gi| {
break :blk self.builder.emit(.{ .global_get = gi.id }, gi.ty);
@@ -5013,7 +5020,11 @@ pub const Lowering = struct {
}
}
// Pattern-match context.allocator.alloc/dealloc → heap_alloc/heap_free
// Pattern-match context.allocator.alloc/dealloc → heap_alloc/heap_free.
// The comptime interp doesn't register the full Allocator
// protocol in ct_module, so the protocol-dispatch chain it
// would otherwise emit can't run. Codegen also benefits —
// direct libc malloc/free, no thunk indirection.
if (self.matchContextAllocCall(fa, args.items)) |ref| return ref;
// Type constructor call: Sx(f32).user(0.5) — obj is a call that returns a type
@@ -5459,15 +5470,18 @@ pub const Lowering = struct {
/// allocators.sx, so the fallback exists strictly for the bootstrapping
/// edge case.
fn allocViaContext(self: *Lowering, size_ref: Ref, void_ptr_ty: TypeId) Ref {
const ctx_gi = self.global_names.get("context") orelse {
if (!self.implicit_ctx_enabled or self.current_ctx_ref == Ref.none) {
return self.builder.emit(.{ .heap_alloc = .{ .operand = size_ref } }, void_ptr_ty);
}
const ctx_ty = self.module.types.findByName(self.module.types.internString("Context")) orelse {
return self.builder.emit(.{ .heap_alloc = .{ .operand = size_ref } }, void_ptr_ty);
};
const ctx_ty_info = self.module.types.get(ctx_gi.ty);
const ctx_ty_info = self.module.types.get(ctx_ty);
if (ctx_ty_info != .@"struct" or ctx_ty_info.@"struct".fields.len < 1) {
return self.builder.emit(.{ .heap_alloc = .{ .operand = size_ref } }, void_ptr_ty);
}
const allocator_ty = ctx_ty_info.@"struct".fields[0].ty;
const ctx = self.builder.emit(.{ .global_get = ctx_gi.id }, ctx_gi.ty);
const ctx = self.builder.load(self.current_ctx_ref, ctx_ty);
const allocator = self.builder.structGet(ctx, 0, allocator_ty);
// #inline Allocator protocol layout: { ctx, alloc_fn_ptr, dealloc_fn_ptr }.
// field 0 = receiver ctx, field 1 = alloc fn-ptr.
@@ -5512,16 +5526,18 @@ pub const Lowering = struct {
return new_args;
}
/// Pattern-match `context.allocator.alloc(size)` → heap_alloc,
/// `context.allocator.dealloc(ptr)` → heap_free.
/// Pattern-match `context.allocator.alloc(size)` → heap_alloc and
/// `context.allocator.dealloc(ptr)` → heap_free. Required because the
/// comptime interpreter doesn't get a full type/protocol registration
/// of the Allocator chain; the protocol-dispatch lowering would
/// produce IR that the interp can't execute. Codegen wins from this
/// short-circuit too (libc malloc/free direct, no thunk indirection
/// for the trivial default-context case).
fn matchContextAllocCall(self: *Lowering, fa: ast.FieldAccess, call_args: []const Ref) ?Ref {
// fa is the callee field_access: expecting .alloc or .dealloc
if (!std.mem.eql(u8, fa.field, "alloc") and !std.mem.eql(u8, fa.field, "dealloc")) return null;
// fa.object should be `context.allocator` — another field_access
if (fa.object.data != .field_access) return null;
const inner = fa.object.data.field_access;
if (!std.mem.eql(u8, inner.field, "allocator")) return null;
// inner.object should be `context` — an identifier
if (inner.object.data != .identifier) return null;
if (!std.mem.eql(u8, inner.object.data.identifier.name, "context")) return null;
@@ -5530,7 +5546,6 @@ pub const Lowering = struct {
const ptr_void = self.module.types.ptrTo(.void);
return self.builder.emit(.{ .heap_alloc = .{ .operand = call_args[0] } }, ptr_void);
} else {
// dealloc
if (call_args.len < 1) return null;
return self.builder.emit(.{ .heap_free = .{ .operand = call_args[0] } }, .void);
}
@@ -6171,23 +6186,30 @@ pub const Lowering = struct {
}
fn lowerPush(self: *Lowering, ps: *const ast.PushStmt) void {
// push context_expr { body }
// → save = global_get(context), global_set(context, new_val), body, global_set(context, save)
const gi = self.global_names.get("context") orelse {
// No context global — just lower the body without push/pop
// push Context.{...} { body } — allocates a fresh Context on the
// stack frame, rebinds the lowering's `current_ctx_ref` to it for
// the body's lexical scope, then restores. No global, no walk.
if (!self.implicit_ctx_enabled) {
self.lowerBlock(ps.body);
return;
}
const ctx_ty = self.module.types.findByName(self.module.types.internString("Context")) orelse {
self.lowerBlock(ps.body);
return;
};
// Save current context
const save = self.builder.emit(.{ .global_get = gi.id }, gi.ty);
// Lower the new context value
const saved_ctx_ref = self.current_ctx_ref;
defer self.current_ctx_ref = saved_ctx_ref;
const saved_target = self.target_type;
self.target_type = ctx_ty;
const ctx_val = self.lowerExpr(ps.context_expr);
// Store into context global
self.builder.emitVoid(.{ .global_set = .{ .global = gi.id, .value = ctx_val } }, .void);
// Lower the body
self.target_type = saved_target;
const slot = self.builder.alloca(ctx_ty);
self.builder.store(slot, ctx_val);
self.current_ctx_ref = slot;
self.lowerBlock(ps.body);
// Restore saved context
self.builder.emitVoid(.{ .global_set = .{ .global = gi.id, .value = save } }, .void);
}
fn lowerMultiAssign(self: *Lowering, ma: *const ast.MultiAssign) void {
@@ -6419,6 +6441,12 @@ pub const Lowering = struct {
ct_lowering.main_file = null; // no main file filtering
ct_lowering.comptime_param_nodes = self.comptime_param_nodes;
ct_lowering.fn_ast_map = self.fn_ast_map; // share AST map for lazy resolution
// Inherit the implicit-ctx switch: the parent program uses
// Context, so functions lowered into ct_module must carry
// __sx_ctx too (otherwise the inserted code's `context.X`
// reads can't resolve through current_ctx_ref).
ct_lowering.implicit_ctx_enabled = self.implicit_ctx_enabled;
ct_module.has_implicit_ctx = self.implicit_ctx_enabled;
// Lower only the functions reachable from this expression.
// For a call like build_format(fmt), we need build_format's AST.
@@ -10419,52 +10447,6 @@ pub const Lowering = struct {
};
}
/// Auto-initialize the global `context` with a default GPA allocator at the start of main().
/// Emits IR instructions equivalent to:
/// __default_gpa : GPA = .{ alloc_count = 0 };
/// context = Context.{ allocator = GPA.create(@__default_gpa), data = null };
fn emitDefaultContextInit(self: *Lowering) void {
// Look up the context global
const ctx_gi = self.global_names.get("context") orelse return;
const ctx_ty = ctx_gi.ty;
// Look up GPA type
const gpa_ty = self.module.types.findByName(self.module.types.internString("GPA")) orelse return;
// Look up Allocator type
const alloc_ty = self.module.types.findByName(self.module.types.internString("Allocator")) orelse return;
// Get GPA→Allocator thunks
const thunks = self.getOrCreateThunks("Allocator", "GPA");
if (thunks.len < 2) return;
// 1. Stack-allocate GPA with alloc_count = 0
const gpa_slot = self.builder.alloca(gpa_ty);
const zero = self.builder.constInt(0, .s64);
const gpa_val = self.builder.emit(.{ .struct_init = .{
.fields = self.alloc.dupe(Ref, &.{zero}) catch return,
} }, gpa_ty);
self.builder.store(gpa_slot, gpa_val);
// 2. Build Allocator inline protocol value: { ctx: *void, alloc_fn, dealloc_fn }
const void_ptr_ty = self.module.types.ptrTo(.void);
const gpa_ptr = gpa_slot; // alloca already gives us *GPA, all pointers are compatible
const alloc_fn = self.builder.emit(.{ .func_ref = thunks[0] }, void_ptr_ty);
const dealloc_fn = self.builder.emit(.{ .func_ref = thunks[1] }, void_ptr_ty);
const alloc_val = self.builder.emit(.{ .struct_init = .{
.fields = self.alloc.dupe(Ref, &.{ gpa_ptr, alloc_fn, dealloc_fn }) catch return,
} }, alloc_ty);
// 3. Build Context struct: { allocator, data: null }
const null_ptr = self.builder.constNull(void_ptr_ty);
const ctx_val = self.builder.emit(.{ .struct_init = .{
.fields = self.alloc.dupe(Ref, &.{ alloc_val, null_ptr }) catch return,
} }, ctx_ty);
// 4. Store into context global
self.builder.emitVoid(.{ .global_set = .{ .global = ctx_gi.id, .value = ctx_val } }, .void);
}
fn emitModuleConst(self: *Lowering, ci: ModuleConstInfo) Ref {
switch (ci.value.data) {
.int_literal => |lit| {

View File

@@ -1,4 +1,4 @@
a 0 : Foo{a: 0, b: 42, c: 0, d: 17}
a 0 : Foo{a: 0, b: 42, c: 1, d: 17}
a 1 : Foo{a: 1, b: 42, c: 8, d: 17}
b: Foo{a: 1, b: 0, c: 101, d: 0}
b: Foo{a: 1, b: 1, c: 101, d: 1}
Pack{a: 1, b: 0, c: 3, d: 5, f: 9, v: 100, x: 3.500000}

View File

@@ -50,38 +50,10 @@ entry:
declare ptr @GPA.init(ptr) #0
; Function Attrs: nounwind
define internal ptr @GPA.alloc(ptr %0, ptr %1, i64 %2) #0 {
entry:
%alloca = alloca ptr, align 8
store ptr %1, ptr %alloca, align 8
%allocaN = alloca i64, align 8
store i64 %2, ptr %allocaN, align 8
%load = load ptr, ptr %alloca, align 8
%gep = getelementptr inbounds { i64 }, ptr %load, i32 0, i32 0
%loadN = load i64, ptr %gep, align 8
%add = add i64 %loadN, 1
store i64 %add, ptr %gep, align 8
%loadN = load i64, ptr %allocaN, align 8
%call = call ptr @malloc(i64 %loadN)
ret ptr %call
}
declare ptr @GPA.alloc(ptr, ptr, i64) #0
; Function Attrs: nounwind
define internal void @GPA.dealloc(ptr %0, ptr %1, ptr %2) #0 {
entry:
%alloca = alloca ptr, align 8
store ptr %1, ptr %alloca, align 8
%allocaN = alloca ptr, align 8
store ptr %2, ptr %allocaN, align 8
%load = load ptr, ptr %alloca, align 8
%gep = getelementptr inbounds { i64 }, ptr %load, i32 0, i32 0
%loadN = load i64, ptr %gep, align 8
%sub = sub i64 %loadN, 1
store i64 %sub, ptr %gep, align 8
%loadN = load ptr, ptr %allocaN, align 8
call void @free(ptr %loadN)
ret void
}
declare void @GPA.dealloc(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare void @Arena.add_chunk(ptr, ptr, i64) #0
@@ -313,14 +285,6 @@ jni.cont8: ; preds = %jni.miss7, %jni.con
; Function Attrs: nounwind
define i32 @main() #0 {
entry:
%alloca = alloca { i64 }, align 8
store { i64 } zeroinitializer, ptr %alloca, align 8
%si = insertvalue { ptr, ptr, ptr } undef, ptr %alloca, 0
%siN = insertvalue { ptr, ptr, ptr } %si, ptr @__thunk_GPA_Allocator_alloc, 1
%siN = insertvalue { ptr, ptr, ptr } %siN, ptr @__thunk_GPA_Allocator_dealloc, 2
%siN = insertvalue { { ptr, ptr, ptr }, ptr } undef, { ptr, ptr, ptr } %siN, 0
%siN = insertvalue { { ptr, ptr, ptr }, ptr } %siN, ptr null, 1
store { { ptr, ptr, ptr }, ptr } %siN, ptr @context, align 8
%gload = load i1, ptr @g_should_call, align 1
br i1 %gload, label %if.then.0, label %if.merge.1
@@ -329,10 +293,10 @@ if.then.0: ; preds = %entry
br label %if.merge.1
if.merge.1: ; preds = %if.then.0, %entry
%allocaN = alloca { ptr, i64 }, align 8
%gep = getelementptr inbounds { ptr, i64 }, ptr %allocaN, i32 0, i32 0
%alloca = alloca { ptr, i64 }, align 8
%gep = getelementptr inbounds { ptr, i64 }, ptr %alloca, i32 0, i32 0
store ptr null, ptr %gep, align 8
%gepN = getelementptr inbounds { ptr, i64 }, ptr %allocaN, i32 0, i32 1
%gepN = getelementptr inbounds { ptr, i64 }, ptr %alloca, i32 0, i32 1
store i64 0, ptr %gepN, align 8
%allocaN = alloca { ptr, i64 }, align 8
store { ptr, i64 } { ptr @str.4, i64 3 }, ptr %allocaN, align 8
@@ -364,20 +328,6 @@ entry:
ret void
}
; Function Attrs: nounwind
define internal ptr @__thunk_GPA_Allocator_alloc(ptr %0, ptr %1, i64 %2) #0 {
entry:
%call = call ptr @GPA.alloc(ptr %0, ptr %1, i64 %2)
ret ptr %call
}
; Function Attrs: nounwind
define internal void @__thunk_GPA_Allocator_dealloc(ptr %0, ptr %1, ptr %2) #0 {
entry:
call void @GPA.dealloc(ptr %0, ptr %1, ptr %2)
ret void
}
; Function Attrs: nounwind
declare ptr @sx_jni_env_tl_get() #0

View File

@@ -48,38 +48,10 @@ entry:
declare ptr @GPA.init(ptr) #0
; Function Attrs: nounwind
define internal ptr @GPA.alloc(ptr %0, ptr %1, i64 %2) #0 {
entry:
%alloca = alloca ptr, align 8
store ptr %1, ptr %alloca, align 8
%allocaN = alloca i64, align 8
store i64 %2, ptr %allocaN, align 8
%load = load ptr, ptr %alloca, align 8
%gep = getelementptr inbounds { i64 }, ptr %load, i32 0, i32 0
%loadN = load i64, ptr %gep, align 8
%add = add i64 %loadN, 1
store i64 %add, ptr %gep, align 8
%loadN = load i64, ptr %allocaN, align 8
%call = call ptr @malloc(i64 %loadN)
ret ptr %call
}
declare ptr @GPA.alloc(ptr, ptr, i64) #0
; Function Attrs: nounwind
define internal void @GPA.dealloc(ptr %0, ptr %1, ptr %2) #0 {
entry:
%alloca = alloca ptr, align 8
store ptr %1, ptr %alloca, align 8
%allocaN = alloca ptr, align 8
store ptr %2, ptr %allocaN, align 8
%load = load ptr, ptr %alloca, align 8
%gep = getelementptr inbounds { i64 }, ptr %load, i32 0, i32 0
%loadN = load i64, ptr %gep, align 8
%sub = sub i64 %loadN, 1
store i64 %sub, ptr %gep, align 8
%loadN = load ptr, ptr %allocaN, align 8
call void @free(ptr %loadN)
ret void
}
declare void @GPA.dealloc(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare void @Arena.add_chunk(ptr, ptr, i64) #0
@@ -286,21 +258,13 @@ jni.cont: ; preds = %jni.miss, %entry
; Function Attrs: nounwind
define i32 @main() #0 {
entry:
%alloca = alloca { i64 }, align 8
store { i64 } zeroinitializer, ptr %alloca, align 8
%si = insertvalue { ptr, ptr, ptr } undef, ptr %alloca, 0
%siN = insertvalue { ptr, ptr, ptr } %si, ptr @__thunk_GPA_Allocator_alloc, 1
%siN = insertvalue { ptr, ptr, ptr } %siN, ptr @__thunk_GPA_Allocator_dealloc, 2
%siN = insertvalue { { ptr, ptr, ptr }, ptr } undef, { ptr, ptr, ptr } %siN, 0
%siN = insertvalue { { ptr, ptr, ptr }, ptr } %siN, ptr null, 1
store { { ptr, ptr, ptr }, ptr } %siN, ptr @context, align 8
%gload = load i1, ptr @g_should_call, align 1
br i1 %gload, label %if.then.0, label %if.merge.1
if.then.0: ; preds = %entry
%call = call i32 @read_int(ptr @__sx_default_context, ptr null, ptr null)
%allocaN = alloca i32, align 4
store i32 %call, ptr %allocaN, align 4
%alloca = alloca i32, align 4
store i32 %call, ptr %alloca, align 4
br label %if.merge.1
if.merge.1: ; preds = %if.then.0, %entry
@@ -339,20 +303,6 @@ entry:
ret void
}
; Function Attrs: nounwind
define internal ptr @__thunk_GPA_Allocator_alloc(ptr %0, ptr %1, i64 %2) #0 {
entry:
%call = call ptr @GPA.alloc(ptr %0, ptr %1, i64 %2)
ret ptr %call
}
; Function Attrs: nounwind
define internal void @__thunk_GPA_Allocator_dealloc(ptr %0, ptr %1, ptr %2) #0 {
entry:
call void @GPA.dealloc(ptr %0, ptr %1, ptr %2)
ret void
}
; Function Attrs: nounwind
declare ptr @sx_jni_env_tl_get() #0

View File

@@ -48,38 +48,10 @@ entry:
declare ptr @GPA.init(ptr) #0
; Function Attrs: nounwind
define internal ptr @GPA.alloc(ptr %0, ptr %1, i64 %2) #0 {
entry:
%alloca = alloca ptr, align 8
store ptr %1, ptr %alloca, align 8
%allocaN = alloca i64, align 8
store i64 %2, ptr %allocaN, align 8
%load = load ptr, ptr %alloca, align 8
%gep = getelementptr inbounds { i64 }, ptr %load, i32 0, i32 0
%loadN = load i64, ptr %gep, align 8
%add = add i64 %loadN, 1
store i64 %add, ptr %gep, align 8
%loadN = load i64, ptr %allocaN, align 8
%call = call ptr @malloc(i64 %loadN)
ret ptr %call
}
declare ptr @GPA.alloc(ptr, ptr, i64) #0
; Function Attrs: nounwind
define internal void @GPA.dealloc(ptr %0, ptr %1, ptr %2) #0 {
entry:
%alloca = alloca ptr, align 8
store ptr %1, ptr %alloca, align 8
%allocaN = alloca ptr, align 8
store ptr %2, ptr %allocaN, align 8
%load = load ptr, ptr %alloca, align 8
%gep = getelementptr inbounds { i64 }, ptr %load, i32 0, i32 0
%loadN = load i64, ptr %gep, align 8
%sub = sub i64 %loadN, 1
store i64 %sub, ptr %gep, align 8
%loadN = load ptr, ptr %allocaN, align 8
call void @free(ptr %loadN)
ret void
}
declare void @GPA.dealloc(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare void @Arena.add_chunk(ptr, ptr, i64) #0
@@ -286,21 +258,13 @@ jni.cont: ; preds = %jni.miss, %entry
; Function Attrs: nounwind
define i32 @main() #0 {
entry:
%alloca = alloca { i64 }, align 8
store { i64 } zeroinitializer, ptr %alloca, align 8
%si = insertvalue { ptr, ptr, ptr } undef, ptr %alloca, 0
%siN = insertvalue { ptr, ptr, ptr } %si, ptr @__thunk_GPA_Allocator_alloc, 1
%siN = insertvalue { ptr, ptr, ptr } %siN, ptr @__thunk_GPA_Allocator_dealloc, 2
%siN = insertvalue { { ptr, ptr, ptr }, ptr } undef, { ptr, ptr, ptr } %siN, 0
%siN = insertvalue { { ptr, ptr, ptr }, ptr } %siN, ptr null, 1
store { { ptr, ptr, ptr }, ptr } %siN, ptr @context, align 8
%gload = load i1, ptr @g_should_call, align 1
br i1 %gload, label %if.then.0, label %if.merge.1
if.then.0: ; preds = %entry
%call = call i64 @read_long(ptr @__sx_default_context, ptr null, ptr null)
%allocaN = alloca i64, align 8
store i64 %call, ptr %allocaN, align 8
%alloca = alloca i64, align 8
store i64 %call, ptr %alloca, align 8
br label %if.merge.1
if.merge.1: ; preds = %if.then.0, %entry
@@ -339,20 +303,6 @@ entry:
ret void
}
; Function Attrs: nounwind
define internal ptr @__thunk_GPA_Allocator_alloc(ptr %0, ptr %1, i64 %2) #0 {
entry:
%call = call ptr @GPA.alloc(ptr %0, ptr %1, i64 %2)
ret ptr %call
}
; Function Attrs: nounwind
define internal void @__thunk_GPA_Allocator_dealloc(ptr %0, ptr %1, ptr %2) #0 {
entry:
call void @GPA.dealloc(ptr %0, ptr %1, ptr %2)
ret void
}
; Function Attrs: nounwind
declare ptr @sx_jni_env_tl_get() #0

View File

@@ -48,38 +48,10 @@ entry:
declare ptr @GPA.init(ptr) #0
; Function Attrs: nounwind
define internal ptr @GPA.alloc(ptr %0, ptr %1, i64 %2) #0 {
entry:
%alloca = alloca ptr, align 8
store ptr %1, ptr %alloca, align 8
%allocaN = alloca i64, align 8
store i64 %2, ptr %allocaN, align 8
%load = load ptr, ptr %alloca, align 8
%gep = getelementptr inbounds { i64 }, ptr %load, i32 0, i32 0
%loadN = load i64, ptr %gep, align 8
%add = add i64 %loadN, 1
store i64 %add, ptr %gep, align 8
%loadN = load i64, ptr %allocaN, align 8
%call = call ptr @malloc(i64 %loadN)
ret ptr %call
}
declare ptr @GPA.alloc(ptr, ptr, i64) #0
; Function Attrs: nounwind
define internal void @GPA.dealloc(ptr %0, ptr %1, ptr %2) #0 {
entry:
%alloca = alloca ptr, align 8
store ptr %1, ptr %alloca, align 8
%allocaN = alloca ptr, align 8
store ptr %2, ptr %allocaN, align 8
%load = load ptr, ptr %alloca, align 8
%gep = getelementptr inbounds { i64 }, ptr %load, i32 0, i32 0
%loadN = load i64, ptr %gep, align 8
%sub = sub i64 %loadN, 1
store i64 %sub, ptr %gep, align 8
%loadN = load ptr, ptr %allocaN, align 8
call void @free(ptr %loadN)
ret void
}
declare void @GPA.dealloc(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare void @Arena.add_chunk(ptr, ptr, i64) #0
@@ -286,21 +258,13 @@ jni.cont: ; preds = %jni.miss, %entry
; Function Attrs: nounwind
define i32 @main() #0 {
entry:
%alloca = alloca { i64 }, align 8
store { i64 } zeroinitializer, ptr %alloca, align 8
%si = insertvalue { ptr, ptr, ptr } undef, ptr %alloca, 0
%siN = insertvalue { ptr, ptr, ptr } %si, ptr @__thunk_GPA_Allocator_alloc, 1
%siN = insertvalue { ptr, ptr, ptr } %siN, ptr @__thunk_GPA_Allocator_dealloc, 2
%siN = insertvalue { { ptr, ptr, ptr }, ptr } undef, { ptr, ptr, ptr } %siN, 0
%siN = insertvalue { { ptr, ptr, ptr }, ptr } %siN, ptr null, 1
store { { ptr, ptr, ptr }, ptr } %siN, ptr @context, align 8
%gload = load i1, ptr @g_should_call, align 1
br i1 %gload, label %if.then.0, label %if.merge.1
if.then.0: ; preds = %entry
%call = call double @read_double(ptr @__sx_default_context, ptr null, ptr null)
%allocaN = alloca double, align 8
store double %call, ptr %allocaN, align 8
%alloca = alloca double, align 8
store double %call, ptr %alloca, align 8
br label %if.merge.1
if.merge.1: ; preds = %if.then.0, %entry
@@ -339,20 +303,6 @@ entry:
ret void
}
; Function Attrs: nounwind
define internal ptr @__thunk_GPA_Allocator_alloc(ptr %0, ptr %1, i64 %2) #0 {
entry:
%call = call ptr @GPA.alloc(ptr %0, ptr %1, i64 %2)
ret ptr %call
}
; Function Attrs: nounwind
define internal void @__thunk_GPA_Allocator_dealloc(ptr %0, ptr %1, ptr %2) #0 {
entry:
call void @GPA.dealloc(ptr %0, ptr %1, ptr %2)
ret void
}
; Function Attrs: nounwind
declare ptr @sx_jni_env_tl_get() #0

View File

@@ -48,38 +48,10 @@ entry:
declare ptr @GPA.init(ptr) #0
; Function Attrs: nounwind
define internal ptr @GPA.alloc(ptr %0, ptr %1, i64 %2) #0 {
entry:
%alloca = alloca ptr, align 8
store ptr %1, ptr %alloca, align 8
%allocaN = alloca i64, align 8
store i64 %2, ptr %allocaN, align 8
%load = load ptr, ptr %alloca, align 8
%gep = getelementptr inbounds { i64 }, ptr %load, i32 0, i32 0
%loadN = load i64, ptr %gep, align 8
%add = add i64 %loadN, 1
store i64 %add, ptr %gep, align 8
%loadN = load i64, ptr %allocaN, align 8
%call = call ptr @malloc(i64 %loadN)
ret ptr %call
}
declare ptr @GPA.alloc(ptr, ptr, i64) #0
; Function Attrs: nounwind
define internal void @GPA.dealloc(ptr %0, ptr %1, ptr %2) #0 {
entry:
%alloca = alloca ptr, align 8
store ptr %1, ptr %alloca, align 8
%allocaN = alloca ptr, align 8
store ptr %2, ptr %allocaN, align 8
%load = load ptr, ptr %alloca, align 8
%gep = getelementptr inbounds { i64 }, ptr %load, i32 0, i32 0
%loadN = load i64, ptr %gep, align 8
%sub = sub i64 %loadN, 1
store i64 %sub, ptr %gep, align 8
%loadN = load ptr, ptr %allocaN, align 8
call void @free(ptr %loadN)
ret void
}
declare void @GPA.dealloc(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare void @Arena.add_chunk(ptr, ptr, i64) #0
@@ -286,21 +258,13 @@ jni.cont: ; preds = %jni.miss, %entry
; Function Attrs: nounwind
define i32 @main() #0 {
entry:
%alloca = alloca { i64 }, align 8
store { i64 } zeroinitializer, ptr %alloca, align 8
%si = insertvalue { ptr, ptr, ptr } undef, ptr %alloca, 0
%siN = insertvalue { ptr, ptr, ptr } %si, ptr @__thunk_GPA_Allocator_alloc, 1
%siN = insertvalue { ptr, ptr, ptr } %siN, ptr @__thunk_GPA_Allocator_dealloc, 2
%siN = insertvalue { { ptr, ptr, ptr }, ptr } undef, { ptr, ptr, ptr } %siN, 0
%siN = insertvalue { { ptr, ptr, ptr }, ptr } %siN, ptr null, 1
store { { ptr, ptr, ptr }, ptr } %siN, ptr @context, align 8
%gload = load i1, ptr @g_should_call, align 1
br i1 %gload, label %if.then.0, label %if.merge.1
if.then.0: ; preds = %entry
%call = call i1 @read_bool(ptr @__sx_default_context, ptr null, ptr null)
%allocaN = alloca i1, align 1
store i1 %call, ptr %allocaN, align 1
%alloca = alloca i1, align 1
store i1 %call, ptr %alloca, align 1
br label %if.merge.1
if.merge.1: ; preds = %if.then.0, %entry
@@ -339,20 +303,6 @@ entry:
ret void
}
; Function Attrs: nounwind
define internal ptr @__thunk_GPA_Allocator_alloc(ptr %0, ptr %1, i64 %2) #0 {
entry:
%call = call ptr @GPA.alloc(ptr %0, ptr %1, i64 %2)
ret ptr %call
}
; Function Attrs: nounwind
define internal void @__thunk_GPA_Allocator_dealloc(ptr %0, ptr %1, ptr %2) #0 {
entry:
call void @GPA.dealloc(ptr %0, ptr %1, ptr %2)
ret void
}
; Function Attrs: nounwind
declare ptr @sx_jni_env_tl_get() #0

View File

@@ -48,38 +48,10 @@ entry:
declare ptr @GPA.init(ptr) #0
; Function Attrs: nounwind
define internal ptr @GPA.alloc(ptr %0, ptr %1, i64 %2) #0 {
entry:
%alloca = alloca ptr, align 8
store ptr %1, ptr %alloca, align 8
%allocaN = alloca i64, align 8
store i64 %2, ptr %allocaN, align 8
%load = load ptr, ptr %alloca, align 8
%gep = getelementptr inbounds { i64 }, ptr %load, i32 0, i32 0
%loadN = load i64, ptr %gep, align 8
%add = add i64 %loadN, 1
store i64 %add, ptr %gep, align 8
%loadN = load i64, ptr %allocaN, align 8
%call = call ptr @malloc(i64 %loadN)
ret ptr %call
}
declare ptr @GPA.alloc(ptr, ptr, i64) #0
; Function Attrs: nounwind
define internal void @GPA.dealloc(ptr %0, ptr %1, ptr %2) #0 {
entry:
%alloca = alloca ptr, align 8
store ptr %1, ptr %alloca, align 8
%allocaN = alloca ptr, align 8
store ptr %2, ptr %allocaN, align 8
%load = load ptr, ptr %alloca, align 8
%gep = getelementptr inbounds { i64 }, ptr %load, i32 0, i32 0
%loadN = load i64, ptr %gep, align 8
%sub = sub i64 %loadN, 1
store i64 %sub, ptr %gep, align 8
%loadN = load ptr, ptr %allocaN, align 8
call void @free(ptr %loadN)
ret void
}
declare void @GPA.dealloc(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare void @Arena.add_chunk(ptr, ptr, i64) #0
@@ -286,21 +258,13 @@ jni.cont: ; preds = %jni.miss, %entry
; Function Attrs: nounwind
define i32 @main() #0 {
entry:
%alloca = alloca { i64 }, align 8
store { i64 } zeroinitializer, ptr %alloca, align 8
%si = insertvalue { ptr, ptr, ptr } undef, ptr %alloca, 0
%siN = insertvalue { ptr, ptr, ptr } %si, ptr @__thunk_GPA_Allocator_alloc, 1
%siN = insertvalue { ptr, ptr, ptr } %siN, ptr @__thunk_GPA_Allocator_dealloc, 2
%siN = insertvalue { { ptr, ptr, ptr }, ptr } undef, { ptr, ptr, ptr } %siN, 0
%siN = insertvalue { { ptr, ptr, ptr }, ptr } %siN, ptr null, 1
store { { ptr, ptr, ptr }, ptr } %siN, ptr @context, align 8
%gload = load i1, ptr @g_should_call, align 1
br i1 %gload, label %if.then.0, label %if.merge.1
if.then.0: ; preds = %entry
%call = call ptr @get_window(ptr @__sx_default_context, ptr null, ptr null)
%allocaN = alloca ptr, align 8
store ptr %call, ptr %allocaN, align 8
%alloca = alloca ptr, align 8
store ptr %call, ptr %alloca, align 8
br label %if.merge.1
if.merge.1: ; preds = %if.then.0, %entry
@@ -339,20 +303,6 @@ entry:
ret void
}
; Function Attrs: nounwind
define internal ptr @__thunk_GPA_Allocator_alloc(ptr %0, ptr %1, i64 %2) #0 {
entry:
%call = call ptr @GPA.alloc(ptr %0, ptr %1, i64 %2)
ret ptr %call
}
; Function Attrs: nounwind
define internal void @__thunk_GPA_Allocator_dealloc(ptr %0, ptr %1, ptr %2) #0 {
entry:
call void @GPA.dealloc(ptr %0, ptr %1, ptr %2)
ret void
}
; Function Attrs: nounwind
declare ptr @sx_jni_env_tl_get() #0

View File

@@ -48,38 +48,10 @@ entry:
declare ptr @GPA.init(ptr) #0
; Function Attrs: nounwind
define internal ptr @GPA.alloc(ptr %0, ptr %1, i64 %2) #0 {
entry:
%alloca = alloca ptr, align 8
store ptr %1, ptr %alloca, align 8
%allocaN = alloca i64, align 8
store i64 %2, ptr %allocaN, align 8
%load = load ptr, ptr %alloca, align 8
%gep = getelementptr inbounds { i64 }, ptr %load, i32 0, i32 0
%loadN = load i64, ptr %gep, align 8
%add = add i64 %loadN, 1
store i64 %add, ptr %gep, align 8
%loadN = load i64, ptr %allocaN, align 8
%call = call ptr @malloc(i64 %loadN)
ret ptr %call
}
declare ptr @GPA.alloc(ptr, ptr, i64) #0
; Function Attrs: nounwind
define internal void @GPA.dealloc(ptr %0, ptr %1, ptr %2) #0 {
entry:
%alloca = alloca ptr, align 8
store ptr %1, ptr %alloca, align 8
%allocaN = alloca ptr, align 8
store ptr %2, ptr %allocaN, align 8
%load = load ptr, ptr %alloca, align 8
%gep = getelementptr inbounds { i64 }, ptr %load, i32 0, i32 0
%loadN = load i64, ptr %gep, align 8
%sub = sub i64 %loadN, 1
store i64 %sub, ptr %gep, align 8
%loadN = load ptr, ptr %allocaN, align 8
call void @free(ptr %loadN)
ret void
}
declare void @GPA.dealloc(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare void @Arena.add_chunk(ptr, ptr, i64) #0
@@ -283,21 +255,13 @@ jni.cont: ; preds = %jni.miss, %entry
; Function Attrs: nounwind
define i32 @main() #0 {
entry:
%alloca = alloca { i64 }, align 8
store { i64 } zeroinitializer, ptr %alloca, align 8
%si = insertvalue { ptr, ptr, ptr } undef, ptr %alloca, 0
%siN = insertvalue { ptr, ptr, ptr } %si, ptr @__thunk_GPA_Allocator_alloc, 1
%siN = insertvalue { ptr, ptr, ptr } %siN, ptr @__thunk_GPA_Allocator_dealloc, 2
%siN = insertvalue { { ptr, ptr, ptr }, ptr } undef, { ptr, ptr, ptr } %siN, 0
%siN = insertvalue { { ptr, ptr, ptr }, ptr } %siN, ptr null, 1
store { { ptr, ptr, ptr }, ptr } %siN, ptr @context, align 8
%gload = load i1, ptr @g_should_call, align 1
br i1 %gload, label %if.then.0, label %if.merge.1
if.then.0: ; preds = %entry
%call = call i32 @call_static_max(ptr @__sx_default_context, ptr null, ptr null)
%allocaN = alloca i32, align 4
store i32 %call, ptr %allocaN, align 4
%alloca = alloca i32, align 4
store i32 %call, ptr %alloca, align 4
br label %if.merge.1
if.merge.1: ; preds = %if.then.0, %entry
@@ -336,20 +300,6 @@ entry:
ret void
}
; Function Attrs: nounwind
define internal ptr @__thunk_GPA_Allocator_alloc(ptr %0, ptr %1, i64 %2) #0 {
entry:
%call = call ptr @GPA.alloc(ptr %0, ptr %1, i64 %2)
ret ptr %call
}
; Function Attrs: nounwind
define internal void @__thunk_GPA_Allocator_dealloc(ptr %0, ptr %1, ptr %2) #0 {
entry:
call void @GPA.dealloc(ptr %0, ptr %1, ptr %2)
ret void
}
; Function Attrs: nounwind
declare ptr @sx_jni_env_tl_get() #0

View File

@@ -48,38 +48,10 @@ entry:
declare ptr @GPA.init(ptr) #0
; Function Attrs: nounwind
define internal ptr @GPA.alloc(ptr %0, ptr %1, i64 %2) #0 {
entry:
%alloca = alloca ptr, align 8
store ptr %1, ptr %alloca, align 8
%allocaN = alloca i64, align 8
store i64 %2, ptr %allocaN, align 8
%load = load ptr, ptr %alloca, align 8
%gep = getelementptr inbounds { i64 }, ptr %load, i32 0, i32 0
%loadN = load i64, ptr %gep, align 8
%add = add i64 %loadN, 1
store i64 %add, ptr %gep, align 8
%loadN = load i64, ptr %allocaN, align 8
%call = call ptr @malloc(i64 %loadN)
ret ptr %call
}
declare ptr @GPA.alloc(ptr, ptr, i64) #0
; Function Attrs: nounwind
define internal void @GPA.dealloc(ptr %0, ptr %1, ptr %2) #0 {
entry:
%alloca = alloca ptr, align 8
store ptr %1, ptr %alloca, align 8
%allocaN = alloca ptr, align 8
store ptr %2, ptr %allocaN, align 8
%load = load ptr, ptr %alloca, align 8
%gep = getelementptr inbounds { i64 }, ptr %load, i32 0, i32 0
%loadN = load i64, ptr %gep, align 8
%sub = sub i64 %loadN, 1
store i64 %sub, ptr %gep, align 8
%loadN = load ptr, ptr %allocaN, align 8
call void @free(ptr %loadN)
ret void
}
declare void @GPA.dealloc(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare void @Arena.add_chunk(ptr, ptr, i64) #0
@@ -288,14 +260,6 @@ jni.cont: ; preds = %jni.miss, %entry
; Function Attrs: nounwind
define i32 @main() #0 {
entry:
%alloca = alloca { i64 }, align 8
store { i64 } zeroinitializer, ptr %alloca, align 8
%si = insertvalue { ptr, ptr, ptr } undef, ptr %alloca, 0
%siN = insertvalue { ptr, ptr, ptr } %si, ptr @__thunk_GPA_Allocator_alloc, 1
%siN = insertvalue { ptr, ptr, ptr } %siN, ptr @__thunk_GPA_Allocator_dealloc, 2
%siN = insertvalue { { ptr, ptr, ptr }, ptr } undef, { ptr, ptr, ptr } %siN, 0
%siN = insertvalue { { ptr, ptr, ptr }, ptr } %siN, ptr null, 1
store { { ptr, ptr, ptr }, ptr } %siN, ptr @context, align 8
%gload = load i1, ptr @g_should_call, align 1
br i1 %gload, label %if.then.0, label %if.merge.1
@@ -304,10 +268,10 @@ if.then.0: ; preds = %entry
br label %if.merge.1
if.merge.1: ; preds = %if.then.0, %entry
%allocaN = alloca { ptr, i64 }, align 8
%gep = getelementptr inbounds { ptr, i64 }, ptr %allocaN, i32 0, i32 0
%alloca = alloca { ptr, i64 }, align 8
%gep = getelementptr inbounds { ptr, i64 }, ptr %alloca, i32 0, i32 0
store ptr null, ptr %gep, align 8
%gepN = getelementptr inbounds { ptr, i64 }, ptr %allocaN, i32 0, i32 1
%gepN = getelementptr inbounds { ptr, i64 }, ptr %alloca, i32 0, i32 1
store i64 0, ptr %gepN, align 8
%allocaN = alloca { ptr, i64 }, align 8
store { ptr, i64 } { ptr @str.2, i64 3 }, ptr %allocaN, align 8
@@ -339,20 +303,6 @@ entry:
ret void
}
; Function Attrs: nounwind
define internal ptr @__thunk_GPA_Allocator_alloc(ptr %0, ptr %1, i64 %2) #0 {
entry:
%call = call ptr @GPA.alloc(ptr %0, ptr %1, i64 %2)
ret ptr %call
}
; Function Attrs: nounwind
define internal void @__thunk_GPA_Allocator_dealloc(ptr %0, ptr %1, ptr %2) #0 {
entry:
call void @GPA.dealloc(ptr %0, ptr %1, ptr %2)
ret void
}
; Function Attrs: nounwind
declare ptr @sx_jni_env_tl_get() #0

View File

@@ -48,38 +48,10 @@ entry:
declare ptr @GPA.init(ptr) #0
; Function Attrs: nounwind
define internal ptr @GPA.alloc(ptr %0, ptr %1, i64 %2) #0 {
entry:
%alloca = alloca ptr, align 8
store ptr %1, ptr %alloca, align 8
%allocaN = alloca i64, align 8
store i64 %2, ptr %allocaN, align 8
%load = load ptr, ptr %alloca, align 8
%gep = getelementptr inbounds { i64 }, ptr %load, i32 0, i32 0
%loadN = load i64, ptr %gep, align 8
%add = add i64 %loadN, 1
store i64 %add, ptr %gep, align 8
%loadN = load i64, ptr %allocaN, align 8
%call = call ptr @malloc(i64 %loadN)
ret ptr %call
}
declare ptr @GPA.alloc(ptr, ptr, i64) #0
; Function Attrs: nounwind
define internal void @GPA.dealloc(ptr %0, ptr %1, ptr %2) #0 {
entry:
%alloca = alloca ptr, align 8
store ptr %1, ptr %alloca, align 8
%allocaN = alloca ptr, align 8
store ptr %2, ptr %allocaN, align 8
%load = load ptr, ptr %alloca, align 8
%gep = getelementptr inbounds { i64 }, ptr %load, i32 0, i32 0
%loadN = load i64, ptr %gep, align 8
%sub = sub i64 %loadN, 1
store i64 %sub, ptr %gep, align 8
%loadN = load ptr, ptr %allocaN, align 8
call void @free(ptr %loadN)
ret void
}
declare void @GPA.dealloc(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare void @Arena.add_chunk(ptr, ptr, i64) #0
@@ -286,14 +258,6 @@ jni.cont: ; preds = %jni.miss, %entry
; Function Attrs: nounwind
define i32 @main() #0 {
entry:
%alloca = alloca { i64 }, align 8
store { i64 } zeroinitializer, ptr %alloca, align 8
%si = insertvalue { ptr, ptr, ptr } undef, ptr %alloca, 0
%siN = insertvalue { ptr, ptr, ptr } %si, ptr @__thunk_GPA_Allocator_alloc, 1
%siN = insertvalue { ptr, ptr, ptr } %siN, ptr @__thunk_GPA_Allocator_dealloc, 2
%siN = insertvalue { { ptr, ptr, ptr }, ptr } undef, { ptr, ptr, ptr } %siN, 0
%siN = insertvalue { { ptr, ptr, ptr }, ptr } %siN, ptr null, 1
store { { ptr, ptr, ptr }, ptr } %siN, ptr @context, align 8
%gload = load i1, ptr @g_should_call, align 1
br i1 %gload, label %if.then.0, label %if.merge.1
@@ -302,10 +266,10 @@ if.then.0: ; preds = %entry
br label %if.merge.1
if.merge.1: ; preds = %if.then.0, %entry
%allocaN = alloca { ptr, i64 }, align 8
%gep = getelementptr inbounds { ptr, i64 }, ptr %allocaN, i32 0, i32 0
%alloca = alloca { ptr, i64 }, align 8
%gep = getelementptr inbounds { ptr, i64 }, ptr %alloca, i32 0, i32 0
store ptr null, ptr %gep, align 8
%gepN = getelementptr inbounds { ptr, i64 }, ptr %allocaN, i32 0, i32 1
%gepN = getelementptr inbounds { ptr, i64 }, ptr %alloca, i32 0, i32 1
store i64 0, ptr %gepN, align 8
%allocaN = alloca { ptr, i64 }, align 8
store { ptr, i64 } { ptr @str.2, i64 3 }, ptr %allocaN, align 8
@@ -337,20 +301,6 @@ entry:
ret void
}
; Function Attrs: nounwind
define internal ptr @__thunk_GPA_Allocator_alloc(ptr %0, ptr %1, i64 %2) #0 {
entry:
%call = call ptr @GPA.alloc(ptr %0, ptr %1, i64 %2)
ret ptr %call
}
; Function Attrs: nounwind
define internal void @__thunk_GPA_Allocator_dealloc(ptr %0, ptr %1, ptr %2) #0 {
entry:
call void @GPA.dealloc(ptr %0, ptr %1, ptr %2)
ret void
}
; Function Attrs: nounwind
declare ptr @sx_jni_env_tl_get() #0

View File

@@ -51,38 +51,10 @@ entry:
declare ptr @GPA.init(ptr) #0
; Function Attrs: nounwind
define internal ptr @GPA.alloc(ptr %0, ptr %1, i64 %2) #0 {
entry:
%alloca = alloca ptr, align 8
store ptr %1, ptr %alloca, align 8
%allocaN = alloca i64, align 8
store i64 %2, ptr %allocaN, align 8
%load = load ptr, ptr %alloca, align 8
%gep = getelementptr inbounds { i64 }, ptr %load, i32 0, i32 0
%loadN = load i64, ptr %gep, align 8
%add = add i64 %loadN, 1
store i64 %add, ptr %gep, align 8
%loadN = load i64, ptr %allocaN, align 8
%call = call ptr @malloc(i64 %loadN)
ret ptr %call
}
declare ptr @GPA.alloc(ptr, ptr, i64) #0
; Function Attrs: nounwind
define internal void @GPA.dealloc(ptr %0, ptr %1, ptr %2) #0 {
entry:
%alloca = alloca ptr, align 8
store ptr %1, ptr %alloca, align 8
%allocaN = alloca ptr, align 8
store ptr %2, ptr %allocaN, align 8
%load = load ptr, ptr %alloca, align 8
%gep = getelementptr inbounds { i64 }, ptr %load, i32 0, i32 0
%loadN = load i64, ptr %gep, align 8
%sub = sub i64 %loadN, 1
store i64 %sub, ptr %gep, align 8
%loadN = load ptr, ptr %allocaN, align 8
call void @free(ptr %loadN)
ret void
}
declare void @GPA.dealloc(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare void @Arena.add_chunk(ptr, ptr, i64) #0
@@ -362,14 +334,6 @@ declare i64 @build_options() #0
define i32 @main() #0 {
entry:
call void @__sx_objc_selector_init()
%alloca = alloca { i64 }, align 8
store { i64 } zeroinitializer, ptr %alloca, align 8
%si = insertvalue { ptr, ptr, ptr } undef, ptr %alloca, 0
%siN = insertvalue { ptr, ptr, ptr } %si, ptr @__thunk_GPA_Allocator_alloc, 1
%siN = insertvalue { ptr, ptr, ptr } %siN, ptr @__thunk_GPA_Allocator_dealloc, 2
%siN = insertvalue { { ptr, ptr, ptr }, ptr } undef, { ptr, ptr, ptr } %siN, 0
%siN = insertvalue { { ptr, ptr, ptr }, ptr } %siN, ptr null, 1
store { { ptr, ptr, ptr }, ptr } %siN, ptr @context, align 8
%load = load ptr, ptr @OBJC_SELECTOR_REFERENCES_init, align 8
call void @objc_msgSend(ptr null, ptr %load)
%loadN = load ptr, ptr @OBJC_SELECTOR_REFERENCES_init, align 8
@@ -378,10 +342,10 @@ entry:
call void @objc_msgSend(ptr null, ptr %loadN)
%loadN = load ptr, ptr @OBJC_SELECTOR_REFERENCES_release, align 8
call void @objc_msgSend(ptr null, ptr %loadN)
%allocaN = alloca { ptr, i64 }, align 8
%gep = getelementptr inbounds { ptr, i64 }, ptr %allocaN, i32 0, i32 0
%alloca = alloca { ptr, i64 }, align 8
%gep = getelementptr inbounds { ptr, i64 }, ptr %alloca, i32 0, i32 0
store ptr null, ptr %gep, align 8
%gepN = getelementptr inbounds { ptr, i64 }, ptr %allocaN, i32 0, i32 1
%gepN = getelementptr inbounds { ptr, i64 }, ptr %alloca, i32 0, i32 1
store i64 0, ptr %gepN, align 8
%allocaN = alloca { ptr, i64 }, align 8
store { ptr, i64 } { ptr @str, i64 3 }, ptr %allocaN, align 8
@@ -413,20 +377,6 @@ entry:
ret void
}
; Function Attrs: nounwind
define internal ptr @__thunk_GPA_Allocator_alloc(ptr %0, ptr %1, i64 %2) #0 {
entry:
%call = call ptr @GPA.alloc(ptr %0, ptr %1, i64 %2)
ret ptr %call
}
; Function Attrs: nounwind
define internal void @__thunk_GPA_Allocator_dealloc(ptr %0, ptr %1, ptr %2) #0 {
entry:
call void @GPA.dealloc(ptr %0, ptr %1, ptr %2)
ret void
}
declare ptr @objc_msgSend(ptr, ptr)
declare i64 @write(i32, ptr, i64)

File diff suppressed because it is too large Load Diff