+ ax_simple (ax.get (), aop_end);
+
+ return ax;
+}
+
+agent_expr_up
+gen_trace_for_return_address (CORE_ADDR scope, struct gdbarch *gdbarch,
+ int trace_string)
+{
+ agent_expr_up ax (new agent_expr (gdbarch, scope));
+ struct axs_value value;
+
+ ax->tracing = 1;
+ ax->trace_string = trace_string;
+
+ gdbarch_gen_return_address (gdbarch, ax.get (), &value, scope);
+
+ /* Make sure we record the final object, and get rid of it. */
+ gen_traced_pop (ax.get (), &value);
+
+ /* Oh, and terminate. */
+ ax_simple (ax.get (), aop_end);
+
+ return ax;
+}
+
+/* Given a collection of printf-style arguments, generate code to
+ evaluate the arguments and pass everything to a special
+ bytecode. */
+
+agent_expr_up
+gen_printf (CORE_ADDR scope, struct gdbarch *gdbarch,
+ CORE_ADDR function, LONGEST channel,
+ const char *format, int fmtlen,
+ int nargs, struct expression **exprs)
+{
+ agent_expr_up ax (new agent_expr (gdbarch, scope));
+ union exp_element *pc;
+ struct axs_value value;
+ int tem;
+
+ /* We're computing values, not doing side effects. */
+ ax->tracing = 0;
+
+ /* Evaluate and push the args on the stack in reverse order,
+ for simplicity of collecting them on the target side. */
+ for (tem = nargs - 1; tem >= 0; --tem)
+ {
+ pc = exprs[tem]->elts;
+ value.optimized_out = 0;
+ gen_expr (exprs[tem], &pc, ax.get (), &value);
+ require_rvalue (ax.get (), &value);
+ }
+
+ /* Push function and channel. */
+ ax_const_l (ax.get (), channel);
+ ax_const_l (ax.get (), function);
+
+ /* Issue the printf bytecode proper. */
+ ax_simple (ax.get (), aop_printf);
+ ax_raw_byte (ax.get (), nargs);
+ ax_string (ax.get (), format, fmtlen);
+
+ /* And terminate. */
+ ax_simple (ax.get (), aop_end);