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

translate-c: support goto #11992

Open
Tracked by #1
kassane opened this issue Jul 4, 2022 · 4 comments · May be fixed by #19146
Open
Tracked by #1

translate-c: support goto #11992

kassane opened this issue Jul 4, 2022 · 4 comments · May be fixed by #19146
Labels
enhancement Solving this issue will likely involve adding new logic or components to the codebase. translate-c C to Zig source translation feature (@cImport)
Milestone

Comments

@kassane
Copy link
Contributor

kassane commented Jul 4, 2022

Zig Version

0.10.0-dev.2836+2360f8c49

Steps to Reproduce

During the code translation a type mismatch occurs.

Original C code:

Full code:

static void str_buf_append(struct str_buf *buf, const char *data, size_t len) {
  str_buf_reserve(buf, len);
  if (buf->errored)
    return;

  memcpy(buf->ptr + buf->len, data, len);
  buf->len += len;
}

static void str_buf_demangle_callback(const char *data, size_t len,
                                      void *opaque) {
  str_buf_append(opaque, data, len);
}

char *rust_demangle(const char *mangled, int flags) {
  struct str_buf out;

  out.ptr = NULL;
  out.len = 0;
  out.cap = 0;
  out.errored = false;

  bool success = rust_demangle_with_callback(mangled, flags,
                                             str_buf_demangle_callback, &out);

  if (!success) {
    free(out.ptr);
    return NULL;
  }

  str_buf_append(&out, "\0", 1);
  return out.ptr;
}

Zig translated

Full code:

pub fn str_buf_append(arg_buf: [*c]struct_str_buf, arg_data: [*c]const u8, arg_len: usize) callconv(.C) void {
    var buf = arg_buf;
    var data = arg_data;
    var len = arg_len;
    str_buf_reserve(buf, len);
    if (buf.*.errored) return;
    _ = memcpy(@ptrCast(?*anyopaque, buf.*.ptr + buf.*.len), @ptrCast(?*const anyopaque, data), len);
    buf.*.len +%= len;
}
pub fn str_buf_demangle_callback(arg_data: [*c]const u8, arg_len: usize, arg_opaque: ?*anyopaque) callconv(.C) void {
    var data = arg_data;
    var len = arg_len;
    var @"opaque" = arg_opaque;
    str_buf_append(@ptrCast([*c]struct_str_buf, @alignCast(@import("std").meta.alignment(struct_str_buf), @"opaque")), data, len);
}
pub export fn rust_demangle(arg_mangled: [*c]const u8, arg_flags: c_int) [*c]u8 {
    var mangled = arg_mangled;
    var flags = arg_flags;
    var out: struct_str_buf = undefined;
    out.ptr = null;
    out.len = 0;
    out.cap = 0;
    out.errored = @as(c_int, 0) != 0;
    var success: bool = rust_demangle_with_callback(mangled, flags, str_buf_demangle_callback, @ptrCast(?*anyopaque, &out));
    if (!success) {
        free(@ptrCast(?*anyopaque, out.ptr));
        return null;
    }
    str_buf_append(&out, "\x00", @bitCast(usize, @as(c_long, @as(c_int, 1))));
    return out.ptr;
}

Expected Behavior

No error

Actual Behavior

./src/demangle.zig:1283:69: error: expected type '*const fn([*c]const u8, usize, ?*anyopaque) callconv(.C) void', found 'fn([*c]const u8, usize, ?*anyopaque) callconv(.C) void'
    var success: bool = rust_demangle_with_callback(mangled, flags, str_buf_demangle_callback, @ptrCast(?*anyopaque, &out));
                                                                    ^
@kassane kassane added the bug Observed behavior contradicts documented or intended behavior label Jul 4, 2022
@Vexu
Copy link
Member

Vexu commented Jul 4, 2022

Cannot reproduce on 0.10.0-dev.2838+314ce5465. It looks like you're getting the stage2 function pointer semantics, can you confirm which version of the compiler you're using?

@kassane
Copy link
Contributor Author

kassane commented Jul 4, 2022

Cannot reproduce on 0.10.0-dev.2838+314ce5465. It looks like you're getting the stage2 function pointer semantics, can you confirm which version of the compiler you're using?

Ops! I am using the -fno-stage1 flag with this compiler version.
I will try it without this flag and see if the same thing happens.

@kassane
Copy link
Contributor Author

kassane commented Jul 4, 2022

After removing the stage2 flag. I succeeded in proceeding, but a linking error occurred.

I noticed that the function below was not completely translated just its declaration.
In my test I don't expect to depend on libc or any other external lib.

Original:

static void print_ident(struct rust_demangler *rdm,
                        struct rust_mangled_ident ident) {
  if (rdm->errored || rdm->skipping_printing)
    return;

  if (!ident.punycode) {
    print_str(rdm, ident.ascii, ident.ascii_len);
    return;
  }

  size_t len = 0;
  size_t cap = 4;
  while (cap < ident.ascii_len) {
    cap *= 2;
    // Check for overflows.
    CHECK_OR((cap * 4) / 4 == cap, return );
  }

  // Store the output codepoints as groups of 4 UTF-8 bytes.
  uint8_t *out = (uint8_t *)malloc(cap * 4);
  CHECK_OR(out, return );

  // Populate initial output from ASCII fragment.
  for (len = 0; len < ident.ascii_len; len++) {
    uint8_t *p = out + 4 * len;
    p[0] = 0;
    p[1] = 0;
    p[2] = 0;
    p[3] = ident.ascii[len];
  }

  // Punycode parameters and initial state.
  size_t base = 36;
  size_t t_min = 1;
  size_t t_max = 26;
  size_t skew = 38;
  size_t damp = 700;
  size_t bias = 72;
  size_t i = 0;
  uint32_t c = 0x80;

  size_t punycode_pos = 0;
  while (punycode_pos < ident.punycode_len) {
    // Read one delta value.
    size_t delta = 0;
    size_t w = 1;
    size_t k = 0;
    size_t t;
    uint8_t d;
    do {
      k += base;
      t = k < bias ? 0 : (k - bias);
      if (t < t_min)
        t = t_min;
      if (t > t_max)
        t = t_max;

      CHECK_OR(punycode_pos < ident.punycode_len, goto cleanup);
      d = ident.punycode[punycode_pos++];

      if (IS_LOWER(d))
        d = d - 'a';
      else if (IS_DIGIT(d))
        d = 26 + (d - '0');
      else
        ERROR_AND(goto cleanup);

      delta += d * w;
      w *= base - t;
    } while (d >= t);

    // Compute the new insert position and character.
    len++;
    i += delta;
    c += i / len;
    i %= len;

    // Ensure enough space is available.
    if (cap < len) {
      cap *= 2;
      // Check for overflows.
      CHECK_OR((cap * 4) / 4 == cap, goto cleanup);
      CHECK_OR(cap >= len, goto cleanup);
    }
    uint8_t *p = (uint8_t *)realloc(out, cap * 4);
    CHECK_OR(p, goto cleanup);
    out = p;

    // Move the characters after the insert position.
    p = out + i * 4;
    memmove(p + 4, p, (len - i - 1) * 4);

    // Insert the new character, as UTF-8 bytes.
    p[0] = c >= 0x10000 ? 0xf0 | (c >> 18) : 0;
    p[1] = c >= 0x800 ? (c < 0x10000 ? 0xe0 : 0x80) | ((c >> 12) & 0x3f) : 0;
    p[2] = (c < 0x800 ? 0xc0 : 0x80) | ((c >> 6) & 0x3f);
    p[3] = 0x80 | (c & 0x3f);

    // If there are no more deltas, decoding is complete.
    if (punycode_pos == ident.punycode_len)
      break;

    i++;

    // Perform bias adaptation.
    delta /= damp;
    damp = 2;

    delta += delta / len;
    k = 0;
    while (delta > ((base - t_min) * t_max) / 2) {
      delta /= base - t_min;
      k += base;
    }
    bias = k + ((base - t_min + 1) * delta) / (delta + skew);
  }

  // Remove all the 0 bytes to leave behind an UTF-8 string.
  size_t j;
  for (i = 0, j = 0; i < len * 4; i++)
    if (out[i] != 0)
      out[j++] = out[i];

  print_str(rdm, (const char *)out, j);

cleanup:
  free(out);
}

output:

pub extern fn print_ident(arg_rdm: [*c]struct_rust_demangler, arg_ident: struct_rust_mangled_ident) callconv(.C) void;

@Vexu
Copy link
Member

Vexu commented Jul 4, 2022

translate-c can't handle goto yet.

@Vexu Vexu added enhancement Solving this issue will likely involve adding new logic or components to the codebase. translate-c C to Zig source translation feature (@cImport) and removed bug Observed behavior contradicts documented or intended behavior labels Jul 4, 2022
@Vexu Vexu added this to the 0.12.0 milestone Jul 4, 2022
@Vexu Vexu changed the title zig translate-c - Error on functor type translate-c: support goto Jul 4, 2022
@rpkak rpkak linked a pull request Mar 2, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Solving this issue will likely involve adding new logic or components to the codebase. translate-c C to Zig source translation feature (@cImport)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants