While the SysV ABI is not that complicated, LLVM does not allow us
direct access to enforce it. By mimicking the IR generated by clang,
we can trick LLVM into doing the right thing. This involves two main
additions:
1. `AGG` ABI class
This is not part of the spec, but since we have to track class per
eightbyte and not per struct, the current enum is not enough. I
considered adding multiple classes like: `INTEGER_INTEGER`,
`INTEGER_SSE`, `SSE_INTEGER`. However, all of those cases would trigger
the same code path so it's simpler to collapse into one. This class is
only used on SysV.
2. LLVM C ABI type
Clang uses different types in C ABI function signatures than the
original structs passed in, and does conversion. For example, this
struct: `{ i8, i8, float }` would use `{ i16, float }` at ABI boundaries.
When passed as an argument, it is instead split into two arguments `i16`
and `float`. Therefore, for every struct that passes ABI boundaries we
need to keep track of its corresponding ABI type. Here are some more
examples:
```
| Struct | ABI equivalent |
| { i8, i8, i8, i8 } | i32 |
| { float, float } | double |
| { float, i32, i8 } | { float, i64 } |
```
Then, we must update function calls, returns, parameter lists and inits
to properly convert back and forth as needed.
@select(
comptime T: type,
pred: std.meta.Vector(len, bool),
a: std.meta.Vector(len, T),
b: std.meta.Vector(len, T)
) std.meta.Vector(len, T)
Constructs a vector from a & b, based on the values in the predicate vector. For indices where the predicate value is true, the corresponding
element from the a vector is selected, and otherwise from b.
When using `build-exe` or `build-lib -dynamic`, `-fcompiler-rt` means building
compiler-rt into a static library and then linking it into the executable.
When using `build-lib`, `-fcompiler-rt` means building compiler-rt into an
object file and then adding it into the static archive.
Before this commit, when using `build-obj`, zig would build compiler-rt
into an object file, and then on ELF, use `lld -r` to merge it into the
main object file. Other linker backends of LLD do not support `-r` to
merge objects, so this failed with error messages for those targets.
Now, `-fcompiler-rt` when used with `build-obj` acts as if the user puts
`_ = @import("compiler_rt");` inside their root source file. The symbols
of compiler-rt go into the same compilation unit as the root source file.
This is hooked up for stage1 only for now. Once stage2 is capable of
building compiler-rt, it should be hooked up there as well.
* Added doc comments for `std.Target.ObjectFormat` enum
* `std.Target.oFileExt` is removed because it is incorrect for Plan-9
targets. Instead, use `std.Target.ObjectFormat.fileExt` and pass a
CPU architecture.
* Added `Compilation.Directory.joinZ` for when a null byte is desired.
* Improvements to `Compilation.create` logic for computing `use_llvm`
and reporting errors in contradictory flags. `-femit-llvm-ir` and
`-femit-llvm-bc` will now imply `-fLLVM`.
* Fix compilation when passing `.bc` files on the command line.
* Improvements to the stage2 LLVM backend:
- cleaned up error messages and error reporting. Properly bubble up
some errors rather than dumping to stderr; others turn into panics.
- properly call ZigLLVMCreateTargetMachine and
ZigLLVMTargetMachineEmitToFile and implement calculation of the
respective parameters (cpu features, code model, abi name, lto,
tsan, etc).
- LLVM module verification only runs in debug builds of the compiler
- use LLVMDumpModule rather than printToString because in the case
that we incorrectly pass a null pointer to LLVM it may crash during
dumping the module and having it partially printed is helpful in
this case.
- support -femit-asm, -fno-emit-bin, -femit-llvm-ir, -femit-llvm-bc
- Support LLVM backend when used with Mach-O and WASM linkers.
This commit intentions to have no functional changes. The only purpose
is to delete the struct IrInst, which is the common base struct that
both IrInstSrc (ZIR) and IrInstGen (AIR) instructions embed.
This untangles stage1 ZIR and AIR memory layout, paving the way for a
following commit to reduce memory usage.
* stage1 backend allows configuring the uwtables function attr
via a flag rather than its own logic.
* stage2 defaults to enabling uwtable attr when
linking libunwind, or always on windows
* stage2 makes link_eh_frame_hdr true automatically if uwtable
attr is set to be on for zig functions
* CLI: add -funwind-tables and -fno-unwind-tables to allow the user to
override the defaults.
* hook it up to `zig cc`
closes#9046
Bitcast the pointer and operands to integer types having the same size,
working around LLVM inability to lower a LL/SC operation when the
operands have floating-point types (and are reasonably sized).
Closes#4457
This is progress towards making Stage1Zir immutable, so that we can
avoid generating it for every comptime function call.
Also rename IrExecutableGen to Stage1Air.
* Extracts AstGen logic from ir.cpp into astgen.cpp. Reduces the
largest file of stage1 from 33,551 lines to 25,510.
* tokenizer: rework it completely to match the stage2 tokenizer logic.
They can now be maintained together; when one is changed, the other
can be changed in the same way.
- Each token now takes up 13 bytes instead of 64 bytes. The tokenizer
does not parse char literals, string literals, integer literals,
etc into meaningful data. Instead, that happens during parsing or
astgen.
- no longer store line offsets. Error messages scan source
files to find the line/column as needed (same as stage2).
- main loop: instead of checking the loop, handle a null byte
explicitly in the switch statements. This is a nice improvement
that we may want to backport to stage2.
- delete some dead tokens, artifacts of past syntax that no longer
exists.
* Parser: fix a TODO by parsing builtin functions as tokens rather than
`@` as a separate token. This is how stage2 does it.
* Remove some debugging infrastructure. These will need to be redone,
if at all, as the code migrates to match stage2.
- remove the ast_render code.
- remove the IR debugging stuff
- remove teh token printing code
Conflicts:
* build.zig
* src/Compilation.zig
* src/codegen/spirv/spec.zig
* src/link/SpirV.zig
* test/stage2/darwin.zig
- this one might be problematic; start.zig looks for `main` in the
root source file, not `_main`. Not sure why there is an underscore
there in master branch.
* AstGen: emit decl lookup ZIR instructions rather than directly
looking up decls in AstGen. This is necessary because we want to
reuse the same immutable ZIR code for multiple generic instantiations
(and comptime function calls).
* AstGen: fix using members_len instead of fields_len for struct decls.
* structs: the struct_decl ZIR instruction is now also a block. This is
so that the type expressions, default field value expressions, and
alignment expressions can be evaluated in a scope that contains the
decls from the struct namespace itself.
* Add "std" and "builtin" packages to the builtin package.
* Don't try to build glibc, musl, or mingw-w64 when using `-ofmt=c`.
* builtin.zig is generated without `usingnamespace`.
* builtin.zig takes advantage of `std.zig.fmtId` for CPU features.
* A first pass at implementing `usingnamespace`. It's problematic and
should either be deleted, or polished, before merging this branch.
* Sema: allow explicitly specifying the namespace in which to look up
Decls. This is used by `struct_decl` in order to put the decls from
the struct namespace itself in scope when evaluating the type
expressions, default value expressions, and alignment expressions.
* Module: fix `analyzeNamespace` assuming that it is the top-level root
declaration node.
* Sema: implement comptime and runtime cmp operator.
* Sema: implement peer type resolution for enums and enum literals.
* Pull in the changes from master branch:
262e09c482.
* ZIR: complete out simple_ptr_type debug printing
Taking a detour trough a f64 is dangerous as the softfloat library
doesn't like converting sNaN values.
The error went unnoticed as an exception is raised by the library but
the stage1 compiler doesn't give a damn.
Happy LLVM 12 Release Day.
Please note that the llvm 12 tag does not include the latest commit in
the release/12.x branch, which is in fact a bug fix for a regression
that is causing a failure in Zig's test suite.
Zig master branch is tracking release/12.x, and will be enabling the
test that is fixed by that commit.
This branch adds "builtin" and "std" to the import table when using the
self-hosted backend.
"builtin" gains one additional item:
```
pub const zig_is_stage2 = true; // false when using stage1 backend
```
This allows the std lib to do conditional compilation based on detecting
which backend is being used. This will be removed from builtin as soon
as self-hosted catches up to feature parity with stage1.
Keep a sharp eye out - people are going to be tempted to abuse this.
The general rule of thumb is do not use `builtin.zig_is_stage2`. However
this commit breaks the rule so that we can gain limited start.zig support
as we incrementally improve the self-hosted compiler.
This commit also implements `fullyQualifiedNameHash` and related
functionality, which effectively puts all Decls in their proper
namespaces. `fullyQualifiedName` is not yet implemented.
Stop printing "todo" log messages for test decls unless we are in test
mode.
Add "previous definition here" error notes for Decl name collisions.
This commit does not bring us yet to a newly passing test case.
Here's what I'm working towards:
```zig
const std = @import("std");
export fn main() c_int {
const a = std.fs.base64_alphabet[0];
return a - 'A';
}
```
Current output:
```
$ ./zig-cache/bin/zig build-exe test.zig
test.zig:3:1: error: TODO implement more analyze elemptr
zig-cache/lib/zig/std/start.zig:38:46: error: TODO implement structInitExpr ty
```
So the next steps are clear:
* Sema: improve elemptr
* AstGen: implement structInitExpr
The current implementation of the target C ABI rules is hopelessly bad,
let's tack some more rules on top in order to prevent some
miscompilations.
Truth to be told the same rule should be applied also to parameters, but
I really can't stand stage1.
LLVM 12 requires sret attributes to have the struct type as a parameter,
and provides no C function for supplying it. Therefore, we must add
another C++ wrapper API for adding the sret attribute.
Fixes ability to build from source in the llvm12 branch.
Conflicts:
* src/clang.zig
* src/llvm.zig
- this file got moved to src/llvm/bindings.zig in master branch so I
had to put the new LLVM arch/os enum tags into it.
* lib/std/target.zig, src/stage1/target.cpp
- haiku had an inconsistency with its default target ABI, gnu vs
eabi. In this commit we make it gnu in both places to match the
latest changes by @hoanga.
* src/translate_c.zig