diff --git a/compiler/compiler.go b/compiler/compiler.go index be15f789..d652f540 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -2258,14 +2258,20 @@ func (b *builder) createConst(prefix string, expr *ssa.Const) llvm.Value { } else if typ.Info()&types.IsString != 0 { str := constant.StringVal(expr.Value) strLen := llvm.ConstInt(b.uintptrType, uint64(len(str)), false) - objname := prefix + "$string" - global := llvm.AddGlobal(b.mod, llvm.ArrayType(b.ctx.Int8Type(), len(str)), objname) - global.SetInitializer(b.ctx.ConstString(str, false)) - global.SetLinkage(llvm.InternalLinkage) - global.SetGlobalConstant(true) - global.SetUnnamedAddr(true) - zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false) - strPtr := b.CreateInBoundsGEP(global, []llvm.Value{zero, zero}, "") + var strPtr llvm.Value + if str != "" { + objname := prefix + "$string" + global := llvm.AddGlobal(b.mod, llvm.ArrayType(b.ctx.Int8Type(), len(str)), objname) + global.SetInitializer(b.ctx.ConstString(str, false)) + global.SetLinkage(llvm.InternalLinkage) + global.SetGlobalConstant(true) + global.SetUnnamedAddr(true) + global.SetAlignment(1) + zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false) + strPtr = b.CreateInBoundsGEP(global, []llvm.Value{zero, zero}, "") + } else { + strPtr = llvm.ConstNull(b.i8ptrType) + } strObj := llvm.ConstNamedStruct(b.getLLVMRuntimeType("_string"), []llvm.Value{strPtr, strLen}) return strObj } else if typ.Kind() == types.UnsafePointer { diff --git a/compiler/symbol.go b/compiler/symbol.go index 5b44c20f..6455fb8f 100644 --- a/compiler/symbol.go +++ b/compiler/symbol.go @@ -355,16 +355,18 @@ func (c *compilerContext) getGlobal(g *ssa.Global) llvm.Value { // Set alignment from the //go:align comment. var alignInBits uint32 - if info.align < 0 || info.align&(info.align-1) != 0 { + alignment := c.targetData.ABITypeAlignment(llvmType) + if info.align > alignment { + alignment = info.align + } + if alignment <= 0 || alignment&(alignment-1) != 0 { // Check for power-of-two (or 0). // See: https://stackoverflow.com/a/108360 c.addError(g.Pos(), "global variable alignment must be a positive power of two") } else { // Set the alignment only when it is a power of two. - alignInBits = uint32(info.align) ^ uint32(info.align-1) - if info.align > c.targetData.ABITypeAlignment(llvmType) { - llvmGlobal.SetAlignment(info.align) - } + alignInBits = uint32(alignment) ^ uint32(alignment-1) + llvmGlobal.SetAlignment(alignment) } if c.Debug && !info.extern { diff --git a/compiler/testdata/string.go b/compiler/testdata/string.go index 3c574d8f..2c37df45 100644 --- a/compiler/testdata/string.go +++ b/compiler/testdata/string.go @@ -1,5 +1,13 @@ package main +func someString() string { + return "foo" +} + +func zeroLengthString() string { + return "" +} + func stringLen(s string) int { return len(s) } diff --git a/compiler/testdata/string.ll b/compiler/testdata/string.ll index 7344a2e5..1c66e9a6 100644 --- a/compiler/testdata/string.ll +++ b/compiler/testdata/string.ll @@ -3,6 +3,10 @@ source_filename = "string.go" target datalayout = "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-f80:32-n8:16:32-S128" target triple = "i686--linux" +%runtime._string = type { i8*, i32 } + +@"main.someString$string" = internal unnamed_addr constant [3 x i8] c"foo", align 1 + declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr { @@ -10,6 +14,16 @@ entry: ret void } +define hidden %runtime._string @main.someString(i8* %context, i8* %parentHandle) unnamed_addr { +entry: + ret %runtime._string { i8* getelementptr inbounds ([3 x i8], [3 x i8]* @"main.someString$string", i32 0, i32 0), i32 3 } +} + +define hidden %runtime._string @main.zeroLengthString(i8* %context, i8* %parentHandle) unnamed_addr { +entry: + ret %runtime._string zeroinitializer +} + define hidden i32 @main.stringLen(i8* %s.data, i32 %s.len, i8* %context, i8* %parentHandle) unnamed_addr { entry: ret i32 %s.len