Commit Graph

94 Commits

Author SHA1 Message Date
Tau
2ca503ec05 translate-c: Fix #12263 2022-10-10 22:29:56 +02:00
Techcable
5b689d389f
translate-c: packed struct implies align(1) on every field
Superceeds PR #12735 (now supporting all packed structs in GNU C)
Fixes issue #12733

This stops translating C packed struct as a Zig packed struct.
Instead use a regular `extern struct` with `align(1)`.

This is because (as @Vexu explained) Zig packed structs are really just integers (not structs).

Alignment issue is more complicated. I think @ifreund was the
first to notice it in his comment on PR #12735

Justification of my interpretion of the C(lang) behavior
comes from a careful reading of the GCC docs for type & variable attributes:

(clang emulates gnu's packed attribute here)

The final line of the documentation for __attribute__ ((aligned)) [on types] says:

> When used on a struct, or struct member, *the aligned attribute can only increase the alignment*; in order to decrease it, the packed attribute must be specified as well.

This implies that GCC uses the `packed` attribute for alignment purposes
in addition to eliminating padding.

The documentation for __attribute__((packed)) [on types], states:

> This attribute, attached to a struct, union, or C++ class type definition, specifies that each of its members (other than zero-width bit-fields) is placed to minimize the memory required. **This is equivalent to specifying the packed attribute on each of the members**.

The key is resolving this indirection, and looking at the documentation
for __attribute__((packed)) [on fields (wierdly under "variables" section)]:

> The packed attribute specifies that a **structure member should have the smallest possible alignment** — one bit for a bit-field and one byte otherwise, unless a larger value is specified with the aligned attribute. The attribute does not apply to non-member objects.

Furthermore, alignment is the only effect of the packed attribute mentioned in the GCC docs (for "common" architecture).
Based on this, it seems safe to completely substitute C 'packed' with Zig 'align(1)'.
Target-specific or undocumented behavior potentially changes this.

Unfortunately, the current implementation of `translate-c` translates as
`packed struct` without alignment info.

Because Zig packed structs are really integers (as mentioned above),
they are the wrong interpretation and we should be using 'extern struct'.

Running `translate-c` on the following code:

```c
struct foo {
    char a;
    int b;
} __attribute__((packed));

struct bar {
    char a;
    int b;
    short c;
    __attribute__((aligned(8))) long d;
} __attribute__((packed));
```

Previously used a 'packed struct' (which was not FFI-safe on stage1).

After applying this change, the translated structures have align(1)
explicitly applied to all of their fields AS EXPECTED (unless explicitly overriden).
This makes Zig behavior for `tranlsate-c` consistent with clang/GCC.

Here is the newly produced (correct) output for the above example:

```zig
pub const struct_foo = extern struct {
    a: u8 align(1),
    b: c_int align(1),
};
pub const struct_bar = extern struct {
    a: u8 align(1),
    b: c_int align(1),
    c: c_short align(1),
    d: c_long align(8),
};
```

Also note for reference: Since the last stable release (0.9.1),
there was a change in the language spec
related to the alignment of packed structures.

The docs for Zig 0.9.1 read:
> Packed structs have 1-byte alignment.

So the old behavior of translate-c (not specifying any alignment) was possibly correct back then.

However the current docs read:

> Packed structs have the same alignment as their backing integer

Suggsestive both to the change to an integer-backed representation
which is incompatible with C's notation.
2022-10-01 15:22:10 -07:00
Andrew Kelley
b7900de168 Merge remote-tracking branch 'origin/master' into llvm15 2022-09-06 19:45:02 -07:00
Veikka Tuominen
c7884af063 translate-c: do not translate packed C structs as packed Zig structs in stage2
Zig's integer backed packed structs are not compatible with C's packed structs.
2022-09-03 03:42:42 +03:00
Andrew Kelley
ea4ef832e3 fix llvm 15 translate-c regressions
by inserting explicit casts.

closes #12682
2022-08-30 19:11:31 -07:00
Andrew Kelley
3c506c8aaa disable tests failing due to LLVM 15 regressions 2022-08-29 22:58:24 -07:00
Jakub Konka
02e6960966 coff: do not pull in std.log into coff.zig definitions 2022-08-26 16:14:44 +02:00
Jakub Konka
ba346ecfe9 run_translated_c: disable failing test on Windows
ziglang/zig#12630
2022-08-25 17:01:49 +02:00
Evan Haas
8632e4fc7b translate-c: use correct number of initializers for vectors
Fixes #12264
2022-07-30 13:24:03 +03:00
Andrew Kelley
401abd793d run-translated-c: disable two failing tests
Issues reported:
 * #12263
 * #12264
2022-07-27 16:19:23 -07:00
Evan Haas
7ba1f9bfb5 translate-c: take address of functions before passing them to @ptrToInt
Fixes #12194
2022-07-27 14:03:08 +03:00
Evan Haas
4b9fd57aa8
translate-c: use nested scope for comma operator in macros
Fixes #11040
2022-03-08 20:38:51 +02:00
Evan Haas
9716a1c3ab translate-c: Add support for cast-to-union
Fixes #10955
2022-02-23 14:11:46 +02:00
Evan Haas
e382e7be2b std: Allow mem.zeroes to work at comptime with extern union
Fixes #10797
2022-02-07 11:34:20 +02:00
Evan Haas
f4b3f1d602 translate-c: Handle typedef'ed void return type for functions.
Fixes #10356
2022-01-11 12:42:23 -05:00
Evan Haas
c6b4fe0066 translate-c: coerce boolean results to c_int when negated
Fixes #10175
2021-11-20 19:52:06 -05:00
Evan Haas
3fefdc1a0b translate-c: Allow negative denominator in remainder (%) operator
Fixes #10176
2021-11-20 13:52:07 -05:00
Matthew Borkowski
2d7b55aa0a translate_c: prevent a while under an if from stealing the else 2021-10-19 13:48:09 -04:00
Josh Soref
664941bf14
Spelling corrections (#9833)
Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>
Co-authored-by: Josh Soref <jsoref@users.noreply.github.com>
2021-09-24 13:39:20 -04:00
Evan Haas
3b25205833 translate-c: allow string literals to be used as char *
In C the type of string literals is `char *`, so when using them in
a non-const context we have to cast the const away.

Fixes #9126
2021-08-21 16:32:09 +03:00
Evan Haas
8028e46f01 translate-c: handle signed array subscripts
A rather complicated workaround for handling signed array subscripts.
Once `[*]T + isize` is allowed, this can be removed.

Fixes #8556
2021-07-28 17:46:02 -04:00
Evan Haas
c090e38340
translate-c: add support for ChooseExpr 2021-07-28 08:06:22 -07:00
Evan Haas
98eea963de
translate-c: fix import path in translation failure comment 2021-07-28 08:06:22 -07:00
Evan Haas
3e67ef5c9f translate-c: Handle underscore when used as an identifier
Use `@` syntax to escape `_` when used as an identifier.

Remove the stage1 astgen prohibition against assigning from `_`

Note: there a few stage1 bugs preventing `_` from being used as an identifier
for a local variable or function parameter; these will be fixed by stage2.
They are unlikely to arise in real C code since identifiers starting with
underscore are reserved for the implementation.
2021-07-19 12:56:23 +03:00
Evan Haas
0e7897a9a2 translate-c: Remove usage of extern enum
Translate enum types as the underlying integer type. Translate enum constants
as top-level integer constants of the correct type (which does not necessarily
match the enum integer type).

If an enum constant's type cannot be translated for some reason, omit it.

See discussion https://github.com/ziglang/zig/issues/2115#issuecomment-827968279

Fixes #9153
2021-06-23 08:44:25 +03:00
Veikka Tuominen
6664679c8c translate-c: don't bother with unwrapping pointers
Dereferencing a c pointer implicitly includes an unwrap,
manually adding it just causes bugs.
2021-06-13 15:23:31 +03:00
Evan Haas
ea4a25287e translate-c: better support for static local variables
Don't move static local variables into the top-level scope since this
can cause name clashes if subsequently-defined variables or parameters
in different scopes share the name.

Instead, use a variable within a struct so that the variable's lexical
scope does not change. This solution was suggested by @LemonBoy

Note that a similar name-shadowing problem exists with `extern` variables
declared within block scope, but a different solution will be needed since
they do need to be moved to the top-level scope and we can't rename them.
2021-06-12 23:12:37 +03:00
xackus
b5c117d051 translate-c: fix enums that require c_uint type 2021-06-12 11:55:39 +03:00
Evan Haas
45212e3b33 translate-c: Implement flexible arrays
Fixes #8759
2021-06-11 21:31:39 +03:00
Evan Haas
fa6546ba74 translate-c: properly handle enums used as boolean expressions 2021-06-07 15:51:42 +03:00
Evan Haas
1273bc277f translate-c: add support for __cleanup__ attribute
Use a `defer` statement to implement the C __cleanup__ attribute.

See https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html
2021-05-19 12:12:18 +03:00
xackus
8f8efcdd6e translate-c: fix typedefs with multiple names 2021-05-10 21:59:42 +03:00
Evan Haas
63304a871e translate-c: group LHS of array access if necessary 2021-04-20 11:33:01 +03:00
Evan Haas
d4d21dd46d translate-c: better handling of int -> enum casts
In std.meta.cast when casting to an enum type from an integer type, first
do a C-style cast from the source value to the tag type of the enum.
This ensures that we don't get an error due to the source value not being
representable by the enum.

In transCCast() use std.meta.cast instead of directly emitting the cast
operation since the enum's underlying type may not be known at translation
time due to an MSVC bug, see https://github.com/ziglang/zig/issues/8003

Fixes #6011
2021-04-15 22:46:22 -04:00
Evan Haas
e761e0ac18 translate-c: wrap switch statements in a while (true) loop
This allows `break` statements to be directly translated from the original C.
Add a break statement as the last statement of the while loop to ensure we
don't have an infinite loop if no breaks / returns are hit in the switch.

Fixes #8387
2021-04-13 11:45:03 -07:00
Evan Haas
8de14a98a6 translate-c: Add support for vector expressions
Includes vector types, __builtin_shufflevector, and __builtin_convertvector
2021-04-06 11:22:27 -07:00
Evan Haas
ab9324e604 translate-c: intcast compound assignment operand if different-sized integer
Use transCCast to cast the RHS of compound assignment if necessary.
2021-03-28 15:21:12 +03:00
Evan Haas
dce612ac2b translate-c: Ensure assignments are within a block when necessary
Ensures that if an assignment statement is the sole statement within a
C if statement, for loop, do loop, or do while loop, then when translated
it resides within a block, even though it does not in the original C.

Fixes the following invalid translation:

`if (1) if (1) 2;` -> `if (true) if (true) _ = @as(c_int, 2);`

To this:
```zig
    if (true) if (true) {
        _ = @as(c_int, 2);
    };
```

Fixes #8159
2021-03-22 10:48:08 +02:00
Veikka Tuominen
ac7217e1f5 translate-c: preserve zero fractional part in float literals 2021-03-18 22:46:00 +02:00
Evan Haas
715370a10a translate-c: demote usage of un-implemented builtins 2021-03-17 09:06:47 +02:00
Evan Haas
c558a1ae26 translate-c: Implement generic selection expressions
Enables translation of C code that uses the `_Generic` keyword
2021-03-17 00:07:33 +02:00
Evan Haas
c760532be0 translate-c: Add compound literal support 2021-03-08 10:09:12 +02:00
Evan Haas
d01bb21173 translate-c: Explicitly cast decayed array to pointer with @ptrCast
This enables translation of code that uses pointer arithmetic with arrays
2021-03-08 00:35:17 +02:00
Evan Haas
6d69a29d75 translate-c: Support compound assignment of pointer and signed int
This handles `ptr += idx` and `ptr -= idx` when `idx` is a
signed integer expression.
2021-03-07 14:54:04 +02:00
Evan Haas
291edafa1b translate-c: enable pointer arithmetic with signed integer operand
Given a pointer operand `ptr` and a signed integer operand `idx`

`ptr + idx` and `idx + ptr` -> ptr + @bitCast(usize, @intCast(isize, idx))
`ptr - idx` -> ptr - @bitCast(usize, @intCast(isize, idx))

Thanks @LemonBoy for pointing out that we can take advantage of wraparound
to dramatically simplify the code.
2021-03-05 14:16:40 +02:00
Veikka Tuominen
904f774563 translate-c: fix c tokenizer giving invalid tokens 2021-03-03 11:33:14 -08:00
Evan Haas
45d220cac6 translate-c: add <assert.h> support
Implement __builtin_expect so C code that uses assert() can be translated.
2021-03-01 10:34:23 +02:00
Evan Haas
294ee1bbc9 translate-c: add limited OffsetOfExpr support
Add support for OffsetOfExpr that contain exactly 1 component, when that component
is a field.

For example, given:

```c
struct S {
  float f;
  double d;
};
struct T {
  long l;
  int i;
  struct S s[10];
};
```

Then:
```c
offsetof(struct T, i)       // supported
offsetof(struct T, s[2].d)  // not supported currently
```
2021-02-28 21:56:57 +02:00
Evan Haas
0816981561 translate-c: add typeof support 2021-02-25 22:33:42 -08:00
Evan Haas
4f11a88b9f translate-c: Add support for pointer subtraction
When two pointers are subtracted, both shall point to elements of the
same array object, or one past the last element of the array object;
the result is the difference of the subscripts of the two array elements.

The size of the result is implementation-defined, and its type
(a signed integer type) is ptrdiff_t defined in the <stddef.h> header.
If the result is not representable in an object of that type,
the behavior is undefined.

See C Standard, §6.5.6 [ISO/IEC 9899:2011]

Fixes #7216
2021-02-25 22:24:11 +02:00