sentinel pointers and c strings
This commit is contained in:
+54
-14
@@ -112,7 +112,8 @@ valid_value :: proc(
|
||||
switch instructions[value_id].op {
|
||||
case .Param, .Const, .String, .Aggregate, .None, .Optional_Some,
|
||||
.Load_Global, .Address_Of, .Load, .Slice, .Length, .Slice_Ptr, .Unwrap, .Orelse,
|
||||
.Widen, .C_Vararg_Promote, .Weaken_Pointer, .Neg_Checked, .Add_Checked, .Pointer_Add, .Call:
|
||||
.Widen, .C_Vararg_Promote, .Weaken_Pointer, .Weaken_Slice, .Decay_Array_Pointer,
|
||||
.Neg_Checked, .Add_Checked, .Pointer_Add, .Call:
|
||||
return true
|
||||
case .Address_Global, .Alloca, .Index_Address, .Field_Address, .Orelse_Begin,
|
||||
.Store, .Trap, .Return, .Return_Void:
|
||||
@@ -306,21 +307,17 @@ emit_instruction_stream :: proc(
|
||||
case .Param, .Const:
|
||||
case .String:
|
||||
string_id := int(instruction.integer)
|
||||
_, array, pointer_ok := types.array_pointer(instruction.type, &emitter.module.types)
|
||||
if string_id < 0 || string_id >= len(emitter.module.strings) ||
|
||||
!types.is_slice(instruction.type, &emitter.module.types) {
|
||||
!pointer_ok || array.child != types.U8 || !array.has_sentinel ||
|
||||
array.sentinel != 0 || array.count != u64(len(emitter.module.strings[string_id])) {
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid string literal")
|
||||
continue
|
||||
}
|
||||
type_name := llvm_type(instruction.type, &emitter.module.types)
|
||||
fmt.sbprintf(
|
||||
&emitter.builder,
|
||||
" %%string_ptr%d = insertvalue %s poison, ptr @bro.str.%d, 0\n",
|
||||
instruction_index, type_name, string_id,
|
||||
)
|
||||
fmt.sbprintf(
|
||||
&emitter.builder,
|
||||
" %%v%d = insertvalue %s %%string_ptr%d, i64 %d, 1\n",
|
||||
instruction_index, type_name, instruction_index, len(emitter.module.strings[string_id]),
|
||||
" %%v%d = getelementptr %s, ptr @bro.str.%d, i64 0\n",
|
||||
instruction_index, llvm_type(types.child_type(instruction.type, &emitter.module.types), &emitter.module.types), string_id,
|
||||
)
|
||||
case .Aggregate:
|
||||
item, ok := types.node(&emitter.module.types, instruction.type)
|
||||
@@ -465,7 +462,7 @@ emit_instruction_stream :: proc(
|
||||
continue
|
||||
}
|
||||
container := instructions[instruction.a]
|
||||
container_node, container_ok := types.node(&emitter.module.types, container.type)
|
||||
container_node, container_ok := types.container(container.type, &emitter.module.types)
|
||||
if !container_ok {
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid index container")
|
||||
continue
|
||||
@@ -504,7 +501,13 @@ emit_instruction_stream :: proc(
|
||||
fmt.sbprintf(&emitter.builder, " unreachable\nindex_continue%d:\n", instruction_index)
|
||||
}
|
||||
if container_node.kind == .Array {
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = getelementptr %s, ptr %s, i64 0, i64 ", instruction_index, llvm_type(container.type, &emitter.module.types), pointer_name)
|
||||
array_type := container.type
|
||||
_, array, array_pointer_ok := types.array_pointer(container.type, &emitter.module.types)
|
||||
if array_pointer_ok {
|
||||
array_type = types.child_type(container.type, &emitter.module.types)
|
||||
container_node = array
|
||||
}
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = getelementptr %s, ptr %s, i64 0, i64 ", instruction_index, llvm_type(array_type, &emitter.module.types), pointer_name)
|
||||
} else {
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = getelementptr %s, ptr %s, i64 ", instruction_index, llvm_type(instruction.type, &emitter.module.types), pointer_name)
|
||||
}
|
||||
@@ -558,7 +561,7 @@ emit_instruction_stream :: proc(
|
||||
continue
|
||||
}
|
||||
container := instructions[instruction.a]
|
||||
item, ok := types.node(&emitter.module.types, container.type)
|
||||
item, ok := types.container(container.type, &emitter.module.types)
|
||||
if !ok || (item.kind != .Array && item.kind != .Slice) {
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid slice container")
|
||||
continue
|
||||
@@ -566,7 +569,11 @@ emit_instruction_stream :: proc(
|
||||
pointer_name := fmt.tprintf("%%v%d", instruction.a)
|
||||
length_name := fmt.tprintf("%d", item.count)
|
||||
if item.kind == .Array {
|
||||
fmt.sbprintf(&emitter.builder, " %%slice_ptr%d = getelementptr %s, ptr %%v%d, i64 0, i64 0\n", instruction_index, llvm_type(container.type, &emitter.module.types), instruction.a)
|
||||
array_type := container.type
|
||||
if types.is_pointer(container.type, &emitter.module.types) {
|
||||
array_type = types.child_type(container.type, &emitter.module.types)
|
||||
}
|
||||
fmt.sbprintf(&emitter.builder, " %%slice_ptr%d = getelementptr %s, ptr %%v%d, i64 0, i64 0\n", instruction_index, llvm_type(array_type, &emitter.module.types), instruction.a)
|
||||
pointer_name = fmt.tprintf("%%slice_ptr%d", instruction_index)
|
||||
} else if item.kind == .Slice {
|
||||
fmt.sbprintf(&emitter.builder, " %%slice_ptr%d = extractvalue %s %%v%d, 0\n", instruction_index, llvm_type(container.type, &emitter.module.types), instruction.a)
|
||||
@@ -621,12 +628,21 @@ emit_instruction_stream :: proc(
|
||||
continue
|
||||
}
|
||||
container_type := instructions[instruction.a].type
|
||||
_, _, array_pointer_ok := types.array_pointer(container_type, &emitter.module.types)
|
||||
if types.is_array(container_type, &emitter.module.types) {
|
||||
fmt.sbprintf(
|
||||
&emitter.builder,
|
||||
" %%v%d = getelementptr %s, ptr %%v%d, i64 0, i64 0\n",
|
||||
instruction_index, llvm_type(container_type, &emitter.module.types), instruction.a,
|
||||
)
|
||||
} else if array_pointer_ok {
|
||||
fmt.sbprintf(
|
||||
&emitter.builder,
|
||||
" %%v%d = getelementptr %s, ptr %%v%d, i64 0, i64 0\n",
|
||||
instruction_index,
|
||||
llvm_type(types.child_type(container_type, &emitter.module.types), &emitter.module.types),
|
||||
instruction.a,
|
||||
)
|
||||
} else if types.is_slice(container_type, &emitter.module.types) {
|
||||
fmt.sbprintf(
|
||||
&emitter.builder,
|
||||
@@ -741,6 +757,30 @@ emit_instruction_stream :: proc(
|
||||
continue
|
||||
}
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = select i1 true, ptr %%v%d, ptr null\n", instruction_index, instruction.a)
|
||||
case .Weaken_Slice:
|
||||
if !valid_instruction(instructions, instruction.a) ||
|
||||
!types.can_weaken_slice(instructions[instruction.a].type, instruction.type, &emitter.module.types) {
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid slice weakening operand")
|
||||
continue
|
||||
}
|
||||
type_name := llvm_type(instruction.type, &emitter.module.types)
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = select i1 true, %s %%v%d, %s zeroinitializer\n", instruction_index, type_name, instruction.a, type_name)
|
||||
case .Decay_Array_Pointer:
|
||||
if !valid_instruction(instructions, instruction.a) ||
|
||||
!types.can_decay_array_pointer(instructions[instruction.a].type, instruction.type, &emitter.module.types) {
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid array pointer decay operand")
|
||||
continue
|
||||
}
|
||||
array_type := types.child_type(instructions[instruction.a].type, &emitter.module.types)
|
||||
array, _ := types.node(&emitter.module.types, array_type)
|
||||
if types.is_pointer(instruction.type, &emitter.module.types) {
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = getelementptr %s, ptr %%v%d, i64 0, i64 0\n", instruction_index, llvm_type(array_type, &emitter.module.types), instruction.a)
|
||||
} else {
|
||||
type_name := llvm_type(instruction.type, &emitter.module.types)
|
||||
fmt.sbprintf(&emitter.builder, " %%decay_ptr%d = getelementptr %s, ptr %%v%d, i64 0, i64 0\n", instruction_index, llvm_type(array_type, &emitter.module.types), instruction.a)
|
||||
fmt.sbprintf(&emitter.builder, " %%decay_slice%d = insertvalue %s poison, ptr %%decay_ptr%d, 0\n", instruction_index, type_name, instruction_index)
|
||||
fmt.sbprintf(&emitter.builder, " %%v%d = insertvalue %s %%decay_slice%d, i64 %d, 1\n", instruction_index, type_name, instruction_index, array.count)
|
||||
}
|
||||
case .Neg_Checked:
|
||||
if !valid_value(instructions, instruction.a, instruction.type, &emitter.module.types) {
|
||||
emit_recovery_value(emitter, instruction_index, instruction, "invalid negation operand")
|
||||
|
||||
Reference in New Issue
Block a user