compiler: implement unsafe.Alignof and unsafe.Sizeof for generic code
For some reason, these aren't lowered when a generic function is instantiated by the SSA package. I've left unsafe.Offsetof to be implemented later, it's a bit difficult to do correctly the way the code is currently structured.
Этот коммит содержится в:
		
							родитель
							
								
									70c52ef1b4
								
							
						
					
					
						коммит
						7b1e5f6f99
					
				
					 3 изменённых файлов: 26 добавлений и 0 удалений
				
			
		|  | @ -1585,6 +1585,20 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues []llvm.Value, c | ||||||
| 		ptr := argValues[0] | 		ptr := argValues[0] | ||||||
| 		len := argValues[1] | 		len := argValues[1] | ||||||
| 		return b.CreateGEP(ptr, []llvm.Value{len}, ""), nil | 		return b.CreateGEP(ptr, []llvm.Value{len}, ""), nil | ||||||
|  | 	case "Alignof": // unsafe.Alignof | ||||||
|  | 		align := b.targetData.ABITypeAlignment(argValues[0].Type()) | ||||||
|  | 		return llvm.ConstInt(b.uintptrType, uint64(align), false), nil | ||||||
|  | 	case "Offsetof": // unsafe.Offsetof | ||||||
|  | 		// This builtin is a bit harder to implement and may need a bit of | ||||||
|  | 		// refactoring to work (it may be easier to implement if we have access | ||||||
|  | 		// to the underlying Go SSA instruction). It is also rarely used: it | ||||||
|  | 		// only applies in generic code and unsafe.Offsetof isn't very commonly | ||||||
|  | 		// used anyway. | ||||||
|  | 		// In other words, postpone it to some other day. | ||||||
|  | 		return llvm.Value{}, b.makeError(pos, "todo: unsafe.Offsetof") | ||||||
|  | 	case "Sizeof": // unsafe.Sizeof | ||||||
|  | 		size := b.targetData.TypeAllocSize(argValues[0].Type()) | ||||||
|  | 		return llvm.ConstInt(b.uintptrType, size, false), nil | ||||||
| 	case "Slice": // unsafe.Slice | 	case "Slice": // unsafe.Slice | ||||||
| 		// This creates a slice from a pointer and a length. | 		// This creates a slice from a pointer and a length. | ||||||
| 		// Note that the exception mentioned in the documentation (if the | 		// Note that the exception mentioned in the documentation (if the | ||||||
|  |  | ||||||
							
								
								
									
										6
									
								
								compiler/testdata/generics.go
									
										
									
									
										предоставленный
									
									
								
							
							
						
						
									
										6
									
								
								compiler/testdata/generics.go
									
										
									
									
										предоставленный
									
									
								
							|  | @ -1,5 +1,7 @@ | ||||||
| package main | package main | ||||||
| 
 | 
 | ||||||
|  | import "unsafe" | ||||||
|  | 
 | ||||||
| type Coord interface { | type Coord interface { | ||||||
| 	int | float32 | 	int | float32 | ||||||
| } | } | ||||||
|  | @ -9,6 +11,8 @@ type Point[T Coord] struct { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func Add[T Coord](a, b Point[T]) Point[T] { | func Add[T Coord](a, b Point[T]) Point[T] { | ||||||
|  | 	checkSize(unsafe.Alignof(a)) | ||||||
|  | 	checkSize(unsafe.Sizeof(a)) | ||||||
| 	return Point[T]{ | 	return Point[T]{ | ||||||
| 		X: a.X + b.X, | 		X: a.X + b.X, | ||||||
| 		Y: a.Y + b.Y, | 		Y: a.Y + b.Y, | ||||||
|  | @ -22,3 +26,5 @@ func main() { | ||||||
| 	var ai, bi Point[int] | 	var ai, bi Point[int] | ||||||
| 	Add(ai, bi) | 	Add(ai, bi) | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func checkSize(uintptr) | ||||||
|  |  | ||||||
							
								
								
									
										6
									
								
								compiler/testdata/generics.ll
									
										
									
									
										предоставленный
									
									
								
							
							
						
						
									
										6
									
								
								compiler/testdata/generics.ll
									
										
									
									
										предоставленный
									
									
								
							|  | @ -94,6 +94,8 @@ entry: | ||||||
|   store float %b.X, float* %b.repack14, align 8 |   store float %b.X, float* %b.repack14, align 8 | ||||||
|   %b.repack15 = getelementptr inbounds %"main.Point[float32]", %"main.Point[float32]"* %b, i32 0, i32 1 |   %b.repack15 = getelementptr inbounds %"main.Point[float32]", %"main.Point[float32]"* %b, i32 0, i32 1 | ||||||
|   store float %b.Y, float* %b.repack15, align 4 |   store float %b.Y, float* %b.repack15, align 4 | ||||||
|  |   call void @main.checkSize(i32 4, i8* undef) #2 | ||||||
|  |   call void @main.checkSize(i32 8, i8* undef) #2 | ||||||
|   %complit.repack = getelementptr inbounds %"main.Point[float32]", %"main.Point[float32]"* %complit, i32 0, i32 0 |   %complit.repack = getelementptr inbounds %"main.Point[float32]", %"main.Point[float32]"* %complit, i32 0, i32 0 | ||||||
|   store float 0.000000e+00, float* %complit.repack, align 8 |   store float 0.000000e+00, float* %complit.repack, align 8 | ||||||
|   %complit.repack17 = getelementptr inbounds %"main.Point[float32]", %"main.Point[float32]"* %complit, i32 0, i32 1 |   %complit.repack17 = getelementptr inbounds %"main.Point[float32]", %"main.Point[float32]"* %complit, i32 0, i32 1 | ||||||
|  | @ -157,6 +159,8 @@ store.throw7:                                     ; preds = %store.next | ||||||
|   unreachable |   unreachable | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | declare void @main.checkSize(i32, i8*) #0 | ||||||
|  | 
 | ||||||
| declare void @runtime.nilPanic(i8*) #0 | declare void @runtime.nilPanic(i8*) #0 | ||||||
| 
 | 
 | ||||||
| ; Function Attrs: nounwind | ; Function Attrs: nounwind | ||||||
|  | @ -185,6 +189,8 @@ entry: | ||||||
|   store i32 %b.X, i32* %b.repack14, align 8 |   store i32 %b.X, i32* %b.repack14, align 8 | ||||||
|   %b.repack15 = getelementptr inbounds %"main.Point[int]", %"main.Point[int]"* %b, i32 0, i32 1 |   %b.repack15 = getelementptr inbounds %"main.Point[int]", %"main.Point[int]"* %b, i32 0, i32 1 | ||||||
|   store i32 %b.Y, i32* %b.repack15, align 4 |   store i32 %b.Y, i32* %b.repack15, align 4 | ||||||
|  |   call void @main.checkSize(i32 4, i8* undef) #2 | ||||||
|  |   call void @main.checkSize(i32 8, i8* undef) #2 | ||||||
|   %complit.repack = getelementptr inbounds %"main.Point[int]", %"main.Point[int]"* %complit, i32 0, i32 0 |   %complit.repack = getelementptr inbounds %"main.Point[int]", %"main.Point[int]"* %complit, i32 0, i32 0 | ||||||
|   store i32 0, i32* %complit.repack, align 8 |   store i32 0, i32* %complit.repack, align 8 | ||||||
|   %complit.repack17 = getelementptr inbounds %"main.Point[int]", %"main.Point[int]"* %complit, i32 0, i32 1 |   %complit.repack17 = getelementptr inbounds %"main.Point[int]", %"main.Point[int]"* %complit, i32 0, i32 1 | ||||||
|  |  | ||||||
		Загрузка…
	
	Создание таблицы
		
		Сослаться в новой задаче
	
	 Ayke van Laethem
						Ayke van Laethem