Merge remote-tracking branch 'origin/master' into llvm7

This commit is contained in:
Andrew Kelley 2018-09-10 12:30:57 -04:00
commit c9474faa4e
No known key found for this signature in database
GPG Key ID: 4E7CD66038A4D47C
33 changed files with 5789 additions and 3665 deletions

View File

@ -199,7 +199,7 @@ else()
if(MSVC)
set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -D_CRT_SECURE_NO_WARNINGS /w")
else()
set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -fno-exceptions -fno-rtti -Wno-comment -Wno-class-memaccess -Wno-unknown-warning-option")
set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -fno-exceptions -fno-rtti -Wno-comment")
endif()
set_target_properties(embedded_lld_lib PROPERTIES
COMPILE_FLAGS ${ZIG_LLD_COMPILE_FLAGS}
@ -775,20 +775,25 @@ include_directories(
"${CMAKE_SOURCE_DIR}/src"
)
if(MSVC)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /w")
elseif(MINGW)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -Werror -Wno-error=format= -Wno-error=format -Wno-error=format-extra-args")
else()
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Werror -Wall")
# These have to go before the -Wno- flags
set(EXE_CFLAGS "-std=c++11")
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
if(MSVC)
set(EXE_CFLAGS "${EXE_CFLAGS} /w")
elseif(MINGW)
set(EXE_CFLAGS "${EXE_CFLAGS} -Wall -Werror -Wno-error=format= -Wno-error=format -Wno-error=format-extra-args")
else()
set(EXE_CFLAGS "${EXE_CFLAGS} -Werror -Wall")
endif()
endif()
if(MSVC)
set(EXE_CFLAGS "-std=c++11")
set(EXE_CFLAGS "${EXE_CFLAGS}")
else()
set(EXE_CFLAGS "-std=c++11 -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D_GNU_SOURCE -fno-exceptions -fno-rtti -Werror=strict-prototypes -Werror=old-style-definition -Werror=type-limits -Wno-missing-braces")
set(EXE_CFLAGS "${EXE_CFLAGS} -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D_GNU_SOURCE -fno-exceptions -fno-rtti -Werror=strict-prototypes -Werror=old-style-definition -Werror=type-limits -Wno-missing-braces")
endif()
set(EXE_LDFLAGS " ")
if(MINGW)
set(EXE_LDFLAGS "-static -static-libgcc -static-libstdc++")

View File

@ -1587,7 +1587,7 @@ test "pointer casting" {
// operation that Zig cannot protect you against. Use @ptrCast only when other
// conversions are not possible.
const bytes align(@alignOf(u32)) = []u8{ 0x12, 0x12, 0x12, 0x12 };
const u32_ptr = @ptrCast(*const u32, &bytes[0]);
const u32_ptr = @ptrCast(*const u32, &bytes);
assert(u32_ptr.* == 0x12121212);
// Even this example is contrived - there are better ways to do the above than

View File

@ -20,12 +20,12 @@
struct AstNode;
struct ImportTableEntry;
struct FnTableEntry;
struct ZigFn;
struct Scope;
struct ScopeBlock;
struct ScopeFnDef;
struct TypeTableEntry;
struct VariableTableEntry;
struct ZigType;
struct ZigVar;
struct ErrorTableEntry;
struct BuiltinFnEntry;
struct TypeStructField;
@ -40,10 +40,17 @@ struct Tld;
struct TldExport;
struct IrAnalyze;
enum X64CABIClass {
X64CABIClass_Unknown,
X64CABIClass_MEMORY,
X64CABIClass_INTEGER,
X64CABIClass_SSE,
};
struct IrExecutable {
ZigList<IrBasicBlock *> basic_block_list;
Buf *name;
FnTableEntry *name_fn;
ZigFn *name_fn;
size_t mem_slot_count;
size_t next_debug_id;
size_t *backward_branch_count;
@ -51,7 +58,7 @@ struct IrExecutable {
bool invalid;
bool is_inline;
bool is_generic_instantiation;
FnTableEntry *fn_entry;
ZigFn *fn_entry;
Buf *c_import_buf;
AstNode *source_node;
IrExecutable *parent_exec;
@ -69,7 +76,7 @@ struct IrExecutable {
IrBasicBlock *coro_normal_final;
IrBasicBlock *coro_suspend_block;
IrBasicBlock *coro_final_cleanup_block;
VariableTableEntry *coro_allocator_var;
ZigVar *coro_allocator_var;
};
enum OutType {
@ -191,7 +198,7 @@ struct ConstPtrValue {
uint64_t addr;
} hard_coded_addr;
struct {
FnTableEntry *fn_entry;
ZigFn *fn_entry;
} fn;
} data;
};
@ -202,7 +209,7 @@ struct ConstErrValue {
};
struct ConstBoundFnValue {
FnTableEntry *fn;
ZigFn *fn;
IrInstruction *first_arg;
};
@ -251,7 +258,7 @@ struct ConstGlobalRefs {
};
struct ConstExprValue {
TypeTableEntry *type;
ZigType *type;
ConstValSpecial special;
ConstGlobalRefs *global_refs;
@ -265,7 +272,7 @@ struct ConstExprValue {
float128_t x_f128;
bool x_bool;
ConstBoundFnValue x_bound_fn;
TypeTableEntry *x_type;
ZigType *x_type;
ConstExprValue *x_optional;
ConstErrValue x_err_union;
ErrorTableEntry *x_err_set;
@ -337,7 +344,7 @@ struct Tld {
struct TldVar {
Tld base;
VariableTableEntry *var;
ZigVar *var;
Buf *extern_lib_name;
Buf *section_name;
};
@ -345,7 +352,7 @@ struct TldVar {
struct TldFn {
Tld base;
FnTableEntry *fn_entry;
ZigFn *fn_entry;
Buf *extern_lib_name;
};
@ -353,7 +360,7 @@ struct TldContainer {
Tld base;
ScopeDecls *decls_scope;
TypeTableEntry *type_entry;
ZigType *type_entry;
};
struct TldCompTime {
@ -370,7 +377,7 @@ struct TypeEnumField {
struct TypeUnionField {
Buf *name;
TypeEnumField *enum_field;
TypeTableEntry *type_entry;
ZigType *type_entry;
AstNode *decl_node;
uint32_t gen_index;
};
@ -973,11 +980,11 @@ struct AstNode {
// this struct is allocated with allocate_nonzero
struct FnTypeParamInfo {
bool is_noalias;
TypeTableEntry *type;
ZigType *type;
};
struct GenericFnTypeId {
FnTableEntry *fn_entry;
ZigFn *fn_entry;
ConstExprValue *params;
size_t param_count;
};
@ -986,14 +993,14 @@ uint32_t generic_fn_type_id_hash(GenericFnTypeId *id);
bool generic_fn_type_id_eql(GenericFnTypeId *a, GenericFnTypeId *b);
struct FnTypeId {
TypeTableEntry *return_type;
ZigType *return_type;
FnTypeParamInfo *param_info;
size_t param_count;
size_t next_param_index;
bool is_var_args;
CallingConvention cc;
uint32_t alignment;
TypeTableEntry *async_allocator_type;
ZigType *async_allocator_type;
};
uint32_t fn_type_id_hash(FnTypeId*);
@ -1004,34 +1011,34 @@ enum PtrLen {
PtrLenSingle,
};
struct TypeTableEntryPointer {
TypeTableEntry *child_type;
struct ZigTypePointer {
ZigType *child_type;
PtrLen ptr_len;
bool is_const;
bool is_volatile;
uint32_t alignment;
uint32_t bit_offset;
uint32_t unaligned_bit_count;
TypeTableEntry *slice_parent;
ZigType *slice_parent;
};
struct TypeTableEntryInt {
struct ZigTypeInt {
uint32_t bit_count;
bool is_signed;
};
struct TypeTableEntryFloat {
struct ZigTypeFloat {
size_t bit_count;
};
struct TypeTableEntryArray {
TypeTableEntry *child_type;
struct ZigTypeArray {
ZigType *child_type;
uint64_t len;
};
struct TypeStructField {
Buf *name;
TypeTableEntry *type_entry;
ZigType *type_entry;
size_t src_index;
size_t gen_index;
// offset from the memory at gen_index
@ -1040,7 +1047,7 @@ struct TypeStructField {
size_t unaligned_bit_count;
AstNode *decl_node;
};
struct TypeTableEntryStruct {
struct ZigTypeStruct {
AstNode *decl_node;
ContainerLayout layout;
uint32_t src_field_count;
@ -1068,28 +1075,28 @@ struct TypeTableEntryStruct {
HashMap<Buf *, TypeStructField *, buf_hash, buf_eql_buf> fields_by_name;
};
struct TypeTableEntryOptional {
TypeTableEntry *child_type;
struct ZigTypeOptional {
ZigType *child_type;
};
struct TypeTableEntryErrorUnion {
TypeTableEntry *err_set_type;
TypeTableEntry *payload_type;
struct ZigTypeErrorUnion {
ZigType *err_set_type;
ZigType *payload_type;
};
struct TypeTableEntryErrorSet {
struct ZigTypeErrorSet {
uint32_t err_count;
ErrorTableEntry **errors;
FnTableEntry *infer_fn;
ZigFn *infer_fn;
};
struct TypeTableEntryEnum {
struct ZigTypeEnum {
AstNode *decl_node;
ContainerLayout layout;
uint32_t src_field_count;
TypeEnumField *fields;
bool is_invalid; // true if any fields are invalid
TypeTableEntry *tag_int_type;
ZigType *tag_int_type;
ScopeDecls *decls_scope;
@ -1107,17 +1114,17 @@ struct TypeTableEntryEnum {
HashMap<Buf *, TypeEnumField *, buf_hash, buf_eql_buf> fields_by_name;
};
uint32_t type_ptr_hash(const TypeTableEntry *ptr);
bool type_ptr_eql(const TypeTableEntry *a, const TypeTableEntry *b);
uint32_t type_ptr_hash(const ZigType *ptr);
bool type_ptr_eql(const ZigType *a, const ZigType *b);
struct TypeTableEntryUnion {
struct ZigTypeUnion {
AstNode *decl_node;
ContainerLayout layout;
uint32_t src_field_count;
uint32_t gen_field_count;
TypeUnionField *fields;
bool is_invalid; // true if any fields are invalid
TypeTableEntry *tag_type; // always an enum or null
ZigType *tag_type; // always an enum or null
LLVMTypeRef union_type_ref;
ScopeDecls *decls_scope;
@ -1142,7 +1149,7 @@ struct TypeTableEntryUnion {
bool have_explicit_tag_type;
uint32_t union_size_bytes;
TypeTableEntry *most_aligned_union_member;
ZigType *most_aligned_union_member;
HashMap<Buf *, TypeUnionField *, buf_hash, buf_eql_buf> fields_by_name;
};
@ -1151,61 +1158,61 @@ struct FnGenParamInfo {
size_t src_index;
size_t gen_index;
bool is_byval;
TypeTableEntry *type;
ZigType *type;
};
struct TypeTableEntryFn {
struct ZigTypeFn {
FnTypeId fn_type_id;
bool is_generic;
TypeTableEntry *gen_return_type;
ZigType *gen_return_type;
size_t gen_param_count;
FnGenParamInfo *gen_param_info;
LLVMTypeRef raw_type_ref;
TypeTableEntry *bound_fn_parent;
ZigType *bound_fn_parent;
};
struct TypeTableEntryBoundFn {
TypeTableEntry *fn_type;
struct ZigTypeBoundFn {
ZigType *fn_type;
};
struct TypeTableEntryPromise {
struct ZigTypePromise {
// null if `promise` instead of `promise->T`
TypeTableEntry *result_type;
ZigType *result_type;
};
enum TypeTableEntryId {
TypeTableEntryIdInvalid,
TypeTableEntryIdMetaType,
TypeTableEntryIdVoid,
TypeTableEntryIdBool,
TypeTableEntryIdUnreachable,
TypeTableEntryIdInt,
TypeTableEntryIdFloat,
TypeTableEntryIdPointer,
TypeTableEntryIdArray,
TypeTableEntryIdStruct,
TypeTableEntryIdComptimeFloat,
TypeTableEntryIdComptimeInt,
TypeTableEntryIdUndefined,
TypeTableEntryIdNull,
TypeTableEntryIdOptional,
TypeTableEntryIdErrorUnion,
TypeTableEntryIdErrorSet,
TypeTableEntryIdEnum,
TypeTableEntryIdUnion,
TypeTableEntryIdFn,
TypeTableEntryIdNamespace,
TypeTableEntryIdBlock,
TypeTableEntryIdBoundFn,
TypeTableEntryIdArgTuple,
TypeTableEntryIdOpaque,
TypeTableEntryIdPromise,
enum ZigTypeId {
ZigTypeIdInvalid,
ZigTypeIdMetaType,
ZigTypeIdVoid,
ZigTypeIdBool,
ZigTypeIdUnreachable,
ZigTypeIdInt,
ZigTypeIdFloat,
ZigTypeIdPointer,
ZigTypeIdArray,
ZigTypeIdStruct,
ZigTypeIdComptimeFloat,
ZigTypeIdComptimeInt,
ZigTypeIdUndefined,
ZigTypeIdNull,
ZigTypeIdOptional,
ZigTypeIdErrorUnion,
ZigTypeIdErrorSet,
ZigTypeIdEnum,
ZigTypeIdUnion,
ZigTypeIdFn,
ZigTypeIdNamespace,
ZigTypeIdBlock,
ZigTypeIdBoundFn,
ZigTypeIdArgTuple,
ZigTypeIdOpaque,
ZigTypeIdPromise,
};
struct TypeTableEntry {
TypeTableEntryId id;
struct ZigType {
ZigTypeId id;
Buf name;
LLVMTypeRef type_ref;
@ -1216,26 +1223,26 @@ struct TypeTableEntry {
bool gen_h_loop_flag;
union {
TypeTableEntryPointer pointer;
TypeTableEntryInt integral;
TypeTableEntryFloat floating;
TypeTableEntryArray array;
TypeTableEntryStruct structure;
TypeTableEntryOptional maybe;
TypeTableEntryErrorUnion error_union;
TypeTableEntryErrorSet error_set;
TypeTableEntryEnum enumeration;
TypeTableEntryUnion unionation;
TypeTableEntryFn fn;
TypeTableEntryBoundFn bound_fn;
TypeTableEntryPromise promise;
ZigTypePointer pointer;
ZigTypeInt integral;
ZigTypeFloat floating;
ZigTypeArray array;
ZigTypeStruct structure;
ZigTypeOptional maybe;
ZigTypeErrorUnion error_union;
ZigTypeErrorSet error_set;
ZigTypeEnum enumeration;
ZigTypeUnion unionation;
ZigTypeFn fn;
ZigTypeBoundFn bound_fn;
ZigTypePromise promise;
} data;
// use these fields to make sure we don't duplicate type table entries for the same type
TypeTableEntry *pointer_parent[2]; // [0 - mut, 1 - const]
TypeTableEntry *optional_parent;
TypeTableEntry *promise_parent;
TypeTableEntry *promise_frame_parent;
ZigType *pointer_parent[2]; // [0 - mut, 1 - const]
ZigType *optional_parent;
ZigType *promise_parent;
ZigType *promise_frame_parent;
// If we generate a constant name value for this type, we memoize it here.
// The type of this is array
ConstExprValue *cached_const_name_val;
@ -1282,7 +1289,7 @@ struct FnExport {
GlobalLinkageId linkage;
};
struct FnTableEntry {
struct ZigFn {
LLVMValueRef llvm_value;
const char *llvm_name;
AstNode *proto_node;
@ -1291,11 +1298,11 @@ struct FnTableEntry {
Scope *child_scope; // parent is scope for last parameter
ScopeBlock *def_scope; // parent is child_scope
Buf symbol_name;
TypeTableEntry *type_entry; // function type
ZigType *type_entry; // function type
// in the case of normal functions this is the implicit return type
// in the case of async functions this is the implicit return type according to the
// zig source code, not according to zig ir
TypeTableEntry *src_implicit_return_type;
ZigType *src_implicit_return_type;
bool is_test;
FnInline fn_inline;
FnAnalState anal_state;
@ -1310,7 +1317,7 @@ struct FnTableEntry {
AstNode *fn_static_eval_set_node;
ZigList<IrInstruction *> alloca_list;
ZigList<VariableTableEntry *> variable_list;
ZigList<ZigVar *> variable_list;
Buf *section_name;
AstNode *set_alignstack_node;
@ -1323,8 +1330,8 @@ struct FnTableEntry {
bool calls_or_awaits_errorable_fn;
};
uint32_t fn_table_entry_hash(FnTableEntry*);
bool fn_table_entry_eql(FnTableEntry *a, FnTableEntry *b);
uint32_t fn_table_entry_hash(ZigFn*);
bool fn_table_entry_eql(ZigFn *a, ZigFn *b);
enum BuiltinFnId {
BuiltinFnIdInvalid,
@ -1445,11 +1452,11 @@ uint32_t fn_eval_hash(Scope*);
bool fn_eval_eql(Scope *a, Scope *b);
struct TypeId {
TypeTableEntryId id;
ZigTypeId id;
union {
struct {
TypeTableEntry *child_type;
ZigType *child_type;
PtrLen ptr_len;
bool is_const;
bool is_volatile;
@ -1458,7 +1465,7 @@ struct TypeId {
uint32_t unaligned_bit_count;
} pointer;
struct {
TypeTableEntry *child_type;
ZigType *child_type;
uint64_t size;
} array;
struct {
@ -1466,8 +1473,8 @@ struct TypeId {
uint32_t bit_count;
} integer;
struct {
TypeTableEntry *err_set_type;
TypeTableEntry *payload_type;
ZigType *err_set_type;
ZigType *payload_type;
} error_union;
} data;
};
@ -1563,17 +1570,17 @@ struct CodeGen {
// reminder: hash tables must be initialized before use
HashMap<Buf *, ImportTableEntry *, buf_hash, buf_eql_buf> import_table;
HashMap<Buf *, BuiltinFnEntry *, buf_hash, buf_eql_buf> builtin_fn_table;
HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> primitive_type_table;
HashMap<TypeId, TypeTableEntry *, type_id_hash, type_id_eql> type_table;
HashMap<FnTypeId *, TypeTableEntry *, fn_type_id_hash, fn_type_id_eql> fn_type_table;
HashMap<Buf *, ZigType *, buf_hash, buf_eql_buf> primitive_type_table;
HashMap<TypeId, ZigType *, type_id_hash, type_id_eql> type_table;
HashMap<FnTypeId *, ZigType *, fn_type_id_hash, fn_type_id_eql> fn_type_table;
HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;
HashMap<GenericFnTypeId *, FnTableEntry *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table;
HashMap<GenericFnTypeId *, ZigFn *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table;
HashMap<Scope *, IrInstruction *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table;
HashMap<ZigLLVMFnKey, LLVMValueRef, zig_llvm_fn_key_hash, zig_llvm_fn_key_eql> llvm_fn_table;
HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> exported_symbol_names;
HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes;
HashMap<Buf *, ConstExprValue *, buf_hash, buf_eql_buf> string_literals_table;
HashMap<const TypeTableEntry *, ConstExprValue *, type_ptr_hash, type_ptr_eql> type_info_cache;
HashMap<const ZigType *, ConstExprValue *, type_ptr_hash, type_ptr_eql> type_info_cache;
ZigList<ImportTableEntry *> import_queue;
@ -1586,38 +1593,38 @@ struct CodeGen {
uint32_t next_unresolved_index;
struct {
TypeTableEntry *entry_bool;
TypeTableEntry *entry_c_int[CIntTypeCount];
TypeTableEntry *entry_c_longdouble;
TypeTableEntry *entry_c_void;
TypeTableEntry *entry_u8;
TypeTableEntry *entry_u16;
TypeTableEntry *entry_u32;
TypeTableEntry *entry_u29;
TypeTableEntry *entry_u64;
TypeTableEntry *entry_i8;
TypeTableEntry *entry_i32;
TypeTableEntry *entry_i64;
TypeTableEntry *entry_isize;
TypeTableEntry *entry_usize;
TypeTableEntry *entry_f16;
TypeTableEntry *entry_f32;
TypeTableEntry *entry_f64;
TypeTableEntry *entry_f128;
TypeTableEntry *entry_void;
TypeTableEntry *entry_unreachable;
TypeTableEntry *entry_type;
TypeTableEntry *entry_invalid;
TypeTableEntry *entry_namespace;
TypeTableEntry *entry_block;
TypeTableEntry *entry_num_lit_int;
TypeTableEntry *entry_num_lit_float;
TypeTableEntry *entry_undef;
TypeTableEntry *entry_null;
TypeTableEntry *entry_var;
TypeTableEntry *entry_global_error_set;
TypeTableEntry *entry_arg_tuple;
TypeTableEntry *entry_promise;
ZigType *entry_bool;
ZigType *entry_c_int[CIntTypeCount];
ZigType *entry_c_longdouble;
ZigType *entry_c_void;
ZigType *entry_u8;
ZigType *entry_u16;
ZigType *entry_u32;
ZigType *entry_u29;
ZigType *entry_u64;
ZigType *entry_i8;
ZigType *entry_i32;
ZigType *entry_i64;
ZigType *entry_isize;
ZigType *entry_usize;
ZigType *entry_f16;
ZigType *entry_f32;
ZigType *entry_f64;
ZigType *entry_f128;
ZigType *entry_void;
ZigType *entry_unreachable;
ZigType *entry_type;
ZigType *entry_invalid;
ZigType *entry_namespace;
ZigType *entry_block;
ZigType *entry_num_lit_int;
ZigType *entry_num_lit_float;
ZigType *entry_undef;
ZigType *entry_null;
ZigType *entry_var;
ZigType *entry_global_error_set;
ZigType *entry_arg_tuple;
ZigType *entry_promise;
} builtin_types;
EmitFileType emit_file_type;
@ -1672,14 +1679,14 @@ struct CodeGen {
const char *linker_script;
// The function definitions this module includes.
ZigList<FnTableEntry *> fn_defs;
ZigList<ZigFn *> fn_defs;
size_t fn_defs_index;
ZigList<TldVar *> global_vars;
OutType out_type;
FnTableEntry *cur_fn;
FnTableEntry *main_fn;
FnTableEntry *panic_fn;
ZigFn *cur_fn;
ZigFn *main_fn;
ZigFn *panic_fn;
LLVMValueRef cur_ret_ptr;
LLVMValueRef cur_fn_val;
LLVMValueRef cur_err_ret_trace_val_arg;
@ -1732,12 +1739,12 @@ struct CodeGen {
const char **llvm_argv;
size_t llvm_argv_len;
ZigList<FnTableEntry *> test_fns;
TypeTableEntry *test_fn_type;
ZigList<ZigFn *> test_fns;
ZigType *test_fn_type;
bool each_lib_rpath;
TypeTableEntry *err_tag_type;
ZigType *err_tag_type;
ZigList<ZigLLVMDIEnumerator *> err_enumerators;
ZigList<ErrorTableEntry *> errors_by_index;
bool generate_error_name_table;
@ -1761,15 +1768,15 @@ struct CodeGen {
ZigList<TimeEvent> timing_events;
Buf *cache_dir;
Buf cache_dir;
Buf *out_h_path;
ZigList<FnTableEntry *> inline_fns;
ZigList<ZigFn *> inline_fns;
ZigList<AstNode *> tld_ref_source_node_stack;
TypeTableEntry *align_amt_type;
TypeTableEntry *stack_trace_type;
TypeTableEntry *ptr_to_stack_trace_type;
ZigType *align_amt_type;
ZigType *stack_trace_type;
ZigType *ptr_to_stack_trace_type;
ZigList<ZigLLVMDIType **> error_di_types;
@ -1784,7 +1791,7 @@ enum VarLinkage {
VarLinkageExternal,
};
struct VariableTableEntry {
struct ZigVar {
Buf name;
ConstExprValue *value;
LLVMValueRef value_ref;
@ -1809,14 +1816,14 @@ struct VariableTableEntry {
// In an inline loop, multiple variables may be created,
// In this case, a reference to a variable should follow
// this pointer to the redefined variable.
VariableTableEntry *next_var;
ZigVar *next_var;
};
struct ErrorTableEntry {
Buf name;
uint32_t value;
AstNode *decl_node;
TypeTableEntry *set_with_only_this_in_it;
ZigType *set_with_only_this_in_it;
// If we generate a constant error name value for this error, we memoize it here.
// The type of this is array
ConstExprValue *cached_error_name_val;
@ -1834,6 +1841,7 @@ enum ScopeId {
ScopeIdFnDef,
ScopeIdCompTime,
ScopeIdCoroPrelude,
ScopeIdRuntime,
};
struct Scope {
@ -1859,7 +1867,7 @@ struct ScopeDecls {
AstNode *fast_math_set_node;
ImportTableEntry *import;
// If this is a scope from a container, this is the type entry, otherwise null
TypeTableEntry *container_type;
ZigType *container_type;
};
// This scope comes from a block expression in user code.
@ -1901,7 +1909,7 @@ struct ScopeVarDecl {
Scope base;
// The variable that creates this scope
VariableTableEntry *var;
ZigVar *var;
};
// This scope is created for a @cImport
@ -1926,6 +1934,15 @@ struct ScopeLoop {
ZigList<IrBasicBlock *> *incoming_blocks;
};
// This scope blocks certain things from working such as comptime continue
// inside a runtime if expression.
// NodeTypeIfBoolExpr, NodeTypeWhileExpr, NodeTypeForExpr
struct ScopeRuntime {
Scope base;
IrInstruction *is_comptime;
};
// This scope is created for a suspend block in order to have labeled
// suspend for breaking out of a suspend and for detecting if a suspend
// block is inside a suspend block.
@ -1948,7 +1965,7 @@ struct ScopeCompTime {
struct ScopeFnDef {
Scope base;
FnTableEntry *fn_entry;
ZigFn *fn_entry;
};
// This scope is created to indicate that the code in the scope
@ -2145,6 +2162,7 @@ enum IrInstructionId {
IrInstructionIdErrSetCast,
IrInstructionIdToBytes,
IrInstructionIdFromBytes,
IrInstructionIdCheckRuntimeScope,
};
struct IrInstruction {
@ -2279,7 +2297,7 @@ struct IrInstructionBinOp {
struct IrInstructionDeclVar {
IrInstruction base;
VariableTableEntry *var;
ZigVar *var;
IrInstruction *var_type;
IrInstruction *align_value;
IrInstruction *init_value;
@ -2336,14 +2354,15 @@ struct IrInstructionElemPtr {
struct IrInstructionVarPtr {
IrInstruction base;
VariableTableEntry *var;
ZigVar *var;
ScopeFnDef *crossed_fndef_scope;
};
struct IrInstructionCall {
IrInstruction base;
IrInstruction *fn_ref;
FnTableEntry *fn_entry;
ZigFn *fn_entry;
size_t arg_count;
IrInstruction **args;
bool is_comptime;
@ -2373,7 +2392,7 @@ struct IrInstructionCast {
IrInstruction base;
IrInstruction *value;
TypeTableEntry *dest_type;
ZigType *dest_type;
CastOp cast_op;
LLVMValueRef tmp_ptr;
};
@ -2410,7 +2429,7 @@ struct IrInstructionStructInitField {
struct IrInstructionStructInit {
IrInstruction base;
TypeTableEntry *struct_type;
ZigType *struct_type;
size_t field_count;
IrInstructionStructInitField *fields;
LLVMValueRef tmp_ptr;
@ -2419,7 +2438,7 @@ struct IrInstructionStructInit {
struct IrInstructionUnionInit {
IrInstruction base;
TypeTableEntry *union_type;
ZigType *union_type;
TypeUnionField *field;
IrInstruction *init_value;
LLVMValueRef tmp_ptr;
@ -2506,7 +2525,7 @@ struct IrInstructionAsm {
// Most information on inline assembly comes from the source node.
IrInstruction **input_list;
IrInstruction **output_types;
VariableTableEntry **output_vars;
ZigVar **output_vars;
size_t return_count;
bool has_side_effects;
};
@ -2648,7 +2667,7 @@ struct IrInstructionCmpxchg {
IrInstruction *failure_order_value;
// if this instruction gets to runtime then we know these values:
TypeTableEntry *type;
ZigType *type;
AtomicOrder success_order;
AtomicOrder failure_order;
@ -2818,7 +2837,7 @@ struct IrInstructionOverflowOp {
IrInstruction *op2;
IrInstruction *result_ptr;
TypeTableEntry *result_ptr_type;
ZigType *result_ptr_type;
};
struct IrInstructionAlignOf {
@ -3234,6 +3253,13 @@ struct IrInstructionSqrt {
IrInstruction *op;
};
struct IrInstructionCheckRuntimeScope {
IrInstruction base;
IrInstruction *scope_is_comptime;
IrInstruction *is_comptime;
};
static const size_t slice_ptr_index = 0;
static const size_t slice_len_index = 1;
@ -3263,4 +3289,53 @@ enum FloatMode {
FloatModeStrict,
};
enum FnWalkId {
FnWalkIdAttrs,
FnWalkIdCall,
FnWalkIdTypes,
FnWalkIdVars,
FnWalkIdInits,
};
struct FnWalkAttrs {
ZigFn *fn;
unsigned gen_i;
};
struct FnWalkCall {
ZigList<LLVMValueRef> *gen_param_values;
IrInstructionCall *inst;
bool is_var_args;
};
struct FnWalkTypes {
ZigList<ZigLLVMDIType *> *param_di_types;
ZigList<LLVMTypeRef> *gen_param_types;
};
struct FnWalkVars {
ImportTableEntry *import;
LLVMValueRef llvm_fn;
ZigFn *fn;
ZigVar *var;
unsigned gen_i;
};
struct FnWalkInits {
LLVMValueRef llvm_fn;
ZigFn *fn;
unsigned gen_i;
};
struct FnWalk {
FnWalkId id;
union {
FnWalkAttrs attrs;
FnWalkCall call;
FnWalkTypes types;
FnWalkVars vars;
FnWalkInits inits;
} data;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -14,103 +14,104 @@
void semantic_analyze(CodeGen *g);
ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg);
ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg);
TypeTableEntry *new_type_table_entry(TypeTableEntryId id);
TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);
TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type, bool is_const,
ZigType *new_type_table_entry(ZigTypeId id);
ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const);
ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,
bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count);
uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry);
uint64_t type_size_bits(CodeGen *g, TypeTableEntry *type_entry);
TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
TypeTableEntry **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type);
TypeTableEntry *get_c_int_type(CodeGen *g, CIntType c_int_type);
TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id);
TypeTableEntry *get_optional_type(CodeGen *g, TypeTableEntry *child_type);
TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t array_size);
TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *ptr_type);
TypeTableEntry *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind,
uint64_t type_size(CodeGen *g, ZigType *type_entry);
uint64_t type_size_bits(CodeGen *g, ZigType *type_entry);
ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type);
ZigType *get_c_int_type(CodeGen *g, CIntType c_int_type);
ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id);
ZigType *get_optional_type(CodeGen *g, ZigType *child_type);
ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size);
ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type);
ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind,
AstNode *decl_node, const char *name, ContainerLayout layout);
TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x);
TypeTableEntry *get_error_union_type(CodeGen *g, TypeTableEntry *err_set_type, TypeTableEntry *payload_type);
TypeTableEntry *get_bound_fn_type(CodeGen *g, FnTableEntry *fn_entry);
TypeTableEntry *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *name);
TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *field_names[],
TypeTableEntry *field_types[], size_t field_count);
TypeTableEntry *get_promise_type(CodeGen *g, TypeTableEntry *result_type);
TypeTableEntry *get_promise_frame_type(CodeGen *g, TypeTableEntry *return_type);
TypeTableEntry *get_test_fn_type(CodeGen *g);
bool handle_is_ptr(TypeTableEntry *type_entry);
ZigType *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x);
ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payload_type);
ZigType *get_bound_fn_type(CodeGen *g, ZigFn *fn_entry);
ZigType *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *name);
ZigType *get_struct_type(CodeGen *g, const char *type_name, const char *field_names[],
ZigType *field_types[], size_t field_count);
ZigType *get_promise_type(CodeGen *g, ZigType *result_type);
ZigType *get_promise_frame_type(CodeGen *g, ZigType *return_type);
ZigType *get_test_fn_type(CodeGen *g);
bool handle_is_ptr(ZigType *type_entry);
void find_libc_include_path(CodeGen *g);
void find_libc_lib_path(CodeGen *g);
bool type_has_bits(TypeTableEntry *type_entry);
bool type_has_bits(ZigType *type_entry);
ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code);
VariableTableEntry *find_variable(CodeGen *g, Scope *orig_context, Buf *name);
ZigVar *find_variable(CodeGen *g, Scope *orig_context, Buf *name, ScopeFnDef **crossed_fndef_scope);
Tld *find_decl(CodeGen *g, Scope *scope, Buf *name);
void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only, AstNode *source_node);
bool type_is_codegen_pointer(TypeTableEntry *type);
bool type_is_codegen_pointer(ZigType *type);
TypeTableEntry *get_codegen_ptr_type(TypeTableEntry *type);
uint32_t get_ptr_align(TypeTableEntry *type);
bool get_ptr_const(TypeTableEntry *type);
TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry);
TypeTableEntry *container_ref_type(TypeTableEntry *type_entry);
bool type_is_complete(TypeTableEntry *type_entry);
bool type_is_invalid(TypeTableEntry *type_entry);
bool type_is_global_error_set(TypeTableEntry *err_set_type);
bool type_has_zero_bits_known(TypeTableEntry *type_entry);
void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry);
ScopeDecls *get_container_scope(TypeTableEntry *type_entry);
TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name);
TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name);
TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name);
TypeEnumField *find_enum_field_by_tag(TypeTableEntry *enum_type, const BigInt *tag);
TypeUnionField *find_union_field_by_tag(TypeTableEntry *type_entry, const BigInt *tag);
ZigType *get_codegen_ptr_type(ZigType *type);
uint32_t get_ptr_align(ZigType *type);
bool get_ptr_const(ZigType *type);
ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry);
ZigType *container_ref_type(ZigType *type_entry);
bool type_is_complete(ZigType *type_entry);
bool type_is_invalid(ZigType *type_entry);
bool type_is_global_error_set(ZigType *err_set_type);
bool type_has_zero_bits_known(ZigType *type_entry);
void resolve_container_type(CodeGen *g, ZigType *type_entry);
ScopeDecls *get_container_scope(ZigType *type_entry);
TypeStructField *find_struct_type_field(ZigType *type_entry, Buf *name);
TypeEnumField *find_enum_type_field(ZigType *enum_type, Buf *name);
TypeUnionField *find_union_type_field(ZigType *type_entry, Buf *name);
TypeEnumField *find_enum_field_by_tag(ZigType *enum_type, const BigInt *tag);
TypeUnionField *find_union_field_by_tag(ZigType *type_entry, const BigInt *tag);
bool is_ref(TypeTableEntry *type_entry);
bool is_array_ref(TypeTableEntry *type_entry);
bool is_container_ref(TypeTableEntry *type_entry);
bool is_ref(ZigType *type_entry);
bool is_array_ref(ZigType *type_entry);
bool is_container_ref(ZigType *type_entry);
void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node);
void scan_import(CodeGen *g, ImportTableEntry *import);
void preview_use_decl(CodeGen *g, AstNode *node);
void resolve_use_decl(CodeGen *g, AstNode *node);
FnTableEntry *scope_fn_entry(Scope *scope);
ZigFn *scope_fn_entry(Scope *scope);
ImportTableEntry *get_scope_import(Scope *scope);
void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source_node, Scope *parent_scope);
VariableTableEntry *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,
ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,
bool is_const, ConstExprValue *init_value, Tld *src_tld);
TypeTableEntry *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node);
FnTableEntry *create_fn(AstNode *proto_node);
FnTableEntry *create_fn_raw(FnInline inline_value, GlobalLinkageId linkage);
ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node);
ZigFn *create_fn(AstNode *proto_node);
ZigFn *create_fn_raw(FnInline inline_value, GlobalLinkageId linkage);
void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_count_alloc);
AstNode *get_param_decl_node(FnTableEntry *fn_entry, size_t index);
FnTableEntry *scope_get_fn_if_root(Scope *scope);
bool type_requires_comptime(TypeTableEntry *type_entry);
Error ATTRIBUTE_MUST_USE ensure_complete_type(CodeGen *g, TypeTableEntry *type_entry);
Error ATTRIBUTE_MUST_USE type_ensure_zero_bits_known(CodeGen *g, TypeTableEntry *type_entry);
void complete_enum(CodeGen *g, TypeTableEntry *enum_type);
bool ir_get_var_is_comptime(VariableTableEntry *var);
AstNode *get_param_decl_node(ZigFn *fn_entry, size_t index);
ZigFn *scope_get_fn_if_root(Scope *scope);
bool type_requires_comptime(ZigType *type_entry);
Error ATTRIBUTE_MUST_USE ensure_complete_type(CodeGen *g, ZigType *type_entry);
Error ATTRIBUTE_MUST_USE type_ensure_zero_bits_known(CodeGen *g, ZigType *type_entry);
void complete_enum(CodeGen *g, ZigType *enum_type);
bool ir_get_var_is_comptime(ZigVar *var);
bool const_values_equal(ConstExprValue *a, ConstExprValue *b);
void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max);
void eval_min_max_value_int(CodeGen *g, TypeTableEntry *int_type, BigInt *bigint, bool is_max);
void eval_min_max_value(CodeGen *g, ZigType *type_entry, ConstExprValue *const_val, bool is_max);
void eval_min_max_value_int(CodeGen *g, ZigType *int_type, BigInt *bigint, bool is_max);
void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val);
void analyze_fn_ir(CodeGen *g, FnTableEntry *fn_table_entry, AstNode *return_type_node);
void analyze_fn_ir(CodeGen *g, ZigFn *fn_table_entry, AstNode *return_type_node);
ScopeBlock *create_block_scope(AstNode *node, Scope *parent);
ScopeDefer *create_defer_scope(AstNode *node, Scope *parent);
ScopeDeferExpr *create_defer_expr_scope(AstNode *node, Scope *parent);
Scope *create_var_scope(AstNode *node, Scope *parent, VariableTableEntry *var);
Scope *create_var_scope(AstNode *node, Scope *parent, ZigVar *var);
ScopeCImport *create_cimport_scope(AstNode *node, Scope *parent);
ScopeLoop *create_loop_scope(AstNode *node, Scope *parent);
ScopeSuspend *create_suspend_scope(AstNode *node, Scope *parent);
ScopeFnDef *create_fndef_scope(AstNode *node, Scope *parent, FnTableEntry *fn_entry);
ScopeDecls *create_decls_scope(AstNode *node, Scope *parent, TypeTableEntry *container_type, ImportTableEntry *import);
ScopeFnDef *create_fndef_scope(AstNode *node, Scope *parent, ZigFn *fn_entry);
ScopeDecls *create_decls_scope(AstNode *node, Scope *parent, ZigType *container_type, ImportTableEntry *import);
Scope *create_comptime_scope(AstNode *node, Scope *parent);
Scope *create_coro_prelude_scope(AstNode *node, Scope *parent);
Scope *create_runtime_scope(AstNode *node, Scope *parent, IrInstruction *is_comptime);
void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str);
ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str);
@ -118,39 +119,39 @@ ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str);
void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *c_str);
ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *c_str);
void init_const_bigint(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *bigint);
ConstExprValue *create_const_bigint(TypeTableEntry *type, const BigInt *bigint);
void init_const_bigint(ConstExprValue *const_val, ZigType *type, const BigInt *bigint);
ConstExprValue *create_const_bigint(ZigType *type, const BigInt *bigint);
void init_const_unsigned_negative(ConstExprValue *const_val, TypeTableEntry *type, uint64_t x, bool negative);
ConstExprValue *create_const_unsigned_negative(TypeTableEntry *type, uint64_t x, bool negative);
void init_const_unsigned_negative(ConstExprValue *const_val, ZigType *type, uint64_t x, bool negative);
ConstExprValue *create_const_unsigned_negative(ZigType *type, uint64_t x, bool negative);
void init_const_signed(ConstExprValue *const_val, TypeTableEntry *type, int64_t x);
ConstExprValue *create_const_signed(TypeTableEntry *type, int64_t x);
void init_const_signed(ConstExprValue *const_val, ZigType *type, int64_t x);
ConstExprValue *create_const_signed(ZigType *type, int64_t x);
void init_const_usize(CodeGen *g, ConstExprValue *const_val, uint64_t x);
ConstExprValue *create_const_usize(CodeGen *g, uint64_t x);
void init_const_float(ConstExprValue *const_val, TypeTableEntry *type, double value);
ConstExprValue *create_const_float(TypeTableEntry *type, double value);
void init_const_float(ConstExprValue *const_val, ZigType *type, double value);
ConstExprValue *create_const_float(ZigType *type, double value);
void init_const_enum(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *tag);
ConstExprValue *create_const_enum(TypeTableEntry *type, const BigInt *tag);
void init_const_enum(ConstExprValue *const_val, ZigType *type, const BigInt *tag);
ConstExprValue *create_const_enum(ZigType *type, const BigInt *tag);
void init_const_bool(CodeGen *g, ConstExprValue *const_val, bool value);
ConstExprValue *create_const_bool(CodeGen *g, bool value);
void init_const_type(CodeGen *g, ConstExprValue *const_val, TypeTableEntry *type_value);
ConstExprValue *create_const_type(CodeGen *g, TypeTableEntry *type_value);
void init_const_type(CodeGen *g, ConstExprValue *const_val, ZigType *type_value);
ConstExprValue *create_const_type(CodeGen *g, ZigType *type_value);
void init_const_runtime(ConstExprValue *const_val, TypeTableEntry *type);
ConstExprValue *create_const_runtime(TypeTableEntry *type);
void init_const_runtime(ConstExprValue *const_val, ZigType *type);
ConstExprValue *create_const_runtime(ZigType *type);
void init_const_ptr_ref(CodeGen *g, ConstExprValue *const_val, ConstExprValue *pointee_val, bool is_const);
ConstExprValue *create_const_ptr_ref(CodeGen *g, ConstExprValue *pointee_val, bool is_const);
void init_const_ptr_hard_coded_addr(CodeGen *g, ConstExprValue *const_val, TypeTableEntry *pointee_type,
void init_const_ptr_hard_coded_addr(CodeGen *g, ConstExprValue *const_val, ZigType *pointee_type,
size_t addr, bool is_const);
ConstExprValue *create_const_ptr_hard_coded_addr(CodeGen *g, TypeTableEntry *pointee_type,
ConstExprValue *create_const_ptr_hard_coded_addr(CodeGen *g, ZigType *pointee_type,
size_t addr, bool is_const);
void init_const_ptr_array(CodeGen *g, ConstExprValue *const_val, ConstExprValue *array_val,
@ -169,41 +170,48 @@ void init_const_undefined(CodeGen *g, ConstExprValue *const_val);
ConstExprValue *create_const_vals(size_t count);
TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
ZigType *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value);
void expand_undef_array(CodeGen *g, ConstExprValue *const_val);
void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value);
const char *type_id_name(TypeTableEntryId id);
TypeTableEntryId type_id_at_index(size_t index);
const char *type_id_name(ZigTypeId id);
ZigTypeId type_id_at_index(size_t index);
size_t type_id_len();
size_t type_id_index(TypeTableEntry *entry);
TypeTableEntry *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id);
Result<bool> type_is_copyable(CodeGen *g, TypeTableEntry *type_entry);
size_t type_id_index(ZigType *entry);
ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id);
Result<bool> type_is_copyable(CodeGen *g, ZigType *type_entry);
LinkLib *create_link_lib(Buf *name);
bool calling_convention_does_first_arg_return(CallingConvention cc);
LinkLib *add_link_lib(CodeGen *codegen, Buf *lib);
uint32_t get_abi_alignment(CodeGen *g, TypeTableEntry *type_entry);
TypeTableEntry *get_align_amt_type(CodeGen *g);
uint32_t get_abi_alignment(CodeGen *g, ZigType *type_entry);
ZigType *get_align_amt_type(CodeGen *g);
PackageTableEntry *new_anonymous_package(void);
Buf *const_value_to_buffer(ConstExprValue *const_val);
void add_fn_export(CodeGen *g, FnTableEntry *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage, bool ccc);
void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage, bool ccc);
ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name);
TypeTableEntry *get_ptr_to_stack_trace_type(CodeGen *g);
bool resolve_inferred_error_set(CodeGen *g, TypeTableEntry *err_set_type, AstNode *source_node);
ZigType *get_ptr_to_stack_trace_type(CodeGen *g);
bool resolve_inferred_error_set(CodeGen *g, ZigType *err_set_type, AstNode *source_node);
TypeTableEntry *get_auto_err_set_type(CodeGen *g, FnTableEntry *fn_entry);
ZigType *get_auto_err_set_type(CodeGen *g, ZigFn *fn_entry);
uint32_t get_coro_frame_align_bytes(CodeGen *g);
bool fn_type_can_fail(FnTypeId *fn_type_id);
bool type_can_fail(TypeTableEntry *type_entry);
bool fn_eval_cacheable(Scope *scope, TypeTableEntry *return_type);
AstNode *type_decl_node(TypeTableEntry *type_entry);
bool type_can_fail(ZigType *type_entry);
bool fn_eval_cacheable(Scope *scope, ZigType *return_type);
AstNode *type_decl_node(ZigType *type_entry);
TypeTableEntry *get_primitive_type(CodeGen *g, Buf *name);
ZigType *get_primitive_type(CodeGen *g, Buf *name);
bool calling_convention_allows_zig_types(CallingConvention cc);
const char *calling_convention_name(CallingConvention cc);
void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk);
X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty);
bool type_is_c_abi_int(CodeGen *g, ZigType *ty);
bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id);
#endif

View File

@ -173,4 +173,9 @@ static inline void buf_upcase(Buf *buf) {
}
}
static inline Slice<uint8_t> buf_to_slice(Buf *buf) {
return Slice<uint8_t>{reinterpret_cast<uint8_t*>(buf_ptr(buf)), buf_len(buf)};
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -47,7 +47,7 @@ void codegen_set_linker_script(CodeGen *g, const char *linker_script);
void codegen_set_test_filter(CodeGen *g, Buf *filter);
void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix);
void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch);
void codegen_set_cache_dir(CodeGen *g, Buf *cache_dir);
void codegen_set_cache_dir(CodeGen *g, Buf cache_dir);
void codegen_set_output_h_path(CodeGen *g, Buf *h_path);
void codegen_add_time_event(CodeGen *g, const char *name);
void codegen_print_timing_report(CodeGen *g, FILE *f);
@ -61,5 +61,4 @@ void codegen_translate_c(CodeGen *g, Buf *path);
Buf *codegen_generate_builtin_source(CodeGen *g);
#endif

3709
src/ir.cpp

File diff suppressed because it is too large Load Diff

View File

@ -11,15 +11,15 @@
#include "all_types.hpp"
bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutable *ir_executable);
bool ir_gen_fn(CodeGen *g, FnTableEntry *fn_entry);
bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry);
IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
TypeTableEntry *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
FnTableEntry *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
IrExecutable *parent_exec);
TypeTableEntry *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,
TypeTableEntry *expected_type, AstNode *expected_type_source_node);
ZigType *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,
ZigType *expected_type, AstNode *expected_type_source_node);
bool ir_has_side_effects(IrInstruction *instruction);
ConstExprValue *const_ptr_pointee(CodeGen *codegen, ConstExprValue *const_val);

View File

@ -957,6 +957,14 @@ static void ir_print_enum_to_int(IrPrint *irp, IrInstructionEnumToInt *instructi
fprintf(irp->f, ")");
}
static void ir_print_check_runtime_scope(IrPrint *irp, IrInstructionCheckRuntimeScope *instruction) {
fprintf(irp->f, "@checkRuntimeScope(");
ir_print_other_instruction(irp, instruction->scope_is_comptime);
fprintf(irp->f, ",");
ir_print_other_instruction(irp, instruction->is_comptime);
fprintf(irp->f, ")");
}
static void ir_print_int_to_err(IrPrint *irp, IrInstructionIntToErr *instruction) {
fprintf(irp->f, "inttoerr ");
ir_print_other_instruction(irp, instruction->target);
@ -1749,6 +1757,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdEnumToInt:
ir_print_enum_to_int(irp, (IrInstructionEnumToInt *)instruction);
break;
case IrInstructionIdCheckRuntimeScope:
ir_print_check_runtime_scope(irp, (IrInstructionCheckRuntimeScope *)instruction);
break;
}
fprintf(irp->f, "\n");
}

View File

@ -66,7 +66,7 @@ static Buf *build_o_raw(CodeGen *parent_gen, const char *oname, Buf *full_path)
const char *o_ext = target_o_file_ext(&child_gen->zig_target);
Buf *o_out_name = buf_sprintf("%s%s", oname, o_ext);
Buf *output_path = buf_alloc();
os_path_join(parent_gen->cache_dir, o_out_name, output_path);
os_path_join(&parent_gen->cache_dir, o_out_name, output_path);
codegen_link(child_gen, buf_ptr(output_path));
codegen_destroy(child_gen);
@ -587,11 +587,11 @@ static void construct_linker_job_coff(LinkJob *lj) {
buf_appendf(def_contents, "\n");
Buf *def_path = buf_alloc();
os_path_join(g->cache_dir, buf_sprintf("%s.def", buf_ptr(link_lib->name)), def_path);
os_path_join(&g->cache_dir, buf_sprintf("%s.def", buf_ptr(link_lib->name)), def_path);
os_write_file(def_path, def_contents);
Buf *generated_lib_path = buf_alloc();
os_path_join(g->cache_dir, buf_sprintf("%s.lib", buf_ptr(link_lib->name)), generated_lib_path);
os_path_join(&g->cache_dir, buf_sprintf("%s.lib", buf_ptr(link_lib->name)), generated_lib_path);
gen_lib_args.resize(0);
gen_lib_args.append("link");

View File

@ -374,25 +374,26 @@ int main(int argc, char **argv) {
CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe, BuildModeDebug, zig_lib_dir_buf);
codegen_set_out_name(g, buf_create_from_str("build"));
Buf build_file_abs = BUF_INIT;
os_path_resolve(buf_create_from_str("."), buf_create_from_str(build_file), &build_file_abs);
Buf *build_file_buf = buf_create_from_str(build_file);
Buf build_file_abs = os_path_resolve(&build_file_buf, 1);
Buf build_file_basename = BUF_INIT;
Buf build_file_dirname = BUF_INIT;
os_path_split(&build_file_abs, &build_file_dirname, &build_file_basename);
Buf *full_cache_dir = buf_alloc();
Buf full_cache_dir = BUF_INIT;
if (cache_dir == nullptr) {
os_path_join(&build_file_dirname, buf_create_from_str(default_zig_cache_name), full_cache_dir);
os_path_join(&build_file_dirname, buf_create_from_str(default_zig_cache_name), &full_cache_dir);
} else {
os_path_resolve(buf_create_from_str("."), buf_create_from_str(cache_dir), full_cache_dir);
Buf *cache_dir_buf = buf_create_from_str(cache_dir);
full_cache_dir = os_path_resolve(&cache_dir_buf, 1);
}
Buf *path_to_build_exe = buf_alloc();
os_path_join(full_cache_dir, buf_create_from_str("build"), path_to_build_exe);
os_path_join(&full_cache_dir, buf_create_from_str("build"), path_to_build_exe);
codegen_set_cache_dir(g, full_cache_dir);
args.items[1] = buf_ptr(&build_file_dirname);
args.items[2] = buf_ptr(full_cache_dir);
args.items[2] = buf_ptr(&full_cache_dir);
bool build_file_exists;
if ((err = os_file_exists(&build_file_abs, &build_file_exists))) {
@ -789,7 +790,7 @@ int main(int argc, char **argv) {
Buf *zig_root_source_file = (cmd == CmdTranslateC) ? nullptr : in_file_buf;
Buf *full_cache_dir = buf_alloc();
Buf full_cache_dir = BUF_INIT;
Buf *run_exec_path = buf_alloc();
if (cmd == CmdRun) {
if (buf_out_name == nullptr) {
@ -799,13 +800,12 @@ int main(int argc, char **argv) {
Buf *global_cache_dir = buf_alloc();
os_get_global_cache_directory(global_cache_dir);
os_path_join(global_cache_dir, buf_out_name, run_exec_path);
os_path_resolve(buf_create_from_str("."), global_cache_dir, full_cache_dir);
full_cache_dir = os_path_resolve(&global_cache_dir, 1);
out_file = buf_ptr(run_exec_path);
} else {
os_path_resolve(buf_create_from_str("."),
buf_create_from_str((cache_dir == nullptr) ? default_zig_cache_name : cache_dir),
full_cache_dir);
Buf *resolve_paths = buf_create_from_str((cache_dir == nullptr) ? default_zig_cache_name : cache_dir);
full_cache_dir = os_path_resolve(&resolve_paths, 1);
}
Buf *zig_lib_dir_buf = resolve_zig_lib_dir();
@ -937,7 +937,7 @@ int main(int argc, char **argv) {
Buf *test_exe_name = buf_sprintf("test%s", target_exe_file_ext(non_null_target));
Buf *test_exe_path = buf_alloc();
os_path_join(full_cache_dir, test_exe_name, test_exe_path);
os_path_join(&full_cache_dir, test_exe_name, test_exe_path);
for (size_t i = 0; i < test_exec_args.length; i += 1) {
if (test_exec_args.items[i] == nullptr) {

View File

@ -57,6 +57,54 @@ static clock_serv_t cclock;
#include <errno.h>
#include <time.h>
// Ported from std/mem.zig.
// Coordinate struct fields with memSplit function
struct SplitIterator {
size_t index;
Slice<uint8_t> buffer;
Slice<uint8_t> split_bytes;
};
// Ported from std/mem.zig.
static bool SplitIterator_isSplitByte(SplitIterator *self, uint8_t byte) {
for (size_t i = 0; i < self->split_bytes.len; i += 1) {
if (byte == self->split_bytes.ptr[i]) {
return true;
}
}
return false;
}
// Ported from std/mem.zig.
static Optional<Slice<uint8_t>> SplitIterator_next(SplitIterator *self) {
// move to beginning of token
while (self->index < self->buffer.len &&
SplitIterator_isSplitByte(self, self->buffer.ptr[self->index]))
{
self->index += 1;
}
size_t start = self->index;
if (start == self->buffer.len) {
return {};
}
// move to end of token
while (self->index < self->buffer.len &&
!SplitIterator_isSplitByte(self, self->buffer.ptr[self->index]))
{
self->index += 1;
}
size_t end = self->index;
return Optional<Slice<uint8_t>>::some(self->buffer.slice(start, end));
}
// Ported from std/mem.zig
static SplitIterator memSplit(Slice<uint8_t> buffer, Slice<uint8_t> split_bytes) {
return SplitIterator{0, buffer, split_bytes};
}
#if defined(ZIG_OS_POSIX)
static void populate_termination(Termination *term, int status) {
if (WIFEXITED(status)) {
@ -266,15 +314,31 @@ int os_path_real(Buf *rel_path, Buf *out_abs_path) {
#endif
}
#if defined(ZIG_OS_WINDOWS)
// Ported from std/os/path.zig
static bool isAbsoluteWindows(Slice<uint8_t> path) {
if (path.ptr[0] == '/')
return true;
if (path.ptr[0] == '\\') {
return true;
}
if (path.len < 3) {
return false;
}
if (path.ptr[1] == ':') {
if (path.ptr[2] == '/')
return true;
if (path.ptr[2] == '\\')
return true;
}
return false;
}
#endif
bool os_path_is_absolute(Buf *path) {
#if defined(ZIG_OS_WINDOWS)
if (buf_starts_with_str(path, "/") || buf_starts_with_str(path, "\\"))
return true;
if (buf_len(path) >= 3 && buf_ptr(path)[1] == ':')
return true;
return false;
return isAbsoluteWindows(buf_to_slice(path));
#elif defined(ZIG_OS_POSIX)
return buf_ptr(path)[0] == '/';
#else
@ -282,14 +346,423 @@ bool os_path_is_absolute(Buf *path) {
#endif
}
void os_path_resolve(Buf *ref_path, Buf *target_path, Buf *out_abs_path) {
if (os_path_is_absolute(target_path)) {
buf_init_from_buf(out_abs_path, target_path);
return;
#if defined(ZIG_OS_WINDOWS)
enum WindowsPathKind {
WindowsPathKindNone,
WindowsPathKindDrive,
WindowsPathKindNetworkShare,
};
struct WindowsPath {
Slice<uint8_t> disk_designator;
WindowsPathKind kind;
bool is_abs;
};
// Ported from std/os/path.zig
static WindowsPath windowsParsePath(Slice<uint8_t> path) {
if (path.len >= 2 && path.ptr[1] == ':') {
return WindowsPath{
path.slice(0, 2),
WindowsPathKindDrive,
isAbsoluteWindows(path),
};
}
if (path.len >= 1 && (path.ptr[0] == '/' || path.ptr[0] == '\\') &&
(path.len == 1 || (path.ptr[1] != '/' && path.ptr[1] != '\\')))
{
return WindowsPath{
path.slice(0, 0),
WindowsPathKindNone,
true,
};
}
WindowsPath relative_path = {
str(""),
WindowsPathKindNone,
false,
};
if (path.len < strlen("//a/b")) {
return relative_path;
}
os_path_join(ref_path, target_path, out_abs_path);
return;
{
if (memStartsWith(path, str("//"))) {
if (path.ptr[2] == '/') {
return relative_path;
}
SplitIterator it = memSplit(path, str("/"));
{
Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
if (!opt_component.is_some) return relative_path;
}
{
Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
if (!opt_component.is_some) return relative_path;
}
return WindowsPath{
path.slice(0, it.index),
WindowsPathKindNetworkShare,
isAbsoluteWindows(path),
};
}
}
{
if (memStartsWith(path, str("\\\\"))) {
if (path.ptr[2] == '\\') {
return relative_path;
}
SplitIterator it = memSplit(path, str("\\"));
{
Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
if (!opt_component.is_some) return relative_path;
}
{
Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
if (!opt_component.is_some) return relative_path;
}
return WindowsPath{
path.slice(0, it.index),
WindowsPathKindNetworkShare,
isAbsoluteWindows(path),
};
}
}
return relative_path;
}
// Ported from std/os/path.zig
static uint8_t asciiUpper(uint8_t byte) {
if (byte >= 'a' && byte <= 'z') {
return 'A' + (byte - 'a');
}
return byte;
}
// Ported from std/os/path.zig
static bool asciiEqlIgnoreCase(Slice<uint8_t> s1, Slice<uint8_t> s2) {
if (s1.len != s2.len)
return false;
for (size_t i = 0; i < s1.len; i += 1) {
if (asciiUpper(s1.ptr[i]) != asciiUpper(s2.ptr[i]))
return false;
}
return true;
}
// Ported from std/os/path.zig
static bool compareDiskDesignators(WindowsPathKind kind, Slice<uint8_t> p1, Slice<uint8_t> p2) {
switch (kind) {
case WindowsPathKindNone:
assert(p1.len == 0);
assert(p2.len == 0);
return true;
case WindowsPathKindDrive:
return asciiUpper(p1.ptr[0]) == asciiUpper(p2.ptr[0]);
case WindowsPathKindNetworkShare:
uint8_t sep1 = p1.ptr[0];
uint8_t sep2 = p2.ptr[0];
SplitIterator it1 = memSplit(p1, {&sep1, 1});
SplitIterator it2 = memSplit(p2, {&sep2, 1});
// TODO ASCII is wrong, we actually need full unicode support to compare paths.
return asciiEqlIgnoreCase(SplitIterator_next(&it1).value, SplitIterator_next(&it2).value) &&
asciiEqlIgnoreCase(SplitIterator_next(&it1).value, SplitIterator_next(&it2).value);
}
zig_unreachable();
}
// Ported from std/os/path.zig
static Buf os_path_resolve_windows(Buf **paths_ptr, size_t paths_len) {
if (paths_len == 0) {
Buf cwd = BUF_INIT;
int err;
if ((err = os_get_cwd(&cwd))) {
zig_panic("get cwd failed");
}
return cwd;
}
// determine which disk designator we will result with, if any
char result_drive_buf[3] = {'_', ':', '\0'}; // 0 needed for strlen later
Slice<uint8_t> result_disk_designator = str("");
WindowsPathKind have_drive_kind = WindowsPathKindNone;
bool have_abs_path = false;
size_t first_index = 0;
size_t max_size = 0;
for (size_t i = 0; i < paths_len; i += 1) {
Slice<uint8_t> p = buf_to_slice(paths_ptr[i]);
WindowsPath parsed = windowsParsePath(p);
if (parsed.is_abs) {
have_abs_path = true;
first_index = i;
max_size = result_disk_designator.len;
}
switch (parsed.kind) {
case WindowsPathKindDrive:
result_drive_buf[0] = asciiUpper(parsed.disk_designator.ptr[0]);
result_disk_designator = str(result_drive_buf);
have_drive_kind = WindowsPathKindDrive;
break;
case WindowsPathKindNetworkShare:
result_disk_designator = parsed.disk_designator;
have_drive_kind = WindowsPathKindNetworkShare;
break;
case WindowsPathKindNone:
break;
}
max_size += p.len + 1;
}
// if we will result with a disk designator, loop again to determine
// which is the last time the disk designator is absolutely specified, if any
// and count up the max bytes for paths related to this disk designator
if (have_drive_kind != WindowsPathKindNone) {
have_abs_path = false;
first_index = 0;
max_size = result_disk_designator.len;
bool correct_disk_designator = false;
for (size_t i = 0; i < paths_len; i += 1) {
Slice<uint8_t> p = buf_to_slice(paths_ptr[i]);
WindowsPath parsed = windowsParsePath(p);
if (parsed.kind != WindowsPathKindNone) {
if (parsed.kind == have_drive_kind) {
correct_disk_designator = compareDiskDesignators(have_drive_kind, result_disk_designator, parsed.disk_designator);
} else {
continue;
}
}
if (!correct_disk_designator) {
continue;
}
if (parsed.is_abs) {
first_index = i;
max_size = result_disk_designator.len;
have_abs_path = true;
}
max_size += p.len + 1;
}
}
// Allocate result and fill in the disk designator, calling getCwd if we have to.
Slice<uint8_t> result;
size_t result_index = 0;
if (have_abs_path) {
switch (have_drive_kind) {
case WindowsPathKindDrive: {
result = Slice<uint8_t>::alloc(max_size);
memCopy(result, result_disk_designator);
result_index += result_disk_designator.len;
break;
}
case WindowsPathKindNetworkShare: {
result = Slice<uint8_t>::alloc(max_size);
SplitIterator it = memSplit(buf_to_slice(paths_ptr[first_index]), str("/\\"));
Slice<uint8_t> server_name = SplitIterator_next(&it).value;
Slice<uint8_t> other_name = SplitIterator_next(&it).value;
result.ptr[result_index] = '\\';
result_index += 1;
result.ptr[result_index] = '\\';
result_index += 1;
memCopy(result.sliceFrom(result_index), server_name);
result_index += server_name.len;
result.ptr[result_index] = '\\';
result_index += 1;
memCopy(result.sliceFrom(result_index), other_name);
result_index += other_name.len;
result_disk_designator = result.slice(0, result_index);
break;
}
case WindowsPathKindNone: {
Buf cwd = BUF_INIT;
int err;
if ((err = os_get_cwd(&cwd))) {
zig_panic("get cwd failed");
}
WindowsPath parsed_cwd = windowsParsePath(buf_to_slice(&cwd));
result = Slice<uint8_t>::alloc(max_size + parsed_cwd.disk_designator.len + 1);
memCopy(result, parsed_cwd.disk_designator);
result_index += parsed_cwd.disk_designator.len;
result_disk_designator = result.slice(0, parsed_cwd.disk_designator.len);
if (parsed_cwd.kind == WindowsPathKindDrive) {
result.ptr[0] = asciiUpper(result.ptr[0]);
}
have_drive_kind = parsed_cwd.kind;
break;
}
}
} else {
// TODO call get cwd for the result_disk_designator instead of the global one
Buf cwd = BUF_INIT;
int err;
if ((err = os_get_cwd(&cwd))) {
zig_panic("get cwd failed");
}
result = Slice<uint8_t>::alloc(max_size + buf_len(&cwd) + 1);
memCopy(result, buf_to_slice(&cwd));
result_index += buf_len(&cwd);
WindowsPath parsed_cwd = windowsParsePath(result.slice(0, result_index));
result_disk_designator = parsed_cwd.disk_designator;
if (parsed_cwd.kind == WindowsPathKindDrive) {
result.ptr[0] = asciiUpper(result.ptr[0]);
}
have_drive_kind = parsed_cwd.kind;
}
// Now we know the disk designator to use, if any, and what kind it is. And our result
// is big enough to append all the paths to.
bool correct_disk_designator = true;
for (size_t i = 0; i < paths_len; i += 1) {
Slice<uint8_t> p = buf_to_slice(paths_ptr[i]);
WindowsPath parsed = windowsParsePath(p);
if (parsed.kind != WindowsPathKindNone) {
if (parsed.kind == have_drive_kind) {
correct_disk_designator = compareDiskDesignators(have_drive_kind, result_disk_designator, parsed.disk_designator);
} else {
continue;
}
}
if (!correct_disk_designator) {
continue;
}
SplitIterator it = memSplit(p.sliceFrom(parsed.disk_designator.len), str("/\\"));
while (true) {
Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
if (!opt_component.is_some) break;
Slice<uint8_t> component = opt_component.value;
if (memEql(component, str("."))) {
continue;
} else if (memEql(component, str(".."))) {
while (true) {
if (result_index == 0 || result_index == result_disk_designator.len)
break;
result_index -= 1;
if (result.ptr[result_index] == '\\' || result.ptr[result_index] == '/')
break;
}
} else {
result.ptr[result_index] = '\\';
result_index += 1;
memCopy(result.sliceFrom(result_index), component);
result_index += component.len;
}
}
}
if (result_index == result_disk_designator.len) {
result.ptr[result_index] = '\\';
result_index += 1;
}
Buf return_value = BUF_INIT;
buf_init_from_mem(&return_value, (char *)result.ptr, result_index);
return return_value;
}
#endif
#if defined(ZIG_OS_POSIX)
// Ported from std/os/path.zig
static Buf os_path_resolve_posix(Buf **paths_ptr, size_t paths_len) {
if (paths_len == 0) {
Buf cwd = BUF_INIT;
int err;
if ((err = os_get_cwd(&cwd))) {
zig_panic("get cwd failed");
}
return cwd;
}
size_t first_index = 0;
bool have_abs = false;
size_t max_size = 0;
for (size_t i = 0; i < paths_len; i += 1) {
Buf *p = paths_ptr[i];
if (os_path_is_absolute(p)) {
first_index = i;
have_abs = true;
max_size = 0;
}
max_size += buf_len(p) + 1;
}
uint8_t *result_ptr;
size_t result_len;
size_t result_index = 0;
if (have_abs) {
result_len = max_size;
result_ptr = allocate_nonzero<uint8_t>(result_len);
} else {
Buf cwd = BUF_INIT;
int err;
if ((err = os_get_cwd(&cwd))) {
zig_panic("get cwd failed");
}
result_len = max_size + buf_len(&cwd) + 1;
result_ptr = allocate_nonzero<uint8_t>(result_len);
memcpy(result_ptr, buf_ptr(&cwd), buf_len(&cwd));
result_index += buf_len(&cwd);
}
for (size_t i = first_index; i < paths_len; i += 1) {
Buf *p = paths_ptr[i];
SplitIterator it = memSplit(buf_to_slice(p), str("/"));
while (true) {
Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
if (!opt_component.is_some) break;
Slice<uint8_t> component = opt_component.value;
if (memEql<uint8_t>(component, str("."))) {
continue;
} else if (memEql<uint8_t>(component, str(".."))) {
while (true) {
if (result_index == 0)
break;
result_index -= 1;
if (result_ptr[result_index] == '/')
break;
}
} else {
result_ptr[result_index] = '/';
result_index += 1;
memcpy(result_ptr + result_index, component.ptr, component.len);
result_index += component.len;
}
}
}
if (result_index == 0) {
result_ptr[0] = '/';
result_index += 1;
}
Buf return_value = BUF_INIT;
buf_init_from_mem(&return_value, (char *)result_ptr, result_index);
return return_value;
}
#endif
// Ported from std/os/path.zig
Buf os_path_resolve(Buf **paths_ptr, size_t paths_len) {
#if defined(ZIG_OS_WINDOWS)
return os_path_resolve_windows(paths_ptr, paths_len);
#elif defined(ZIG_OS_POSIX)
return os_path_resolve_posix(paths_ptr, paths_len);
#else
#error "missing os_path_resolve implementation"
#endif
}
int os_fetch_file(FILE *f, Buf *out_buf, bool skip_shebang) {
@ -558,7 +1031,7 @@ int os_exec_process(const char *exe, ZigList<const char *> &args,
void os_write_file(Buf *full_path, Buf *contents) {
FILE *f = fopen(buf_ptr(full_path), "wb");
if (!f) {
zig_panic("open failed");
zig_panic("os_write_file failed for %s", buf_ptr(full_path));
}
size_t amt_written = fwrite(buf_ptr(contents), 1, buf_len(contents), f);
if (amt_written != (size_t)buf_len(contents))
@ -645,21 +1118,19 @@ int os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang) {
int os_get_cwd(Buf *out_cwd) {
#if defined(ZIG_OS_WINDOWS)
buf_resize(out_cwd, 4096);
if (GetCurrentDirectory(buf_len(out_cwd), buf_ptr(out_cwd)) == 0) {
char buf[4096];
if (GetCurrentDirectory(4096, buf) == 0) {
zig_panic("GetCurrentDirectory failed");
}
buf_init_from_str(out_cwd, buf);
return 0;
#elif defined(ZIG_OS_POSIX)
int err = ERANGE;
buf_resize(out_cwd, 512);
while (err == ERANGE) {
buf_resize(out_cwd, buf_len(out_cwd) * 2);
err = getcwd(buf_ptr(out_cwd), buf_len(out_cwd)) ? 0 : errno;
char buf[PATH_MAX];
char *res = getcwd(buf, PATH_MAX);
if (res == nullptr) {
zig_panic("unable to get cwd: %s", strerror(errno));
}
if (err)
zig_panic("unable to get cwd: %s", strerror(err));
buf_init_from_str(out_cwd, res);
return 0;
#else
#error "missing os_get_cwd implementation"
@ -898,21 +1369,20 @@ double os_get_time(void) {
}
int os_make_path(Buf *path) {
Buf *resolved_path = buf_alloc();
os_path_resolve(buf_create_from_str("."), path, resolved_path);
Buf resolved_path = os_path_resolve(&path, 1);
size_t end_index = buf_len(resolved_path);
size_t end_index = buf_len(&resolved_path);
int err;
while (true) {
if ((err = os_make_dir(buf_slice(resolved_path, 0, end_index)))) {
if ((err = os_make_dir(buf_slice(&resolved_path, 0, end_index)))) {
if (err == ErrorPathAlreadyExists) {
if (end_index == buf_len(resolved_path))
if (end_index == buf_len(&resolved_path))
return 0;
} else if (err == ErrorFileNotFound) {
// march end_index backward until next path component
while (true) {
end_index -= 1;
if (os_is_sep(buf_ptr(resolved_path)[end_index]))
if (os_is_sep(buf_ptr(&resolved_path)[end_index]))
break;
}
continue;
@ -920,12 +1390,12 @@ int os_make_path(Buf *path) {
return err;
}
}
if (end_index == buf_len(resolved_path))
if (end_index == buf_len(&resolved_path))
return 0;
// march end_index forward until next path component
while (true) {
end_index += 1;
if (end_index == buf_len(resolved_path) || os_is_sep(buf_ptr(resolved_path)[end_index]))
if (end_index == buf_len(&resolved_path) || os_is_sep(buf_ptr(&resolved_path)[end_index]))
break;
}
}

View File

@ -49,7 +49,7 @@ void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename);
void os_path_extname(Buf *full_path, Buf *out_basename, Buf *out_extname);
void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path);
int os_path_real(Buf *rel_path, Buf *out_abs_path);
void os_path_resolve(Buf *ref_path, Buf *target_path, Buf *out_abs_path);
Buf os_path_resolve(Buf **paths_ptr, size_t paths_len);
bool os_path_is_absolute(Buf *path);
int os_get_global_cache_directory(Buf *out_tmp_path);

View File

@ -186,4 +186,72 @@ static inline double zig_f16_to_double(float16_t x) {
return z;
}
template<typename T>
struct Optional {
T value;
bool is_some;
static inline Optional<T> some(T x) {
return {x, true};
}
};
template<typename T>
struct Slice {
T *ptr;
size_t len;
inline Slice<T> slice(size_t start, size_t end) {
assert(end <= len);
assert(end >= start);
return {
ptr + start,
end - start,
};
}
inline Slice<T> sliceFrom(size_t start) {
assert(start <= len);
return {
ptr + start,
len - start,
};
}
static inline Slice<T> alloc(size_t n) {
return {allocate_nonzero<T>(n), n};
}
};
static inline Slice<uint8_t> str(const char *literal) {
return {(uint8_t*)(literal), strlen(literal)};
}
// Ported from std/mem.zig
template<typename T>
static inline bool memEql(Slice<T> a, Slice<T> b) {
if (a.len != b.len)
return false;
for (size_t i = 0; i < a.len; i += 1) {
if (a.ptr[i] != b.ptr[i])
return false;
}
return true;
}
// Ported from std/mem.zig
template<typename T>
static inline bool memStartsWith(Slice<T> haystack, Slice<T> needle) {
if (needle.len > haystack.len)
return false;
return memEql(haystack.slice(0, needle.len), needle);
}
// Ported from std/mem.zig
template<typename T>
static inline void memCopy(Slice<T> dest, Slice<T> src) {
assert(dest.len >= src.len);
memcpy(dest.ptr, src.ptr, src.len * sizeof(T));
}
#endif

View File

@ -62,6 +62,10 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
return self.len;
}
pub fn capacity(self: Self) usize {
return self.items.len;
}
/// ArrayList takes ownership of the passed in slice. The slice must have been
/// allocated with `allocator`.
/// Deinitialize with `deinit` or use `toOwnedSlice`.
@ -102,6 +106,11 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
new_item_ptr.* = item;
}
pub fn appendAssumeCapacity(self: *Self, item: T) void {
const new_item_ptr = self.addOneAssumeCapacity();
new_item_ptr.* = item;
}
/// Removes the element at the specified index and returns it.
/// The empty slot is filled from the end of the list.
pub fn swapRemove(self: *Self, i: usize) T {
@ -138,7 +147,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
}
pub fn ensureCapacity(self: *Self, new_capacity: usize) !void {
var better_capacity = self.items.len;
var better_capacity = self.capacity();
if (better_capacity >= new_capacity) return;
while (true) {
better_capacity += better_capacity / 2 + 8;
@ -150,8 +159,13 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
pub fn addOne(self: *Self) !*T {
const new_length = self.len + 1;
try self.ensureCapacity(new_length);
return self.addOneAssumeCapacity();
}
pub fn addOneAssumeCapacity(self: *Self) *T {
assert(self.count() < self.capacity());
const result = &self.items[self.len];
self.len = new_length;
self.len += 1;
return result;
}
@ -191,6 +205,17 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
};
}
test "std.ArrayList.init" {
var bytes: [1024]u8 = undefined;
const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator;
var list = ArrayList(i32).init(allocator);
defer list.deinit();
assert(list.count() == 0);
assert(list.capacity() == 0);
}
test "std.ArrayList.basic" {
var bytes: [1024]u8 = undefined;
const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator;

View File

@ -48,6 +48,12 @@ pub const Builder = struct {
cache_root: []const u8,
release_mode: ?builtin.Mode,
pub const CStd = enum {
C89,
C99,
C11,
};
const UserInputOptionsMap = HashMap([]const u8, UserInputOption, mem.hash_slice_u8, mem.eql_slice_u8);
const AvailableOptionsMap = HashMap([]const u8, AvailableOption, mem.hash_slice_u8, mem.eql_slice_u8);
@ -817,6 +823,7 @@ pub const LibExeObjStep = struct {
frameworks: BufSet,
verbose_link: bool,
no_rosegment: bool,
c_std: Builder.CStd,
// zig only stuff
root_src: ?[]const u8,
@ -918,6 +925,7 @@ pub const LibExeObjStep = struct {
.object_src = undefined,
.disable_libc = true,
.build_options_contents = std.Buffer.initSize(builder.allocator, 0) catch unreachable,
.c_std = Builder.CStd.C99,
};
self.computeOutFileNames();
return self;
@ -952,6 +960,7 @@ pub const LibExeObjStep = struct {
.disable_libc = false,
.is_zig = false,
.linker_script = null,
.c_std = Builder.CStd.C99,
.root_src = undefined,
.verbose_link = false,
@ -1392,6 +1401,13 @@ pub const LibExeObjStep = struct {
const is_darwin = self.target.isDarwin();
const c_std_arg = switch (self.c_std) {
Builder.CStd.C89 => "-std=c89",
Builder.CStd.C99 => "-std=c99",
Builder.CStd.C11 => "-std=c11",
};
try cc_args.append(c_std_arg);
switch (self.kind) {
Kind.Obj => {
cc_args.append("-c") catch unreachable;
@ -1678,6 +1694,17 @@ pub const TestStep = struct {
self.filter = text;
}
pub fn addObject(self: *TestStep, obj: *LibExeObjStep) void {
assert(obj.kind == LibExeObjStep.Kind.Obj);
self.step.dependOn(&obj.step);
self.object_files.append(obj.getOutputPath()) catch unreachable;
// TODO should be some kind of isolated directory that only has this header in it
self.include_dirs.append(self.builder.cache_root) catch unreachable;
}
pub fn addObjectFile(self: *TestStep, path: []const u8) void {
self.object_files.append(path) catch unreachable;
}

View File

@ -130,7 +130,7 @@ fn printPad(stdout: var, s: []const u8) !void {
pub fn main() !void {
var stdout_file = try std.io.getStdOut();
var stdout_out_stream = std.io.FileOutStream.init(&stdout_file);
var stdout_out_stream = std.io.FileOutStream.init(stdout_file);
const stdout = &stdout_out_stream.stream;
var buffer: [1024]u8 = undefined;

View File

@ -4,6 +4,7 @@
const std = @import("../index.zig");
const builtin = @import("builtin");
const fmt = std.fmt;
const Endian = builtin.Endian;
const readInt = std.mem.readInt;
@ -114,7 +115,7 @@ pub const X25519 = struct {
return !zerocmp(u8, out);
}
pub fn createPublicKey(public_key: []const u8, private_key: []const u8) bool {
pub fn createPublicKey(public_key: [] u8, private_key: []const u8) bool {
var base_point = []u8{9} ++ []u8{0} ** 31;
return create(public_key, private_key, base_point);
}
@ -573,6 +574,16 @@ const Fe = struct {
}
};
test "x25519 public key calculation from secret key" {
var sk: [32]u8 = undefined;
var pk_expected: [32]u8 = undefined;
var pk_calculated: [32]u8 = undefined;
try fmt.hexToBytes(sk[0..], "8052030376d47112be7f73ed7a019293dd12ad910b654455798b4667d73de166");
try fmt.hexToBytes(pk_expected[0..], "f1814f0e8ff1043d8a44d25babff3cedcae6c22c3edaa48f857ae70de2baae50");
std.debug.assert(X25519.createPublicKey(pk_calculated[0..], sk));
std.debug.assert(std.mem.eql(u8, pk_calculated, pk_expected));
}
test "x25519 rfc7748 vector1" {
const secret_key = "\xa5\x46\xe3\x6b\xf0\x52\x7c\x9d\x3b\x16\x15\x4b\x82\x46\x5e\xdd\x62\x14\x4c\x0a\xc1\xfc\x5a\x18\x50\x6a\x22\x44\xba\x44\x9a\xc4";
const public_key = "\xe6\xdb\x68\x67\x58\x30\x30\xdb\x35\x94\xc1\xa4\x24\xb1\x5f\x7c\x72\x66\x24\xec\x26\xb3\x35\x3b\x10\xa9\x03\xa6\xd0\xab\x1c\x4c";

View File

@ -9,12 +9,12 @@ comptime {
_ = @import("cases/bitcast.zig");
_ = @import("cases/bool.zig");
_ = @import("cases/bugs/1111.zig");
_ = @import("cases/bugs/1230.zig");
_ = @import("cases/bugs/1277.zig");
_ = @import("cases/bugs/1421.zig");
_ = @import("cases/bugs/394.zig");
_ = @import("cases/bugs/655.zig");
_ = @import("cases/bugs/656.zig");
_ = @import("cases/bugs/726.zig");
_ = @import("cases/bugs/828.zig");
_ = @import("cases/bugs/920.zig");
_ = @import("cases/byval_arg_var.zig");

View File

@ -28,4 +28,10 @@ pub fn addCases(cases: *tests.BuildExamplesContext) void {
// TODO figure out how to make this work on darwin - probably libSystem has dlopen/dlsym in it
cases.addBuildFile("test/standalone/load_dynamic_library/build.zig");
}
if (!is_windows // TODO support compiling C files on windows with zig build system
and builtin.arch == builtin.Arch.x86_64 // TODO add C ABI support for other architectures
) {
cases.addBuildFile("test/stage1/c_abi/build.zig");
}
}

View File

@ -1,14 +0,0 @@
const assert = @import("std").debug.assert;
const S = extern struct {
x: i32,
};
extern fn ret_struct() S {
return S{ .x = 42 };
}
test "extern return small struct (bug 1230)" {
const s = ret_struct();
assert(s.x == 42);
}

16
test/cases/bugs/726.zig Normal file
View File

@ -0,0 +1,16 @@
const assert = @import("std").debug.assert;
test "@ptrCast from const to nullable" {
const c: u8 = 4;
var x: ?*const u8 = @ptrCast(?*const u8, &c);
assert(x.?.* == 4);
}
test "@ptrCast from var in empty struct to nullable" {
const container = struct {
var c: u8 = 4;
};
var x: ?*const u8 = @ptrCast(?*const u8, &container.c);
assert(x.?.* == 4);
}

View File

@ -356,6 +356,7 @@ fn testFloatToInts() void {
expectFloatToInt(f32, 255.1, u8, 255);
expectFloatToInt(f32, 127.2, i8, 127);
expectFloatToInt(f32, -128.2, i8, -128);
expectFloatToInt(comptime_int, 1234, i16, 1234);
}
fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) void {

View File

@ -674,3 +674,11 @@ test "inline for with same type but different values" {
}
assert(res == 5);
}
test "refer to the type of a generic function" {
const Func = fn (type) void;
const f: Func = doNothingWithType;
f(i32);
}
fn doNothingWithType(comptime T: type) void {}

View File

@ -176,3 +176,18 @@ test "pass by non-copying value as method, at comptime" {
assert(pt.addPointCoords() == 3);
}
}
fn outer(y: u32) fn (u32) u32 {
const Y = @typeOf(y);
const st = struct {
fn get(z: u32) u32 {
return z + @sizeOf(Y);
}
};
return st.get;
}
test "return inner function which references comptime variable of outer function" {
var func = outer(10);
assert(func(3) == 7);
}

View File

@ -311,3 +311,16 @@ fn testTaggedUnionInit(x: var) bool {
const y = TaggedUnionWithAVoid{ .A = x };
return @TagType(TaggedUnionWithAVoid)(y) == TaggedUnionWithAVoid.A;
}
pub const UnionEnumNoPayloads = union(enum) {
A,
B,
};
test "tagged union with no payloads" {
const a = UnionEnumNoPayloads{ .B = {} };
switch (a) {
@TagType(UnionEnumNoPayloads).A => @panic("wrong"),
@TagType(UnionEnumNoPayloads).B => {},
}
}

View File

@ -1,6 +1,228 @@
const tests = @import("tests.zig");
pub fn addCases(cases: *tests.CompileErrorContext) void {
cases.add(
"variable initialization compile error then referenced",
\\fn Undeclared() type {
\\ return T;
\\}
\\fn Gen() type {
\\ const X = Undeclared();
\\ return struct {
\\ x: X,
\\ };
\\}
\\export fn entry() void {
\\ const S = Gen();
\\}
,
".tmp_source.zig:2:12: error: use of undeclared identifier 'T'",
);
cases.add(
"refer to the type of a generic function",
\\export fn entry() void {
\\ const Func = fn (type) void;
\\ const f: Func = undefined;
\\ f(i32);
\\}
,
".tmp_source.zig:4:5: error: use of undefined value",
);
cases.add(
"accessing runtime parameter from outer function",
\\fn outer(y: u32) fn (u32) u32 {
\\ const st = struct {
\\ fn get(z: u32) u32 {
\\ return z + y;
\\ }
\\ };
\\ return st.get;
\\}
\\export fn entry() void {
\\ var func = outer(10);
\\ var x = func(3);
\\}
,
".tmp_source.zig:4:24: error: 'y' not accessible from inner function",
".tmp_source.zig:3:28: note: crossed function definition here",
".tmp_source.zig:1:10: note: declared here",
);
cases.add(
"non int passed to @intToFloat",
\\export fn entry() void {
\\ const x = @intToFloat(f32, 1.1);
\\}
,
".tmp_source.zig:2:32: error: expected int type, found 'comptime_float'",
);
cases.add(
"non float passed to @floatToInt",
\\export fn entry() void {
\\ const x = @floatToInt(i32, i32(54));
\\}
,
".tmp_source.zig:2:35: error: expected float type, found 'i32'",
);
cases.add(
"out of range comptime_int passed to @floatToInt",
\\export fn entry() void {
\\ const x = @floatToInt(i8, 200);
\\}
,
".tmp_source.zig:2:31: error: integer value 200 cannot be implicitly casted to type 'i8'",
);
cases.add(
"load too many bytes from comptime reinterpreted pointer",
\\export fn entry() void {
\\ const float: f32 = 5.99999999999994648725e-01;
\\ const float_ptr = &float;
\\ const int_ptr = @ptrCast(*const i64, float_ptr);
\\ const int_val = int_ptr.*;
\\}
,
".tmp_source.zig:5:28: error: attempt to read 8 bytes from pointer to f32 which is 4 bytes",
);
cases.add(
"invalid type used in array type",
\\const Item = struct {
\\ field: SomeNonexistentType,
\\};
\\var items: [100]Item = undefined;
\\export fn entry() void {
\\ const a = items[0];
\\}
,
".tmp_source.zig:2:12: error: use of undeclared identifier 'SomeNonexistentType'",
);
cases.add(
"@noInlineCall on an inline function",
\\inline fn foo() void {}
\\
\\export fn entry() void {
\\ @noInlineCall(foo);
\\}
,
".tmp_source.zig:4:5: error: no-inline call of inline function",
);
cases.add(
"comptime continue inside runtime switch",
\\export fn entry() void {
\\ var p: i32 = undefined;
\\ comptime var q = true;
\\ inline while (q) {
\\ switch (p) {
\\ 11 => continue,
\\ else => {},
\\ }
\\ q = false;
\\ }
\\}
,
".tmp_source.zig:6:19: error: comptime control flow inside runtime block",
".tmp_source.zig:5:9: note: runtime block created here",
);
cases.add(
"comptime continue inside runtime while error",
\\export fn entry() void {
\\ var p: error!usize = undefined;
\\ comptime var q = true;
\\ outer: inline while (q) {
\\ while (p) |_| {
\\ continue :outer;
\\ } else |_| {}
\\ q = false;
\\ }
\\}
,
".tmp_source.zig:6:13: error: comptime control flow inside runtime block",
".tmp_source.zig:5:9: note: runtime block created here",
);
cases.add(
"comptime continue inside runtime while optional",
\\export fn entry() void {
\\ var p: ?usize = undefined;
\\ comptime var q = true;
\\ outer: inline while (q) {
\\ while (p) |_| continue :outer;
\\ q = false;
\\ }
\\}
,
".tmp_source.zig:5:23: error: comptime control flow inside runtime block",
".tmp_source.zig:5:9: note: runtime block created here",
);
cases.add(
"comptime continue inside runtime while bool",
\\export fn entry() void {
\\ var p: usize = undefined;
\\ comptime var q = true;
\\ outer: inline while (q) {
\\ while (p == 11) continue :outer;
\\ q = false;
\\ }
\\}
,
".tmp_source.zig:5:25: error: comptime control flow inside runtime block",
".tmp_source.zig:5:9: note: runtime block created here",
);
cases.add(
"comptime continue inside runtime if error",
\\export fn entry() void {
\\ var p: error!i32 = undefined;
\\ comptime var q = true;
\\ inline while (q) {
\\ if (p) |_| continue else |_| {}
\\ q = false;
\\ }
\\}
,
".tmp_source.zig:5:20: error: comptime control flow inside runtime block",
".tmp_source.zig:5:9: note: runtime block created here",
);
cases.add(
"comptime continue inside runtime if optional",
\\export fn entry() void {
\\ var p: ?i32 = undefined;
\\ comptime var q = true;
\\ inline while (q) {
\\ if (p) |_| continue;
\\ q = false;
\\ }
\\}
,
".tmp_source.zig:5:20: error: comptime control flow inside runtime block",
".tmp_source.zig:5:9: note: runtime block created here",
);
cases.add(
"comptime continue inside runtime if bool",
\\export fn entry() void {
\\ var p: usize = undefined;
\\ comptime var q = true;
\\ inline while (q) {
\\ if (p == 11) continue;
\\ q = false;
\\ }
\\}
,
".tmp_source.zig:5:22: error: comptime control flow inside runtime block",
".tmp_source.zig:5:9: note: runtime block created here",
);
cases.add(
"switch with invalid expression parameter",
\\export fn entry() void {
@ -340,15 +562,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
".tmp_source.zig:2:20: error: return type cannot be opaque",
);
cases.add(
"non int passed to @intToFloat",
\\export fn entry() void {
\\ const x = @intToFloat(f32, 1.1);
\\}
,
".tmp_source.zig:2:32: error: expected int type, found 'comptime_float'",
);
cases.add(
"use implicit casts to assign null to non-nullable pointer",
\\export fn entry() void {

View File

@ -20,6 +20,9 @@ pub fn addCases(cases: *tests.GenHContext) void {
\\ A: i32,
\\ B: f32,
\\ C: bool,
\\ D: u64,
\\ E: u64,
\\ F: u64,
\\};
\\export fn entry(foo: Foo) void { }
,
@ -27,6 +30,9 @@ pub fn addCases(cases: *tests.GenHContext) void {
\\ int32_t A;
\\ float B;
\\ bool C;
\\ uint64_t D;
\\ uint64_t E;
\\ uint64_t F;
\\};
\\
\\TEST_EXPORT void entry(struct Foo foo);
@ -34,17 +40,34 @@ pub fn addCases(cases: *tests.GenHContext) void {
);
cases.add("declare union",
\\const Big = extern struct {
\\ A: u64,
\\ B: u64,
\\ C: u64,
\\ D: u64,
\\ E: u64,
\\};
\\const Foo = extern union {
\\ A: i32,
\\ B: f32,
\\ C: bool,
\\ D: Big,
\\};
\\export fn entry(foo: Foo) void { }
\\export fn entry(foo: Foo) void {}
,
\\struct Big {
\\ uint64_t A;
\\ uint64_t B;
\\ uint64_t C;
\\ uint64_t D;
\\ uint64_t E;
\\};
\\
\\union Foo {
\\ int32_t A;
\\ float B;
\\ bool C;
\\ struct Big D;
\\};
\\
\\TEST_EXPORT void entry(union Foo foo);
@ -85,7 +108,6 @@ pub fn addCases(cases: *tests.GenHContext) void {
\\export fn a(s: *S) u8 {
\\ return s.a;
\\}
,
\\struct S;
\\TEST_EXPORT uint8_t a(struct S * s);
@ -101,7 +123,6 @@ pub fn addCases(cases: *tests.GenHContext) void {
\\export fn a(s: *U) u8 {
\\ return s.A;
\\}
,
\\union U;
\\TEST_EXPORT uint8_t a(union U * s);
@ -117,7 +138,6 @@ pub fn addCases(cases: *tests.GenHContext) void {
\\export fn a(s: *E) u8 {
\\ return @enumToInt(s.*);
\\}
,
\\enum E;
\\TEST_EXPORT uint8_t a(enum E * s);

View File

@ -0,0 +1,18 @@
const Builder = @import("std").build.Builder;
pub fn build(b: *Builder) void {
const rel_opts = b.standardReleaseOptions();
const c_obj = b.addCObject("cfuncs", "cfuncs.c");
c_obj.setBuildMode(rel_opts);
c_obj.setNoStdLib(true);
const main = b.addTest("main.zig");
main.setBuildMode(rel_opts);
main.addObject(c_obj);
const test_step = b.step("test", "Test the program");
test_step.dependOn(&main.step);
b.default_step.dependOn(test_step);
}

208
test/stage1/c_abi/cfuncs.c Normal file
View File

@ -0,0 +1,208 @@
#include <inttypes.h>
#include <stdlib.h>
#include <stdbool.h>
void zig_panic();
static void assert_or_panic(bool ok) {
if (!ok) {
zig_panic();
}
}
void zig_u8(uint8_t);
void zig_u16(uint16_t);
void zig_u32(uint32_t);
void zig_u64(uint64_t);
void zig_i8(int8_t);
void zig_i16(int16_t);
void zig_i32(int32_t);
void zig_i64(int64_t);
void zig_f32(float);
void zig_f64(double);
void zig_ptr(void *);
void zig_bool(bool);
void zig_array(uint8_t[10]);
struct BigStruct {
uint64_t a;
uint64_t b;
uint64_t c;
uint64_t d;
uint8_t e;
};
void zig_big_struct(struct BigStruct);
union BigUnion {
struct BigStruct a;
};
void zig_big_union(union BigUnion);
struct SmallStructInts {
uint8_t a;
uint8_t b;
uint8_t c;
uint8_t d;
};
void zig_small_struct_ints(struct SmallStructInts);
struct SplitStructInts {
uint64_t a;
uint8_t b;
uint32_t c;
};
void zig_split_struct_ints(struct SplitStructInts);
struct BigStruct zig_big_struct_both(struct BigStruct);
void run_c_tests(void) {
zig_u8(0xff);
zig_u16(0xfffe);
zig_u32(0xfffffffd);
zig_u64(0xfffffffffffffffc);
zig_i8(-1);
zig_i16(-2);
zig_i32(-3);
zig_i64(-4);
zig_f32(12.34f);
zig_f64(56.78);
zig_ptr((void*)0xdeadbeefL);
zig_bool(true);
uint8_t array[10] = {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
zig_array(array);
{
struct BigStruct s = {1, 2, 3, 4, 5};
zig_big_struct(s);
}
{
struct SmallStructInts s = {1, 2, 3, 4};
zig_small_struct_ints(s);
}
{
struct SplitStructInts s = {1234, 100, 1337};
zig_split_struct_ints(s);
}
{
struct BigStruct s = {30, 31, 32, 33, 34};
struct BigStruct res = zig_big_struct_both(s);
assert_or_panic(res.a == 20);
assert_or_panic(res.b == 21);
assert_or_panic(res.c == 22);
assert_or_panic(res.d == 23);
assert_or_panic(res.e == 24);
}
}
void c_u8(uint8_t x) {
assert_or_panic(x == 0xff);
}
void c_u16(uint16_t x) {
assert_or_panic(x == 0xfffe);
}
void c_u32(uint32_t x) {
assert_or_panic(x == 0xfffffffd);
}
void c_u64(uint64_t x) {
assert_or_panic(x == 0xfffffffffffffffcULL);
}
void c_i8(int8_t x) {
assert_or_panic(x == -1);
}
void c_i16(int16_t x) {
assert_or_panic(x == -2);
}
void c_i32(int32_t x) {
assert_or_panic(x == -3);
}
void c_i64(int64_t x) {
assert_or_panic(x == -4);
}
void c_f32(float x) {
assert_or_panic(x == 12.34f);
}
void c_f64(double x) {
assert_or_panic(x == 56.78);
}
void c_ptr(void *x) {
assert_or_panic(x == (void*)0xdeadbeefL);
}
void c_bool(bool x) {
assert_or_panic(x);
}
void c_array(uint8_t x[10]) {
assert_or_panic(x[0] == '1');
assert_or_panic(x[1] == '2');
assert_or_panic(x[2] == '3');
assert_or_panic(x[3] == '4');
assert_or_panic(x[4] == '5');
assert_or_panic(x[5] == '6');
assert_or_panic(x[6] == '7');
assert_or_panic(x[7] == '8');
assert_or_panic(x[8] == '9');
assert_or_panic(x[9] == '0');
}
void c_big_struct(struct BigStruct x) {
assert_or_panic(x.a == 1);
assert_or_panic(x.b == 2);
assert_or_panic(x.c == 3);
assert_or_panic(x.d == 4);
assert_or_panic(x.e == 5);
}
void c_big_union(union BigUnion x) {
assert_or_panic(x.a.a == 1);
assert_or_panic(x.a.b == 2);
assert_or_panic(x.a.c == 3);
assert_or_panic(x.a.d == 4);
}
void c_small_struct_ints(struct SmallStructInts x) {
assert_or_panic(x.a == 1);
assert_or_panic(x.b == 2);
assert_or_panic(x.c == 3);
assert_or_panic(x.d == 4);
}
void c_split_struct_ints(struct SplitStructInts x) {
assert_or_panic(x.a == 1234);
assert_or_panic(x.b == 100);
assert_or_panic(x.c == 1337);
}
struct BigStruct c_big_struct_both(struct BigStruct x) {
assert_or_panic(x.a == 1);
assert_or_panic(x.b == 2);
assert_or_panic(x.c == 3);
assert_or_panic(x.d == 4);
assert_or_panic(x.e == 5);
struct BigStruct y = {10, 11, 12, 13, 14};
return y;
}

239
test/stage1/c_abi/main.zig Normal file
View File

@ -0,0 +1,239 @@
const std = @import("std");
const assertOrPanic = std.debug.assertOrPanic;
extern fn run_c_tests() void;
export fn zig_panic() noreturn {
@panic("zig_panic called from C");
}
test "C importing Zig ABI Tests" {
run_c_tests();
}
extern fn c_u8(u8) void;
extern fn c_u16(u16) void;
extern fn c_u32(u32) void;
extern fn c_u64(u64) void;
extern fn c_i8(i8) void;
extern fn c_i16(i16) void;
extern fn c_i32(i32) void;
extern fn c_i64(i64) void;
test "C ABI integers" {
c_u8(0xff);
c_u16(0xfffe);
c_u32(0xfffffffd);
c_u64(0xfffffffffffffffc);
c_i8(-1);
c_i16(-2);
c_i32(-3);
c_i64(-4);
}
export fn zig_u8(x: u8) void {
assertOrPanic(x == 0xff);
}
export fn zig_u16(x: u16) void {
assertOrPanic(x == 0xfffe);
}
export fn zig_u32(x: u32) void {
assertOrPanic(x == 0xfffffffd);
}
export fn zig_u64(x: u64) void {
assertOrPanic(x == 0xfffffffffffffffc);
}
export fn zig_i8(x: i8) void {
assertOrPanic(x == -1);
}
export fn zig_i16(x: i16) void {
assertOrPanic(x == -2);
}
export fn zig_i32(x: i32) void {
assertOrPanic(x == -3);
}
export fn zig_i64(x: i64) void {
assertOrPanic(x == -4);
}
extern fn c_f32(f32) void;
extern fn c_f64(f64) void;
test "C ABI floats" {
c_f32(12.34);
c_f64(56.78);
}
export fn zig_f32(x: f32) void {
assertOrPanic(x == 12.34);
}
export fn zig_f64(x: f64) void {
assertOrPanic(x == 56.78);
}
extern fn c_ptr(*c_void) void;
test "C ABI pointer" {
c_ptr(@intToPtr(*c_void, 0xdeadbeef));
}
export fn zig_ptr(x: *c_void) void {
assertOrPanic(@ptrToInt(x) == 0xdeadbeef);
}
extern fn c_bool(bool) void;
test "C ABI bool" {
c_bool(true);
}
export fn zig_bool(x: bool) void {
assertOrPanic(x);
}
extern fn c_array([10]u8) void;
test "C ABI array" {
var array: [10]u8 = "1234567890";
c_array(array);
}
export fn zig_array(x: [10]u8) void {
assertOrPanic(std.mem.eql(u8, x, "1234567890"));
}
const BigStruct = extern struct {
a: u64,
b: u64,
c: u64,
d: u64,
e: u8,
};
extern fn c_big_struct(BigStruct) void;
test "C ABI big struct" {
var s = BigStruct{
.a = 1,
.b = 2,
.c = 3,
.d = 4,
.e = 5,
};
c_big_struct(s);
}
export fn zig_big_struct(x: BigStruct) void {
assertOrPanic(x.a == 1);
assertOrPanic(x.b == 2);
assertOrPanic(x.c == 3);
assertOrPanic(x.d == 4);
assertOrPanic(x.e == 5);
}
const BigUnion = extern union {
a: BigStruct,
};
extern fn c_big_union(BigUnion) void;
test "C ABI big union" {
var x = BigUnion{
.a = BigStruct{
.a = 1,
.b = 2,
.c = 3,
.d = 4,
.e = 5,
},
};
c_big_union(x);
}
export fn zig_big_union(x: BigUnion) void {
assertOrPanic(x.a.a == 1);
assertOrPanic(x.a.b == 2);
assertOrPanic(x.a.c == 3);
assertOrPanic(x.a.d == 4);
assertOrPanic(x.a.e == 5);
}
const SmallStructInts = extern struct {
a: u8,
b: u8,
c: u8,
d: u8,
};
extern fn c_small_struct_ints(SmallStructInts) void;
test "C ABI small struct of ints" {
var s = SmallStructInts{
.a = 1,
.b = 2,
.c = 3,
.d = 4,
};
c_small_struct_ints(s);
}
export fn zig_small_struct_ints(x: SmallStructInts) void {
assertOrPanic(x.a == 1);
assertOrPanic(x.b == 2);
assertOrPanic(x.c == 3);
assertOrPanic(x.d == 4);
}
const SplitStructInt = extern struct {
a: u64,
b: u8,
c: u32,
};
extern fn c_split_struct_ints(SplitStructInt) void;
test "C ABI split struct of ints" {
var s = SplitStructInt{
.a = 1234,
.b = 100,
.c = 1337,
};
c_split_struct_ints(s);
}
export fn zig_split_struct_ints(x: SplitStructInt) void {
assertOrPanic(x.a == 1234);
assertOrPanic(x.b == 100);
assertOrPanic(x.c == 1337);
}
extern fn c_big_struct_both(BigStruct) BigStruct;
test "C ABI sret and byval together" {
var s = BigStruct{
.a = 1,
.b = 2,
.c = 3,
.d = 4,
.e = 5,
};
var y = c_big_struct_both(s);
assertOrPanic(y.a == 10);
assertOrPanic(y.b == 11);
assertOrPanic(y.c == 12);
assertOrPanic(y.d == 13);
assertOrPanic(y.e == 14);
}
export fn zig_big_struct_both(x: BigStruct) BigStruct {
assertOrPanic(x.a == 30);
assertOrPanic(x.b == 31);
assertOrPanic(x.c == 32);
assertOrPanic(x.d == 33);
assertOrPanic(x.e == 34);
var s = BigStruct{
.a = 20,
.b = 21,
.c = 22,
.d = 23,
.e = 24,
};
return s;
}