Generator now adds null terminator to c-strings

This commit is contained in:
Sasha Koshka 2023-11-29 00:45:38 -05:00
parent 37819645cd
commit c5a61e15f6

View File

@ -90,7 +90,7 @@ func (this *generator) generateLiteralArrayLoc (literal *entity.LiteralArray) (l
func (this *generator) generateLiteralStringLoc (literal *entity.LiteralString) (llvm.Value, error) { func (this *generator) generateLiteralStringLoc (literal *entity.LiteralString) (llvm.Value, error) {
base := analyzer.ReduceToBase(literal.Type()) base := analyzer.ReduceToBase(literal.Type())
makeData := func (anyElementType entity.Type) (llvm.Value, int64, error) { makeData := func (anyElementType entity.Type, cstring bool) (llvm.Value, int64, error) {
elementType, ok := analyzer.ReduceToBase(anyElementType).(*entity.TypeInt) elementType, ok := analyzer.ReduceToBase(anyElementType).(*entity.TypeInt)
if !ok { if !ok {
return nil, 0, errors.New(fmt.Sprintln("string can't be used as ", base)) return nil, 0, errors.New(fmt.Sprintln("string can't be used as ", base))
@ -99,57 +99,87 @@ func (this *generator) generateLiteralStringLoc (literal *entity.LiteralString)
switch { switch {
case elementType.Width >= 32: case elementType.Width >= 32:
length := len(literal.ValueUTF32) length := len(literal.ValueUTF32)
if cstring { length += 1 }
irArrayType, err := this.generateType(&entity.TypeArray { irArrayType, err := this.generateType(&entity.TypeArray {
Element: elementType, Element: elementType,
Length: length, Length: length,
}) })
if err != nil { return nil, 0, err } if err != nil { return nil, 0, err }
array := this.blockManager.newAllocaFront(irArrayType) array := this.blockManager.newAllocaFront(irArrayType)
for index, element := range literal.ValueUTF32 {
for index := 0; index < length; index ++ {
var element int64
if index >= len(literal.ValueUTF32) {
element = 0
} else {
element = int64(literal.ValueUTF32[index])
}
elementPointer := this.blockManager.NewGetElementPtr ( elementPointer := this.blockManager.NewGetElementPtr (
irArrayType, array, irArrayType, array,
llvm.NewConstInt(llvm.I32, 0), llvm.NewConstInt(llvm.I32, 0),
llvm.NewConstInt(llvm.I32, int64(index))) llvm.NewConstInt(llvm.I32, int64(index)))
this.blockManager.NewStore ( this.blockManager.NewStore (
llvm.NewConstInt(llvm.I32, int64(element)), llvm.NewConstInt(llvm.I32, element),
elementPointer) elementPointer)
} }
return array, int64(length), nil return array, int64(length), nil
case elementType.Width >= 16: case elementType.Width >= 16:
length := len(literal.ValueUTF16) length := len(literal.ValueUTF16)
if cstring { length += 1 }
irArrayType, err := this.generateType(&entity.TypeArray { irArrayType, err := this.generateType(&entity.TypeArray {
Element: elementType, Element: elementType,
Length: length, Length: length,
}) })
if err != nil { return nil, 0, err } if err != nil { return nil, 0, err }
array := this.blockManager.newAllocaFront(irArrayType) array := this.blockManager.newAllocaFront(irArrayType)
for index, element := range literal.ValueUTF16 {
for index := 0; index < length; index ++ {
var element int64
if index >= len(literal.ValueUTF16) {
element = 0
} else {
element = int64(literal.ValueUTF16[index])
}
elementPointer := this.blockManager.NewGetElementPtr ( elementPointer := this.blockManager.NewGetElementPtr (
irArrayType, array, irArrayType, array,
llvm.NewConstInt(llvm.I32, 0), llvm.NewConstInt(llvm.I32, 0),
llvm.NewConstInt(llvm.I32, int64(index))) llvm.NewConstInt(llvm.I32, int64(index)))
this.blockManager.NewStore ( this.blockManager.NewStore (
llvm.NewConstInt(llvm.I16, int64(element)), llvm.NewConstInt(llvm.I16, element),
elementPointer) elementPointer)
} }
return array, int64(length), nil return array, int64(length), nil
default: default:
length := len(literal.ValueUTF8) length := len(literal.ValueUTF8)
if cstring { length += 1 }
irArrayType, err := this.generateType(&entity.TypeArray { irArrayType, err := this.generateType(&entity.TypeArray {
Element: elementType, Element: elementType,
Length: length, Length: length,
}) })
if err != nil { return nil, 0, err } if err != nil { return nil, 0, err }
array := this.blockManager.newAllocaFront(irArrayType) array := this.blockManager.newAllocaFront(irArrayType)
for index, element := range literal.ValueUTF8 {
for index := 0; index < length; index ++ {
var element int64
if index >= len(literal.ValueUTF8) {
element = 0
} else {
element = int64(literal.ValueUTF8[index])
}
elementPointer := this.blockManager.NewGetElementPtr ( elementPointer := this.blockManager.NewGetElementPtr (
irArrayType, array, irArrayType, array,
llvm.NewConstInt(llvm.I32, 0), llvm.NewConstInt(llvm.I32, 0),
llvm.NewConstInt(llvm.I32, int64(index))) llvm.NewConstInt(llvm.I32, int64(index)))
this.blockManager.NewStore ( this.blockManager.NewStore (
llvm.NewConstInt(llvm.I8, int64(element)), llvm.NewConstInt(llvm.I8, element),
elementPointer) elementPointer)
} }
return array, int64(length), nil return array, int64(length), nil
@ -174,11 +204,11 @@ func (this *generator) generateLiteralStringLoc (literal *entity.LiteralString)
return char, nil return char, nil
case *entity.TypeArray: case *entity.TypeArray:
value, _, err := makeData(base.Element) value, _, err := makeData(base.Element, false)
return value, err return value, err
case *entity.TypeSlice: case *entity.TypeSlice:
array, length, err := makeData(base.Element) array, length, err := makeData(base.Element, false)
if err != nil { return nil, err } if err != nil { return nil, err }
irType, err := this.generateType(base) irType, err := this.generateType(base)
if err != nil { return nil, err } if err != nil { return nil, err }
@ -207,7 +237,7 @@ func (this *generator) generateLiteralStringLoc (literal *entity.LiteralString)
return slice, nil return slice, nil
case *entity.TypePointer: case *entity.TypePointer:
array, _, err := makeData(base.Referenced) array, _, err := makeData(base.Referenced, true)
if err != nil { return nil, err } if err != nil { return nil, err }
return this.valueToLocation(array), nil return this.valueToLocation(array), nil