interp: fix alignment of untyped globals
During a run of interp, some memory (for example, memory allocated through runtime.alloc) may not have a known LLVM type. This memory is alllocated by creating an i8 array. This does not necessarily work, as i8 has no alignment requirements while the allocated object may have allocation requirements. Therefore, the resulting global may have an alignment that is too loose. This works on some microcontrollers but notably does not work on a Cortex-M0 or Cortex-M0+, as all load/store operations must be aligned. This commit fixes this by setting the alignment of untyped memory to the maximum alignment. The determination of "maximum alignment" is not great but should get the job done on most architectures.
Этот коммит содержится в:
родитель
30df912565
коммит
5917b8baa2
2 изменённых файлов: 7 добавлений и 3 удалений
|
@ -21,6 +21,8 @@ type runner struct {
|
|||
targetData llvm.TargetData
|
||||
builder llvm.Builder
|
||||
pointerSize uint32 // cached pointer size from the TargetData
|
||||
i8ptrType llvm.Type // often used type so created in advance
|
||||
maxAlign int // maximum alignment of an object, alignment of runtime.alloc() result
|
||||
debug bool // log debug messages
|
||||
pkgName string // package name of the currently executing package
|
||||
functionCache map[llvm.Value]*function // cache of compiled functions
|
||||
|
@ -43,6 +45,8 @@ func Run(mod llvm.Module, debug bool) error {
|
|||
start: time.Now(),
|
||||
}
|
||||
r.pointerSize = uint32(r.targetData.PointerSize())
|
||||
r.i8ptrType = llvm.PointerType(mod.Context().Int8Type(), 0)
|
||||
r.maxAlign = r.targetData.PrefTypeAlignment(r.i8ptrType) // assume pointers are maximally aligned (this is not always the case)
|
||||
|
||||
initAll := mod.NamedFunction("runtime.initAll")
|
||||
bb := initAll.EntryBasicBlock()
|
||||
|
|
|
@ -522,6 +522,7 @@ func (v pointerValue) toLLVMValue(llvmType llvm.Type, mem *memoryView) llvm.Valu
|
|||
globalType := initializer.Type()
|
||||
llvmValue = llvm.AddGlobal(mem.r.mod, globalType, obj.globalName)
|
||||
llvmValue.SetInitializer(initializer)
|
||||
llvmValue.SetAlignment(mem.r.maxAlign)
|
||||
obj.llvmGlobal = llvmValue
|
||||
mem.put(v.index(), obj)
|
||||
} else {
|
||||
|
@ -795,7 +796,6 @@ func (v *mapValue) toLLVMValue(hashmapType llvm.Type, mem *memoryView) llvm.Valu
|
|||
|
||||
// Convert these buckets into LLVM global variables.
|
||||
ctx := v.r.mod.Context()
|
||||
i8ptrType := llvm.PointerType(ctx.Int8Type(), 0)
|
||||
var nextBucket llvm.Value
|
||||
for i := len(buckets) - 1; i >= 0; i-- {
|
||||
bucket = buckets[i]
|
||||
|
@ -804,9 +804,9 @@ func (v *mapValue) toLLVMValue(hashmapType llvm.Type, mem *memoryView) llvm.Valu
|
|||
}
|
||||
firstBucket := nextBucket
|
||||
if firstBucket.IsNil() {
|
||||
firstBucket = llvm.ConstNull(i8ptrType)
|
||||
firstBucket = llvm.ConstNull(mem.r.i8ptrType)
|
||||
} else {
|
||||
firstBucket = llvm.ConstBitCast(firstBucket, i8ptrType)
|
||||
firstBucket = llvm.ConstBitCast(firstBucket, mem.r.i8ptrType)
|
||||
}
|
||||
|
||||
// Create the hashmap itself, pointing to these buckets.
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче